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

📄 library.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
/* @(#)library.c	4.1 Ultrix 7/3/90 *//************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ *									* *			Modification History				* *									* *	001 - Merged in 4.3 changes.					* *	      (Victoria Holt, April 29, 1986)				* *									* *      002 - Added an xdb "magic cookie" to error messages if dbx has  * *            been called with the -x flag.				* *            (David Metsky, March 8, 1988)				* *									* ************************************************************************//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic char sccsid[] = "@(#)library.c	5.1 (Berkeley) 5/31/85";#endif not lintstatic char rcsid[] = "$Header: library.c,v 1.5 84/12/26 10:39:52 linton Exp $";/* * General purpose routines. */#include <stdio.h>#include <errno.h>#include <signal.h>#define public#define private static#define and &&#define or ||#define not !#define ord(enumcon)	((int) enumcon)#define nil(type)	((type) 0)#define XDBMARK "xdb"typedef int integer;typedef enum { FALSE, TRUE } boolean;typedef char *String;typedef FILE *File;typedef String Filename;#undef FILEboolean xdb = FALSE;		/* xdb specific features */String cmdname;			/* name of command for error messages */Filename errfilename;		/* current file associated with error */short errlineno;		/* line number associated with error *//* * Definitions for doing memory allocation. */extern char *malloc();#define alloc(n, type)	((type *) malloc((unsigned) (n) * sizeof(type)))#define dispose(p)	{ free((char *) p); p = 0; }/* * Macros for doing freads + fwrites. */#define get(fp, var)	fread((char *) &(var), sizeof(var), 1, fp)#define put(fp, var)	fwrite((char *) &(var), sizeof(var), 1, fp)/* * String definitions. */extern String strcpy(), index(), rindex();extern int strlen();#define strdup(s)		strcpy(malloc((unsigned) strlen(s) + 1), s)#define streq(s1, s2)	(strcmp(s1, s2) == 0)typedef int INTFUNC();typedef struct {    INTFUNC *func;} ERRINFO;#define ERR_IGNORE ((INTFUNC *) 0)#define ERR_CATCH  ((INTFUNC *) 1)/* * Call a program. * * Four entries: * *	call, callv - call a program and wait for it, returning status *	back, backv - call a program and don't wait, returning process id * * The command's standard input and output are passed as FILE's. */#define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */#define BADEXEC 127	/* exec fails */#define ischild(pid)    ((pid) == 0)/* VARARGS3 */public int call(name, in, out, args)String name;File in;File out;String args;{    String *ap, *argp;    String argv[MAXNARGS];    argp = &argv[0];    *argp++ = name;    ap = &args;    while (*ap != nil(String)) {	*argp++ = *ap++;    }    *argp = nil(String);    return callv(name, in, out, argv);}/* VARARGS3 */public int back(name, in, out, args)String name;File in;File out;String args;{    String *ap, *argp;    String argv[MAXNARGS];    argp = &argv[0];    *argp++ = name;    ap = &args;    while (*ap != nil(String)) {	*argp++ = *ap++;    }    *argp = nil(String);    return backv(name, in, out, argv);}public int callv(name, in, out, argv)String name;File in;File out;String *argv;{    int pid, status;    pid = backv(name, in, out, argv);    pwait(pid, &status);    return status;}public int backv(name, in, out, argv)String name;File in;File out;String *argv;{    int pid;    fflush(stdout);    if (ischild(pid = fork())) {	fswap(0, fileno(in));	fswap(1, fileno(out));	onsyserr(EACCES, ERR_IGNORE);	execvp(name, argv);	_exit(BADEXEC);    }    return pid;}/* * Swap file numbers so as to redirect standard input and output. */private fswap(oldfd, newfd)int oldfd;int newfd;{    if (oldfd != newfd) {	close(oldfd);	dup(newfd);	close(newfd);    }}/* * Invoke a shell on a command line. */#define DEF_SHELL	"csh"public shell(s)String s;{    extern String getenv();    String sh;    if ((sh = getenv("SHELL")) == nil(String)) {	sh = DEF_SHELL;    }    if (s != nil(String) and *s != '\0') {	call(sh, stdin, stdout, "-c", s, 0);    } else {	call(sh, stdin, stdout, 0);    }}/* * Wait for a process the right way.  We wait for a particular * process and if any others come along in between, we remember them * in case they are eventually waited for. * * This routine is not very efficient when the number of processes * to be remembered is large. * * To deal with a kernel idiosyncrasy, we keep a list on the side * of "traced" processes, and do not notice them when waiting for * another process. */typedef struct pidlist {    int pid;    int status;    struct pidlist *next;} Pidlist;private Pidlist *pidlist, *ptrclist, *pfind();public ptraced(pid)int pid;{    Pidlist *p;    p = alloc(1, Pidlist);    p->pid = pid;    p->next = ptrclist;    ptrclist = p;}public unptraced(pid)int pid;{    register Pidlist *p, *prev;    prev = nil(Pidlist *);    p = ptrclist;    while (p != nil(Pidlist *) and p->pid != pid) {	prev = p;	p = p->next;    }    if (p != nil(Pidlist *)) {	if (prev == nil(Pidlist *)) {	    ptrclist = p->next;	} else {	    prev->next = p->next;	}	dispose(p);    }}private boolean isptraced(pid)int pid;{    register Pidlist *p;    p = ptrclist;    while (p != nil(Pidlist *) and p->pid != pid) {	p = p->next;    }    return (boolean) (p != nil(Pidlist *));}public pwait(pid, statusp)int pid, *statusp;{    Pidlist *p;    int pnum, status;    p = pfind(pid);    if (p != nil(Pidlist *)) {	*statusp = p->status;	dispose(p);    } else {	pnum = wait(&status);	while (pnum != pid and pnum >= 0) {	    if (not isptraced(pnum)) {		p = alloc(1, Pidlist);		p->pid = pnum;		p->status = status;		p->next = pidlist;		pidlist = p;	    }	    pnum = wait(&status);	}	if (pnum < 0) {	    p = pfind(pid);	    if (p == nil(Pidlist *)) {		panic("pwait: pid %d not found", pid);	    }	    *statusp = p->status;	    dispose(p);	} else {	    *statusp = status;	}    }}/* * Look for the given process id on the pidlist. * * Unlink it from list if found. */private Pidlist *pfind(pid)int pid;{    register Pidlist *p, *prev;    prev = nil(Pidlist *);    for (p = pidlist; p != nil(Pidlist *); p = p->next) {	if (p->pid == pid) {	    break;	}	prev = p;    }    if (p != nil(Pidlist *)) {	if (prev == nil(Pidlist *)) {	    pidlist = p->next;	} else {	    prev->next = p->next;	}    }    return p;}/* * System call error handler. * * The syserr routine is called when a system call is about to * set the c-bit to report an error.  Certain errors are caught * and cause the process to print a message and immediately exit. */extern int sys_nerr;extern char *sys_errlist[]; /* * Before calling syserr, the integer errno is set to contain the * number of the error.  The routine "_mycerror" is a dummy which * is used to force the loader to get my version of cerror rather * than the usual one. */extern int errno;extern _mycerror();/* * Initialize error information, setting defaults for handling errors. */private ERRINFO *errinfo;private initErrInfo (){    integer i;    errinfo = alloc(sys_nerr, ERRINFO);    for (i = 0; i < sys_nerr; i++) {	errinfo[i].func = ERR_CATCH;    }    errinfo[0].func = ERR_IGNORE;    errinfo[EPERM].func = ERR_IGNORE;    errinfo[ENOENT].func = ERR_IGNORE;    errinfo[ESRCH].func = ERR_IGNORE;    errinfo[EBADF].func = ERR_IGNORE;    errinfo[ENOTTY].func = ERR_IGNORE;    errinfo[EOPNOTSUPP].func = ERR_IGNORE;}public syserr(){    ERRINFO *e;    if (errno < 0 or errno > sys_nerr) {	fatal("errno %d", errno);    } else {	if (errinfo == nil(ERRINFO *)) {	    initErrInfo();	}	e = &(errinfo[errno]);	if (e->func == ERR_CATCH) {	    fatal(sys_errlist[errno]);	} else if (e->func != ERR_IGNORE) {	    (*e->func)();	}    }}/* * Catcherrs' purpose is to initialize the errinfo table, get this module * loaded, and make sure my cerror is loaded (only applicable when this is * in a library). */public catcherrs(){    _mycerror();    initErrInfo();}/* * Turn off the error catching mechanism completely by having all errors * ignored.  This is most useful between a fork and an exec. */public nocatcherrs(){    integer i;    for (i = 0; i < sys_nerr; i++) {	errinfo[i].func = ERR_IGNORE;    }}/* * Change the action on receipt of an error. */public onsyserr(n, f)int n;INTFUNC *f;{    if (errinfo == nil(ERRINFO *)) {	initErrInfo();    }    errinfo[n].func = f;}/* * Print the message associated with the given signal. * Like a "perror" for signals. */public int sys_nsig = NSIG;public psignal(s, n)String s;integer n;{    String msg;    integer len;    extern String sys_siglist[];    if (n >= 0 and n < sys_nsig) {	msg = sys_siglist[n];    } else {	msg = "Unknown signal";    }    len = strlen(s);    if (len > 0) {	write(2, s, len);	write(2, ": ", 2);    }    write(2, msg, strlen(msg));    write(2, "\n", 1);}/* * Standard error handling routines. */private short nerrs;private short nwarnings;/* * Main driver of error message reporting. *//* VARARGS2 */private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)String errname;boolean shouldquit;String s;{    if (xdb) {     /* 002 - DNM */	fprintf(stderr, XDBMARK);    }    fflush(stdout);    if (shouldquit and cmdname != nil(String)) {	fprintf(stderr, "%s: ", cmdname);    }    if (errfilename != nil(Filename)) {	fprintf(stderr, "%s: ", errfilename);    }    if (errlineno > 0) {	fprintf(stderr, "%d: ", errlineno);    }    if (errname != nil(String)) {	fprintf(stderr, "%s: ", errname);    }    fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);    putc('\n', stderr);    if (shouldquit) {	quit(1);    }}/* * For when printf isn't sufficient for printing the error message ... */public beginerrmsg(){    fflush(stdout);    if (errfilename != nil(String)) {	fprintf(stderr, "%s: ", errfilename);    }    if (errlineno > 0) {	fprintf(stderr, "%d: ", errlineno);    }}public enderrmsg(){    putc('\n', stderr);    erecover();}/* * The messages are listed in increasing order of seriousness. * * First are warnings. *//* VARARGS1 */public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)String s;{    nwarnings++;    errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);}/* * Errors are a little worse, they mean something is wrong, * but not so bad that processing can't continue. * * The routine "erecover" is called to recover from the error, * a default routine is provided that does nothing. *//* VARARGS1 */public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)String s;{    extern erecover();    nerrs++;    errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);    erecover();}/* * Non-recoverable user error. *//* VARARGS1 */public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)String s;{    errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);}/* * Panics indicate an internal program error. *//* VARARGS1 */public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)String s;{    errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);}short numerrors(){    short r;    r = nerrs;    nerrs = 0;    return r;}short numwarnings(){    short r;    r = nwarnings;    nwarnings = 0;    return r;}/* * Recover from an error. * * This is the default routine which we aren't using since we have our own. *public erecover(){} * *//* * Default way to quit from a program is just to exit. *public quit(r)int r;{    exit(r);} * *//* * Compare n-byte areas pointed to by s1 and s2 * if n is 0 then compare up until one has a null byte. */public int cmp(s1, s2, n)register char *s1, *s2;register unsigned int n;{    if (s1 == nil(char *) || s2 == nil(char *)) {	panic("cmp: nil pointer");    }    if (n == 0) {	while (*s1 == *s2++) {	    if (*s1++ == '\0') {		return(0);	    }	}	return(*s1 - *(s2-1));    } else {	for (; n != 0; n--) {	    if (*s1++ != *s2++) {		return(*(s1-1) - *(s2-1));	    }	}	return(0);    }}/* * Move n bytes from src to dest. * If n is 0 move until a null is found. */public mov(src, dest, n)register char *src, *dest;register unsigned int n;{    if (src == nil(char *))	panic("mov: nil source");    if (dest == nil(char *))	panic("mov: nil destination");    if (n != 0) {	for (; n != 0; n--) {	    *dest++ = *src++;	}    } else {	while ((*dest++ = *src++) != '\0');    }}

⌨️ 快捷键说明

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