]>
Commit | Line | Data |
---|---|---|
cf7098dd MM |
1 | diff -urN ash-0.4.0/Makefile ash-0.4.0-/Makefile |
2 | --- ash-0.4.0/Makefile Tue Apr 24 00:57:33 2001 | |
3 | +++ ash-0.4.0-/Makefile Tue Apr 24 00:59:53 2001 | |
4 | @@ -7,7 +7,7 @@ | |
5 | SHSRCS= alias.c cd.c echo.c error.c eval.c exec.c expand.c \ | |
6 | histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ | |
7 | mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \ | |
8 | - test.c setmode.c test.c | |
9 | + test.c setmode.c test.c hetio.c | |
10 | GENSRCS=builtins.c builtins.h init.c nodes.c arith.c arith.h lex.yy.c \ | |
11 | nodes.h syntax.c syntax.h token.h signames.c | |
12 | SRCS= ${SHSRCS} ${GENSRCS} | |
13 | @@ -17,12 +17,13 @@ | |
14 | mystring.o options.o output.o parser.o redir.o show.o \ | |
15 | trap.o var.o bltin/test.o signames.o \ | |
16 | builtins.o init.o nodes.o syntax.o arith.o lex.yy.o \ | |
17 | - setmode.o bltin/times.o | |
18 | + setmode.o bltin/times.o hetio.o | |
19 | ||
20 | OPT_FLAGS=-O2 -g | |
21 | LDFLAGS=-g | |
22 | CFLAGS=$(OPT_FLAGS) -DSHELL -I. -DNO_HISTORY -DBSD=1 -DSMALL -D_GNU_SOURCE \ | |
23 | - -DGLOB_BROKEN -D__COPYRIGHT\(x\)= -D__RCSID\(x\)= -D_DIAGASSERT\(x\)= | |
24 | + -DGLOB_BROKEN -D__COPYRIGHT\(x\)= -D__RCSID\(x\)= -D_DIAGASSERT\(x\)= \ | |
25 | + -DHETIO | |
26 | ||
27 | all: $(PROG) | |
28 | ||
29 | diff -urN ash-0.4.0/hetio.c ash-0.4.0-/hetio.c | |
30 | --- ash-0.4.0/hetio.c Thu Jan 1 01:00:00 1970 | |
31 | +++ ash-0.4.0-/hetio.c Tue Apr 24 01:06:59 2001 | |
32 | @@ -0,0 +1,377 @@ | |
33 | +/* | |
34 | + * Termios command line History and Editting for NetBSD sh (ash) | |
35 | + * Copyright (c) 1999 | |
36 | + * Main code: Adam Rogoyski <rogoyski@cs.utexas.edu> | |
37 | + * Etc: Dave Cinege <dcinege@psychosis.com> | |
38 | + * | |
39 | + * You may use this code as you wish, so long as the original author(s) | |
40 | + * are attributed in any redistributions of the source code. | |
41 | + * This code is 'as is' with no warranty. | |
42 | + * This code may safely be consumed by a BSD or GPL license. | |
43 | + * | |
44 | + * v 0.5 19990328 Initial release | |
45 | + * | |
46 | + * Future plans: Simple file and path name completion. (like BASH) | |
47 | + * | |
48 | + */ | |
49 | + | |
50 | +/* | |
51 | +Usage and Known bugs: | |
52 | + Terminal key codes are not extensive, and more will probably | |
53 | + need to be added. This version was created on Debian GNU/Linux 2.x. | |
54 | + Delete, Backspace, Home, End, and the arrow keys were tested | |
55 | + to work in an Xterm and console. Ctrl-A also works as Home. | |
56 | + Ctrl-E also works as End. The binary size increase is <3K. | |
57 | + | |
58 | + Editting will not display correctly for lines greater then the | |
59 | + terminal width. (more then one line.) However, history will. | |
60 | +*/ | |
61 | + | |
62 | +#include <stdio.h> | |
63 | +#include <unistd.h> | |
64 | +#include <stdlib.h> | |
65 | +#include <string.h> | |
66 | +#include <termios.h> | |
67 | +#include <ctype.h> | |
68 | +#include <sys/ioctl.h> | |
69 | + | |
70 | +#include "input.h" | |
71 | +#include "output.h" | |
72 | + | |
73 | +#ifdef HETIO | |
74 | + | |
75 | +#include "hetio.h" | |
76 | + | |
77 | + | |
78 | +#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */ | |
79 | + | |
80 | +#define ESC 27 | |
81 | +#define DEL 127 | |
82 | + | |
83 | +static struct history *his_front = NULL; /* First element in command line list */ | |
84 | +static struct history *his_end = NULL; /* Last element in command line list */ | |
85 | +static struct termios old_term, new_term; /* Current termio and the previous termio before starting ash */ | |
86 | + | |
87 | +static int history_counter = 0; /* Number of commands in history list */ | |
88 | +static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */ | |
89 | +static int hetio_inter = 0; | |
90 | + | |
91 | +struct history | |
92 | +{ | |
93 | + char *s; | |
94 | + struct history *p; | |
95 | + struct history *n; | |
96 | +}; | |
97 | + | |
98 | + | |
99 | +void input_delete (int); | |
100 | +void input_home (int *); | |
101 | +void input_end (int *, int); | |
102 | +void input_backspace (int *, int *); | |
103 | + | |
104 | + | |
105 | + | |
106 | +void hetio_init(void) | |
107 | +{ | |
108 | + hetio_inter = 1; | |
109 | +} | |
110 | + | |
111 | + | |
112 | +void hetio_reset_term(void) | |
113 | +{ | |
114 | + if (reset_term) | |
115 | + tcsetattr(1, TCSANOW, &old_term); | |
116 | +} | |
117 | + | |
118 | + | |
119 | +void setIO(struct termios *new, struct termios *old) /* Set terminal IO to canonical mode, and save old term settings. */ | |
120 | +{ | |
121 | + tcgetattr(0, old); | |
122 | + memcpy(new, old, sizeof(*new)); | |
123 | + new->c_cc[VMIN] = 1; | |
124 | + new->c_cc[VTIME] = 0; | |
125 | + new->c_lflag &= ~ICANON; /* unbuffered input */ | |
126 | + new->c_lflag &= ~ECHO; | |
127 | + tcsetattr(0, TCSANOW, new); | |
128 | +} | |
129 | + | |
130 | +void input_home(int *cursor) /* Command line input routines */ | |
131 | +{ | |
132 | + while (*cursor > 0) { | |
133 | + out1c('\b'); | |
134 | + --*cursor; | |
135 | + } | |
136 | + flushout(&output); | |
137 | +} | |
138 | + | |
139 | + | |
140 | +void input_delete(int cursor) | |
141 | +{ | |
142 | + int j = 0; | |
143 | + | |
144 | + memmove(parsenextc + cursor, parsenextc + cursor + 1, | |
145 | + BUFSIZ - cursor - 1); | |
146 | + for (j = cursor; j < (BUFSIZ - 1); j++) { | |
147 | + if (!*(parsenextc + j)) | |
148 | + break; | |
149 | + else | |
150 | + out1c(*(parsenextc + j)); | |
151 | + } | |
152 | + | |
153 | + out1str(" \b"); | |
154 | + | |
155 | + while (j-- > cursor) | |
156 | + out1c('\b'); | |
157 | + flushout(&output); | |
158 | +} | |
159 | + | |
160 | + | |
161 | +void input_end(int *cursor, int len) | |
162 | +{ | |
163 | + while (*cursor < len) { | |
164 | + out1str("\033[C"); | |
165 | + ++*cursor; | |
166 | + } | |
167 | + flushout(&output); | |
168 | +} | |
169 | + | |
170 | + | |
171 | +void | |
172 | +input_backspace(int *cursor, int *len) | |
173 | +{ | |
174 | + int j = 0; | |
175 | + | |
176 | + if (*cursor > 0) { | |
177 | + out1str("\b \b"); | |
178 | + --*cursor; | |
179 | + memmove(parsenextc + *cursor, parsenextc + *cursor + 1, | |
180 | + BUFSIZ - *cursor + 1); | |
181 | + | |
182 | + for (j = *cursor; j < (BUFSIZ - 1); j++) { | |
183 | + if (!*(parsenextc + j)) | |
184 | + break; | |
185 | + else | |
186 | + out1c(*(parsenextc + j)); | |
187 | + } | |
188 | + | |
189 | + out1str(" \b"); | |
190 | + | |
191 | + while (j-- > *cursor) | |
192 | + out1c('\b'); | |
193 | + | |
194 | + --*len; | |
195 | + flushout(&output); | |
196 | + } | |
197 | +} | |
198 | + | |
199 | +int hetio_read_input(int fd) | |
200 | +{ | |
201 | + int nr = 0; | |
202 | + | |
203 | + if (!hetio_inter) { /* Are we an interactive shell? */ | |
204 | + return -255; | |
205 | + } else { | |
206 | + int len = 0; | |
207 | + int j = 0; | |
208 | + int cursor = 0; | |
209 | + int break_out = 0; | |
210 | + int ret = 0; | |
211 | + char c = 0; | |
212 | + struct history *hp = his_end; | |
213 | + | |
214 | + if (!reset_term) { | |
215 | + setIO(&new_term, &old_term); | |
216 | + reset_term = 1; | |
217 | + } else { | |
218 | + tcsetattr(0, TCSANOW, &new_term); | |
219 | + } | |
220 | + | |
221 | + memset(parsenextc, 0, BUFSIZ); | |
222 | + | |
223 | + while (1) { | |
224 | + if ((ret = read(fd, &c, 1)) < 1) | |
225 | + return ret; | |
226 | + | |
227 | + switch (c) { | |
228 | + case 1: /* Control-A Beginning of line */ | |
229 | + input_home(&cursor); | |
230 | + break; | |
231 | + case 5: /* Control-E EOL */ | |
232 | + input_end(&cursor, len); | |
233 | + break; | |
234 | + case 4: /* Control-D */ | |
235 | +#ifndef CTRL_D_DELETE | |
236 | + return 0; | |
237 | +#else | |
238 | + if (cursor != len) { | |
239 | + input_delete(cursor); | |
240 | + len--; | |
241 | + } | |
242 | + break; | |
243 | +#endif | |
244 | + case '\b': /* Backspace */ | |
245 | + case DEL: | |
246 | + input_backspace(&cursor, &len); | |
247 | + break; | |
248 | + case '\n': /* Enter */ | |
249 | + *(parsenextc + len++ + 1) = c; | |
250 | + out1c(c); | |
251 | + flushout(&output); | |
252 | + break_out = 1; | |
253 | + break; | |
254 | + case ESC: /* escape sequence follows */ | |
255 | + if ((ret = read(fd, &c, 1)) < 1) | |
256 | + return ret; | |
257 | + | |
258 | + if (c == '[' || c == 'O' ) { /* 91 */ | |
259 | + if ((ret = read(fd, &c, 1)) < 1) | |
260 | + return ret; | |
261 | + | |
262 | + switch (c) { | |
263 | + case 'A': | |
264 | + if (hp && hp->p) { /* Up */ | |
265 | + hp = hp->p; | |
266 | + goto hop; | |
267 | + } | |
268 | + break; | |
269 | + case 'B': | |
270 | + if (hp && hp->n && hp->n->s) { /* Down */ | |
271 | + hp = hp->n; | |
272 | + goto hop; | |
273 | + } | |
274 | + break; | |
275 | + | |
276 | +hop: /* hop */ | |
277 | + len = strlen(parsenextc); | |
278 | + | |
279 | + for (; cursor > 0; cursor--) /* return to begining of line */ | |
280 | + out1c('\b'); | |
281 | + | |
282 | + for (j = 0; j < len; j++) /* erase old command */ | |
283 | + out1c(' '); | |
284 | + | |
285 | + for (j = len; j > 0; j--) /* return to begining of line */ | |
286 | + out1c('\b'); | |
287 | + | |
288 | + strcpy (parsenextc, hp->s); /* write new command */ | |
289 | + len = strlen (hp->s); | |
290 | + out1str(parsenextc); | |
291 | + flushout(&output); | |
292 | + cursor = len; | |
293 | + break; | |
294 | + case 'C': /* Right */ | |
295 | + if (cursor < len) { | |
296 | + out1str("\033[C"); | |
297 | + cursor++; | |
298 | + flushout(&output); | |
299 | + } | |
300 | + break; | |
301 | + case 'D': /* Left */ | |
302 | + if (cursor > 0) { | |
303 | + out1str("\033[D"); | |
304 | + cursor--; | |
305 | + flushout(&output); | |
306 | + } | |
307 | + break; | |
308 | + case '3': /* Delete */ | |
309 | + if (cursor != len) { | |
310 | + input_delete(cursor); | |
311 | + len--; | |
312 | + } | |
313 | + break; | |
314 | + case 'H': /* Home (xterm) */ | |
315 | + case '1': /* Home (Ctrl-A) */ | |
316 | + input_home(&cursor); | |
317 | + break; | |
318 | + case 'F': /* End (xterm_ */ | |
319 | + case '4': /* End (Ctrl-E) */ | |
320 | + input_end(&cursor, len); | |
321 | + break; | |
322 | + } | |
323 | + if (c == '1' || c == '3' || c == '4') | |
324 | + if ((ret = read(fd, &c, 1)) < 1) | |
325 | + return ret; /* read 126 (~) */ | |
326 | + } | |
327 | + | |
328 | + c = 0; | |
329 | + break; | |
330 | + | |
331 | + default: /* If it's regular input, do the normal thing */ | |
332 | + | |
333 | + if (!isprint(c)) /* Skip non-printable characters */ | |
334 | + break; | |
335 | + | |
336 | + if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ | |
337 | + break; | |
338 | + | |
339 | + len++; | |
340 | + | |
341 | + if (cursor == (len - 1)) { /* Append if at the end of the line */ | |
342 | + *(parsenextc + cursor) = c; | |
343 | + } else { /* Insert otherwise */ | |
344 | + memmove(parsenextc + cursor + 1, parsenextc + cursor, | |
345 | + len - cursor - 1); | |
346 | + | |
347 | + *(parsenextc + cursor) = c; | |
348 | + | |
349 | + for (j = cursor; j < len; j++) | |
350 | + out1c(*(parsenextc + j)); | |
351 | + for (; j > cursor; j--) | |
352 | + out1str("\033[D"); | |
353 | + } | |
354 | + | |
355 | + cursor++; | |
356 | + out1c(c); | |
357 | + flushout(&output); | |
358 | + break; | |
359 | + } | |
360 | + | |
361 | + if (break_out) /* Enter is the command terminator, no more input. */ | |
362 | + break; | |
363 | + } | |
364 | + | |
365 | + nr = len + 1; | |
366 | + tcsetattr(0, TCSANOW, &old_term); | |
367 | + | |
368 | + | |
369 | + if (*(parsenextc)) { /* Handle command history log */ | |
370 | + struct history *h = his_end; | |
371 | + | |
372 | + if (!h) { /* No previous history */ | |
373 | + h = his_front = malloc(sizeof (struct history)); | |
374 | + h->n = malloc(sizeof (struct history)); | |
375 | + h->p = NULL; | |
376 | + h->s = strdup(parsenextc); | |
377 | + | |
378 | + h->n->p = h; | |
379 | + h->n->n = NULL; | |
380 | + h->n->s = NULL; | |
381 | + his_end = h->n; | |
382 | + history_counter++; | |
383 | + } else { /* Add a new history command */ | |
384 | + | |
385 | + h->n = malloc(sizeof (struct history)); | |
386 | + | |
387 | + h->n->p = h; | |
388 | + h->n->n = NULL; | |
389 | + h->n->s = NULL; | |
390 | + h->s = strdup(parsenextc); | |
391 | + his_end = h->n; | |
392 | + | |
393 | + if (history_counter >= MAX_HISTORY) { /* After max history, remove the last known command */ | |
394 | + struct history *p = his_front->n; | |
395 | + | |
396 | + p->p = NULL; | |
397 | + free(his_front->s); | |
398 | + free(his_front); | |
399 | + his_front = p; | |
400 | + } else { | |
401 | + history_counter++; | |
402 | + } | |
403 | + } | |
404 | + } | |
405 | + } | |
406 | + | |
407 | + return nr; | |
408 | +} | |
409 | +#endif | |
410 | diff -urN ash-0.4.0/hetio.h ash-0.4.0-/hetio.h | |
411 | --- ash-0.4.0/hetio.h Thu Jan 1 01:00:00 1970 | |
412 | +++ ash-0.4.0-/hetio.h Tue Apr 24 00:13:57 2001 | |
413 | @@ -0,0 +1,22 @@ | |
414 | +/* | |
415 | + * Termios command line History and Editting for NetBSD sh (ash) | |
416 | + * Copyright (c) 1999 | |
417 | + * Main code: Adam Rogoyski <rogoyski@cs.utexas.edu> | |
418 | + * Etc: Dave Cinege <dcinege@psychosis.com> | |
419 | + * | |
420 | + * You may use this code as you wish, so long as the original author(s) | |
421 | + * are attributed in any redistributions of the source code. | |
422 | + * This code is 'as is' with no warranty. | |
423 | + * This code may safely be consumed by a BSD or GPL license. | |
424 | + * | |
425 | + * v 0.5 19990328 Initial release | |
426 | + * | |
427 | + * Future plans: Simple file and path name completion. (like BASH) | |
428 | + * | |
429 | + */ | |
430 | + | |
431 | +void hetio_init(void); | |
432 | +int hetio_read_input(int fd); | |
433 | +void hetio_reset_term(void); | |
434 | + | |
435 | +extern int hetio_inter; | |
436 | diff -urN ash-0.4.0/histedit.c ash-0.4.0-/histedit.c | |
437 | --- ash-0.4.0/histedit.c Fri Jan 12 17:50:35 2001 | |
438 | +++ ash-0.4.0-/histedit.c Tue Apr 24 00:13:57 2001 | |
439 | @@ -60,9 +60,9 @@ | |
440 | #include "main.h" | |
441 | #include "output.h" | |
442 | #include "mystring.h" | |
443 | -#include "myhistedit.h" | |
444 | #include "error.h" | |
445 | #ifndef SMALL | |
446 | +#include "myhistedit.h" | |
447 | #include "eval.h" | |
448 | #include "memalloc.h" | |
449 | ||
450 | @@ -219,7 +219,11 @@ | |
451 | if (argc == 1) | |
452 | error("missing history argument"); | |
453 | ||
454 | +#ifdef __GLIBC__ | |
455 | + optind = 1; | |
456 | +#else | |
457 | optreset = 1; optind = 1; /* initialize getopt */ | |
458 | +#endif | |
459 | while (not_fcnumber(argv[optind]) && | |
460 | (ch = getopt(argc, argv, ":e:lnrs")) != -1) | |
461 | switch ((char)ch) { | |
462 | diff -urN ash-0.4.0/input.c ash-0.4.0-/input.c | |
463 | --- ash-0.4.0/input.c Tue May 23 12:03:19 2000 | |
464 | +++ ash-0.4.0-/input.c Tue Apr 24 00:13:57 2001 | |
465 | @@ -66,7 +66,13 @@ | |
466 | #include "error.h" | |
467 | #include "alias.h" | |
468 | #include "parser.h" | |
469 | +#ifndef SMALL | |
470 | #include "myhistedit.h" | |
471 | +#endif | |
472 | + | |
473 | +#ifdef HETIO | |
474 | +#include "hetio.h" | |
475 | +#endif | |
476 | ||
477 | #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ | |
478 | ||
479 | @@ -108,7 +114,9 @@ | |
480 | int init_editline = 0; /* editline library initialized? */ | |
481 | int whichprompt; /* 1 == PS1, 2 == PS2 */ | |
482 | ||
483 | +#ifndef SMALL | |
484 | EditLine *el; /* cookie for editline package */ | |
485 | +#endif | |
486 | ||
487 | STATIC void pushfile __P((void)); | |
488 | static int preadfd __P((void)); | |
489 | @@ -197,6 +205,11 @@ | |
490 | (void) strcpy(buf, rl_cp); | |
491 | } | |
492 | } else | |
493 | +#endif | |
494 | + | |
495 | +#ifdef HETIO | |
496 | + nr = hetio_read_input(parsefile->fd); | |
497 | + if (nr == -255) | |
498 | #endif | |
499 | nr = read(parsefile->fd, buf, BUFSIZ - 1); | |
500 | ||
501 | diff -urN ash-0.4.0/main.c ash-0.4.0-/main.c | |
502 | --- ash-0.4.0/main.c Tue Apr 24 00:57:33 2001 | |
503 | +++ ash-0.4.0-/main.c Tue Apr 24 00:13:57 2001 | |
504 | @@ -79,6 +79,10 @@ | |
505 | #include "exec.h" | |
506 | #include "cd.h" | |
507 | ||
508 | +#ifdef HETIO | |
509 | +#include "hetio.h" | |
510 | +#endif | |
511 | + | |
512 | #define PROFILE 0 | |
513 | ||
514 | int rootpid; | |
515 | @@ -242,6 +246,10 @@ | |
516 | ||
517 | TRACE(("cmdloop(%d) called\n", top)); | |
518 | setstackmark(&smark); | |
519 | +#ifdef HETIO | |
520 | + if(iflag && top) | |
521 | + hetio_init(); | |
522 | +#endif | |
523 | for (;;) { | |
524 | if (pendingsigs) | |
525 | dotrap(); | |
526 | Binary files ash-0.4.0/mksignames and ash-0.4.0-/mksignames differ | |
527 | diff -urN ash-0.4.0/trap.c ash-0.4.0-/trap.c | |
528 | --- ash-0.4.0/trap.c Tue Apr 24 00:57:33 2001 | |
529 | +++ ash-0.4.0-/trap.c Tue Apr 24 00:13:57 2001 | |
530 | @@ -62,7 +62,11 @@ | |
531 | #include "error.h" | |
532 | #include "trap.h" | |
533 | #include "mystring.h" | |
534 | +#include "mail.h" | |
535 | ||
536 | +#ifdef HETIO | |
537 | +#include "hetio.h" | |
538 | +#endif | |
539 | ||
540 | /* | |
541 | * Sigmode records the current value of the signal handlers for the various | |
542 | @@ -341,6 +345,7 @@ | |
543 | setsignal(SIGINT); | |
544 | setsignal(SIGQUIT); | |
545 | setsignal(SIGTERM); | |
546 | + chkmail(1); | |
547 | is_interactive = on; | |
548 | } | |
549 | ||
550 | @@ -358,6 +363,9 @@ | |
551 | char *p; | |
552 | ||
553 | TRACE(("exitshell(%d) pid=%d\n", status, getpid())); | |
554 | +#ifdef HETIO | |
555 | + hetio_reset_term(); | |
556 | +#endif | |
557 | if (setjmp(loc1.loc)) { | |
558 | goto l1; | |
559 | } |