/* :ts=8 */ /* $Header: yyy:work/sh/RCS/line.c,v 1.15 90/08/28 01:16:08 john Beta $ */ /* * known bugs: * o env var args limited to 20 * o any number of them at end of long line * o recognises scripts, but doesn't know what to do with them */ #include #include #include #include #include #include #include #pragma amicall(ArpBase,0x276,BaseName(a0)) #pragma amicall(ArpBase,0xea,FPrintf(d0,a0,a1)) #pragma amicall(ArpBase,0xfc,GADS(a0,d0,a1,a2,a3)) #pragma amicall(ArpBase,0x11a,Getenv(a0,a1,d0)) #pragma amicall(ArpBase,0x14a,PathName(d0,a0,d1)) #pragma amicall(ArpBase,0xe4,Printf(a0,a1)) #pragma amicall(ArpBase,0x210,Strncmp(a0,a1,d0)) #pragma amicall(ArpBase,0x21c,SyncRun(a0,a1,d0,d1)) struct ArpBase *ArpBase; char *tmpnam (char *_s); #define CSI 0x9b #define KEY_UNKNOWN -1 #define CTRL(c) ('c'&037) #define WERASE CTRL(w) #define KILL CTRL(u) #define ESC '\033' #define TAB CTRL(i) #define BS CTRL(h) #define RET CTRL(j) #define NL CTRL(m) #define QUIT CTRL(q) #define AMIKILL CTRL(x) #define BIGNUMBER 256 #define MAXLINE 255 #define ALIASLOOP 20 #define BUILTIN 9 #define IGNORE "" #define PROMPT "%N> " #define TMPDIR "tmp:" #define STARTUP "s:.linerc" #define MAXHIST 20 #define MAXALIAS 20 #define MAXPP 5 #define DOS_TRUE -1 #define DOS_FALSE 0 #define raw() ttymode(DOS_TRUE) #define cooked() ttymode(DOS_FALSE) typedef unsigned char byte; typedef char bool; char *progname; bool is_dflt=TRUE; char *prompt=PROMPT, *ignorelist=IGNORE, *tmpdir=TMPDIR; char *startup=STARTUP; struct FileInfoBlock *fib; struct MsgPort *rp; struct StandardPacket *packet; #define A_EMPTY(x) (!A[x].name) int a_max=MAXALIAS; struct alias { char *name, *sub; } *A; #define hINC(i) (((i)+1) % h_max) #define hDEC(i) (!(i) ? h_max-1 : (i)-1) int h_num, h_max=MAXHIST, cmd_number; struct history { int num; char line[MAXLINE+1]; } *H; int pp_max=MAXPP, pp_sp=-1; long *pp_stk; int errcode=-1; int fprintf (long _fh, const char *_format, ...) { return (FPrintf (_fh, _format, (char *) &_format + sizeof (char *))); } int printf (const char *_format, ...) { return (Printf (_format, (char *) &_format + sizeof (char *))); } int do_csi () { char ch; Read (Input(), &ch, 1); switch (ch) { case 'A': case 'B': case 'C': case 'D': case 'T': case 'S': break; case '1': Read (Input(), &ch, 1); if (ch == '~') break; /* else falls through */ case '?': case ' ': default: Read (Input(), &ch, 1); } return (KEY_UNKNOWN); } /* * The code for ttymode() was garnered directly from code * by Chuck McManis, CBM (Phil Lindsay, Carolyn Scheppner, * && Andy Finkel), and a tutorial from Michael van Elst. */ void ttymode (mode) long mode; { long fh; struct MsgPort *mp; fh = Input(); mp = ((struct FileHandle *)(fh<<2))->fh_Type; packet->sp_Msg.mn_Node.ln_Name = (char *) &packet->sp_Pkt; packet->sp_Pkt.dp_Link = &packet->sp_Msg; packet->sp_Pkt.dp_Port = rp; packet->sp_Pkt.dp_Type = ACTION_SCREEN_MODE; packet->sp_Pkt.dp_Arg1 = mode; PutMsg (mp, (struct Message *) packet); WaitPort (rp); GetMsg (rp); } void cleanup () { int i; if (pp_stk) for (i = 0; i < pp_max; i++) if (pp_stk[i]) UnLock (pp_stk[i]); CloseLibrary (ArpBase); if (fib) FreeMem (fib, sizeof (struct FileInfoBlock)); if (packet) FreeMem (packet, sizeof (struct StandardPacket)); if (rp) DeletePort (rp); } void _abort () { /* stub */ } void _wb_parse () { /* stub */ } char *toint (p, i) char *p; int *i; { *i = 0; while (isdigit (*p)) *i = *i * 10 + (*p++ - '0'); return (p); } void makeargs (s, n, args) char *s, ***args; int *n; { int i, j; i = *n = 0; while (s[i]) { while (s[i] && isspace(s[i])) i++; if (s[i]) (*n)++; while (s[i] && !isspace(s[i])) { if (s[i] == '\"') { i++; while (s[i] && s[i] != '\"') i++; } i++; } } if ( !(*args = (char **) malloc (*n * sizeof (char *))) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } i = j = 0; while (s[i]) { while (s[i] && isspace(s[i])) i++; if (s[i]) { (*args)[j] = &s[i]; j++; } while (s[i] && !isspace(s[i])) { if (s[i] == '\"') { i++; while (s[i] && s[i] != '\"') i++; } i++; } if (s[i]) s[i++] = '\0'; } } /* * return -1 if error (-2 if it be fatal), 0 if not builtin, * 1 otherwise */ int builtin (name, args, fh) char *name, *args; long fh; { int i, j, k, orig_len; char **argv, *p, t[MAXLINE]; static char rcsid[] = "$Revision: 1.15 $\n" "$Date: 90/08/28 01:16:08 $\n"; /* if adding commands, don't forget to update BUILTIN */ static char *C[] = { "cls", "history", "alias", "unalias", "dirs", "push", "pop", "ver", "exit" }; for (i = 0; i < BUILTIN && strcmp (C[i], name); i++) ; switch (i) { case 0: /* cls */ if (args && *args) goto bi_err; fprintf (fh, "\f"); break; case 1: /* history */ if (args && *args) goto bi_err; for (i = h_num, j = 0; j < h_max; i = hDEC(i), j++) if (H[i].line[0]) fprintf (fh, "%6ld %s\n", H[i].num, H[i].line); break; case 2: /* alias */ if (!args) { for (i = 0; i < a_max; i++) if (!A_EMPTY(i)) fprintf (fh, "%s\t%s\n", A[i].name, A[i].sub); } else { orig_len = strlen (args); makeargs (args, &i, &argv); if (i == 1) { for (j = 0; j < a_max; j++) if (!A_EMPTY(j) && !strcmp (A[j].name, argv[0])) break; if (j != a_max) fprintf (fh, "%s\n", A[j].sub); } else { for (j = 0; j < a_max && !A_EMPTY(j) && strcmp (A[j].name, argv[0]); j++) ; if (j == a_max) { fprintf (fh, "Too many aliases\n"); return (-1); } else if (A_EMPTY(j)) { if ( !(A[j].name = (char *) malloc (strlen (argv[0]) + 1)) ) { printf ("%s: out of memory\n", progname); return (-2); } strcpy (A[j].name, argv[0]); } else free (A[j].sub); p = argv[1]; for (k = 0; k < orig_len; k++) if (!args[k]) args[k] = ' '; if ( !(A[j].sub = (char *) malloc (strlen (p) + 1)) ) { printf ("%s: out of memory\n", progname); return (-2); } strcpy (A[j].sub, p); } free (argv); } break; case 3: /* unalias */ if (!args) break; makeargs (args, &i, &argv); for ( ; i; --i) { for (j = 0; j < a_max; j++) if (!A_EMPTY(j) && !strcmp (A[j].name, argv[i-1])) { free (A[j].name); free (A[j].sub); A[j].name = A[j].sub = NULL; break; } } free (argv); break; case 4: /* dirs */ if (args && *args) goto bi_err; for (i = pp_sp; i >= 0; --i) { PathName (pp_stk[i], t, BIGNUMBER); fprintf (fh, "%s\n", t); } break; case 5: /* push */ if (args && *args) goto bi_err; if (pp_sp < pp_max-1) { if ( !(pp_stk[++pp_sp] = Lock ("", ACCESS_READ)) || !PathName (pp_stk[pp_sp], t, BIGNUMBER) ) { --pp_sp; break; } fprintf (fh, "(%s)\n", t); } else { fprintf (fh, "Directory stack full\n"); return (-1); } break; case 6: /* pop */ if (args && *args) goto bi_err; if (pp_sp >= 0) { CurrentDir ((struct FileLock *) pp_stk[pp_sp]); PathName (pp_stk[pp_sp], t, BIGNUMBER); pp_stk[pp_sp--] = 0L; fprintf (fh, "(%s)\n", t); } else { fprintf (fh, "Directory stack empty\n"); return (-1); } break; case 7: /* ver */ if (args && *args) goto bi_err; fprintf (fh, "%s... by John D Aycock\n%s", progname, rcsid); break; case 8: /* exit */ if (args && *args) goto bi_err; errcode = RETURN_OK; return (-2); case BUILTIN: return (0); } return (1); bi_err: printf ("Syntax error\n"); return (-1); } /* * returns NULL if no alias sub done, else char * to * malloc'ed substitution... amount malloc'ed is MAXLINE+1 */ char *alias (arg) char *arg; { int i; char *ret, *p, *q; for (i = 0; i < a_max; i++) { if (!A_EMPTY(i) && !strcmp (A[i].name, arg)) { if ( !(ret = (char *) malloc (MAXLINE+1)) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } for (p = A[i].sub, q = ret; *p; ) if (*p == '\"') p++; else if (*p == '!' && *(p+1) == '\'') { p += 2; *q++ = '\"'; } else *q++ = *p++; *q = '\0'; return (ret); } } return (NULL); } /* * returns 0 if no history substitution done, * -1 if error, or char * to new (malloc'ed) arg */ char *history (arg) char *arg; { int num, len, s_len, r_len, repl; char *new, *s=NULL, *r; register int i, j; if (!h_max) return (NULL); if (*arg == '!') { if (*++arg == '!') arg++, num = -1; else if (isdigit (*arg)) arg = toint (arg, &num); else if (*arg == '-') { arg = toint (++arg, &num); num = -num; } else if (*arg) { len = strlen (arg); for (i = hINC(h_num); i != h_num; i = hINC(i)) if (!strncmp (H[i].line, arg, len)) break; if (strncmp (H[i].line, arg, len)) goto h_fail; num = H[i].num; arg += len; } else goto h_err; } else if (*arg == '^') { for (r = s = ++arg; *r && *r != '^'; r++) ; if (!*r || !(s_len = r - s) ) goto h_err; for (arg = ++r; *arg && *arg != '^'; arg++) ; r_len = arg - r; if (*arg) arg++; /* skip optional final '^' */ num = -1; } else return (NULL); if (!num) { h_err: printf ("Syntax error\n"); return ((char *) -1); } if (num < 0) { if ((num = -num) > h_max) goto h_fail; for (i = h_num; num; i = hINC(i), --num) ; } else { for (i = 0; i < h_max; i++) if (H[i].num == num) break; if (i == h_max) goto h_fail; } if (!H[i].line[0]) { h_fail: printf ("Invalid history substitution\n"); return ((char *) -1); } if ( !(new = (char *) malloc (MAXLINE+1)) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } strcpy (new, H[i].line); if (s) { for (i = repl = 0; new[i]; i++) { if (!strncmp (&new[i], s, s_len)) { len = strlen (new); for (j = s_len + i; j <= len; j++) new[j-s_len] = new[j]; len -= s_len; for (j = len + r_len; j >= i; --j) if (j < MAXLINE+1) new[j] = new[j-r_len]; new[MAXLINE] = '\0'; strncpy (&new[i], r, r_len); i += r_len; repl++; } } if (!repl) goto h_fail; } strcat (new, arg); return (new); } #define STDIN 0 #define STDOUT 0 #define PIPE 1 #define REDIRECT 2 #define issep(x) ((*(x)=='|'||*(x)==';')&&*((x)+1)=='\0') struct command { byte I, O; char *name, *args, *in_fname, *out_fname; }; void doit (s, tmpdir) char *s, *tmpdir; { int argc, n_cmds, cur_cmd, cmd_st, len, arg_st; int orig_len, h_len, rv, aliascnt=0, a_len, copy_args; long in_fh, out_fh; bool h_sub=FALSE, re_eval, aliasing=FALSE, fatal=FALSE; char **argv=NULL, *p, ch, *hist, *aka, *q; struct command *cmd=NULL; register int i, j, cmd_end; X: re_eval = FALSE; orig_len = strlen (s); makeargs (s, &argc, &argv); for (i = 0, n_cmds = 1; i < argc; i++) if (issep (argv[i])) n_cmds++; if ( !(cmd = (struct command *) calloc (n_cmds, sizeof (struct command))) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } for (cur_cmd = cmd_end = 0; cur_cmd < n_cmds; cur_cmd++, cmd_end++) { for (cmd_st = cmd_end, len = 0; cmd_end < argc && !issep (argv[cmd_end]); ++cmd_end) { if (cmd_st == cmd_end) cmd[cur_cmd].name = argv[cmd_st]; else { if (*argv[cmd_end] == '<') { i = cmd_end; cmd[cur_cmd].in_fname = (*(argv[cmd_end]+1) ? argv[cmd_end]+1 : argv[++cmd_end]); if (cmd_end >= argc || issep (cmd[cur_cmd].in_fname) || cmd[cur_cmd].I) { printf ("Syntax error\n"); goto error; } cmd[cur_cmd].I = REDIRECT; argv[i] = argv[cmd_end] = NULL; } else if (*argv[cmd_end] == '>') { i = cmd_end; cmd[cur_cmd].out_fname = (*(argv[cmd_end]+1) ? argv[cmd_end]+1 : argv[++cmd_end]); if (cmd_end >= argc || issep (cmd[cur_cmd].out_fname) || cmd[cur_cmd].O) { printf ("Syntax error\n"); goto error; } cmd[cur_cmd].O = REDIRECT; argv[i] = argv[cmd_end] = NULL; } else { len += strlen (argv[cmd_end]) + 1; if (cmd_end - cmd_st == 1) arg_st = cmd_end; } } } if (len) { if ( !(cmd[cur_cmd].args = (char *) malloc (len)) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } for (i = arg_st, *(cmd[cur_cmd].args) = '\0'; i < cmd_end; i++) { if (!argv[i]) continue; strcat (cmd[cur_cmd].args, argv[i]); for (j = i+1; j <= cmd_end && !argv[j]; j++) ; if (j < cmd_end) strcat (cmd[cur_cmd].args, " "); } } if (cmd_end < argc && !strcmp (argv[cmd_end], "|")) { if (cmd[cur_cmd].O || cur_cmd+1 >= n_cmds) { printf ("Syntax error\n"); goto error; } cmd[cur_cmd].O = cmd[cur_cmd+1].I = PIPE; } if (!cmd[cur_cmd].name) { printf ("Syntax error\n"); goto error; } } for (i = 0; !aliasing && i < n_cmds; i++) { if ( !(hist = history (cmd[i].name)) ) continue; else if ((int) hist == -1) goto error; h_len = strlen (cmd[i].name); for (j = 0; j < orig_len; j++) if (!s[j]) s[j] = ' '; for (j = (cmd[i].name - s) + h_len; j <= orig_len; j++) s[j-h_len] = s[j]; orig_len -= h_len; h_len = strlen (hist); for (j = orig_len + h_len; j >= cmd[i].name - s; --j) if (j < MAXLINE+1) s[j] = s[j-h_len]; s[MAXLINE] = '\0'; strncpy (&s[j]+1, hist, h_len); free (hist); h_sub = re_eval = TRUE; goto error; /* loops back up && re-evaluates */ } if (!aliasing && h_max) { H[h_num].num = cmd_number; for (i = 0; i < orig_len; i++) H[h_num].line[i] = (!s[i] ? ' ' : s[i]); H[h_num].line[i] = '\0'; if (h_sub) printf ("%s\n", H[h_num].line); h_num = hDEC(h_num); } if (a_max) for (i = 0; i < n_cmds; i++) { if ( !(aka = alias (cmd[i].name)) ) continue; for (j = copy_args = 0; aka[j]; j++) if (aka[j] == '!' && aka[j+1] == '*') copy_args++; for (arg_st = 0; argv[arg_st] != cmd[i].name; arg_st++) ; for ( ; arg_st < argc && !issep (argv[arg_st]); arg_st++) ; if (arg_st == argc) len = orig_len - (cmd[i].name - s + strlen (cmd[i].name) + 1); else len = argv[arg_st] - cmd[i].name - strlen (cmd[i].name) - 2; if (len < 0) len = 0; if (!len) p = &ch; else if ( !(p = (char *) malloc (len + 1)) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } q = cmd[i].name + strlen (cmd[i].name) + 1; for (j = 0; j < len; j++) p[j] = (!q[j] ? ' ' : q[j]); p[j] = '\0'; a_len = strlen (cmd[i].name); if (copy_args) a_len += len + (len ? 1 : 0); for (j = 0; j < orig_len; j++) if (!s[j]) s[j] = ' '; for (j = (cmd[i].name - s) + a_len; j <= orig_len; j++) s[j-a_len] = s[j]; orig_len -= a_len; a_len = strlen (aka) - 2*copy_args + copy_args*len; for (j = orig_len + a_len; j >= cmd[i].name - s; --j) if (j < MAXLINE+1) s[j] = s[j-a_len]; s[MAXLINE] = '\0'; for (j = 0, q = cmd[i].name; aka[j]; j++) if (aka[j] == '!' && aka[j+1] == '*') { strncpy (q, p, len); q += len; j++; } else *q++ = aka[j]; if (len) free (p); free (aka); aliasing = TRUE; if (++aliascnt > ALIASLOOP) { printf ("Alias loop\n"); goto error; } re_eval = TRUE; goto error; } cmd_number++; for (i = 0; i < n_cmds; i++) { switch (cmd[i].I) { case STDIN: in_fh = Input (); break; case PIPE: in_fh = out_fh; if (Seek (in_fh, 0L, OFFSET_BEGINNING) == -1) { printf ("Error in pipe\n"); Close (in_fh); DeleteFile (cmd[i-1].out_fname); free (cmd[i-1].out_fname); goto error; } break; case REDIRECT: if ( !(in_fh = Open (cmd[i].in_fname, MODE_OLDFILE)) ) { printf ("Error on input redirection\n"); goto error; } break; } switch (cmd[i].O) { case STDOUT: out_fh = Output (); break; case PIPE: p = tmpnam (NULL); if ( !(cmd[i].out_fname = (char *) malloc (strlen (tmpdir) + strlen (p) + 1)) ) { printf ("%s: out of memory\n", progname); if (cmd[i].I) Close (in_fh); if (cmd[i].I == PIPE) DeleteFile (cmd[i-1].out_fname); exit (RETURN_FAIL); } strcpy (cmd[i].out_fname, tmpdir); ch = tmpdir[strlen(tmpdir)-1]; if (*tmpdir && ch != ':' && ch != '/') strcat (cmd[i].out_fname, "/"); strcat (cmd[i].out_fname, p); if ( !(out_fh = Open (cmd[i].out_fname, MODE_NEWFILE)) ) { printf ("Error in pipe\n"); if (cmd[i].I) Close (in_fh); if (cmd[i].I == PIPE) { DeleteFile (cmd[i-1].out_fname); free (cmd[i-1].out_fname); } goto error; } break; case REDIRECT: if ( !(out_fh = Open (cmd[i].out_fname, MODE_NEWFILE)) ) { printf ("Error on output redirection\n"); if (cmd[i].I) Close (in_fh); if (cmd[i].I == PIPE) { DeleteFile (cmd[i-1].out_fname); free (cmd[i-1].out_fname); } goto error; } break; } rv = 0; if ( (rv = builtin (cmd[i].name, cmd[i].args, out_fh)) == -2) fatal = TRUE; if (rv < 0) goto do_err; if (!rv && (rv=SyncRun (cmd[i].name, cmd[i].args, in_fh, out_fh))) { switch (rv) { case PR_NOFILE: printf ("Unknown command %s\n", cmd[i].name); break; case PR_NOEXEC: printf ("Execute bit not set for %s\n", cmd[i].name); break; case PR_SCRIPT: printf ("Script bit set for %s\n", cmd[i].name); break; case PR_WANTSMESSAGE: printf ("Program returned error #%ld\n", IoErr()); break; default: if (rv < 0) printf ("Error %ld from SyncRun()\n", rv); } do_err: if (cmd[i].I) Close (in_fh); if (cmd[i].I == PIPE) { DeleteFile (cmd[i-1].out_fname); free (cmd[i-1].out_fname); } if (cmd[i].O) Close (out_fh); if (cmd[i].O == PIPE) { DeleteFile (cmd[i].out_fname); free (cmd[i].out_fname); } if (fatal) exit (errcode); break; } if (cmd[i].I) Close (in_fh); if (cmd[i].I == PIPE) { DeleteFile (cmd[i-1].out_fname); free (cmd[i-1].out_fname); } if (cmd[i].O == REDIRECT) Close (out_fh); } error: free (argv); if (cmd) { for (i = 0; i < n_cmds; i++) if (cmd[i].args) free (cmd[i].args); free (cmd); cmd = NULL; } if (re_eval) goto X; } bool fignore (s, list) char *s, *list; { int s_len, e_len; char *l_ptr; s_len = strlen (s); while (*list) { if (l_ptr = strchr (list, '|')) e_len = l_ptr - list; else { e_len = strlen (list); l_ptr = " "; /* makes it look like end of list */ } if ( !Strncmp (list, &s[s_len-e_len], e_len) ) return (TRUE); list = l_ptr + 1; } return (FALSE); } char *fcomp (s, n, ignorelist) char *s, *ignorelist; int *n; /* RETURN */ { int bn_len; long lock; bool first=TRUE; char *p, *q, basename[FCHARS], pathname[FCHARS]; static char common[FCHARS]; p = BaseName (s); bn_len = strlen (p); *n = 0; strcpy (basename, p); strcpy (pathname, s); if (p == s) *pathname = '\0'; else *(pathname+strlen(s)-bn_len) = '\0'; if ( !(lock = Lock (pathname, ACCESS_READ)) || !Examine (lock, (BPTR) fib) ) { if (lock) UnLock (lock); return (""); } strcpy (common, basename); while (ExNext (lock, (BPTR) fib)) { if (!bn_len || !Strncmp (basename, fib->fib_FileName, bn_len)) { if (fignore (fib->fib_FileName, ignorelist)) continue; if (first) { strcpy (common, fib->fib_FileName); first = FALSE; } else { for (p = common+bn_len, q = fib->fib_FileName+bn_len; *p && *q && tolower(*p) == tolower(*q); p++, q++) ; *p = '\0'; } } } UnLock (lock); *n = bn_len; return (common); } char *int2s (p, i) char *p; int i; { int off=0; char buffer[20]; /* arbitrary */ do { buffer[off++] = i % 10 + '0'; i /= 10; } while (i); while (off > 0) *p++ = buffer[--off]; return (p); } char *makeprompt (format) char *format; { int len; long lock; struct Process *proc; register char *pf, *pb; static char prompt[MAXLINE]; for (pf = format, pb = prompt; *pf; pf++) { if (*pf != '%') *pb++ = *pf; else if (*(pf+1)) { switch (*++pf) { case 'b': if ( !(lock = Lock ("", ACCESS_READ)) || !Examine (lock, (BPTR) fib) ) { if (lock) UnLock (lock); break; } strcpy (pb, fib->fib_FileName); pb += strlen (fib->fib_FileName); UnLock (lock); break; case 'c': pb = int2s (pb, cmd_number); break; case 'e': *pb++ = ESC; break; case 'h': *pb++ = BS; break; case 'i': *pb++ = TAB; break; case 'n': *pb++ = NL; break; case 'p': if ( !(lock = Lock ("", ACCESS_READ)) || !(len = PathName (lock, pb, BIGNUMBER)) ) { if (lock) UnLock (lock); break; } pb += len; UnLock (lock); break; case 'N': proc = (struct Process *) FindTask (NULL); pb = int2s (pb, proc->pr_TaskNum); break; default: *pb++ = *pf; break; } } } *pb = '\0'; return (prompt); } void edit (prompt, ignorelist, tmpdir) char *prompt, *ignorelist, *tmpdir; { int b_i, n; char buf[MAXLINE+1], *rest; unsigned char ch; register int i; raw (); b_i = 0; printf (makeprompt (prompt)); while (1) { if (Read (Input(), (char *) &ch, 1) != 1) ch = QUIT; switch (ch) { case CSI: (void) do_csi (); break; case WERASE: for (i = b_i; i && isspace (buf[i-1]); --i) ; for ( ; i && !isspace (buf[i-1]); --i) ; for ( ; b_i > i; --b_i) printf ("\b \b"); break; case TAB: buf[b_i] = '\0'; for (i = b_i; i && !isspace (buf[i-1]); --i) ; rest = fcomp (&buf[i], &n, ignorelist); if (n) printf ("\033[%ldD", n); b_i -= n; for ( ; b_i < MAXLINE && *rest; rest++) { buf[b_i++] = *rest; Write (Output(), rest, 1); } break; case AMIKILL: case KILL: for (i = 0; i < b_i; i++) printf ("\b \b"); b_i = 0; break; case BS: if (b_i) { printf ("\b \b"); --b_i; } break; case RET: case NL: for (i = 0; i < b_i && isspace(buf[i]); i++) ; printf ("\n"); if (b_i && i != b_i) { cooked (); buf[b_i] = '\0'; doit (buf, tmpdir); b_i = 0; raw (); } printf (makeprompt (prompt)); break; case QUIT: for (i = 0; i < b_i; i++) printf ("\b \b"); printf ("\n"); cooked (); return; default: if (!iscntrl (ch) && b_i < MAXLINE) { buf[b_i++] = ch; Write (Output(), (char *) &ch, 1); } break; } } } void parseargs (start_arg, argc, argv) int start_arg, argc; char **argv; { int i; char *cp; for (i = start_arg; i < argc; i++) { if (*(cp = argv[i]) == '-') { switch (*++cp) { case 'a': if (*(cp+1)) cp++; else if (i < argc-1) cp = argv[++i]; else cp = "0"; toint (cp, &a_max); break; case 'c': if (*(cp+1)) cp++; else if (i < argc-1) cp = argv[++i]; else cp = "0"; toint (cp, &h_max); break; case 'd': if (*(cp+1)) cp++; else if (i < argc-1) cp = argv[++i]; else cp = "0"; toint (cp, &pp_max); break; case 'f': if (*(cp+1)) ignorelist = cp+1; else if (i < argc-1) ignorelist = argv[++i]; else ignorelist = ""; break; case 'p': if (*(cp+1)) prompt = cp+1; else if (i < argc-1) prompt = argv[++i]; else prompt = ""; break; case 'h': printf ("Usage: %s [-a] [-c] " "[-d] [-f] [-p] " "[-s] [-t]\n", progname); printf (" %s -h[elp]\n", progname); exit (RETURN_OK); case 's': if (*(cp+1)) startup = cp+1; else if (i < argc-1) startup = argv[++i]; else startup = NULL; is_dflt = FALSE; break; case 't': if (*(cp+1)) tmpdir = cp+1; else if (i < argc-1) tmpdir = argv[++i]; else tmpdir = ""; break; default: printf ("%s: bad option\n", progname); exit (RETURN_ERROR); } } else { printf ("%s: bad arguments\n", progname); exit (RETURN_ERROR); } } } void main (argc, argv) int argc; char *argv[]; { int i, h_tmp, j, want, actual, lines; long fh; char ch, t[MAXLINE+1], cmd_buf[MAXLINE+1]; int E_argc; long E_argv[20]; char E[MAXLINE+1]; Enable_Abort = FALSE; if ( !(ArpBase = (struct ArpBase *) OpenLibrary ("arp.library", 0L)) ) { Write (Output(), "Can\'t open arp.library\n", 23); exit (RETURN_FAIL); } atexit (cleanup); if ( !(rp = (struct MsgPort *) CreatePort (NULL, 0)) ) { printf ("Can\'t create port\n"); exit (RETURN_FAIL); } if ( !(packet = (struct StandardPacket *) AllocMem (sizeof (struct StandardPacket), MEMF_PUBLIC|MEMF_CLEAR)) || !(fib = (struct FileInfoBlock *) AllocMem (sizeof (struct FileInfoBlock), 0L)) ) { printf ("Can\'t allocate memory\n"); exit (RETURN_FAIL); } progname = BaseName (argv[0]); if (Getenv ("LINEOPTS", E, MAXLINE+1)) { E_argc = GADS (E, strlen(E), NULL, E_argv, ",,,,,,,,,,,,,,,,,,,"); parseargs (0, E_argc, (char **) E_argv); } parseargs (1, argc, argv); if ( h_max && !(H = (struct history *) calloc (h_max, sizeof (struct history))) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } if ( a_max && !(A = (struct alias *) calloc (a_max, sizeof (struct alias))) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } if ( pp_max && !(pp_stk = (long *) calloc (pp_max, sizeof (long))) ) { printf ("%s: out of memory\n", progname); exit (RETURN_FAIL); } if (startup) { if ( !(fh = Open (startup, MODE_OLDFILE)) ) { if (!is_dflt) printf ("Can\'t open %s\n", startup); } else { /* temporarily disable history */ h_tmp = h_max; h_max = 0; j = 0; want = MAXLINE; while ((actual = Read (fh, &t[j], want)) > 0) { actual += j; for (i = lines = 0; i < actual; ) if (t[i++]=='\n') lines++; if (!lines) { printf ("Error reading %s\n", startup); break; } for ( ; lines-- ; ) { for (i = 0; t[i] != '\n'; i++) ; t[i] = '\0'; for (j = 0; t[j] && isspace(t[j]); j++) ; if (t[j] && t[j] != '#') { strcpy (cmd_buf, &t[j]); doit (cmd_buf, tmpdir); } for (j = 0, i++; i < actual; ) t[j++] = t[i++]; actual = j; } want = MAXLINE - j; } h_max = h_tmp; Close (fh); } } cmd_number = 1; edit (prompt, ignorelist, tmpdir); exit (RETURN_OK); }