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