rc: remove historical unix and win32 ports
This commit is contained in:
parent
45d6bca5f0
commit
4ad3f4f2fd
8 changed files with 25 additions and 3160 deletions
|
@ -108,13 +108,10 @@ outcode(tree *t, int eflag)
|
|||
break;
|
||||
case '&':
|
||||
emitf(Xasync);
|
||||
if(havefork){
|
||||
p = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
} else
|
||||
emits(fnstr(c0));
|
||||
p = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
break;
|
||||
case ';':
|
||||
outcode(c0, eflag);
|
||||
|
@ -129,13 +126,10 @@ outcode(tree *t, int eflag)
|
|||
break;
|
||||
case '`':
|
||||
emitf(Xbackq);
|
||||
if(havefork){
|
||||
p = emiti(0);
|
||||
outcode(c0, 0);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
} else
|
||||
emits(fnstr(c0));
|
||||
p = emiti(0);
|
||||
outcode(c0, 0);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
break;
|
||||
case ANDAND:
|
||||
outcode(c0, 0);
|
||||
|
@ -211,13 +205,10 @@ outcode(tree *t, int eflag)
|
|||
break;
|
||||
case SUBSHELL:
|
||||
emitf(Xsubshell);
|
||||
if(havefork){
|
||||
p = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
} else
|
||||
emits(fnstr(c0));
|
||||
p = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
if(eflag)
|
||||
emitf(Xeflag);
|
||||
break;
|
||||
|
@ -304,14 +295,10 @@ outcode(tree *t, int eflag)
|
|||
case PIPEFD:
|
||||
emitf(Xpipefd);
|
||||
emiti(t->rtype);
|
||||
if(havefork){
|
||||
p = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
} else {
|
||||
emits(fnstr(c0));
|
||||
}
|
||||
p = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
break;
|
||||
case REDIR:
|
||||
emitf(Xmark);
|
||||
|
@ -366,16 +353,11 @@ outcode(tree *t, int eflag)
|
|||
emitf(Xpipe);
|
||||
emiti(t->fd0);
|
||||
emiti(t->fd1);
|
||||
if(havefork){
|
||||
p = emiti(0);
|
||||
q = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
} else {
|
||||
emits(fnstr(c0));
|
||||
q = emiti(0);
|
||||
}
|
||||
p = emiti(0);
|
||||
q = emiti(0);
|
||||
outcode(c0, eflag);
|
||||
emitf(Xexit);
|
||||
stuffdot(p);
|
||||
outcode(c1, eflag);
|
||||
emitf(Xreturn);
|
||||
stuffdot(q);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -68,7 +68,6 @@ struct builtin{
|
|||
};
|
||||
extern struct builtin Builtin[];
|
||||
int eflagok; /* kludge flag so that -e doesn't exit in startup */
|
||||
int havefork;
|
||||
|
||||
void execcd(void), execwhatis(void), execeval(void), execexec(void);
|
||||
int execforkexec(void);
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include "io.h"
|
||||
#include "fns.h"
|
||||
|
||||
int havefork = 1;
|
||||
|
||||
void
|
||||
Xasync(void)
|
||||
{
|
||||
|
|
|
@ -1,217 +0,0 @@
|
|||
#include "rc.h"
|
||||
#include "getflags.h"
|
||||
#include "exec.h"
|
||||
#include "io.h"
|
||||
#include "fns.h"
|
||||
|
||||
int havefork = 0;
|
||||
|
||||
static char **
|
||||
rcargv(char *s)
|
||||
{
|
||||
int argc;
|
||||
char **argv;
|
||||
word *p;
|
||||
|
||||
p = vlook("*")->val;
|
||||
argv = emalloc((count(p)+6)*sizeof(char*));
|
||||
argc = 0;
|
||||
argv[argc++] = argv0;
|
||||
if(flag['e'])
|
||||
argv[argc++] = "-Se";
|
||||
else
|
||||
argv[argc++] = "-S";
|
||||
argv[argc++] = "-c";
|
||||
argv[argc++] = s;
|
||||
for(p = vlook("*")->val; p; p = p->next)
|
||||
argv[argc++] = p->word;
|
||||
argv[argc] = 0;
|
||||
return argv;
|
||||
}
|
||||
|
||||
void
|
||||
Xasync(void)
|
||||
{
|
||||
uint pid;
|
||||
char buf[20], **argv;
|
||||
|
||||
Updenv();
|
||||
|
||||
argv = rcargv(runq->code[runq->pc].s);
|
||||
pid = ForkExecute(argv0, argv, -1, 1, 2);
|
||||
free(argv);
|
||||
|
||||
if(pid == 0) {
|
||||
Xerror("proc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
runq->pc++;
|
||||
sprint(buf, "%d", pid);
|
||||
setvar("apid", newword(buf, (word *)0));
|
||||
}
|
||||
|
||||
enum { Stralloc = 100, };
|
||||
|
||||
void
|
||||
Xbackq(void)
|
||||
{
|
||||
char **argv;
|
||||
int c, l;
|
||||
char *s, *wd, *ewd, *stop;
|
||||
struct io *f;
|
||||
var *ifs = vlook("ifs");
|
||||
word *v, *nextv;
|
||||
int pfd[2];
|
||||
int pid;
|
||||
|
||||
stop = ifs->val?ifs->val->word:"";
|
||||
if(pipe(pfd)<0){
|
||||
Xerror("can't make pipe");
|
||||
return;
|
||||
}
|
||||
|
||||
Updenv();
|
||||
|
||||
argv = rcargv(runq->code[runq->pc].s);
|
||||
pid = ForkExecute(argv0, argv, -1, pfd[1], 2);
|
||||
free(argv);
|
||||
|
||||
close(pfd[1]);
|
||||
|
||||
if(pid == 0) {
|
||||
Xerror("proc failed");
|
||||
close(pfd[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
f = openfd(pfd[0]);
|
||||
s = wd = ewd = 0;
|
||||
v = 0;
|
||||
while((c=rchr(f))!=EOF){
|
||||
if(s==ewd){
|
||||
l = s-wd;
|
||||
wd = erealloc(wd, l+Stralloc);
|
||||
ewd = wd+l+Stralloc-1;
|
||||
s = wd+l;
|
||||
}
|
||||
if(strchr(stop, c)){
|
||||
if(s!=wd){
|
||||
*s='\0';
|
||||
v = newword(wd, v);
|
||||
s = wd;
|
||||
}
|
||||
}
|
||||
else *s++=c;
|
||||
}
|
||||
if(s!=wd){
|
||||
*s='\0';
|
||||
v=newword(wd, v);
|
||||
}
|
||||
free(wd);
|
||||
closeio(f);
|
||||
Waitfor(pid, 1);
|
||||
/* v points to reversed arglist -- reverse it onto argv */
|
||||
while(v){
|
||||
nextv=v->next;
|
||||
v->next=runq->argv->words;
|
||||
runq->argv->words=v;
|
||||
v=nextv;
|
||||
}
|
||||
runq->pc++;
|
||||
}
|
||||
|
||||
void
|
||||
Xpipe(void)
|
||||
{
|
||||
thread *p=runq;
|
||||
int pc=p->pc, pid;
|
||||
int rfd=p->code[pc+1].i;
|
||||
int pfd[2];
|
||||
char **argv;
|
||||
|
||||
if(pipe(pfd)<0){
|
||||
Xerror1("can't get pipe");
|
||||
return;
|
||||
}
|
||||
|
||||
Updenv();
|
||||
|
||||
argv = rcargv(runq->code[pc+2].s);
|
||||
pid = ForkExecute(argv0, argv, 0, pfd[1], 2);
|
||||
free(argv);
|
||||
close(pfd[1]);
|
||||
|
||||
if(pid == 0) {
|
||||
Xerror("proc failed");
|
||||
close(pfd[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
start(p->code, pc+4, runq->local);
|
||||
pushredir(ROPEN, pfd[0], rfd);
|
||||
p->pc=p->code[pc+3].i;
|
||||
p->pid=pid;
|
||||
}
|
||||
|
||||
void
|
||||
Xpipefd(void)
|
||||
{
|
||||
Abort();
|
||||
}
|
||||
|
||||
void
|
||||
Xsubshell(void)
|
||||
{
|
||||
char **argv;
|
||||
int pid;
|
||||
|
||||
Updenv();
|
||||
|
||||
argv = rcargv(runq->code[runq->pc].s);
|
||||
pid = ForkExecute(argv0, argv, -1, 1, 2);
|
||||
free(argv);
|
||||
|
||||
if(pid < 0) {
|
||||
Xerror("proc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
Waitfor(pid, 1);
|
||||
runq->pc++;
|
||||
}
|
||||
|
||||
/*
|
||||
* start a process running the cmd on the stack and return its pid.
|
||||
*/
|
||||
int
|
||||
execforkexec(void)
|
||||
{
|
||||
char **argv;
|
||||
char file[1024];
|
||||
int nc, mc;
|
||||
word *path;
|
||||
int pid;
|
||||
|
||||
if(runq->argv->words==0)
|
||||
return -1;
|
||||
argv = mkargv(runq->argv->words);
|
||||
mc = strlen(argv[1])+1;
|
||||
for(path = searchpath(runq->argv->words->word);path;path = path->next){
|
||||
nc = strlen(path->word);
|
||||
if(nc + mc >= sizeof file - 1) /* 1 for / */
|
||||
continue;
|
||||
if(nc > 0){
|
||||
memmove(file, path->word, nc);
|
||||
file[nc++] = '/';
|
||||
}
|
||||
memmove(file+nc, argv[1], mc);
|
||||
pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
|
||||
if(pid >= 0){
|
||||
free(argv);
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
free(argv);
|
||||
return -1;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=rc
|
||||
COMMONOFILES=\
|
||||
OFILES=\
|
||||
code.$O\
|
||||
exec.$O\
|
||||
getflags.$O\
|
||||
|
@ -17,12 +17,8 @@ COMMONOFILES=\
|
|||
tree.$O\
|
||||
var.$O\
|
||||
havefork.$O\
|
||||
|
||||
PLAN9OFILES=plan9.$O\
|
||||
|
||||
UNIXOFILES=unix.$O\
|
||||
|
||||
OFILES=$COMMONOFILES $PLAN9OFILES y.tab.$O
|
||||
plan9.$O\
|
||||
y.tab.$O\
|
||||
|
||||
HFILES=rc.h\
|
||||
x.tab.h\
|
||||
|
@ -38,9 +34,7 @@ BIN=/$objtype/bin
|
|||
UPDATE=\
|
||||
mkfile\
|
||||
$HFILES\
|
||||
${COMMONOFILES:%.$O=%.c}\
|
||||
${UNIXOFILES:%.$O=%.c}\
|
||||
${PLAN9OFILES:%.$O=%.c}\
|
||||
${OFILES:%.$O=%.c}\
|
||||
$YFILES\
|
||||
${TARG:%=/386/bin/%}\
|
||||
|
||||
|
@ -51,13 +45,3 @@ x.tab.h: y.tab.h
|
|||
|
||||
clean:V:
|
||||
rm -f [$OS].out *.[$OS] [xy].tab.? y.debug $TARG
|
||||
|
||||
regress: $O.out
|
||||
cd test
|
||||
mk
|
||||
|
||||
unregress:V:
|
||||
for(test in test/*.test) rc $test >$test.out
|
||||
|
||||
listing:
|
||||
pr mkfile $HFILES $FILES $FILES9 $FILESUNIX $YFILES|lp -du
|
||||
|
|
|
@ -1,466 +0,0 @@
|
|||
/*
|
||||
* Unix versions of system-specific functions
|
||||
* By convention, exported routines herein have names beginning with an
|
||||
* upper case letter.
|
||||
*/
|
||||
#include "rc.h"
|
||||
#include "exec.h"
|
||||
#include <errno.h>
|
||||
char Rcmain[]="/usr/lib/rcmain";
|
||||
char Fdprefix[]="/dev/fd/";
|
||||
int execumask(), execfinit();
|
||||
struct builtin Builtin[] = {
|
||||
"cd", execcd,
|
||||
"whatis", execwhatis,
|
||||
"eval", execeval,
|
||||
"exec", execexec, /* but with popword first */
|
||||
"exit", execexit,
|
||||
"shift", execshift,
|
||||
"wait", execwait,
|
||||
"umask", execumask,
|
||||
".", execdot,
|
||||
"finit", execfinit,
|
||||
"flag", execflag,
|
||||
0
|
||||
};
|
||||
#define SEP '\1'
|
||||
char **environp;
|
||||
|
||||
struct word*
|
||||
enval(s)
|
||||
register char *s;
|
||||
{
|
||||
char *t, c;
|
||||
struct word *v;
|
||||
for(t = s;*t && *t!=SEP;t++);
|
||||
c=*t;
|
||||
*t='\0';
|
||||
v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
|
||||
*t = c;
|
||||
return v;
|
||||
}
|
||||
Vinit(){
|
||||
extern char **environ;
|
||||
char *s;
|
||||
char **env = environ;
|
||||
environp = env;
|
||||
for(;*env;env++){
|
||||
for(s=*env;*s && *s!='(' && *s!='=';s++);
|
||||
switch(*s){
|
||||
case '\0':
|
||||
pfmt(err, "environment %q?\n", *env);
|
||||
break;
|
||||
case '=':
|
||||
*s='\0';
|
||||
setvar(*env, enval(s+1));
|
||||
*s='=';
|
||||
break;
|
||||
case '(': /* ignore functions for now */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
char **envp;
|
||||
Xrdfn(){
|
||||
char *s;
|
||||
int len;
|
||||
for(;*envp;envp++){
|
||||
for(s=*envp;*s && *s!='(' && *s!='=';s++);
|
||||
switch(*s){
|
||||
case '\0':
|
||||
pfmt(err, "environment %q?\n", *envp);
|
||||
break;
|
||||
case '=': /* ignore variables */
|
||||
break;
|
||||
case '(': /* Bourne again */
|
||||
s=*envp+3;
|
||||
envp++;
|
||||
len = strlen(s);
|
||||
s[len]='\n';
|
||||
execcmds(opencore(s, len+1));
|
||||
s[len]='\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
Xreturn();
|
||||
}
|
||||
union code rdfns[4];
|
||||
execfinit(){
|
||||
static int first = 1;
|
||||
if(first){
|
||||
rdfns[0].i = 1;
|
||||
rdfns[1].f = Xrdfn;
|
||||
rdfns[2].f = Xjump;
|
||||
rdfns[3].i = 1;
|
||||
first = 0;
|
||||
}
|
||||
Xpopm();
|
||||
envp = environp;
|
||||
start(rdfns, 1, runq->local);
|
||||
}
|
||||
cmpenv(a, b)
|
||||
char **a, **b;
|
||||
{
|
||||
return strcmp(*a, *b);
|
||||
}
|
||||
|
||||
char*
|
||||
*mkenv()
|
||||
{
|
||||
char **env, **ep, *p, *q;
|
||||
struct var **h, *v;
|
||||
struct word *a;
|
||||
int nvar = 0, nchr = 0, sep;
|
||||
/*
|
||||
* Slightly kludgy loops look at locals then globals
|
||||
*/
|
||||
for(h = var-1;h!=&var[NVAR];h++) for(v = h>=var?*h:runq->local;v;v = v->next){
|
||||
if((v==vlook(v->name)) && v->val){
|
||||
nvar++;
|
||||
nchr+=strlen(v->name)+1;
|
||||
for(a = v->val;a;a = a->next)
|
||||
nchr+=strlen(a->word)+1;
|
||||
}
|
||||
if(v->fn){
|
||||
nvar++;
|
||||
nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
|
||||
}
|
||||
}
|
||||
env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
|
||||
ep = env;
|
||||
p = (char *)&env[nvar+1];
|
||||
for(h = var-1;h!=&var[NVAR];h++) for(v = h>=var?*h:runq->local;v;v = v->next){
|
||||
if((v==vlook(v->name)) && v->val){
|
||||
*ep++=p;
|
||||
q = v->name;
|
||||
while(*q) *p++=*q++;
|
||||
sep='=';
|
||||
for(a = v->val;a;a = a->next){
|
||||
*p++=sep;
|
||||
sep = SEP;
|
||||
q = a->word;
|
||||
while(*q) *p++=*q++;
|
||||
}
|
||||
*p++='\0';
|
||||
}
|
||||
if(v->fn){
|
||||
*ep++=p;
|
||||
*p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
|
||||
*p++='f'; *p++='n'; *p++=' ';
|
||||
q = v->name;
|
||||
while(*q) *p++=*q++;
|
||||
*p++=' ';
|
||||
q = v->fn[v->pc-1].s;
|
||||
while(*q) *p++=*q++;
|
||||
*p++='\0';
|
||||
}
|
||||
}
|
||||
*ep = 0;
|
||||
qsort((char *)env, nvar, sizeof ep[0], cmpenv);
|
||||
return env;
|
||||
}
|
||||
char *sigmsg[] = {
|
||||
/* 0 normal */ 0,
|
||||
/* 1 SIGHUP */ "Hangup",
|
||||
/* 2 SIGINT */ 0,
|
||||
/* 3 SIGQUIT */ "Quit",
|
||||
/* 4 SIGILL */ "Illegal instruction",
|
||||
/* 5 SIGTRAP */ "Trace/BPT trap",
|
||||
/* 6 SIGIOT */ "abort",
|
||||
/* 7 SIGEMT */ "EMT trap",
|
||||
/* 8 SIGFPE */ "Floating exception",
|
||||
/* 9 SIGKILL */ "Killed",
|
||||
/* 10 SIGBUS */ "Bus error",
|
||||
/* 11 SIGSEGV */ "Memory fault",
|
||||
/* 12 SIGSYS */ "Bad system call",
|
||||
/* 13 SIGPIPE */ 0,
|
||||
/* 14 SIGALRM */ "Alarm call",
|
||||
/* 15 SIGTERM */ "Terminated",
|
||||
/* 16 unused */ "signal 16",
|
||||
/* 17 SIGSTOP */ "Process stopped",
|
||||
/* 18 unused */ "signal 18",
|
||||
/* 19 SIGCONT */ "Process continued",
|
||||
/* 20 SIGCHLD */ "Child death",
|
||||
};
|
||||
Waitfor(pid, persist){
|
||||
int wpid, sig;
|
||||
struct thread *p;
|
||||
int wstat;
|
||||
char wstatstr[12];
|
||||
for(;;){
|
||||
errno = 0;
|
||||
wpid = wait(&wstat);
|
||||
if(errno==EINTR && persist)
|
||||
continue;
|
||||
if(wpid==-1)
|
||||
break;
|
||||
sig = wstat&0177;
|
||||
if(sig==0177){
|
||||
pfmt(err, "trace: ");
|
||||
sig = (wstat>>8)&0177;
|
||||
}
|
||||
if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
|
||||
if(pid!=wpid)
|
||||
pfmt(err, "%d: ", wpid);
|
||||
if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))
|
||||
pfmt(err, "%s", sigmsg[sig]);
|
||||
else if(sig==0177) pfmt(err, "stopped by ptrace");
|
||||
else pfmt(err, "signal %d", sig);
|
||||
if(wstat&0200)pfmt(err, " -- core dumped");
|
||||
pfmt(err, "\n");
|
||||
}
|
||||
wstat = sig?sig+1000:(wstat>>8)&0xFF;
|
||||
if(wpid==pid){
|
||||
inttoascii(wstatstr, wstat);
|
||||
setstatus(wstatstr);
|
||||
break;
|
||||
}
|
||||
else{
|
||||
for(p = runq->ret;p;p = p->ret)
|
||||
if(p->pid==wpid){
|
||||
p->pid=-1;
|
||||
inttoascii(p->status, wstat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
*mkargv(a)
|
||||
register struct word *a;
|
||||
{
|
||||
char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
|
||||
char **argp = argv+1; /* leave one at front for runcoms */
|
||||
for(;a;a = a->next) *argp++=a->word;
|
||||
*argp = 0;
|
||||
return argv;
|
||||
}
|
||||
Updenv(){}
|
||||
Execute(args, path)
|
||||
register struct word *args, *path;
|
||||
{
|
||||
char *msg="not found";
|
||||
int txtbusy = 0;
|
||||
char **env = mkenv();
|
||||
char **argv = mkargv(args);
|
||||
char file[512];
|
||||
for(;path;path = path->next){
|
||||
strcpy(file, path->word);
|
||||
if(file[0])
|
||||
strcat(file, "/");
|
||||
strcat(file, argv[1]);
|
||||
ReExec:
|
||||
execve(file, argv+1, env);
|
||||
switch(errno){
|
||||
case ENOEXEC:
|
||||
pfmt(err, "%s: Bourne again\n", argv[1]);
|
||||
argv[0]="sh";
|
||||
argv[1] = estrdup(file);
|
||||
execve("/bin/sh", argv, env);
|
||||
goto Bad;
|
||||
case ETXTBSY:
|
||||
if(++txtbusy!=5){
|
||||
sleep(txtbusy);
|
||||
goto ReExec;
|
||||
}
|
||||
msg="text busy"; goto Bad;
|
||||
case EACCES:
|
||||
msg="no access";
|
||||
break;
|
||||
case ENOMEM:
|
||||
msg="not enough memory"; goto Bad;
|
||||
case E2BIG:
|
||||
msg="too big"; goto Bad;
|
||||
}
|
||||
}
|
||||
Bad:
|
||||
setstatus(msg);
|
||||
pfmt(err, "%s: %s\n", argv[1], msg);
|
||||
free(env);
|
||||
free(argv);
|
||||
}
|
||||
#define NDIR 14 /* should get this from param.h */
|
||||
Globsize(p)
|
||||
register char *p;
|
||||
{
|
||||
int isglob = 0, globlen = NDIR+1;
|
||||
for(;*p;p++){
|
||||
if(*p==GLOB){
|
||||
p++;
|
||||
if(*p!=GLOB)
|
||||
isglob++;
|
||||
globlen+=*p=='*'?NDIR:1;
|
||||
}
|
||||
else
|
||||
globlen++;
|
||||
}
|
||||
return isglob?globlen:0;
|
||||
}
|
||||
#include <sys/types.h>
|
||||
#include <ndir.h>
|
||||
#define NDIRLIST 50
|
||||
DIR *dirlist[NDIRLIST];
|
||||
Opendir(name)
|
||||
char *name;
|
||||
{
|
||||
DIR **dp;
|
||||
for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
|
||||
if(*dp==0){
|
||||
*dp = opendir(name);
|
||||
return *dp?dp-dirlist:-1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
Readdir(f, p, onlydirs)
|
||||
int f;
|
||||
void *p;
|
||||
int onlydirs; /* ignored, just advisory */
|
||||
{
|
||||
struct direct *dp = readdir(dirlist[f]);
|
||||
if(dp==0)
|
||||
return 0;
|
||||
strncpy(p, dp->d_name, NDIR);
|
||||
return 1;
|
||||
}
|
||||
Closedir(f){
|
||||
closedir(dirlist[f]);
|
||||
dirlist[f] = 0;
|
||||
}
|
||||
char *Signame[] = {
|
||||
"sigexit", "sighup", "sigint", "sigquit",
|
||||
"sigill", "sigtrap", "sigiot", "sigemt",
|
||||
"sigfpe", "sigkill", "sigbus", "sigsegv",
|
||||
"sigsys", "sigpipe", "sigalrm", "sigterm",
|
||||
"sig16", "sigstop", "sigtstp", "sigcont",
|
||||
"sigchld", "sigttin", "sigttou", "sigtint",
|
||||
"sigxcpu", "sigxfsz", "sig26", "sig27",
|
||||
"sig28", "sig29", "sig30", "sig31",
|
||||
0,
|
||||
};
|
||||
|
||||
int
|
||||
gettrap(sig)
|
||||
{
|
||||
signal(sig, gettrap);
|
||||
trap[sig]++;
|
||||
ntrap++;
|
||||
if(ntrap>=NSIG){
|
||||
pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
|
||||
signal(SIGIOT, (int (*)())0);
|
||||
kill(getpid(), SIGIOT);
|
||||
}
|
||||
}
|
||||
Trapinit(){
|
||||
int i;
|
||||
int (*sig)();
|
||||
if(1 || flag['d']){ /* wrong!!! */
|
||||
sig = signal(SIGINT, gettrap);
|
||||
if(sig==SIG_IGN)
|
||||
signal(SIGINT, SIG_IGN);
|
||||
}
|
||||
else{
|
||||
for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
|
||||
sig = signal(i, gettrap);
|
||||
if(sig==SIG_IGN)
|
||||
signal(i, SIG_IGN);
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlink(name)
|
||||
char *name;
|
||||
{
|
||||
return unlink(name);
|
||||
}
|
||||
Write(fd, buf, cnt)
|
||||
void *buf;
|
||||
{
|
||||
return write(fd, buf, cnt);
|
||||
}
|
||||
Read(fd, buf, cnt)
|
||||
void *buf;
|
||||
{
|
||||
return read(fd, buf, cnt);
|
||||
}
|
||||
Seek(fd, cnt, whence)
|
||||
long cnt;
|
||||
{
|
||||
return lseek(fd, cnt, whence);
|
||||
}
|
||||
Executable(file)
|
||||
char *file;
|
||||
{
|
||||
return(access(file, 01)==0);
|
||||
}
|
||||
Creat(file)
|
||||
char *file;
|
||||
{
|
||||
return creat(file, 0666);
|
||||
}
|
||||
Dup(a, b){
|
||||
return dup2(a, b);
|
||||
}
|
||||
Dup1(a){
|
||||
return dup(a);
|
||||
}
|
||||
/*
|
||||
* Wrong: should go through components of a|b|c and return the maximum.
|
||||
*/
|
||||
Exit(stat)
|
||||
register char *stat;
|
||||
{
|
||||
int n = 0;
|
||||
while(*stat){
|
||||
if(*stat!='|'){
|
||||
if(*stat<'0' || '9'<*stat)
|
||||
exit(1);
|
||||
else n = n*10+*stat-'0';
|
||||
}
|
||||
stat++;
|
||||
}
|
||||
exit(n);
|
||||
}
|
||||
Eintr(){
|
||||
return errno==EINTR;
|
||||
}
|
||||
Noerror(){
|
||||
errno = 0;
|
||||
}
|
||||
Isatty(fd){
|
||||
return isatty(fd);
|
||||
}
|
||||
Abort(){
|
||||
abort();
|
||||
}
|
||||
static int
|
||||
octal(char *s)
|
||||
{
|
||||
int n = 0;
|
||||
while(*s==' ' || *s=='\t' || *s=='\n') s++;
|
||||
while('0'<=*s && *s<='7') n = n*8+*s++-'0';
|
||||
return n;
|
||||
}
|
||||
execumask(){ /* wrong -- should fork before writing */
|
||||
int m;
|
||||
struct io out[1];
|
||||
switch(count(runq->argv->words)){
|
||||
default:
|
||||
pfmt(err, "Usage: umask [umask]\n");
|
||||
setstatus("umask usage");
|
||||
poplist();
|
||||
return;
|
||||
case 2:
|
||||
umask(octal(runq->argv->words->next->word));
|
||||
break;
|
||||
case 1:
|
||||
umask(m = umask(0));
|
||||
out->fd = mapfd(1);
|
||||
out->bufp = out->buf;
|
||||
out->ebuf=&out->buf[NBUF];
|
||||
out->strp = 0;
|
||||
pfmt(out, "%o\n", m);
|
||||
break;
|
||||
}
|
||||
setstatus("");
|
||||
poplist();
|
||||
}
|
|
@ -1,549 +0,0 @@
|
|||
/*
|
||||
* Plan 9 versions of system-specific functions
|
||||
* By convention, exported routines herein have names beginning with an
|
||||
* upper case letter.
|
||||
*/
|
||||
#include "rc.h"
|
||||
#include "exec.h"
|
||||
#include "io.h"
|
||||
#include "fns.h"
|
||||
#include "getflags.h"
|
||||
char *Signame[] = {
|
||||
"sigexit", "sighup", "sigint", "sigquit",
|
||||
"sigalrm", "sigkill", "sigfpe", "sigterm",
|
||||
0
|
||||
};
|
||||
char *syssigname[] = {
|
||||
"exit", /* can't happen */
|
||||
"hangup",
|
||||
"interrupt",
|
||||
"quit", /* can't happen */
|
||||
"alarm",
|
||||
"kill",
|
||||
"sys: fp: ",
|
||||
"term",
|
||||
0
|
||||
};
|
||||
char Rcmain[]="/rc/lib/rcmain";
|
||||
char Fdprefix[]="/fd/";
|
||||
void execfinit(void);
|
||||
void execbind(void);
|
||||
|
||||
builtin Builtin[] = {
|
||||
"cd", execcd,
|
||||
"whatis", execwhatis,
|
||||
"eval", execeval,
|
||||
"exec", execexec, /* but with popword first */
|
||||
"exit", execexit,
|
||||
"shift", execshift,
|
||||
"wait", execwait,
|
||||
".", execdot,
|
||||
"finit", execfinit,
|
||||
"flag", execflag,
|
||||
0
|
||||
};
|
||||
|
||||
void
|
||||
Vinit(void)
|
||||
{
|
||||
int dir, f, len;
|
||||
word *val;
|
||||
char *buf, *s;
|
||||
Dir *ent;
|
||||
int i, nent;
|
||||
char envname[256];
|
||||
dir = open("/env", OREAD);
|
||||
if(dir<0){
|
||||
pfmt(err, "rc: can't open /env: %r\n");
|
||||
return;
|
||||
}
|
||||
ent = nil;
|
||||
for(;;){
|
||||
nent = dirread(dir, &ent);
|
||||
if(nent <= 0)
|
||||
break;
|
||||
for(i = 0; i<nent; i++){
|
||||
len = ent[i].length;
|
||||
if(len && strncmp(ent[i].name, "fn#", 3)!=0){
|
||||
snprint(envname, sizeof envname, "/env/%s", ent[i].name);
|
||||
if((f = open(envname, 0))>=0){
|
||||
buf = emalloc((int)len+1);
|
||||
read(f, buf, (long)len);
|
||||
val = 0;
|
||||
/* Charitably add a 0 at the end if need be */
|
||||
if(buf[len-1])
|
||||
buf[len++]='\0';
|
||||
s = buf+len-1;
|
||||
for(;;){
|
||||
while(s!=buf && s[-1]!='\0') --s;
|
||||
val = newword(s, val);
|
||||
if(s==buf)
|
||||
break;
|
||||
--s;
|
||||
}
|
||||
setvar(ent[i].name, val);
|
||||
vlook(ent[i].name)->changed = 0;
|
||||
close(f);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(ent);
|
||||
}
|
||||
close(dir);
|
||||
}
|
||||
int envdir;
|
||||
|
||||
void
|
||||
Xrdfn(void)
|
||||
{
|
||||
int f, len;
|
||||
static Dir *ent, *allocent;
|
||||
static int nent;
|
||||
Dir *e;
|
||||
char envname[256];
|
||||
|
||||
for(;;){
|
||||
if(nent == 0){
|
||||
free(allocent);
|
||||
nent = dirread(envdir, &allocent);
|
||||
ent = allocent;
|
||||
}
|
||||
if(nent <= 0)
|
||||
break;
|
||||
while(nent){
|
||||
e = ent++;
|
||||
nent--;
|
||||
len = e->length;
|
||||
if(len && strncmp(e->name, "fn#", 3)==0){
|
||||
snprint(envname, sizeof envname, "/env/%s", e->name);
|
||||
if((f = open(envname, 0))>=0){
|
||||
execcmds(openfd(f));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(envdir);
|
||||
Xreturn();
|
||||
}
|
||||
union code rdfns[4];
|
||||
|
||||
void
|
||||
execfinit(void)
|
||||
{
|
||||
static int first = 1;
|
||||
if(first){
|
||||
rdfns[0].i = 1;
|
||||
rdfns[1].f = Xrdfn;
|
||||
rdfns[2].f = Xjump;
|
||||
rdfns[3].i = 1;
|
||||
first = 0;
|
||||
}
|
||||
Xpopm();
|
||||
envdir = open("/env", 0);
|
||||
if(envdir<0){
|
||||
pfmt(err, "rc: can't open /env: %r\n");
|
||||
return;
|
||||
}
|
||||
start(rdfns, 1, runq->local);
|
||||
}
|
||||
|
||||
int
|
||||
Waitfor(int pid, int persist)
|
||||
{
|
||||
thread *p;
|
||||
Waitmsg *w;
|
||||
char errbuf[ERRMAX];
|
||||
|
||||
while((w = wait()) != nil){
|
||||
if(w->pid==pid){
|
||||
setstatus(w->msg);
|
||||
free(w);
|
||||
return 0;
|
||||
}
|
||||
for(p = runq->ret;p;p = p->ret)
|
||||
if(p->pid==w->pid){
|
||||
p->pid=-1;
|
||||
strcpy(p->status, w->msg);
|
||||
}
|
||||
free(w);
|
||||
}
|
||||
|
||||
errstr(errbuf, sizeof errbuf);
|
||||
if(strcmp(errbuf, "interrupted")==0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
*mkargv(word *a)
|
||||
{
|
||||
char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
|
||||
char **argp = argv+1; /* leave one at front for runcoms */
|
||||
for(;a;a = a->next) *argp++=a->word;
|
||||
*argp = 0;
|
||||
return argv;
|
||||
}
|
||||
|
||||
void
|
||||
addenv(var *v)
|
||||
{
|
||||
char envname[256];
|
||||
word *w;
|
||||
int f;
|
||||
io *fd;
|
||||
if(v->changed){
|
||||
v->changed = 0;
|
||||
snprint(envname, sizeof envname, "/env/%s", v->name);
|
||||
if((f = Creat(envname))<0)
|
||||
pfmt(err, "rc: can't open %s: %r\n", envname);
|
||||
else{
|
||||
for(w = v->val;w;w = w->next)
|
||||
write(f, w->word, strlen(w->word)+1L);
|
||||
close(f);
|
||||
}
|
||||
}
|
||||
if(v->fnchanged){
|
||||
v->fnchanged = 0;
|
||||
snprint(envname, sizeof envname, "/env/fn#%s", v->name);
|
||||
if((f = Creat(envname))<0)
|
||||
pfmt(err, "rc: can't open %s: %r\n", envname);
|
||||
else{
|
||||
if(v->fn){
|
||||
fd = openfd(f);
|
||||
pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
|
||||
closeio(fd);
|
||||
}
|
||||
close(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
updenvlocal(var *v)
|
||||
{
|
||||
if(v){
|
||||
updenvlocal(v->next);
|
||||
addenv(v);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Updenv(void)
|
||||
{
|
||||
var *v, **h;
|
||||
for(h = gvar;h!=&gvar[NVAR];h++)
|
||||
for(v=*h;v;v = v->next)
|
||||
addenv(v);
|
||||
if(runq)
|
||||
updenvlocal(runq->local);
|
||||
}
|
||||
|
||||
int
|
||||
ForkExecute(char *file, char **argv, int sin, int sout, int serr)
|
||||
{
|
||||
int pid;
|
||||
|
||||
{int i;
|
||||
fprint(2, "forkexec %s", file);
|
||||
for(i = 0; argv[i]; i++)fprint(2, " %s", argv[i]);
|
||||
fprint(2, " %d %d %d\n", sin, sout, serr);
|
||||
}
|
||||
if(access(file, 1) != 0)
|
||||
return -1;
|
||||
fprint(2, "forking\n");
|
||||
switch(pid = fork()){
|
||||
case -1:
|
||||
return -1;
|
||||
case 0:
|
||||
if(sin >= 0)
|
||||
dup(sin, 0);
|
||||
else
|
||||
close(0);
|
||||
if(sout >= 0)
|
||||
dup(sout, 1);
|
||||
else
|
||||
close(1);
|
||||
if(serr >= 0)
|
||||
dup(serr, 2);
|
||||
else
|
||||
close(2);
|
||||
fprint(2, "execing\n");
|
||||
exec(file, argv);
|
||||
fprint(2, "exec: %r\n");
|
||||
exits(file);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
void
|
||||
Execute(word *args, word *path)
|
||||
{
|
||||
char **argv = mkargv(args);
|
||||
char file[1024];
|
||||
int nc;
|
||||
Updenv();
|
||||
for(;path;path = path->next){
|
||||
nc = strlen(path->word);
|
||||
if(nc<1024){
|
||||
strcpy(file, path->word);
|
||||
if(file[0]){
|
||||
strcat(file, "/");
|
||||
nc++;
|
||||
}
|
||||
if(nc+strlen(argv[1])<1024){
|
||||
strcat(file, argv[1]);
|
||||
exec(file, argv+1);
|
||||
}
|
||||
else werrstr("command name too long");
|
||||
}
|
||||
}
|
||||
rerrstr(file, sizeof file);
|
||||
setstatus(file);
|
||||
pfmt(err, "%s: %s\n", argv[1], file);
|
||||
free(argv);
|
||||
}
|
||||
#define NDIR 256 /* shoud be a better way */
|
||||
|
||||
int
|
||||
Globsize(char *p)
|
||||
{
|
||||
int isglob = 0, globlen = NDIR+1;
|
||||
for(;*p;p++){
|
||||
if(*p==GLOB){
|
||||
p++;
|
||||
if(*p!=GLOB)
|
||||
isglob++;
|
||||
globlen+=*p=='*'?NDIR:1;
|
||||
}
|
||||
else
|
||||
globlen++;
|
||||
}
|
||||
return isglob?globlen:0;
|
||||
}
|
||||
#define NFD 50
|
||||
#define NDBUF 32
|
||||
struct{
|
||||
Dir *dbuf;
|
||||
int i;
|
||||
int n;
|
||||
}dir[NFD];
|
||||
|
||||
int
|
||||
Opendir(char *name)
|
||||
{
|
||||
Dir *db;
|
||||
int f;
|
||||
f = open(name, 0);
|
||||
if(f==-1)
|
||||
return f;
|
||||
db = dirfstat(f);
|
||||
if(db!=nil && (db->mode&DMDIR)){
|
||||
if(f<NFD){
|
||||
dir[f].i = 0;
|
||||
dir[f].n = 0;
|
||||
}
|
||||
free(db);
|
||||
return f;
|
||||
}
|
||||
free(db);
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
trimdirs(Dir *d, int nd)
|
||||
{
|
||||
int r, w;
|
||||
|
||||
for(r=w=0; r<nd; r++)
|
||||
if(d[r].mode&DMDIR)
|
||||
d[w++] = d[r];
|
||||
return w;
|
||||
}
|
||||
|
||||
/*
|
||||
* onlydirs is advisory -- it means you only
|
||||
* need to return the directories. it's okay to
|
||||
* return files too (e.g., on unix where you can't
|
||||
* tell during the readdir), but that just makes
|
||||
* the globber work harder.
|
||||
*/
|
||||
int
|
||||
Readdir(int f, void *p, int onlydirs)
|
||||
{
|
||||
int n;
|
||||
|
||||
if(f<0 || f>=NFD)
|
||||
return 0;
|
||||
Again:
|
||||
if(dir[f].i==dir[f].n){ /* read */
|
||||
free(dir[f].dbuf);
|
||||
dir[f].dbuf = 0;
|
||||
n = dirread(f, &dir[f].dbuf);
|
||||
if(n>0){
|
||||
if(onlydirs){
|
||||
n = trimdirs(dir[f].dbuf, n);
|
||||
if(n == 0)
|
||||
goto Again;
|
||||
}
|
||||
dir[f].n = n;
|
||||
}else
|
||||
dir[f].n = 0;
|
||||
dir[f].i = 0;
|
||||
}
|
||||
if(dir[f].i == dir[f].n)
|
||||
return 0;
|
||||
strncpy(p, dir[f].dbuf[dir[f].i].name, NDIR);
|
||||
dir[f].i++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
Closedir(int f)
|
||||
{
|
||||
if(f>=0 && f<NFD){
|
||||
free(dir[f].dbuf);
|
||||
dir[f].i = 0;
|
||||
dir[f].n = 0;
|
||||
dir[f].dbuf = 0;
|
||||
}
|
||||
close(f);
|
||||
}
|
||||
int interrupted = 0;
|
||||
void
|
||||
notifyf(void*, char *s)
|
||||
{
|
||||
int i;
|
||||
for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
|
||||
if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
|
||||
goto Out;
|
||||
}
|
||||
pfmt(err, "rc: note: %s\n", s);
|
||||
noted(NDFLT);
|
||||
return;
|
||||
Out:
|
||||
if(strcmp(s, "interrupt")!=0 || trap[i]==0){
|
||||
trap[i]++;
|
||||
ntrap++;
|
||||
}
|
||||
if(ntrap>=32){ /* rc is probably in a trap loop */
|
||||
pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
|
||||
abort();
|
||||
}
|
||||
noted(NCONT);
|
||||
}
|
||||
|
||||
void
|
||||
Trapinit(void)
|
||||
{
|
||||
notify(notifyf);
|
||||
}
|
||||
|
||||
void
|
||||
Unlink(char *name)
|
||||
{
|
||||
remove(name);
|
||||
}
|
||||
|
||||
long
|
||||
Write(int fd, void *buf, long cnt)
|
||||
{
|
||||
return write(fd, buf, (long)cnt);
|
||||
}
|
||||
|
||||
long
|
||||
Read(int fd, void *buf, long cnt)
|
||||
{
|
||||
return read(fd, buf, cnt);
|
||||
}
|
||||
|
||||
long
|
||||
Seek(int fd, long cnt, long whence)
|
||||
{
|
||||
return seek(fd, cnt, whence);
|
||||
}
|
||||
|
||||
int
|
||||
Executable(char *file)
|
||||
{
|
||||
Dir *statbuf;
|
||||
int ret;
|
||||
|
||||
statbuf = dirstat(file);
|
||||
if(statbuf == nil)
|
||||
return 0;
|
||||
ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
|
||||
free(statbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
Creat(char *file)
|
||||
{
|
||||
return create(file, 1, 0666L);
|
||||
}
|
||||
|
||||
int
|
||||
Dup(int a, int b)
|
||||
{
|
||||
return dup(a, b);
|
||||
}
|
||||
|
||||
int
|
||||
Dup1(int)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Exit(char *stat)
|
||||
{
|
||||
Updenv();
|
||||
setstatus(stat);
|
||||
exits(truestatus()?"":getstatus());
|
||||
}
|
||||
|
||||
int
|
||||
Eintr(void)
|
||||
{
|
||||
return interrupted;
|
||||
}
|
||||
|
||||
void
|
||||
Noerror(void)
|
||||
{
|
||||
interrupted = 0;
|
||||
}
|
||||
|
||||
int
|
||||
Isatty(int fd)
|
||||
{
|
||||
Dir *d1, *d2;
|
||||
int ret;
|
||||
|
||||
d1 = dirfstat(fd);
|
||||
if(d1 == nil)
|
||||
return 0;
|
||||
if(strncmp(d1->name, "ptty", 4)==0){ /* fwd complaints to philw */
|
||||
free(d1);
|
||||
return 1;
|
||||
}
|
||||
d2 = dirstat("/dev/cons");
|
||||
if(d2 == nil){
|
||||
free(d1);
|
||||
return 0;
|
||||
}
|
||||
ret = (d1->type==d2->type&&d1->dev==d2->dev&&d1->qid.path==d2->qid.path);
|
||||
free(d1);
|
||||
free(d2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
Abort(void)
|
||||
{
|
||||
pfmt(err, "aborting\n");
|
||||
flush(err);
|
||||
Exit("aborting");
|
||||
}
|
Loading…
Reference in a new issue