commit 771ece25e89882a39700d0a24febbda42363d2ef
parent 1987ae4bacf58c588bbc967434be4e39125c37f9
Author: Anselm R Garbe <garbeam@gmail.com>
Date:   Sun,  1 Jun 2008 18:02:48 +0100

applied Matthias-Christians changes to std.c

Diffstat:
Mstd.c | 342++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 339 insertions(+), 3 deletions(-)

diff --git a/std.c b/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 - * 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; +}