1 /* See LICENSE file for copyright and license details. */
7 #if !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
17 #define LENGTH(x) (sizeof(x) / sizeof((x)[0]))
18 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
19 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
22 unsigned char data[BUFSIZ];
28 unsigned char data[BUFSIZ];
33 static void buffer(char c);
34 static void cmd(const char *cmdstr, ...);
35 static int getch(ReadBuffer *buf);
36 static void getpty(void);
37 static void movea(int x, int y);
38 static void mover(int x, int y);
39 static void parsecmd(void);
40 static void parseesc(void);
41 static void scroll(int l);
42 static void shell(void);
43 static void sigchld(int n);
44 static char unbuffer(void);
45 static void ungetch(ReadBuffer *buf, int c);
47 static int cols = 80, lines = 25;
48 static int cx = 0, cy = 0;
51 static _Bool bold, digit, qmark;
53 static RingBuffer buf;
54 static ReadBuffer cmdbuf, ptmbuf;
58 if(buf.n < LENGTH(buf.data))
61 buf.s = (buf.s + 1) % LENGTH(buf.data);
62 buf.data[buf.e++] = c;
63 buf.e %= LENGTH(buf.data);
67 cmd(const char *cmdstr, ...) {
73 vfprintf(stdout, cmdstr, ap);
78 getch(ReadBuffer *buf) {
79 if(buf->i++ >= buf->n) {
80 buf->n = read(buf->fd, buf->data, BUFSIZ);
82 err(EXIT_FAILURE, "cannot read");
85 return buf->data[buf->i];
94 cmd("seek(%d,%d)", x, y);
99 movea(cx + x, cy + y);
111 memset(arg, 0, LENGTH(arg));
116 for(j = 0; j < LENGTH(arg);) {
126 errx(EXIT_FAILURE, "syntax error");
143 mover(0, j ? arg[0] : 1);
146 mover(0, j ? -arg[0] : -1);
149 mover(j ? arg[0] : 1, 0);
152 mover(j ? -arg[0] : -1, 0);
155 /* movel(j ? arg[0] : 1); */
158 /* movel(j ? -arg[0] : -1); */
162 movea(j ? arg[0] : 1, cy);
166 movea(arg[1] ? arg[1] : 1, arg[0] ? arg[0] : 1);
168 /* insline(j ? arg[0] : 1); */
171 /* delline(j ? arg[0] : 1); */
176 scroll(j ? arg[0] : 1);
179 scroll(j ? -arg[0] : -1);
182 movea(cx, j ? arg[0] : 1);
185 for(i = 0; i < j; i++) {
186 if(arg[i] >= 30 && arg[i] <= 37)
187 cmd("#%d", arg[i] - 30);
188 if(arg[i] >= 40 && arg[i] <= 47)
189 cmd("|%d", arg[i] - 40);
190 /* xterm bright colors */
191 if(arg[i] >= 90 && arg[i] <= 97)
192 cmd("#%d", arg[i] - 90);
193 if(arg[i] >= 100 && arg[i] <= 107)
194 cmd("|%d", arg[i] - 100);
217 cmd("seek(%d,%d)", cx, cy + l);
224 #if defined(_GNU_SOURCE)
226 #elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
227 ptm = posix_openpt(O_RDWR);
229 ptm = open("/dev/ptmx", O_RDWR);
231 if(openpty(&ptm, &pts, NULL, NULL, NULL) == -1)
232 err(EXIT_FAILURE, "cannot open pty");
234 #if defined(_XOPEN_SOURCE)
236 if(grantpt(ptm) == -1)
237 err(EXIT_FAILURE, "cannot grant access to pty");
238 if(unlockpt(ptm) == -1)
239 err(EXIT_FAILURE, "cannot unlock pty");
240 ptsdev = ptsname(ptm);
242 err(EXIT_FAILURE, "slave pty name undefined");
243 pts = open(ptsdev, O_RDWR);
245 err(EXIT_FAILURE, "cannot open slave pty");
248 err(EXIT_FAILURE, "cannot open pty");
254 static char *shell = NULL;
256 if(!shell && !(shell = getenv("SHELL")))
261 err(EXIT_FAILURE, "cannot fork");
264 dup2(pts, STDIN_FILENO);
265 dup2(pts, STDOUT_FILENO);
266 dup2(pts, STDERR_FILENO);
268 putenv("TERM=vt102");
273 signal(SIGCHLD, sigchld);
281 if(waitpid(pid, &ret, 0) == -1)
282 err(EXIT_FAILURE, "waiting for child failed");
284 exit(WEXITSTATUS(ret));
293 c = buf.data[buf.s++];
294 buf.s %= LENGTH(buf.data);
300 ungetch(ReadBuffer *buf, int c) {
301 if(buf->i + 1 >= buf->n)
302 errx(EXIT_FAILURE, "buffer full");
303 buf->data[buf->i++] = c;
307 main(int argc, char *argv[]) {
310 if(argc == 2 && !strcmp("-v", argv[1]))
311 errx(EXIT_SUCCESS, "std-"VERSION", © 2008 Matthias-Christian Ott");
313 errx(EXIT_FAILURE, "usage: std [-v]");
316 cmdbuf.fd = STDIN_FILENO;
319 FD_SET(STDIN_FILENO, &rfds);
322 if(select(ptm + 1, &rfds, NULL, NULL, NULL) == -1)
323 err(EXIT_FAILURE, "cannot select");
324 if(FD_ISSET(STDIN_FILENO, &rfds))
334 } while(cmdbuf.i < cmdbuf.n);
335 if(FD_ISSET(ptm, &rfds)) {
345 } while(ptmbuf.i < ptmbuf.n);