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

📄 libsys.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "common.h"#include <auth.h>#include <ndb.h>/* *  number of predefined fd's */int nsysfile=3;static char err[Errlen];/* *  return the date */extern char *thedate(void){	static char now[64];	char *cp;	strcpy(now, ctime(time(0)));	cp = strchr(now, '\n');	if(cp)		*cp = 0;	return now;}/* *  return the user id of the current user */extern char *getlog(void){	static char user[64];	int fd;	int n;	fd = open("/dev/user", 0);	if(fd < 0)		return nil;	if((n=read(fd, user, sizeof(user)-1)) <= 0)		return nil;	close(fd);	user[n] = 0;	return user;}/* *  return the lock name (we use one lock per directory) */static String *lockname(char *path){	String *lp;	char *cp;	/*	 *  get the name of the lock file	 */	lp = s_new();	cp = strrchr(path, '/');	if(cp)		s_nappend(lp, path, cp - path + 1);	s_append(lp, "L.mbox");	return lp;}intsyscreatelocked(char *path, int mode, int perm){	return create(path, mode, DMEXCL|perm);}intsysopenlocked(char *path, int mode){/*	return open(path, OEXCL|mode);/**/	return open(path, mode);		/* until system call is fixed */}intsysunlockfile(int fd){	return close(fd);}/* *  try opening a lock file.  If it doesn't exist try creating it. */static intopenlockfile(Mlock *l){	int fd;	Dir *d;	Dir nd;	char *p;	fd = open(s_to_c(l->name), OREAD);	if(fd >= 0){		l->fd = fd;		return 0;	}	d = dirstat(s_to_c(l->name));	if(d == nil){		/* file doesn't exist */		/* try creating it */		fd = create(s_to_c(l->name), OREAD, DMEXCL|0666);		if(fd >= 0){			nulldir(&nd);			nd.mode = DMEXCL|0666;			if(dirfwstat(fd, &nd) < 0){				/* if we can't chmod, don't bother */				/* live without the lock but log it */				syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));				remove(s_to_c(l->name));			}			l->fd = fd;			return 0;		}		/* couldn't create */		/* do we have write access to the directory? */		p = strrchr(s_to_c(l->name), '/');		if(p != 0){			*p = 0;			fd = access(s_to_c(l->name), 2);			*p = '/';			if(fd < 0){				/* live without the lock but log it */				syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));				return 0;			}		} else {			fd = access(".", 2);			if(fd < 0){				/* live without the lock but log it */				syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));				return 0;			}		}	} else		free(d);	return 1; /* try again later */}#define LSECS 5*60/* *  Set a lock for a particular file.  The lock is a file in the same directory *  and has L. prepended to the name of the last element of the file name. */extern Mlock *syslock(char *path){	Mlock *l;	int tries;	l = mallocz(sizeof(Mlock), 1);	if(l == 0)		return nil;	l->name = lockname(path);	/*	 *  wait LSECS seconds for it to unlock	 */	for(tries = 0; tries < LSECS*2; tries++){		switch(openlockfile(l)){		case 0:			return l;		case 1:			sleep(500);			break;		default:			goto noway;		}	}noway:	s_free(l->name);	free(l);	return nil;}/* *  like lock except don't wait */extern Mlock *trylock(char *path){	Mlock *l;	char buf[1];	int fd;	l = malloc(sizeof(Mlock));	if(l == 0)		return 0;	l->name = lockname(path);	if(openlockfile(l) != 0){		s_free(l->name);		free(l);		return 0;	}		/* fork process to keep lock alive */	switch(l->pid = rfork(RFPROC)){	default:		break;	case 0:		fd = l->fd;		for(;;){			sleep(1000*60);			if(pread(fd, buf, 1, 0) < 0)				break;		}		_exits(0);	}	return l;}extern voidsyslockrefresh(Mlock *l){	char buf[1];	pread(l->fd, buf, 1, 0);}extern voidsysunlock(Mlock *l){	if(l == 0)		return;	if(l->name){		s_free(l->name);	}	if(l->fd >= 0)		close(l->fd);	if(l->pid > 0)		postnote(PNPROC, l->pid, "time to die");	free(l);}/* *  Open a file.  The modes are: * *	l	- locked *	a	- set append permissions *	r	- readable *	w	- writable *	A	- append only (doesn't exist in Bio) */extern Biobuf *sysopen(char *path, char *mode, ulong perm){	int sysperm;	int sysmode;	int fd;	int docreate;	int append;	int truncate;	Dir *d, nd;	Biobuf *bp;	/*	 *  decode the request	 */	sysperm = 0;	sysmode = -1;	docreate = 0;	append = 0;	truncate = 0; 	for(; mode && *mode; mode++)		switch(*mode){		case 'A':			sysmode = OWRITE;			append = 1;			break;		case 'c':			docreate = 1;			break;		case 'l':			sysperm |= DMEXCL;			break;		case 'a':			sysperm |= DMAPPEND;			break;		case 'w':			if(sysmode == -1)				sysmode = OWRITE;			else				sysmode = ORDWR;			break;		case 'r':			if(sysmode == -1)				sysmode = OREAD;			else				sysmode = ORDWR;			break;		case 't':			truncate = 1;			break;		default:			break;		}	switch(sysmode){	case OREAD:	case OWRITE:	case ORDWR:		break;	default:		if(sysperm&DMAPPEND)			sysmode = OWRITE;		else			sysmode = OREAD;		break;	}	/*	 *  create file if we need to	 */	if(truncate)		sysmode |= OTRUNC;	fd = open(path, sysmode);	if(fd < 0){		d = dirstat(path);		if(d == nil){			if(docreate == 0)				return 0;			fd = create(path, sysmode, sysperm|perm);			if(fd < 0)				return 0;			nulldir(&nd);			nd.mode = sysperm|perm;			dirfwstat(fd, &nd);		} else {			free(d);			return 0;		}	}	bp = (Biobuf*)malloc(sizeof(Biobuf));	if(bp == 0){		close(fd);		return 0;	}	memset(bp, 0, sizeof(Biobuf));	Binit(bp, fd, sysmode&~OTRUNC);	if(append)		Bseek(bp, 0, 2);	return bp;}/* *  close the file, etc. */intsysclose(Biobuf *bp){	int rv;	rv = Bterm(bp);	close(Bfildes(bp));	free(bp);	return rv;}/* *  create a file */intsyscreate(char *file, int mode, ulong perm){	return create(file, mode, perm);}/* *  make a directory */intsysmkdir(char *file, ulong perm){	int fd;	if((fd = create(file, OREAD, DMDIR|perm)) < 0)		return -1;	close(fd);	return 0;}/* *  change the group of a file */intsyschgrp(char *file, char *group){	Dir nd;	if(group == 0)		return -1;	nulldir(&nd);	nd.gid = group;	return dirwstat(file, &nd);}extern intsysdirreadall(int fd, Dir **d){	return dirreadall(fd, d);}/* *  read in the system name */extern char *sysname_read(void){	static char name[128];	char *cp;	cp = getenv("site");	if(cp == 0 || *cp == 0)		cp = alt_sysname_read();	if(cp == 0 || *cp == 0)		cp = "kremvax";	strecpy(name, name+sizeof name, cp);	return name;}extern char *alt_sysname_read(void){	static char name[128];	int n, fd;	fd = open("/dev/sysname", OREAD);	if(fd < 0)		return 0;	n = read(fd, name, sizeof(name)-1);	close(fd);	if(n <= 0)		return 0;	name[n] = 0;	return name;}/* *  get all names */extern char**sysnames_read(void){	static char **namev;	Ndbtuple *t, *nt;	int n;	char *cp;	if(namev)		return namev;	free(csgetvalue(0, "sys", alt_sysname_read(), "dom", &t));	n = 0;	for(nt = t; nt; nt = nt->entry)		if(strcmp(nt->attr, "dom") == 0)			n++;	namev = (char**)malloc(sizeof(char *)*(n+3));	if(namev){		n = 0;		namev[n++] = strdup(sysname_read());		cp = alt_sysname_read();		if(cp)			namev[n++] = strdup(cp);		for(nt = t; nt; nt = nt->entry)			if(strcmp(nt->attr, "dom") == 0)				namev[n++] = strdup(nt->val);		namev[n] = 0;	}	if(t)		ndbfree(t);	return namev;}/* *  read in the domain name */extern char *domainname_read(void){	char **namev;	for(namev = sysnames_read(); *namev; namev++)		if(strchr(*namev, '.'))			return *namev;	return 0;}/* *  return true if the last error message meant file *  did not exist. */extern inte_nonexistent(void){	rerrstr(err, sizeof(err));	return strcmp(err, "file does not exist") == 0;}/* *  return true if the last error message meant file *  was locked. */extern inte_locked(void){	rerrstr(err, sizeof(err));	return strcmp(err, "open/create -- file is locked") == 0;}/* *  return the length of a file */extern longsysfilelen(Biobuf *fp){	Dir *d;	long rv;	d = dirfstat(Bfildes(fp));	if(d == nil)		return -1;	rv = d->length;	free(d);	return rv;}/* *  remove a file */extern intsysremove(char *path){	return remove(path);}/* *  rename a file, fails unless both are in the same directory */extern intsysrename(char *old, char *new){	Dir d;	char *obase;	char *nbase;	obase = strrchr(old, '/');	nbase = strrchr(new, '/');	if(obase){		if(nbase == 0)			return -1;		if(strncmp(old, new, obase-old) != 0)			return -1;		nbase++;	} else {		if(nbase)			return -1;		nbase = new;	}	nulldir(&d);	d.name = nbase;	return dirwstat(old, &d);}/* *  see if a file exists */extern intsysexist(char *file){	Dir	*d;	d = dirstat(file);	if(d == nil)		return 0;	free(d);	return 1;}/* *  return nonzero if file is a directory */extern intsysisdir(char *file){	Dir	*d;	int	rv;	d = dirstat(file);	if(d == nil)		return 0;	rv = d->mode & DMDIR;	free(d);	return rv;}/* * kill a process or process group */static intstomp(int pid, char *file){	char name[64];	int fd;	snprint(name, sizeof(name), "/proc/%d/%s", pid, file);	fd = open(name, 1);	if(fd < 0)		return -1;	if(write(fd, "die: yankee pig dog\n", sizeof("die: yankee pig dog\n") - 1) <= 0){		close(fd);		return -1;	}	close(fd);	return 0;	}/* *  kill a process */extern intsyskill(int pid){	return stomp(pid, "note");	}/* *  kill a process group */extern intsyskillpg(int pid){	return stomp(pid, "notepg");}extern intsysdetach(void){	if(rfork(RFENVG|RFNAMEG|RFNOTEG) < 0) {		werrstr("rfork failed");		return -1;	}	return 0;}/* *  catch a write on a closed pipe */static int *closedflag;static intcatchpipe(void *a, char *msg){	static char *foo = "sys: write on closed pipe";	USED(a);	if(strncmp(msg, foo, strlen(foo)) == 0){		if(closedflag)			*closedflag = 1;		return 1;	}	return 0;}voidpipesig(int *flagp){	closedflag = flagp;	atnotify(catchpipe, 1);}voidpipesigoff(void){	atnotify(catchpipe, 0);}voidexit(int i){	char buf[32];	if(i == 0)		exits(0);	snprint(buf, sizeof(buf), "%d", i);	exits(buf);}static intislikeatty(int fd){	char buf[64];	if(fd2path(fd, buf, sizeof buf) != 0)		return 0;	/* might be /mnt/term/dev/cons */	return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;}extern intholdon(void){	int fd;	if(!islikeatty(0))		return -1;	fd = open("/dev/consctl", OWRITE);	write(fd, "holdon", 6);	return fd;}extern intsysopentty(void){	return open("/dev/cons", ORDWR);}extern voidholdoff(int fd){	write(fd, "holdoff", 7);	close(fd);}extern intsysfiles(void){	return 128;}/* *  expand a path relative to the user's mailbox directory * *  if the path starts with / or ./, don't change it * */extern String *mboxpath(char *path, char *user, String *to, int dot){	if (dot || *path=='/' || strncmp(path, "./", 2) == 0			      || strncmp(path, "../", 3) == 0) {		to = s_append(to, path);	} else {		to = s_append(to, MAILROOT);		to = s_append(to, "/box/");		to = s_append(to, user);		to = s_append(to, "/");		to = s_append(to, path);	}	return to;}extern String *mboxname(char *user, String *to){	return mboxpath("mbox", user, to, 0);}extern String *deadletter(String *to)		/* pass in sender??? */{	char *cp;	cp = getlog();	if(cp == 0)		return 0;	return mboxpath("dead.letter", cp, to, 0);}char *homedir(char *user){	USED(user);	return getenv("home");}String *readlock(String *file){	char *cp;	cp = getlog();	if(cp == 0)		return 0;	return mboxpath("reading", cp, file, 0);}String *username(String *from){	int n;	Biobuf *bp;	char *p, *q;	String *s;	bp = Bopen("/adm/keys.who", OREAD);	if(bp == 0)		bp = Bopen("/adm/netkeys.who", OREAD);	if(bp == 0)		return 0;	s = 0;	n = strlen(s_to_c(from));	for(;;) {		p = Brdline(bp, '\n');		if(p == 0)			break;		p[Blinelen(bp)-1] = 0;		if(strncmp(p, s_to_c(from), n))			continue;		p += n;		if(*p != ' ' && *p != '\t')	/* must be full match */			continue;		while(*p && (*p == ' ' || *p == '\t'))				p++;		if(*p == 0)			continue;		for(q = p; *q; q++)			if(('0' <= *q && *q <= '9') || *q == '<')				break;		while(q > p && q[-1] != ' ' && q[-1] != '\t')			q--;		while(q > p && (q[-1] == ' ' || q[-1] == '\t'))			q--;		*q = 0;		s = s_new();		s_append(s, "\"");		s_append(s, p);		s_append(s, "\"");		break;	}	Bterm(bp);	return s;}char *remoteaddr(int fd, char *dir){	char buf[128], *p;	int n;	if(dir == 0){		if(fd2path(fd, buf, sizeof(buf)) != 0)			return "";		/* parse something of the form /net/tcp/nnnn/data */		p = strrchr(buf, '/');		if(p == 0)			return "";		strncpy(p+1, "remote", sizeof(buf)-(p-buf)-2);	} else		snprint(buf, sizeof buf, "%s/remote", dir);	buf[sizeof(buf)-1] = 0;	fd = open(buf, OREAD);	if(fd < 0)		return "";	n = read(fd, buf, sizeof(buf)-1);	close(fd);	if(n > 0){		buf[n] = 0;		p = strchr(buf, '!');		if(p)			*p = 0;		return strdup(buf);	}	return "";}//  create a file and //	1) ensure the modes we asked for//	2) make gid == uidstatic intdocreate(char *file, int perm){	int fd;	Dir ndir;	Dir *d;	//  create the mbox	fd = create(file, OREAD, perm);	if(fd < 0){		fprint(2, "couldn't create %s\n", file);		return -1;	}	d = dirfstat(fd);	if(d == nil){		fprint(2, "couldn't stat %s\n", file);		return -1;	}	nulldir(&ndir);	ndir.mode = perm;	ndir.gid = d->uid;	if(dirfwstat(fd, &ndir) < 0)		fprint(2, "couldn't chmod %s: %r\n", file);	close(fd);	return 0;}//  create a mailboxintcreatembox(char *user, char *folder){	char *p;	String *mailfile;	char buf[512];	Mlock *ml;	mailfile = s_new();	if(folder == 0)		mboxname(user, mailfile);	else {		snprint(buf, sizeof(buf), "%s/mbox", folder);		mboxpath(buf, user, mailfile, 0);	}	// don't destroy existing mailbox	if(access(s_to_c(mailfile), 0) == 0){		fprint(2, "mailbox already exists\n");		return -1;	}	fprint(2, "creating new mbox: %s\n", s_to_c(mailfile));	//  make sure preceding levels exist	for(p = s_to_c(mailfile); p; p++) {		if(*p == '/')	/* skip leading or consecutive slashes */			continue;		p = strchr(p, '/');		if(p == 0)			break;		*p = 0;		if(access(s_to_c(mailfile), 0) != 0){			if(docreate(s_to_c(mailfile), DMDIR|0711) < 0)				return -1;		}		*p = '/';	}	//  create the mbox	if(docreate(s_to_c(mailfile), 0622|DMAPPEND|DMEXCL) < 0)		return -1;	/*	 *  create the lock file if it doesn't exist	 */	ml = trylock(s_to_c(mailfile));	if(ml != nil)		sysunlock(ml);	return 0;}

⌨️ 快捷键说明

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