dillon@CORY.BERKELEY.EDU (Matt Dillon) (01/03/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # main.c # run.c # set.c # sort.c # sub.c # c.asm # fexec2.asm # shell.h # This archive created: Sat Jan 3 01:02:29 1987 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'main.c'" '(2695 characters)' if test -f 'main.c' then echo shar: "will not over-write existing file 'main.c'" else cat << \!Funky!Stuff! > 'main.c' /* * MAIN.C * * (c)1986 Matthew Dillon 9 October 1986 * * Contains initialization and other stuff. Note that there is no * support for workbench startup. This isn't simply a matter of * setting up a window.... to get this baby to work from workbench we * would need to simulate an entire CLI (proc->pr_CLI must be valid). * */ #include "shell.h" #include <libraries/dosextens.h> extern long SetSignal(); char Inline[256]; main(argc, argv) short argc; register char *argv[]; { char *prompt; struct Process *proc; register short i; check32(); proc = (struct Process *)FindTask(0); if (proc->pr_CLI == NULL) /* sorry, no WB startup */ exit(1000); init_vars(); init(); seterr(); do_cd(NULL, -1); for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "-c") == 0) { Inline[0] = '\0'; for (++i; i < argc; ++i) { if (*argv[i] == '\"') { /* CLI quotes? */ strcat(Inline, argv[i]+1); /* remove quotes */ Inline[strlen(Inline)-1] = '\0'; } else { strcat(Inline, argv[i]); } if (i + 1 < argc) strcat(Inline, " "); } exec_command(Inline); main_exit(0); } strcpy (Inline, "source "); strcat (Inline, argv[i]); av[1] = argv[i]; do_source (Inline, 0); } for (;;) { if ((prompt = get_var (LEVEL_SET, V_PROMPT)) == NULL) prompt = "echo -n \"% \""; if (CHECKBREAK()) { while (WaitForChar(Input(), 1)) gets(Inline); } ++H_stack; ++Exec_ignoreresult; exec_command (prompt); --Exec_ignoreresult; --H_stack; if (Quit || !gets(Inline)) main_exit(0); breakreset(); if (*Inline == '^') hat_replace(Inline); if (*Inline) exec_command(Inline); } } init_vars() { if (IsInteractive(Input())) set_var (LEVEL_SET, V_PROMPT, "echo -n \"% \""); else set_var (LEVEL_SET, V_PROMPT, ""); set_var (LEVEL_SET, V_HIST, "20"); set_var (LEVEL_SET, V_PATH, "ram:,ram:c/,c:,df1:c/,df0:c/"); } init() { static char pipe1[32], pipe2[32]; Cin = Input(); Cout= Cerr = Output(); Uniq= (long)pipe1; /* address of some global variable */ Pipe1 = pipe1; Pipe2 = pipe2; sprintf (pipe1, "ram:pipe1_%ld", Uniq); sprintf (pipe2, "ram:pipe2_%ld", Uniq); } main_exit(n) { free_memory(); exit (n); } breakcheck() { if (SetSignal(0,0) & SIGBREAKF_CTRL_C) return (1); else return (0); } breakreset() { SetSignal(0, SIGBREAKF_CTRL_C); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'run.c'" '(810 characters)' if test -f 'run.c' then echo shar: "will not over-write existing file 'run.c'" else cat << \!Funky!Stuff! > 'run.c' /* * RUN.C * * (c)1986 Matthew Dillon 9 October 1986 * * RUN handles running of external commands. * */ #include "shell.h" #include "libraries/dos.h" extern long *SysRegs; do_run(str) char *str; { int i; if (fexecv(av[0], av, Cin_name, Cout_name, Cout_append) >= 0) { i = wait(); } else { register long lock; char buf[128]; register char *copy; lock = Lock(FindIt(av[0], ".sh", buf), ACCESS_READ); if (lock == NULL) { Eputs("Command Not Found"); return (-1); } UnLock(lock); av[1] = buf; /* particular to do_source() */ copy = malloc(strlen(str)+3); strcpy(copy+2,str); copy[0] = 'x'; copy[1] = ' '; i = do_source(copy); free(copy); } return (i); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'set.c'" '(3741 characters)' if test -f 'set.c' then echo shar: "will not over-write existing file 'set.c'" else cat << \!Funky!Stuff! > 'set.c' /* * SET.C * * (c)1986 Matthew Dillon 9 October 1986 * * Handles the variable lists for normal variables, aliases, and labels. * * */ #include "shell.h" #define MAXLEVELS (3 + MAXSRC) struct MASTER { struct MASTER *next; struct MASTER *last; char *name; char *text; }; static struct MASTER *Mbase[MAXLEVELS]; char * set_var(level, name, str) short level; register char *name, *str; { register struct MASTER *base = Mbase[level]; register struct MASTER *last; register short len; for (len = 0; isalphanum(name[len]); ++len); while (base != NULL) { if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) { Free (base->text); goto gotit; } last = base; base = base->next; } if (base == Mbase[level]) { base = Mbase[level] = (struct MASTER *)malloc (sizeof(struct MASTER)); base->last = NULL; } else { base = (struct MASTER *)malloc (sizeof(struct MASTER)); base->last = last; last->next = base; } base->name = malloc (len + 1); bmov (name, base->name, len); base->name[len] = 0; base->next = NULL; gotit: base->text = malloc (strlen(str) + 1); strcpy (base->text, str); return (base->text); } char * get_var (level, name) short level; register char *name; { register struct MASTER *base = Mbase[level]; register unsigned char *scr; register short len; for (scr = name; *scr && *scr != 0x80 && *scr != ' ' && *scr != ';' && *scr != '|'; ++scr); len = scr - name; while (base != NULL) { if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) return (base->text); base = base->next; } return (NULL); } unset_level(level) short level; { register struct MASTER *base = Mbase[level]; while (base) { Free (base->name); Free (base->text); Free (base); base = base->next; } Mbase[level] = NULL; } unset_var(level, name) short level; char *name; { register struct MASTER *base = Mbase[level]; register struct MASTER *last = NULL; register short len; for (len = 0; isalphanum(name[len]); ++len); while (base) { if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) { if (base != Mbase[level]) last->next = base->next; else Mbase[level] = base->next; if (base->next != NULL) base->next->last = last; if (base == Mbase[level]) Mbase[level] = base->next; Free (base->name); Free (base->text); Free (base); return (1); } last = base; base = base->next; } return (-1); } do_unset_var(garbage, level) short level; char *garbage; { register short i; for (i = 1; i < ac; ++i) unset_var (level, av[i]); return (0); } do_set_var(command, level) short level; char *command; { register struct MASTER *base = Mbase[level]; register char *str; if (ac == 1) { while (base) { fprintf (Cout, "%-10s ", base->name); Oputs (base->text); base = base->next; } return (0); } if (ac == 2) { str = get_var (level, av[1]); if (str) { fprintf (Cout, "%-10s ", av[1]); Oputs(str); } else { set_var (level, av[1], ""); } } if (ac > 2) set_var (level, av[1], next_word (next_word (command))); if (*av[1] == '_') { S_histlen = (str = get_var(LEVEL_SET, V_HIST)) ? atoi(str) : 0; Debug = (str = get_var(LEVEL_SET, V_DEBUG)) ? atoi(str) : 0; Verbose = (get_var(LEVEL_SET, V_VERBOSE)) ? 1 : 0; if (S_histlen < 2) S_histlen = 2; } return (0); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'sort.c'" '(728 characters)' if test -f 'sort.c' then echo shar: "will not over-write existing file 'sort.c'" else cat << \!Funky!Stuff! > 'sort.c' /* * SORT.C * * a QuickSort is used for speed, simplicity, and small code size. * */ extern short QSplit(); QuickSort(av, n) char *av[]; short n; { short b; if (n > 0) { b = QSplit(av, n); QuickSort(av, b); QuickSort(av+b+1, n - b - 1); } } /* * QSplit called as a second routine so I don't waste stack on QuickSort's * recursivness. */ short QSplit(av, n) register char *av[]; short n; { register short i, b; register char *element, *scr; element = av[0]; for (b = 0, i = 1; i < n; ++i) { if (strcmp(av[i], element) < 0) { ++b; scr = av[i]; av[i] = av[b]; av[b] = scr; } } scr = av[0]; av[0] = av[b]; av[b] = scr; return (b); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'sub.c'" '(11170 characters)' if test -f 'sub.c' then echo shar: "will not over-write existing file 'sub.c'" else cat << \!Funky!Stuff! > 'sub.c' /* * SUB.C * * (c)1986 Matthew Dillon 9 October 1986 * * Subroutines used throughout the shell (not very descriptive, am I?) * * */ #include <exec/types.h> #include <exec/exec.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include "shell.h" #define HM_STR 0 /* various HISTORY retrieval modes */ #define HM_REL 1 #define HM_ABS 2 extern struct FileLock *Lock(), *DupLock(), *CurrentDir(); extern struct FileLock *Clock; seterr() { char buf[32]; int stat; sprintf(buf, "%ld", Lastresult); set_var(LEVEL_SET, V_LASTERR, buf); stat = atoi(get_var(LEVEL_SET, V_STAT)); if (stat < Lastresult) stat = Lastresult; sprintf(buf, "%ld", stat); set_var(LEVEL_SET, V_STAT, buf); } char * next_word(str) register char *str; { while (*str && *str != ' ' && *str != 9) ++str; while (*str && (*str == ' ' || *str == 9)) ++str; return (str); } char * compile_av(av, start, end) short start, end; char **av; { char *cstr; short i, len; len = 0; for (i = start; i < end; ++i) len += strlen(av[i]) + 1; cstr = malloc(len + 1); *cstr = '\0'; for (i = start; i < end; ++i) { strcat (cstr, av[i]); strcat (cstr, " "); } return (cstr); } /* * FREE(ptr) --frees without actually freeing, so the data is still good * immediately after the free. */ Free(ptr) char *ptr; { static char *old_ptr; if (old_ptr) free (old_ptr); old_ptr = ptr; } /* * Add new string to history (H_head, H_tail, H_len, * S_histlen */ add_history(str) char *str; { register struct HIST *hist; while (H_len > S_histlen) del_history(); hist = (struct HIST *)malloc (sizeof(struct HIST)); if (H_head == NULL) { H_head = H_tail = hist; hist->next = NULL; } else { hist->next = H_head; H_head->prev = hist; H_head = hist; } hist->prev = NULL; hist->line = malloc (strlen(str) + 1); strcpy (hist->line, str); ++H_len; } del_history() { if (H_tail) { --H_len; ++H_tail_base; free (H_tail->line); if (H_tail->prev) { H_tail = H_tail->prev; free (H_tail->next); H_tail->next = NULL; } else { free (H_tail); H_tail = H_head = NULL; } } } char * last_history_entry() { if (H_head) return(H_head->line); return(""); } char * get_history(ptr) char *ptr; { register struct HIST *hist; register short len; short mode = HM_REL; long num = 1; char *str; char *result = NULL; if (ptr[1] >= '0' && ptr[1] <= '9') { mode = HM_ABS; num = atoi(&ptr[1]); goto skip; } switch (ptr[1]) { case '!': break; case '-': num += atoi(&ptr[2]); break; default: mode = HM_STR; str = ptr + 1; break; } skip: switch (mode) { case HM_STR: len = strlen(str); for (hist = H_head; hist; hist = hist->next) { if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') { result = hist->line; break; } } break; case HM_REL: for (hist = H_head; hist && num--; hist = hist->next); if (hist) result = hist->line; break; case HM_ABS: len = H_tail_base; for (hist = H_tail; hist && len != num; hist = hist->prev, ++len); if (hist) result = hist->line; break; } if (result) { Eputs (result); return(result); } Eputs ("History substitution failed"); return (""); } replace_head(str) char *str; { if (str == NULL) str = ""; if (H_head) { free (H_head->line); H_head->line = malloc (strlen(str)+1); strcpy (H_head->line, str); } } perror(str) char *str; { ierror(str, IoErr()); } ierror(str, err) register char *str; short err; { register struct PERROR *per = Perror; if (err) { for (; per->errstr; ++per) { if (per->errnum == err) { fprintf (Cerr, "%s%s%s\n", per->errstr, (str) ? ": " : "", (str) ? str : ""); return (err); } } fprintf (Cerr, "Unknown DOS error %ld %s\n", err, (str) ? str : ""); } return (err); } /* * Disk directory routines * * dptr = dopen(name, stat) * struct DPTR *dptr; * char *name; * int *stat; * * dnext(dptr, name, stat) * struct DPTR *dptr; * char **name; * int *stat; * * dclose(dptr) -may be called with NULL without harm * * dopen() returns a struct DPTR, or NULL if the given file does not * exist. stat will be set to 1 if the file is a directory. If the * name is "", then the current directory is openned. * * dnext() returns 1 until there are no more entries. The **name and * *stat are set. *stat = 1 if the file is a directory. * * dclose() closes a directory channel. * */ struct DPTR * dopen(name, stat) char *name; register int *stat; { register struct DPTR *dp; *stat = 0; dp = (struct DPTR *)malloc(sizeof(struct DPTR)); if (*name == '\0') dp->lock = DupLock (Clock); else dp->lock = Lock (name, ACCESS_READ); if (dp->lock == NULL) { free (dp); return (NULL); } dp->fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC); if (!Examine (dp->lock, dp->fib)) { perror (name); dclose (dp); return (NULL); } if (dp->fib->fib_DirEntryType >= 0) *stat = 1; return (dp); } dnext(dp, pname, stat) register struct DPTR *dp; char **pname; int *stat; { if (dp == NULL) return (0); if (ExNext (dp->lock, dp->fib)) { *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1; *pname = dp->fib->fib_FileName; return (1); } return (0); } dclose(dp) register struct DPTR *dp; { if (dp == NULL) return (1); if (dp->fib) FreeMem (dp->fib, sizeof(*dp->fib)); if (dp->lock) UnLock (dp->lock); free (dp); return (1); } isdir(file) char *file; { register struct DPTR *dp; int stat; stat = 0; if (dp = dopen (file, &stat)) dclose(dp); return (stat == 1); } free_expand(av) register char **av; { register char **base = av; if (av) { while (*av) { free (*av); ++av; } free (base); } } /* * EXPAND(wild_name, pac) * wild_name - char * (example: "df0:*.c") * pac - int * will be set to # of arguments. * * Standalone, except in requires Clock to point to the Current-Directory * lock. */ char ** expand(base, pac) char *base; int *pac; { register char *ptr; char **eav = (char **)malloc (sizeof(char *)); short eleft, eac; char *name; char *bname, *ename, *tail; int stat, scr; register struct DPTR *dp; *pac = eleft = eac = 0; base = strcpy(malloc(strlen(base)+1), base); for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr); for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr); if (ptr < base) { bname = strcpy (malloc(1), ""); } else { scr = ptr[1]; ptr[1] = '\0'; bname = strcpy (malloc(strlen(base)+1), base); ptr[1] = scr; } ename = ptr + 1; for (ptr = ename; *ptr && *ptr != '/'; ++ptr); scr = *ptr; *ptr = '\0'; tail = (scr) ? ptr + 1 : NULL; if ((dp = dopen (bname, &stat)) == NULL || stat == 0) { free (bname); free (base); free (eav); Eputs ("Could not open directory"); return (NULL); } while (dnext (dp, &name, &stat)) { if (compare_ok(ename, name)) { if (tail) { int alt_ac; char *search, **alt_av, **scrav; struct FileLock *lock; if (!stat) /* expect more dirs, but this not a dir */ continue; lock = CurrentDir (Clock = dp->lock); search = malloc(strlen(name)+strlen(tail)+2); strcpy (search, name); strcat (search, "/"); strcat (search, tail); scrav = alt_av = expand (search, &alt_ac); CurrentDir (Clock = lock); if (scrav) { while (*scrav) { if (eleft < 2) { char **scrav = (char **)malloc(sizeof(char *) * (eac + 10)); bmov (eav, scrav, (eac + 1) << 2); free (eav); eav = scrav; eleft = 10; } eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1); strcpy(eav[eac], bname); strcat(eav[eac], *scrav); free (*scrav); ++scrav; --eleft, ++eac; } free (alt_av); } } else { if (eleft < 2) { char **scrav = (char **)malloc(sizeof(char *) * (eac + 10)); bmov (eav, scrav, (eac + 1) << 2); free (eav); eav = scrav; eleft = 10; } eav[eac] = malloc (strlen(bname)+strlen(name)+1); eav[eac] = strcpy(eav[eac], bname); strcat(eav[eac], name); --eleft, ++eac; } } } dclose (dp); *pac = eac; eav[eac] = NULL; free (bname); free (base); if (eac) return (eav); free (eav); return (NULL); } /* * Compare a wild card name with a normal name */ #define MAXB 8 compare_ok(wild, name) char *wild, *name; { register char *w = wild; register char *n = name; char *back[MAXB][2]; register char s1, s2; register short bi = 0; while (*n || *w) { switch (*w) { case '*': if (bi == MAXB) { Eputs ("Too many levels of '*'"); return (0); } back[bi][0] = w; back[bi][1] = n; ++bi; ++w; continue; goback: --bi; while (bi >= 0 && *back[bi][1] == '\0') --bi; if (bi < 0) return (0); w = back[bi][0] + 1; n = ++back[bi][1]; ++bi; continue; case '?': if (!*n) { if (bi) goto goback; return (0); } break; default: s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n; s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w; if (s1 != s2) { if (bi) goto goback; return (0); } break; } if (*n) ++n; if (*w) ++w; } return (1); } Oputs(str) char *str; { Write (Cout, str, strlen(str)); Write (Cout, "\n", 1); } Eputs(str) char *str; { Write (Cerr, str, strlen(str)); Write (Cerr, "\n", 1); } char * Ogets(str) char *str; { register int i = 0; while (Read(Cin, str + i, 1) == 1) { if (str[i] == '\n') { str[i] = 0; return (str); } if (++i == 255) { str[i] = 0; return (str); } } return (NULL); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'c.asm'" '(8559 characters)' if test -f 'c.asm' then echo shar: "will not over-write existing file 'c.asm'" else cat << \!Funky!Stuff! > 'c.asm' * C.ASM (ASTARTUP.ASM with modifications) * * * This is exactly Lattice's Astartup.asm with some small modificatons * to save the BCPL register state on startup. * ************************************************************************ * * C Program Startup/Exit (Combo Version: CLI and WorkBench) * ************************************************************************ * * Source Control: * * $Header$ * * $Locker$ * * $Log$ * ************************************************************************ ******* Included Files ************************************************* INCLUDE "exec/types.i" INCLUDE "exec/alerts.i" INCLUDE "exec/nodes.i" INCLUDE "exec/lists.i" INCLUDE "exec/ports.i" INCLUDE "exec/libraries.i" INCLUDE "exec/tasks.i" INCLUDE "libraries/dos.i" INCLUDE "libraries/dosextens.i" INCLUDE "workbench/startup.i" ******* Imported ******************************************************* xlib macro xref _LVO\1 endm xref _AbsExecBase xref _Input xref _Output xref _main ; C code entry point xlib Alert xlib FindTask xlib Forbid xlib GetMsg xlib OpenLibrary xlib CloseLibrary xlib ReplyMsg xlib Wait xlib WaitPort xlib CurrentDir xlib Open ******* Exported ******************************************************* xdef _SysBase xdef _DOSBase xdef _errno xdef _stdin xdef _stdout xdef _stderr xdef _exit ; standard C exit function xdef _SysRegs ; D0-D7 A0-A6 system registers on startup callsys macro CALLLIB _LVO\1 endm ************************************************************************ * * Standard Program Entry Point * ************************************************************************ * * main (argc, argv) * int argc; * char *argv[]; * ************************************************************************ startup: ; reference for Wack users movem.l D0-D7/A0-A6,_SysRegs move.l sp,initialSP ; initial task stack pointer move.l d0,dosCmdLen move.l a0,dosCmdBuf clr.l returnMsg ;------ get Exec's library base pointer: move.l _AbsExecBase,a6 move.l a6,_SysBase ;------ get the address of our task suba.l a1,a1 callsys FindTask move.l d0,a4 ;------ are we running as a son of Workbench? tst.l pr_CLI(A4) beq fromWorkbench ;======================================================================= ;====== CLI Startup Code =============================================== ;======================================================================= fromCLI: ;------ attempt to open DOS library: bsr openDOS ;------ find command name: move.l pr_CLI(a4),a0 add.l a0,a0 ; bcpl pointer conversion add.l a0,a0 move.l cli_CommandName(a0),a0 add.l a0,a0 ; bcpl pointer conversion add.l a0,a0 ;------ create buffer and array: * link a6,#-(100+16*4+2*4) movem.l d2/a2/a3,-(sp) lea argvBuffer,a2 lea argvArray,a3 * move.l a3,16(sp) ; save moveq.l #1,d2 ; param counter ;------ fetch command name: moveq.l #0,d0 move.b (a0)+,d0 ; size of command name move.l a2,(a3)+ ; ptr to command name bra.s 1$ 2$: move.b (a0)+,(a2)+ 1$: dbf d0,2$ clr.b (a2)+ ;------ collect parameters: move.l dosCmdLen,d0 move.l dosCmdBuf,a0 ;------ skip control characters and space: 3$: move.b (a0)+,d1 subq.l #1,d0 ble.s parmExit cmp.b #' ',d1 ble.s 3$ ;------ copy parameter: addq.l #1,d2 move.l a2,(a3)+ bra.s 5$ 4$: move.b (a0)+,d1 subq.l #1,d0 cmp.b #' ',d1 ble.s 6$ 5$: move.b d1,(a2)+ bra.s 4$ 6$: clr.b (a2)+ bra.s 3$ parmExit: clr.b (a2)+ clr.l (a3)+ move.l d2,d0 movem.l (sp)+,d2/a2/a3 pea argvArray move.l d0,-(sp) * * The above code relies on the end of line containing a control * character of any type, i.e. a valid character must not be the * last. This fact is ensured by DOS. * ;------ get standard input handle: jsr _Input move.l d0,_stdin ;------ get standard output handle: jsr _Output move.l d0,_stdout move.l d0,_stderr ;------ call C main entry point jsr _main ;------ return success code: moveq.l #0,D0 move.l initialSP,sp ; restore stack ptr rts ;======================================================================= ;====== Workbench Startup Code ========================================= ;======================================================================= fromWorkbench: ;------ open the DOS library: bsr openDOS ;------ we are now set up. wait for a message from our starter bsr waitmsg ;------ save the message so we can return it later move.l d0,returnMsg NOTE: no GetMsg performed ;------ push the message on the stack for wbmain clr.l -(SP) indicate: run from Workbench move.l d0,-(SP) ;------ get the first argument move.l d0,a2 move.l sm_ArgList(a2),d0 beq.s docons ;------ and set the current directory to the same directory move.l _DOSBase,a6 move.l d0,a0 move.l wa_Lock(a0),d1 callsys CurrentDir docons: ;------ get the toolwindow argument move.l sm_ToolWindow(A2),d1 beq.s domain ;------ open up the file move.l #MODE_OLDFILE,d2 callsys Open ;------ set the C input and output descriptors move.l d0,_stdin move.l d0,_stdout move.l d0,_stderr beq.s domain ;------ set the console task (so Open( "*", mode ) will work ; waitmsg has left the task pointer in A4 for us lsl.l #2,d0 move.l d0,a0 move.l fh_Type(a0),pr_ConsoleTask(A4) domain: jsr _main moveq.l #0,d0 Successful return code bra.s exit2 ************************************************************************ * * C Program Exit Function * ************************************************************************ * * Warning: this function really needs to do more than this. * ************************************************************************ _exit: move.l 4(SP),d0 ; extract return code exit2: move.l initialSP,SP ; restore stack pointer move.l d0,-(SP) ; save return code ;------ close DOS library: move.l _AbsExecBase,A6 move.l _DOSBase,d0 beq.s 1$ move.l d0,a1 1$: callsys CloseLibrary ;------ if we ran from CLI, skip workbench cleanup: tst.l returnMsg beq.s exitToDOS ;------ return the startup message to our parent ; we forbid so workbench can't UnLoadSeg() us ; before we are done: callsys Forbid move.l returnMsg,a1 callsys ReplyMsg ;------ this rts sends us back to DOS: exitToDOS: move.l (SP)+,d0 rts ;----------------------------------------------------------------------- noDOS: ALERT (AG_OpenLib!AO_DOSLib) moveq.l #100,d0 bra.s exit2 ;----------------------------------------------------------------------- ; This routine gets the message that workbench will send to us ; called with task id in A4 waitmsg: lea pr_MsgPort(A4),a0 * our process base callsys WaitPort lea pr_MsgPort(A4),a0 * our process base callsys GetMsg rts ;----------------------------------------------------------------------- ; Open the DOS library: openDOS clr.l _DOSBase lea DOSName,A1 move.l #LIBRARY_VERSION,d0 callsys OpenLibrary move.l D0,_DOSBase beq noDOS rts ************************************************************************ DATA ************************************************************************ VerRev dc.w 1,0 _SysBase dc.l 0 _DOSBase dc.l 0 _SysRegs ds.l 16 _errno dc.l 0 _stdin dc.l 0 _stdout dc.l 0 _stderr dc.l 0 initialSP dc.l 0 returnMsg dc.l 0 dosCmdLen dc.l 0 dosCmdBuf dc.l 0 argvArray ds.l 32 argvBuffer ds.b 256 DOSName DOSNAME END !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'fexec2.asm'" '(1524 characters)' if test -f 'fexec2.asm' then echo shar: "will not over-write existing file 'fexec2.asm'" else cat << \!Funky!Stuff! > 'fexec2.asm' ;FEXEC2.ASM ; ; Again, this code originated from Manx, but has been heavily re-written ; xdef _doexec xref _LVOFreeMem xref _SysRegs xref _SysBase ; ;doexec(len, arg, (seg+1)<<2, stk) ; D0 A0 A4 A7 ; _doexec: move.l sp,savefp ;save Frame Pointer movem.l d2-d7/a2-a6,-(sp) ;save Registers move.l sp,savsp ;save current SP movem.l _SysRegs,D0-D7/A0-A6 ;Get System Startup Registers (BCPL stuff) move.l savefp,A0 ;A0 = frame pointer movem.l 4(A0),d0/a0/a4/a7 ;load parameters, including new SP move.l d0,12(a1) ;set length move.l a0,d1 ;copy to dreg lsr.l #2,d1 ;convert to BPTR move.l d1,8(a1) ;set ptr jsr (a4) ;call new program movem.l (sp)+,d2/d3 ;get stk siz and old sp move.l sp,a1 ;save current sp move.l savsp,sp ;get back our sp move.l d0,-(sp) ;save return code so we don't loose it sub.l d2,a1 ;Backup from end of stack to start sub.l #8,a1 ;point over header placed on stack move.l (a1),d0 ;get size to free move.l _SysBase,a6 ;get ExecBase jsr _LVOFreeMem(a6) ;Free memory allocated for stack move.l (sp)+,d0 ;D0 = return code movem.l (sp)+,D2-D7/A2-A6 ;restore Registers rts savsp: dc.l 0 savefp: dc.l 0 !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'shell.h'" '(3258 characters)' if test -f 'shell.h' then echo shar: "will not over-write existing file 'shell.h'" else cat << \!Funky!Stuff! > 'shell.h' /* * SHELL.H * * (c)1986 Matthew Dillon 9 October 1986 * * * SHELL include file.. contains shell parameters and extern's * * */ #include <exec/types.h> #define MAXAV 128 /* Max. # arguments */ #define MAXSRC 5 /* Max. # of source file levels */ #define MAXIF 10 /* Max. # of if levels */ #define MAXALIAS 20 /* Max. # of alias levels */ #define LEVEL_SET 0 /* which variable list to use */ #define LEVEL_ALIAS 1 #define LEVEL_LABEL 2 #define V_PROMPT "_prompt" /* your prompt (ascii command) */ #define V_HIST "_history" /* set history depth (value) */ #define V_HISTNUM "_histnum" /* set history numbering var */ #define V_DEBUG "_debug" /* set debug mode */ #define V_VERBOSE "_verbose" /* set verbose for source files */ #define V_STAT "_maxerr" /* worst return value to date */ #define V_LASTERR "_lasterr" /* return value from last comm. */ #define V_CWD "_cwd" /* current directory */ #define V_EXCEPT "_except" /* "nnn;command" */ #define V_PASSED "_passed" /* passed arguments to source fle*/ #define V_PATH "_path" /* path prefix,prefix,prefix.. */ /* EXECOM.C defines */ #define FL_DOLLAR 0x01 /* One of the following */ #define FL_BANG 0x02 #define FL_PERCENT 0x04 #define FL_QUOTE 0x08 #define FL_IDOLLAR 0x10 /* Any or all of the following may be set */ #define FL_EOC 0x20 #define FL_EOL 0x40 #define FL_OVERIDE 0x80 #define FL_WILD 0x100 #define FL_MASK (FL_DOLLAR|FL_BANG|FL_PERCENT|FL_QUOTE) #define VERSION "V2.04 (c)1986 Matthew Dillon. 22Oct86" #ifndef NULL #define NULL 0L #endif #define CHECKBREAK() ( breakcheck() ? (printf("^C\n"),1) : 0) struct HIST { struct HIST *next, *prev; /* doubly linked list */ char *line; /* line in history */ }; struct PERROR { short errnum; /* Format of global error lookup */ char *errstr; }; struct DPTR { /* Format of directory fetch pointer */ struct FileLock *lock; /* lock on directory */ struct FileInfoBlock *fib; /* mod'd fib for entry */ }; extern struct HIST *H_head, *H_tail; extern struct PERROR Perror[]; extern struct DPTR *dopen(); extern char *set_var(), *get_var(), *next_word(); extern char *get_history(), *compile_av(); extern char *malloc(), *strcpy(), *strcat(), *AllocMem(), *gets(), *Ogets(); extern char **expand(), *FindIt(); extern char *av[]; extern char *Current; extern short H_len, H_tail_base, H_stack; extern short E_stack; extern short Src_stack, If_stack; extern short ac; extern short Debug, Verbose, Disable, Quit; extern long Lastresult; extern short Exec_abortline, Exec_ignoreresult; extern short S_histlen; extern long Uniq; extern long Cin, Cout, Cerr, Cout_append; extern char *Cin_name, *Cout_name; extern char Cin_type, Cout_type; /* these variables are in transition */ extern char *Pipe1, *Pipe2; extern int Src_base[MAXSRC]; extern long Src_pos[MAXSRC]; extern char If_base[MAXIF]; !Funky!Stuff! fi # end of overwriting check exit 0 # End of shell archive