home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d457
/
line
/
line.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-14
|
27KB
|
1,115 lines
/* :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 <ctype.h>
#include <string.h>
#include <arpbase.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <functions.h>
#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<maxaliases>] [-c<histsize>] "
"[-d<dirstack>] [-f<ignorelist>] [-p<prompt>] "
"[-s<startup>] [-t<tmpdir>]\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);
}