applied Matthias-Christians changes to std.c
This commit is contained in:
		
							parent
							
								
									1987ae4bac
								
							
						
					
					
						commit
						771ece25e8
					
				
							
								
								
									
										342
									
								
								std.c
									
									
									
									
									
								
							
							
						
						
									
										342
									
								
								std.c
									
									
									
									
									
								
							| @ -1,4 +1,340 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ | #include <sys/ioctl.h> | ||||||
|  | #include <sys/select.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/wait.h> | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <unistd.h> | ||||||
| 
 | 
 | ||||||
| /* TODO: add the necessary code into here, which is going to be fork()ed from
 | #define LENGTH(x)	(sizeof (x) / sizeof (x)[0]) | ||||||
|  * st if this isn't an attach process */ | #define MAX(a,b)	(((a) > (b)) ? (a) : (b)) | ||||||
|  | #define MIN(a,b)	(((a) < (b)) ? (a) : (b)) | ||||||
|  | 
 | ||||||
|  | void buffer(char c); | ||||||
|  | void cmd(const char *cmdstr, ...); | ||||||
|  | void *emallocz(unsigned int size); | ||||||
|  | void eprint(const char *errstr, ...); | ||||||
|  | void eprintn(const char *errstr, ...); | ||||||
|  | void getpty(void); | ||||||
|  | void movea(int x, int y); | ||||||
|  | void mover(int x, int y); | ||||||
|  | void parse(void); | ||||||
|  | void scroll(int l); | ||||||
|  | void shell(void); | ||||||
|  | void sigchld(int n); | ||||||
|  | char unbuffer(void); | ||||||
|  | 
 | ||||||
|  | enum { QuestionMark = 1, Digit = 2 }; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	unsigned char data[BUFSIZ]; | ||||||
|  | 	int s, e; | ||||||
|  | 	int n; | ||||||
|  | } RingBuffer; | ||||||
|  | 
 | ||||||
|  | int cols = 80, lines = 25; | ||||||
|  | int cx = 0, cy = 0; | ||||||
|  | int c, s; | ||||||
|  | FILE *fptm = NULL; | ||||||
|  | int ptm, pts; | ||||||
|  | _Bool bold; | ||||||
|  | pid_t pid; | ||||||
|  | RingBuffer buf; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | buffer(char c) { | ||||||
|  | 	if(buf.n < LENGTH(buf.data)) | ||||||
|  | 		buf.n++; | ||||||
|  | 	else | ||||||
|  | 		buf.s = (buf.s + 1) % LENGTH(buf.data); | ||||||
|  | 	buf.data[buf.e++] = c; | ||||||
|  | 	buf.e %= LENGTH(buf.data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | cmd(const char *cmdstr, ...) { | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	putchar('\n'); | ||||||
|  | 	putchar(':'); | ||||||
|  | 	va_start(ap, cmdstr); | ||||||
|  | 	vfprintf(stdout, cmdstr, ap); | ||||||
|  | 	va_end(ap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void * | ||||||
|  | emallocz(unsigned int size) { | ||||||
|  | 	void *res = calloc(1, size); | ||||||
|  | 
 | ||||||
|  | 	if(!res) | ||||||
|  | 		eprint("fatal: could not malloc() %u bytes\n", size); | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | eprint(const char *errstr, ...) { | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	va_start(ap, errstr); | ||||||
|  | 	vfprintf(stderr, errstr, ap); | ||||||
|  | 	va_end(ap); | ||||||
|  | 	exit(EXIT_FAILURE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | eprintn(const char *errstr, ...) { | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	va_start(ap, errstr); | ||||||
|  | 	vfprintf(stderr, errstr, ap); | ||||||
|  | 	va_end(ap); | ||||||
|  | 	fprintf(stderr, ": %s\n", strerror(errno)); | ||||||
|  | 	exit(EXIT_FAILURE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | getpty(void) { | ||||||
|  | 	char *ptsdev; | ||||||
|  | 
 | ||||||
|  | #if defined(_GNU_SOURCE) | ||||||
|  | 	ptm = getpt(); | ||||||
|  | #elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 | ||||||
|  | 	ptm = posix_openpt(O_RDWR); | ||||||
|  | #elif defined(__sgi) | ||||||
|  | 	ttydev = _getpty(&ptm, O_RDWR, 0622, 0); | ||||||
|  | #elif defined(_AIX) | ||||||
|  | 	ptm = open("/dev/ptc", O_RDWR); | ||||||
|  | #else | ||||||
|  | 	ptm = open("/dev/ptmx", O_RDWR); | ||||||
|  | #if defined(__hpux) | ||||||
|  | 	if(ptm == -1) | ||||||
|  | 		ptm = open("/dev/ptym/clone", O_RDWR); | ||||||
|  | #endif | ||||||
|  | 	if(ptm == -1) { | ||||||
|  | 		if(openpty(&ptm, &pts, NULL, NULL, NULL) == -1) | ||||||
|  | 			eprintn("error, cannot open pty"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 	if(ptm != -1) { | ||||||
|  | #if defined(_XOPEN_SOURCE) || !defined(__sgi) || !defined(_AIX) | ||||||
|  | 		if(grantpt(ptm) == -1) | ||||||
|  | 			eprintn("error, cannot grant access to pty"); | ||||||
|  | 		if(unlockpt(ptm) == -1) | ||||||
|  | 			eprintn("error, cannot unlock pty"); | ||||||
|  | 		ptsdev = ptsname(ptm); | ||||||
|  | #elif defined(_AIX) | ||||||
|  | 		ptsdev = ttyname(ptm); | ||||||
|  | #endif | ||||||
|  | 		if(!ptsdev) | ||||||
|  | 			eprintn("error, slave pty name undefined"); | ||||||
|  | 		pts = open(ptsdev, O_RDWR); | ||||||
|  | 		if(pts == -1) | ||||||
|  | 			eprintn("error, cannot open slave pty"); | ||||||
|  | 		puts(ptsdev); | ||||||
|  | #if defined(__hpux) || defined(sun) || defined(__sun) | ||||||
|  | 		ioctl(pts, I_PUSH, "ptem"); | ||||||
|  | 		ioctl(pts, I_PUSH, "ldterm"); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		eprintn("error, cannot open pty"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | movea(int x, int y) { | ||||||
|  | 	x = MAX(x, cols); | ||||||
|  | 	y = MAX(y, lines); | ||||||
|  | 	cx = x; | ||||||
|  | 	cy = y; | ||||||
|  | 	cmd("s %d,%d", x, y); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | mover(int x, int y) { | ||||||
|  | 	movea(cx + x, cy + y); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | parseesc(void) { | ||||||
|  | 	int i, j; | ||||||
|  | 	int arg[16]; | ||||||
|  | 
 | ||||||
|  | 	memset(arg, 0, LENGTH(arg)); | ||||||
|  | 	s = 0; | ||||||
|  | 	c = getc(fptm); | ||||||
|  | 	switch(c) { | ||||||
|  | 	case '[': | ||||||
|  | 		c = getc(fptm); | ||||||
|  | 		for(j = 0; j < LENGTH(arg);) { | ||||||
|  | 			if(isdigit(c)) { | ||||||
|  | 				s |= Digit; | ||||||
|  | 				arg[j] *= 10; | ||||||
|  | 				arg[j] += c - '0'; | ||||||
|  | 			} | ||||||
|  | 			else if(c == '?') | ||||||
|  | 				s |= QuestionMark;  | ||||||
|  | 			else if(c == ';') { | ||||||
|  | 				if(!(s & Digit)) | ||||||
|  | 					eprint("syntax error"); | ||||||
|  | 				s &= ~Digit; | ||||||
|  | 				j++; | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				if(s & Digit) { | ||||||
|  | 					s &= ~Digit; | ||||||
|  | 					j++; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			c = getc(fptm); | ||||||
|  | 		} | ||||||
|  | 		switch(c) { | ||||||
|  | 		case '@': | ||||||
|  | 			break; | ||||||
|  | 		case 'A': | ||||||
|  | 			mover(0, j ? arg[0] : 1); | ||||||
|  | 			break; | ||||||
|  | 		case 'B': | ||||||
|  | 			mover(0, j ? -arg[0] : -1); | ||||||
|  | 			break; | ||||||
|  | 		case 'C': | ||||||
|  | 			mover(j ? arg[0] : 1, 0); | ||||||
|  | 			break; | ||||||
|  | 		case 'D': | ||||||
|  | 			mover(j ? -arg[0] : -1, 0); | ||||||
|  | 			break; | ||||||
|  | 		case 'E': | ||||||
|  | 			/* movel(j ? arg[0] : 1); */ | ||||||
|  | 			break; | ||||||
|  | 		case 'F': | ||||||
|  | 			/* movel(j ? -arg[0] : -1); */ | ||||||
|  | 			break; | ||||||
|  | 		case '`': | ||||||
|  | 		case 'G': | ||||||
|  | 			movea(j ? arg[0] : 1, cy); | ||||||
|  | 			break; | ||||||
|  | 		case 'f': | ||||||
|  | 		case 'H': | ||||||
|  | 			movea(arg[1] ? arg[1] : 1, arg[0] ? arg[0] : 1); | ||||||
|  | 		case 'L': | ||||||
|  | 			/* insline(j ? arg[0] : 1); */ | ||||||
|  | 			break; | ||||||
|  | 		case 'M': | ||||||
|  | 			/* delline(j ? arg[0] : 1); */ | ||||||
|  | 			break; | ||||||
|  | 		case 'P': | ||||||
|  | 			break; | ||||||
|  | 		case 'S': | ||||||
|  | 			scroll(j ? arg[0] : 1); | ||||||
|  | 			break; | ||||||
|  | 		case 'T': | ||||||
|  | 			scroll(j ? -arg[0] : -1); | ||||||
|  | 			break; | ||||||
|  | 		case 'd': | ||||||
|  | 			movea(cx, j ? arg[0] : 1); | ||||||
|  | 			break; | ||||||
|  | 		case 'm': | ||||||
|  | 			for(i = 0; i < j; i++) { | ||||||
|  | 				if(arg[i] >= 30 && arg[i] <= 37) | ||||||
|  | 					cmd("#%d", arg[i] - 30); | ||||||
|  | 				if(arg[i] >= 40 && arg[i] <= 47) | ||||||
|  | 					cmd("|%d", arg[i] - 40); | ||||||
|  | 				/* xterm bright colors */ | ||||||
|  | 				if(arg[i] >= 90 && arg[i] <= 97) | ||||||
|  | 					cmd("#%d", arg[i] - 90); | ||||||
|  | 				if(arg[i] >= 100 && arg[i] <= 107) | ||||||
|  | 					cmd("|%d", arg[i] - 100); | ||||||
|  | 				switch(arg[i]) { | ||||||
|  | 				case 0: | ||||||
|  | 				case 22: | ||||||
|  | 					if(bold) | ||||||
|  | 						cmd("b"); | ||||||
|  | 				case 1: | ||||||
|  | 					if(!bold) | ||||||
|  | 						cmd("b"); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		putchar('\033'); | ||||||
|  | 		ungetc(c, fptm); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | scroll(int l) { | ||||||
|  | 	cmd("s %d, %d", cx, cy + l); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | shell(void) { | ||||||
|  | 	static char *shell = NULL; | ||||||
|  | 
 | ||||||
|  | 	if(!shell && !(shell = getenv("SHELL"))) | ||||||
|  | 		shell = "/bin/sh"; | ||||||
|  | 	pid = fork(); | ||||||
|  | 	switch(pid) { | ||||||
|  | 	case -1: | ||||||
|  | 		eprint("error, cannot fork\n"); | ||||||
|  | 	case 0: | ||||||
|  | 		setsid(); | ||||||
|  | 		dup2(pts, STDIN_FILENO); | ||||||
|  | 		dup2(pts, STDOUT_FILENO); | ||||||
|  | 		dup2(pts, STDERR_FILENO); | ||||||
|  | 		close(ptm); | ||||||
|  | 		putenv("TERM=vt102"); | ||||||
|  | 		execvp(shell, NULL); | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		close(pts); | ||||||
|  | 		signal(SIGCHLD, sigchld); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | sigchld(int n) { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	if(waitpid(pid, &ret, 0) == -1) | ||||||
|  | 		eprintn("error, waiting for child failed"); | ||||||
|  | 	if(WIFEXITED(ret)) | ||||||
|  | 		exit(WEXITSTATUS(ret)); | ||||||
|  | 	else | ||||||
|  | 		exit(EXIT_SUCCESS); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char | ||||||
|  | unbuffer(void) { | ||||||
|  | 	char c; | ||||||
|  | 
 | ||||||
|  | 	c = buf.data[buf.s++]; | ||||||
|  | 	buf.s %= LENGTH(buf.data); | ||||||
|  | 	buf.n--; | ||||||
|  | 	return c; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main(int argc, char *argv[]) { | ||||||
|  | 	fd_set rd; | ||||||
|  | 	if(argc == 2 && !strcmp("-v", argv[1])) | ||||||
|  | 		eprint("std-"VERSION", © 2008 Matthias-Christian Ott\n"); | ||||||
|  | 	else if(argc == 1) | ||||||
|  | 		eprint("usage: st [-v]\n"); | ||||||
|  | 	getpty(); | ||||||
|  | 	shell(); | ||||||
|  | 	fdopen(fptm, "r+"); | ||||||
|  | 	if(!fptm) | ||||||
|  | 		eprintn("cannot open slave pty"); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user