tapplied Matthias-Christians changes to std.c - st - [fork] customized build of… | |
git clone git://src.adamsgaard.dk/st | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 771ece25e89882a39700d0a24febbda42363d2ef | |
parent 1987ae4bacf58c588bbc967434be4e39125c37f9 | |
Author: Anselm R Garbe <[email protected]> | |
Date: Sun, 1 Jun 2008 18:02:48 +0100 | |
applied Matthias-Christians changes to std.c | |
Diffstat: | |
M std.c | 342 +++++++++++++++++++++++++++++… | |
1 file changed, 339 insertions(+), 3 deletions(-) | |
--- | |
diff --git a/std.c b/std.c | |
t@@ -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; | |
+} |