File:  [Plan 9 NeXT] / lucent / sys / src / cmd / rc / plan9.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:01:01 2018 UTC (8 years, 1 month ago) by root
Branches: lucent, MAIN
CVS tags: plan9, HEAD
Plan 9 NeXT

/*
 * 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);
void execmount(void);
void execnewpgrp(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,
	"rfork",	execnewpgrp,
	0
};
void execnewpgrp(void){
	int arg;
	char *s;
	switch(count(runq->argv->words)){
	case 1: arg=RFENVG|RFNAMEG|RFNOTEG; break;
	case 2:
		arg=0;
		for(s=runq->argv->words->next->word;*s;s++) switch(*s){
		default:
			goto Usage;
		case 'n': arg|=RFNAMEG;  break;
		case 'N': arg|=RFCNAMEG; break;
		case 'e': arg|=RFENVG;   break;
		case 'E': arg|=RFCENVG;  break;
		case 's': arg|=RFNOTEG;  break;
		case 'f': arg|=RFFDG;    break;
		case 'F': arg|=RFCFDG;   break;
		}
		break;
	default:
	Usage:
		pfmt(err, "Usage: %s [fnesFNE]\n", runq->argv->words->word);
		setstatus("rfork usage");
		poplist();
		return;
	}
	if(rfork(arg)==-1){
		pfmt(err, "rc: %s failed\n", runq->argv->words->word);
		setstatus("rfork failed");
	}
	else
		setstatus("");
	poplist();
}
void Vinit(void){
	int dir=open("#e", 0), f, len;
	word *val;
	char *buf, *s;
	Dir ent;
	char envname[NAMELEN+6];
	if(dir<0){
		pfmt(err, "rc: can't open #e\n");
		return;
	}
	while(dirread(dir, &ent, sizeof ent)==sizeof ent){
		len=ent.length;
		if(len && strncmp(ent.name, "fn#", 3)!=0){
			strcpy(envname, "#e/");
			strcat(envname, ent.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.name, val);
				vlook(ent.name)->changed=0;
				close(f);
				efree(buf);
			}
		}
	}
	close(dir);
}
#ifdef old_execfinit
void Xrdfn(void){}
void execfinit(void){
	Xpopm();
}
#else
int envdir;
void Xrdfn(void){
	int f, len;
	Dir ent;
	char envname[NAMELEN+6];
	while(dirread(envdir, &ent, sizeof ent)==sizeof ent){
		len=ent.length;
		if(len && strncmp(ent.name, "fn#", 3)==0){
			strcpy(envname, "#e/");
			strcat(envname, ent.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("#e", 0);
	if(envdir<0){
		pfmt(err, "rc: can't open #e\n");
		return;
	}
	start(rdfns, 1, runq->local);
}
#endif
int Waitfor(int pid, int persist){
	thread *p;
	Waitmsg w;
	int cpid;
	char errbuf[ERRLEN];
	while((cpid=wait(&w))>=0){
		if(pid==cpid){
			setstatus(w.msg);
			return 0;
		}
		for(p=runq->ret;p;p=p->ret)
			if(p->pid==cpid){
				p->pid=-1;
				strcpy(p->status, w.msg);
			}
	}
	errstr(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[NAMELEN+9];
	word *w;
	int f;
	io *fd;
	if(v->changed){
		v->changed=0;
		strcpy(envname, "#e/");
		strcat(envname, v->name);
		if((f=Creat(envname))<0)
			pfmt(err, "rc: can't open %s\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;
		strcpy(envname, "#e/fn#");
		strcat(envname, v->name);
		if((f=Creat(envname))<0)
			pfmt(err, "rc: can't open %s\n", envname);
		else{
			if(v->fn){
				fd=openfd(f);
				pfmt(fd, "fn %s %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);
}
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");
		}
	}
	errstr(file);
	pfmt(err, "%s: %s\n", argv[1], file);
	efree((char *)argv);
}
int Globsize(char *p)
{
	ulong isglob=0, globlen=NAMELEN+1;
	for(;*p;p++){
		if(*p==GLOB){
			p++;
			if(*p!=GLOB) isglob++;
			globlen+=*p=='*'?NAMELEN:1;
		}
		else
			globlen++;
	}
	return isglob?globlen:0;
}
#define NFD	50
#define	NDBUF	32
struct{
	char	*buf;
	int	n;
}dir[NFD];
int Opendir(char *name)
{
	Dir db;
	int f;
	f=open(name, 0);
	if(f==-1)
		return f;
	if(dirfstat(f, &db)!=-1 && (db.mode&0x80000000)){
		if(f<NFD && dir[f].buf){
			free(dir[f].buf);
			dir[f].buf=0;
		}
		return f;
	}
	close(f);
	return -1;
}
int Readdir(int f, char *p)
{
	char dirent[DIRLEN];
	int n;
	if(f<0 || f>=NFD){
   slow:
		while(read(f, dirent, sizeof dirent)==sizeof dirent){
			strcpy(p, dirent);
			return 1;
		}
		return 0;
	}
	if(dir[f].buf==0){	/* allocate */
		dir[f].buf=malloc(NDBUF*DIRLEN);
		if(dir[f].buf==0)
			goto slow;
		dir[f].n=0;
	}
	if(dir[f].n==0){	/* read */
		memset(dir[f].buf, 0, NDBUF*DIRLEN);
		n = read(f, dir[f].buf, NDBUF*DIRLEN);
		if(n>0 && n<NDBUF*DIRLEN){
			memmove(dir[f].buf+NDBUF*DIRLEN-n, dir[f].buf, n);
			dir[f].n=NDBUF-n/DIRLEN;
		}else
			dir[f].n=0;
	}
	if(dir[f].buf[dir[f].n*DIRLEN]==0)
		return 0;
	strcpy(p, &dir[f].buf[dir[f].n*DIRLEN]);
	dir[f].n++;
	if(dir[f].n==NDBUF)
		dir[f].n=0;
	return 1;
}
void Closedir(int f){
	if(f>=0 && f<NFD && dir[f].buf){
		free(dir[f].buf);
		dir[f].buf=0;
	}
	close(f);
}
int interrupted = 0;
void
notifyf(void *a, 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, char *buf, long cnt)
{
	return write(fd, buf, (long)cnt);
}
long Read(int fd, char *buf, long cnt)
{
	int n;

	return read(fd, buf, cnt);
}
long Seek(int fd, long cnt, int whence)
{
	return seek(fd, cnt, whence);
}
int Executable(char *file)
{
	Dir statbuf;

	return dirstat(file, &statbuf)!=-1 && (statbuf.mode&0111)!=0 && (statbuf.mode&CHDIR)==0;
}
int Creat(char *file)
{
	return create(file, 1, 0666L);
}
int Dup(int a, int b){
	return dup(a, b);
}
int Dup1(int a){
	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;

	if(dirfstat(0, &d1)==-1) return 0;
	if(strncmp(d1.name, "ptty", 4)==0) return 1;	/* fwd complaints to philw */
	if(dirstat("/dev/cons", &d2)==-1) return 0;
	return d1.type==d2.type&&d1.dev==d2.dev&&d1.qid.path==d2.qid.path;
}
void Abort(void){
	pfmt(err, "aborting\n");
	flush(err);
	Exit("aborting");
}
void Memcpy(char *a, char *b, long n)
{
	memmove(a, b, (long)n);
}
void *Malloc(ulong n){
	return malloc(n);
}
char *Geterrstr(void){
	static char error[ERRLEN];
	error[0]='\0';
	errstr(error);
	return error;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.