716 lines · 11.7 KB · C
RawDownload
#include "sam.h" Rune	genbuf[BLOCKSIZE];int	io;int	panicking;int	rescuing;String	genstr;String	rhs;String	curwd;String	cmdstr;Rune	empty[] = { 0 };char	*genc;File	*curfile;File	*flist;File	*cmd;jmp_buf	mainloop;List	tempfile = { 'p' };int	quitok = TRUE;int	downloaded;int	dflag;int	Rflag;char	*machine;char	*home;int	bpipeok;int	termlocked;char	*samterm = SAMTERM;char	*rsamname = RSAM;File	*lastfile;Disk	*disk;long	seq; Rune	baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; void	usage(void); void main(int argc, char *argv[]){	int i;	String *t;	char *termargs[10], **ap;		ap = termargs;	*ap++ = "samterm";	ARGBEGIN{	case 'd':		dflag++;		break;	case 'r':		machine = EARGF(usage());		break;	case 'R':		Rflag++;		break;	case 't':		samterm = EARGF(usage());		break;	case 's':		rsamname = EARGF(usage());		break;	default:		dprint("sam: unknown flag %c\n", ARGC());		usage();	/* options for samterm */	case 'a':		*ap++ = "-a";		break;	}ARGEND	*ap = nil;		Strinit(&cmdstr);	Strinit0(&lastpat);	Strinit0(&lastregexp);	Strinit0(&genstr);	Strinit0(&rhs);	Strinit0(&curwd);	Strinit0(&plan9cmd);	home = getenv(HOME);	disk = diskinit();	if(home == 0)		home = "/";	if(!dflag)		startup(machine, Rflag, termargs, argv);	notify(notifyf);	getcurwd();	if(argc>0){		for(i=0; i<argc; i++){			if(!setjmp(mainloop)){				t = tmpcstr(argv[i]);				Straddc(t, '\0');				Strduplstr(&genstr, t);				freetmpstr(t);				fixname(&genstr);				logsetname(newfile(), &genstr);			}		}	}else if(!downloaded)		newfile();	seq++;	if(file.nused)		current(file.filepptr[0]);	setjmp(mainloop);	cmdloop();	trytoquit();	/* if we already q'ed, quitok will be TRUE */	exits(0);} voidusage(void){	dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n");	exits("usage");} voidrescue(void){	int i, nblank = 0;	File *f;	char *c;	char buf[256]; 	if(rescuing++)		return;	io = -1;	for(i=0; i<file.nused; i++){		f = file.filepptr[i];		if(f==cmd || f->nc==0 || !fileisdirty(f))			continue;		if(io == -1){			sprint(buf, "%s/sam.save", home);			io = create(buf, 1, 0777);			if(io<0)				return;		}		if(f->name.s[0]){			c = Strtoc(&f->name);			strncpy(buf, c, sizeof buf-1);			buf[sizeof buf-1] = 0;			free(c);		}else			sprint(buf, "nameless.%d", nblank++);		fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf);		addr.r.p1 = 0, addr.r.p2 = f->nc;		writeio(f);		fprint(io, "\n---%s\n", (char *)buf);	}} voidpanic(char *s){	int wasd; 	if(!panicking++ && !setjmp(mainloop)){		wasd = downloaded;		downloaded = 0;		dprint("sam: panic: %s: %r\n", s);		if(wasd)			fprint(2, "sam: panic: %s: %r\n", s);		rescue();		abort();	}} voidhiccough(char *s){	File *f;	int i; 	if(rescuing)		exits("rescue");	if(s)		dprint("%s\n", s);	resetcmd();	resetxec();	resetsys();	if(io > 0)		close(io); 	/*	 * back out any logged changes & restore old sequences	 */	for(i=0; i<file.nused; i++){		f = file.filepptr[i];		if(f==cmd)			continue;		if(f->seq==seq){			bufdelete(&f->epsilon, 0, f->epsilon.nc);			f->seq = f->prevseq;			f->dot.r = f->prevdot;			f->mark = f->prevmark;			state(f, f->prevmod ? Dirty: Clean);		}	} 	update();	if (curfile) {		if (curfile->unread)			curfile->unread = FALSE;		else if (downloaded)			outTs(Hcurrent, curfile->tag);	}	longjmp(mainloop, 1);} voidintr(void){	error(Eintr);} voidtrytoclose(File *f){	char *t;	char buf[256]; 	if(f == cmd)	/* possible? */		return;	if(f->deleted)		return;	if(fileisdirty(f) && !f->closeok){		f->closeok = TRUE;		if(f->name.s[0]){			t = Strtoc(&f->name);			strncpy(buf, t, sizeof buf-1);			free(t);		}else			strcpy(buf, "nameless file");		error_s(Emodified, buf);	}	f->deleted = TRUE;} voidtrytoquit(void){	int c;	File *f; 	if(!quitok){		for(c = 0; c<file.nused; c++){			f = file.filepptr[c];			if(f!=cmd && fileisdirty(f)){				quitok = TRUE;				eof = FALSE;				error(Echanges);			}		}	}} voidload(File *f){	Address saveaddr; 	Strduplstr(&genstr, &f->name);	filename(f);	if(f->name.s[0]){		saveaddr = addr;		edit(f, 'I');		addr = saveaddr;	}else{		f->unread = 0;		f->cleanseq = f->seq;	} 	fileupdate(f, TRUE, TRUE);} voidcmdupdate(void){	if(cmd && cmd->seq!=0){		fileupdate(cmd, FALSE, downloaded);		cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;		telldot(cmd);	}} voiddelete(File *f){	if(downloaded && f->rasp)		outTs(Hclose, f->tag);	delfile(f);	if(f == curfile)		current(0);} voidupdate(void){	int i, anymod;	File *f; 	settempfile();	for(anymod = i=0; i<tempfile.nused; i++){		f = tempfile.filepptr[i];		if(f==cmd)	/* cmd gets done in main() */			continue;		if(f->deleted) {			delete(f);			continue;		}		if(f->seq==seq && fileupdate(f, FALSE, downloaded))			anymod++;		if(f->rasp)			telldot(f);	}	if(anymod)		seq++;} File *current(File *f){	return curfile = f;} voidedit(File *f, int cmd){	int empty = TRUE;	Posn p;	int nulls; 	if(cmd == 'r')		logdelete(f, addr.r.p1, addr.r.p2);	if(cmd=='e' || cmd=='I'){		logdelete(f, (Posn)0, f->nc);		addr.r.p2 = f->nc;	}else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0))		empty = FALSE;	if((io = open(genc, OREAD))<0) {		if (curfile && curfile->unread)			curfile->unread = FALSE;		error_r(Eopen, genc);	}	p = readio(f, &nulls, empty, TRUE);	closeio((cmd=='e' || cmd=='I')? -1 : p);	if(cmd == 'r')		f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p;	else		f->ndot.r.p1 = f->ndot.r.p2 = 0;	f->closeok = empty;	if (quitok)		quitok = empty;	else		quitok = FALSE;	state(f, empty && !nulls? Clean : Dirty);	if(empty && !nulls)		f->cleanseq = f->seq;	if(cmd == 'e')		filename(f);} intgetname(File *f, String *s, int save){	int c, i; 	Strzero(&genstr);	if(genc){		free(genc);		genc = 0;	}	if(s==0 || (c = s->s[0])==0){		/* no name provided */		if(f)			Strduplstr(&genstr, &f->name);		goto Return;	}	if(c!=' ' && c!='\t')		error(Eblank);	for(i=0; (c=s->s[i])==' ' || c=='\t'; i++)		;	while(s->s[i] > ' ')		Straddc(&genstr, s->s[i++]);	if(s->s[i])		error(Enewline);	fixname(&genstr);	if(f && (save || f->name.s[0]==0)){		logsetname(f, &genstr);		if(Strcmp(&f->name, &genstr)){			quitok = f->closeok = FALSE;			f->qidpath = 0;			f->mtime = 0;			state(f, Dirty); /* if it's 'e', fix later */		}	}    Return:	genc = Strtoc(&genstr);	i = genstr.n;	if(i && genstr.s[i-1]==0)		i--;	return i;	/* strlen(name) */} voidfilename(File *f){	if(genc)		free(genc);	genc = Strtoc(&genstr);	dprint("%c%c%c %s\n", " '"[f->mod],		"-+"[f->rasp!=0], " ."[f==curfile], genc);} voidundostep(File *f, int isundo){	uint p1, p2;	int mod; 	mod = f->mod;	fileundo(f, isundo, 1, &p1, &p2, TRUE);	f->ndot = f->dot;	if(f->mod){		f->closeok = 0;		quitok = 0;	}else		f->closeok = 1; 	if(f->mod != mod){		f->mod = mod;		if(mod)			mod = Clean;		else			mod = Dirty;		state(f, mod);	}} intundo(int isundo){	File *f;	int i;	Mod max; 	max = undoseq(curfile, isundo);	if(max == 0)		return 0;	settempfile();	for(i = 0; i<tempfile.nused; i++){		f = tempfile.filepptr[i];		if(f!=cmd && undoseq(f, isundo)==max)			undostep(f, isundo);	}	return 1;} intreadcmd(String *s){	int retcode; 	if(flist != 0)		fileclose(flist);	flist = fileopen(); 	addr.r.p1 = 0, addr.r.p2 = flist->nc;	retcode = plan9(flist, '<', s, FALSE);	fileupdate(flist, FALSE, FALSE);	flist->seq = 0;	if (flist->nc > BLOCKSIZE)		error(Etoolong);	Strzero(&genstr);	Strinsure(&genstr, flist->nc);	bufread(flist, (Posn)0, genbuf, flist->nc);	memmove(genstr.s, genbuf, flist->nc*RUNESIZE);	genstr.n = flist->nc;	Straddc(&genstr, '\0');	return retcode;} voidgetcurwd(void){	String *t;	char buf[256]; 	buf[0] = 0;	getwd(buf, sizeof(buf));	t = tmpcstr(buf);	Strduplstr(&curwd, t);	freetmpstr(t);	if(curwd.n == 0)		warn(Wpwd);	else if(curwd.s[curwd.n-1] != '/')		Straddc(&curwd, '/');} voidcd(String *str){	int i, fd;	char *s;

Lines 1–500 of 716.