diff options
| author | Anselm R Garbe <garbeam@gmail.com> | 2008-06-01 18:02:48 +0100 | 
|---|---|---|
| committer | Anselm R Garbe <garbeam@gmail.com> | 2008-06-01 18:02:48 +0100 | 
| commit | d272d5a95e3ca34f4260b3e4dece25833cae7dfa (patch) | |
| tree | 623629b626707d2caddbe169930b36d3f5086370 | |
| parent | a4e3e95194684e280bb5ec7d3a1fe2ccda3c59be (diff) | |
| download | st-d272d5a95e3ca34f4260b3e4dece25833cae7dfa.tar.xz st-d272d5a95e3ca34f4260b3e4dece25833cae7dfa.zip | |
applied Matthias-Christians changes to std.c
| -rw-r--r-- | std.c | 342 | 
1 files changed, 339 insertions, 3 deletions
| @@ -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 - * st if this isn't an attach process */ +#define LENGTH(x)	(sizeof (x) / sizeof (x)[0]) +#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; +} | 
