⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sam.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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;	File *f;	String owd;	getcurwd();	if(getname((File *)0, str, FALSE))		s = genc;	else		s = home;	if(chdir(s))		syserror("chdir");	fd = open("/dev/wdir", OWRITE);	if(fd > 0)		write(fd, s, strlen(s));	dprint("!\n");	Strinit(&owd);	Strduplstr(&owd, &curwd);	getcurwd();	settempfile();	for(i=0; i<tempfile.nused; i++){		f = tempfile.filepptr[i];		if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){			Strinsert(&f->name, &owd, (Posn)0);			fixname(&f->name);			sortname(f);		}else if(f != cmd && Strispre(&curwd, &f->name)){			fixname(&f->name);			sortname(f);		}	}	Strclose(&owd);}intloadflist(String *s){	int c, i;	c = s->s[0];	for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++)		;	if((c==' ' || c=='\t') && s->s[i]!='\n'){		if(s->s[i]=='<'){			Strdelete(s, 0L, (long)i+1);			readcmd(s);		}else{			Strzero(&genstr);			while((c = s->s[i++]) && c!='\n')				Straddc(&genstr, c);			Straddc(&genstr, '\0');		}	}else{		if(c != '\n')			error(Eblank);		Strdupl(&genstr, empty);	}	if(genc)		free(genc);	genc = Strtoc(&genstr);	return genstr.s[0];}File *readflist(int readall, int delete){	Posn i;	int c;	File *f;	String t;	Strinit(&t);	for(i=0,f=0; f==0 || readall || delete; i++){	/* ++ skips blank */		Strdelete(&genstr, (Posn)0, i);		for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++)			;		if(i >= genstr.n)			break;		Strdelete(&genstr, (Posn)0, i);		for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++)			;		if(i == 0)			break;		genstr.s[i] = 0;		Strduplstr(&t, tmprstr(genstr.s, i+1));		fixname(&t);		f = lookfile(&t);		if(delete){			if(f == 0)				warn_S(Wfile, &t);			else				trytoclose(f);		}else if(f==0 && readall)			logsetname(f = newfile(), &t);	}	Strclose(&t);	return f;}File *tofile(String *s){	File *f;	if(s->s[0] != ' ')		error(Eblank);	if(loadflist(s) == 0){		f = lookfile(&genstr);	/* empty string ==> nameless file */		if(f == 0)			error_s(Emenu, genc);	}else if((f=readflist(FALSE, FALSE)) == 0)		error_s(Emenu, genc);	return current(f);}File *getfile(String *s){	File *f;	if(loadflist(s) == 0)		logsetname(f = newfile(), &genstr);	else if((f=readflist(TRUE, FALSE)) == 0)		error(Eblank);	return current(f);}voidclosefiles(File *f, String *s){	if(s->s[0] == 0){		if(f == 0)			error(Enofile);		trytoclose(f);		return;	}	if(s->s[0] != ' ')		error(Eblank);	if(loadflist(s) == 0)		error(Enewline);	readflist(FALSE, TRUE);}voidcopy(File *f, Address addr2){	Posn p;	int ni;	for(p=addr.r.p1; p<addr.r.p2; p+=ni){		ni = addr.r.p2-p;		if(ni > BLOCKSIZE)			ni = BLOCKSIZE;		bufread(f, p, genbuf, ni);		loginsert(addr2.f, addr2.r.p2, tmprstr(genbuf, ni)->s, ni);	}	addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1);	addr2.f->ndot.r.p1 = addr2.r.p2;}voidmove(File *f, Address addr2){	if(addr.r.p2 <= addr2.r.p2){		logdelete(f, addr.r.p1, addr.r.p2);		copy(f, addr2);	}else if(addr.r.p1 >= addr2.r.p2){		copy(f, addr2);		logdelete(f, addr.r.p1, addr.r.p2);	}else		error(Eoverlap);}Posnnlcount(File *f, Posn p0, Posn p1){	Posn nl = 0;	while(p0 < p1)		if(filereadc(f, p0++)=='\n')			nl++;	return nl;}voidprintposn(File *f, int charsonly){	Posn l1, l2;	if(!charsonly){		l1 = 1+nlcount(f, (Posn)0, addr.r.p1);		l2 = l1+nlcount(f, addr.r.p1, addr.r.p2);		/* check if addr ends with '\n' */		if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && filereadc(f, addr.r.p2-1)=='\n')			--l2;		dprint("%lud", l1);		if(l2 != l1)			dprint(",%lud", l2);		dprint("; ");	}	dprint("#%lud", addr.r.p1);	if(addr.r.p2 != addr.r.p1)		dprint(",#%lud", addr.r.p2);	dprint("\n");}voidsettempfile(void){	if(tempfile.nalloc < file.nused){		if(tempfile.filepptr)			free(tempfile.filepptr);		tempfile.filepptr = emalloc(sizeof(File*)*file.nused);		tempfile.nalloc = file.nused;	}	memmove(tempfile.filepptr, file.filepptr, sizeof(File*)*file.nused);	tempfile.nused = file.nused;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -