📄 appendix_b.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>C:\WINDOWS\Desktop\UnixProg\7.htm</title>
</head>
<body>
<font SIZE="2">
<h1 align="center">附录 B </h1>
<p>其它源代码 </p>
<p>B.1 我们的头文件 </p>
<p>在书正文中的大多数程序都包含头文件ourhdr.h,这示于程序B.1中。其中</p>
<p>定义了 </p>
<p>常数(例如MAXLINE)和我们自编函数的原型。 </p>
<p>因为大多数程序序包含下列头文件:<stdio.h>、<stdlib.h>(其中有exit</p>
<p>函数原 </p>
<p>型),以及<unistd.h>(其中包含所有标准Unix函数的原型),所以</p>
<p>ourhdr.h包含 </p>
<p>了这些系统头文件,同时还包含了<string.h>。这样就减少了本书正文中所</p>
<p>有程序 </p>
<p>的长度。 </p>
<p>/* Our own header, to be included *after* all standard</p>
<p>system headers * </p>
<p>/ </p>
<p>#ifndef __ourhdr_h </p>
<p>#define __ourhdr_h </p>
<p>#include <sys/types.h> /* required for some of our</p>
<p>prototypes */ </p>
<p>#include <stdio.h> /* for convenience */ </p>
<p>#include <stdlib.h> /* for convenience */ </p>
<p>#include <string.h> /* for convenience */ </p>
<p>#include <unistd.h> /* for convenience */ </p>
<p>#define MAXLINE 4096 /* max line length */ </p>
<p>#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) </p>
<p>/* default file access permissions for n </p>
<p>w files */ </p>
<p>#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH) </p>
<p>/* default permissions for new directori </p>
<p>s */ </p>
<p>typedef void Sigfunc(int); /* for signal handlers */ </p>
<p>/* 4.3BSD Reno <signal.h> doesn't define </p>
<p>SIG_ERR */ </p>
<p>#if defined(SIG_IGN) && !defined(SIG_ERR) </p>
<p>#define SIG_ERR ((Sigfunc *)-1) </p>
<p>#endif </p>
<p>#define min(a,b) ((a) < (b) ? (a) : (b)) </p>
<p>#define max(a,b) ((a) > (b) ? (a) : (b)) </p>
<p>/* prototypes for our own functions */ </p>
<p>char *path_alloc(int *); /* {Prog pathalloc} */ </p>
<p>int open_max(void); /* {Prog openmax} */ </p>
<p>void clr_fl(int, int); /* {Prog setfl} */ </p>
<p>void set_fl(int, int); /* {Prog setfl} */ </p>
<p>void pr_exit(int); /* {Prog prexit} */ </p>
<p>void pr_mask(const char *); /* {Prog prmask} */ </p>
<p>Sigfunc *signal_intr(int, Sigfunc *);/* {Prog</p>
<p>signal_intr_function} */ </p>
<p>int tty_cbreak(int); /* {Prog raw} */ </p>
<p>int tty_raw(int); /* {Prog raw} */ </p>
<p>int tty_reset(int); /* {Prog raw} */ </p>
<p>void tty_atexit(void); /* {Prog raw} */ </p>
<p>#ifdef ECHO /* only if <termios.h> has been included */ </p>
<p>struct termios *tty_termios(void); /* {Prog raw} */ </p>
<p>#endif </p>
<p>void sleep_us(unsigned int); /* {Ex sleepus} */ </p>
<p>ssize_t readn(int, void *, size_t);/* {Prog readn} */ </p>
<p>ssize_t writen(int, const void *, size_t);/* {Prog writen}</p>
<p>*/ </p>
<p>int daemon_init(void); /* {Prog daemoninit} */ </p>
<p>int s_pipe(int *); /* {Progs svr4_spipe bsd </p>
<p>spipe} */ </p>
<p>int recv_fd(int, ssize_t (*func)(int, const void *,</p>
<p>size_t)); </p>
<p>/* {Prog </p>
<p>recvfd_svr4 recvfd_43bsd} */ </p>
<p>int send_fd(int, int); /* {Progs sendfd_svr4 se </p>
<p>dfd_43bsd} */ </p>
<p>int send_err(int, int, const char *);/* {Prog senderr} */ </p>
<p>int serv_listen(const char *); /* {Progs servlisten_svr4</p>
<p>servli </p>
<p>ten_4 </p>
<p>4bsd} */ </p>
<p>int serv_accept(int, uid_t *); /* {Progs servaccept_svr4</p>
<p>servac </p>
<p>ept_4 </p>
<p>4bsd} */ </p>
<p>int cli_conn(const char *); /* {Progs cliconn_svr4 cliconn_4</p>
<p>bsd} */ </p>
<p>int buf_args(char *, int (*func)(int, char **)); </p>
<p>/* {Prog </p>
<p>bufargs} */ </p>
<p>int ptym_open(char *); /* {Progs ptyopen_svr4 p </p>
<p>yopen_44bsd} */ </p>
<p>int ptys_open(int, char *); /* {Progs ptyopen_svr4 ptyopen_4</p>
<p>bsd} */ </p>
<p>#ifdef TIOCGWINSZ </p>
<p>pid_t pty_fork(int *, char *, const struct termios *, </p>
<p>const struct winsize *); /* {Prog ptyfork </p>
<p>*/ </p>
<p>#endif </p>
<p>int lock_reg(int, int, int, off_t, int, off_t); </p>
<p>/* {Prog </p>
<p>lockreg} */ </p>
<p>#define read_lock(fd, offset, whence, len) \ </p>
<p>lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len) </p>
<p>#define readw_lock(fd, offset, whence, len) \ </p>
<p>lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len) </p>
<p>#define write_lock(fd, offset, whence, len) \ </p>
<p>lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len) </p>
<p>#define writew_lock(fd, offset, whence, len) \ </p>
<p>lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len) </p>
<p>#define un_lock(fd, offset, whence, len) \ </p>
<p>lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len) </p>
<p>pid_t lock_test(int, int, off_t, int, off_t); </p>
<p>/* {Prog </p>
<p>locktest} */ </p>
<p>#define is_readlock(fd, offset, whence, len) \ </p>
<p>lock_test(fd, F_RDLCK, offset, whence, len) </p>
<p>#define is_writelock(fd, offset, whence, len) \ </p>
<p>lock_test(fd, F_WRLCK, offset, whence, len) </p>
<p>void err_dump(const char *, ...); /* {App misc_source} */ </p>
<p>void err_msg(const char *, ...); </p>
<p>void err_quit(const char *, ...); </p>
<p>void err_ret(const char *, ...); </p>
<p>void err_sys(const char *, ...); </p>
<p>void log_msg(const char *, ...); /* {App misc_source} */ </p>
<p>void log_open(const char *, int, int); </p>
<p>void log_quit(const char *, ...); </p>
<p>void log_ret(const char *, ...); </p>
<p>void log_sys(const char *, ...); </p>
<p>void TELL_WAIT(void); /* parent/child from {Sec</p>
<p>race_condition </p>
<p>} */ </p>
<p>void TELL_PARENT(pid_t); </p>
<p>void TELL_CHILD(pid_t); </p>
<p>void WAIT_PARENT(void); </p>
<p>void WAIT_CHILD(void); </p>
<p>#endif /* __ourhdr_h */ </p>
<p>程序B.1 我们的头文件ourhdr.h </p>
<p>在程序中先包括一般系统头文件,然后再包括ourhdr.h,这样就能解决某些</p>
<p>系统 </p>
<p>之间的差别(例如4.3BSDReno中没有定义SIG_ERR),并且也可定义一些我</p>
<p>们的函 </p>
<p>数原型,而这些仅当包括一般系统头文件之后才是需要的。当尚未定义某个结</p>
<p>构就 </p>
<p>在原型中引用该结构时,某些ANSI C编译会认为不正常。 </p>
<p>B.2 标准出错处理例程 </p>
<p>我们提供了两套出错处理例程,它们用于本书中大多数实例以处理各种出错情</p>
<p>况 </p>
<p>。一套例程以err_开头,并向标准出错文件输出一条出错消息。另一套例程</p>
<p>以log </p>
<p>_开头,用于精灵进程(第十三章),它们多半没有控制终端。 </p>
<p>提供了这些出错处理函数后,只要在程序中写一行代码就可以进行出错处理,</p>
<p>例 </p>
<p>如: </p>
<p>if (出错条件) </p>
<p>err_dump(带任意参数的printf格式); </p>
<p>这样也就不再需要使用下列代码: </p>
<p>if (出错条件) { </p>
<p>char buff[200]; </p>
<p>sprintf(buff, 带任意参数的printf格式); </p>
<p>perror(buff); </p>
<p>abort( ); </p>
<p>} </p>
<p>我们的出错处理函数使用了ANSI C的变长参数表功能。其详细说明见</p>
<p>Kernighan和 </p>
<p>Ritchie[1998]的7.3接。应当注意的是这一ANSI C功能与较早系统(例如</p>
<p>SVR3和4 </p>
<p>..3BSD)提供的varargs功能不同。宏的名字相同,但更改了某些宏的参</p>
<p>数。 </p>
<p>图B.1列出了各个出错处理函数之间的区别。 </p>
<p>Function strerror(errno)? Teerminate? </p>
<p>Err_ret yes return; </p>
<p>Err_sys yes exit(0); </p>
<p>Err_dump yes abort(); </p>
<p>Err_msg no return; </p>
<p>Err_quit no exit(1); </p>
<p>Log_ret yes return; </p>
<p>Log_sys yes exit(2); </p>
<p>Log_msg no return; </p>
<p>if (出错条件) </p>
<p>err_dump(带任意参数的printf格式); </p>
<p>这样也就不再需要使用下列代码: </p>
<p>if (出错条件) { </p>
<p>char buff[200]; </p>
<p>sprintf(buff, 带任意参数的printf格式); </p>
<p>perror(buff); </p>
<p>abort( ); </p>
<p>} </p>
<p>我们的出错处理函数使用了ANSI C的变长参数表功能。其详细说明见</p>
<p>Kernighan和 </p>
<p>Ritchie[1998]的7.3接。应当注意的是这一ANSI C功能与较早系统(例如</p>
<p>SVR3和4 </p>
<p>..3BSD)提供的varargs功能不同。宏的名字相同,但更改了某些宏的参</p>
<p>数。 </p>
<p>图B.1列出了各个出错处理函数之间的区别。 </p>
<p>Function strerror(errno)? Teerminate? </p>
<p>Err_ret yes return; </p>
<p>Err_sys yes exit(0); </p>
<p>Err_dump yes abort(); </p>
<p>Err_msg no return; </p>
<p>Err_quit no exit(1); </p>
<p>Log_ret yes return; </p>
<p>Log_sys yes exit(2); </p>
<p>Log_msg no return; </p>
<p>Log_quit no exit(2); </p>
<p>图B.1 我们的标准出错处理函数 </p>
<p>程序B.2包括了输出至标准出错文件的各个出错处理函数。 </p>
<p>#include <errno.h> /* for definition of errno */ </p>
<p>#include <stdarg.h> /* ANSI C header file */ </p>
<p>#include "ourhdr.h" </p>
<p>static void err_doit(int, const char *, va_list); </p>
<p>char *pname = NULL; /* caller can set this from argv[0] */ </p>
<p>/* Nonfatal error related to a system call. </p>
<p>* Print a message and return. */ </p>
<p>void </p>
<p>err_ret(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>err_doit(1, fmt, ap); </p>
<p>va_end(ap); </p>
<p>return; </p>
<p>} </p>
<p>/* Fatal error related to a system call. </p>
<p>* Print a message and terminate. */ </p>
<p>void </p>
<p>err_sys(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>err_doit(1, fmt, ap); </p>
<p>va_end(ap); </p>
<p>exit(1); </p>
<p>} </p>
<p>/* Fatal error related to a system call. </p>
<p>* Print a message, dump core, and terminate. */ </p>
<p>void </p>
<p>err_dump(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>err_doit(1, fmt, ap); </p>
<p>va_end(ap); </p>
<p>abort(); /* dump core and terminate */ </p>
<p>exit(1); /* shouldn't get here */ </p>
<p>} </p>
<p>/* Nonfatal error unrelated to a system call. </p>
<p>* Caller specifies "errnoflag". */ </p>
<p>static void </p>
<p>err_doit(int errnoflag, const char *fmt, va_list ap) </p>
<p>{ </p>
<p>int errno_save; </p>
<p>char buf[MAXLINE]; </p>
<p>errno_save = errno; /* value caller might want printed */ </p>
<p>vsprintf(buf, fmt, ap); </p>
<p>if (errnoflag) </p>
<p>sprintf(buf+strlen(buf), ": %s", strerror(errno_save)); </p>
<p>strcat(buf, "\n"); </p>
<p>fflush(stdout); /* in case stdout and stderr are the same */</p>
<p>fputs(buf, stderr); </p>
<p>fflush(stderr); /* SunOS 4.1.* doesn't grok NULL argument */</p>
<p>return; </p>
<p>} </p>
<p>程序B.2 输出至标准出错文件的出错处理函数 </p>
<p>程序B.3包括了各log_xxx出错处理函数。若进程不以精灵进程方式进行,那</p>
<p>么调 </p>
<p>用者应当定义变量debug,并将其设置为非0值。在这种情况下,出错消息被</p>
<p>送至标 </p>
<p>准出错文件。若debug标志为0,则使用syslog功能(见13.4.2节)。 </p>
<p>/* Error routines for programs that can run as a daemon. */ </p>
<p>#include <errno.h> /* for definition of errno */ </p>
<p>#include <stdarg.h> /* ANSI C header file */ </p>
<p>#include <syslog.h> </p>
<p>#include "ourhdr.h" </p>
<p>static void log_doit(int, int, const char *, va_list ap); </p>
<p>extern int debug; /* caller must define and set this: </p>
<p>nonzero if interactive, zero if daemon */ </p>
<p>/* Initialize syslog(), if running as daemon. */ </p>
<p>void </p>
<p>log_open(const char *ident, int option, int facility) </p>
<p>{ </p>
<p>if (debug == 0) </p>
<p>openlog(ident, option, facility); </p>
<p>} </p>
<p>/* Nonfatal error related to a system call. </p>
<p>* Print a message with the system's errno value and return.</p>
<p>*/ </p>
<p>void </p>
<p>log_ret(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>log_doit(1, LOG_ERR, fmt, ap); </p>
<p>va_end(ap); </p>
<p>return; </p>
<p>} </p>
<p>/* Fatal error related to a system call. </p>
<p>* Print a message and terminate. */ </p>
<p>void </p>
<p>log_sys(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>log_doit(1, LOG_ERR, fmt, ap); </p>
<p>va_end(ap); </p>
<p>exit(2); </p>
<p>} </p>
<p>/* Nonfatal error unrelated to a system call. </p>
<p>* Print a message and return. */ </p>
<p>void </p>
<p>log_msg(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>log_doit(0, LOG_ERR, fmt, ap); </p>
<p>va_end(ap); </p>
<p>return; </p>
<p>} </p>
<p>/* Fatal error unrelated to a system call. </p>
<p>* Print a message and terminate. */ </p>
<p>void </p>
<p>log_quit(const char *fmt, ...) </p>
<p>{ </p>
<p>va_list ap; </p>
<p>va_start(ap, fmt); </p>
<p>log_doit(0, LOG_ERR, fmt, ap); </p>
<p>va_end(ap); </p>
<p>exit(2); </p>
<p>} </p>
<p>/* Print a message and return to caller. </p>
<p>* Caller specifies "errnoflag" and "priority". */ </p>
<p>static void </p>
<p>log_doit(int errnoflag, int priority, const char *fmt,</p>
<p>va_list ap) </p>
<p>{ </p>
<p>int errno_save; </p>
<p>char buf[MAXLINE]; </p>
<p>errno_save = errno; /* value caller might want printed */ </p>
<p>vsprintf(buf, fmt, ap); </p>
<p>if (errnoflag) </p>
<p>sprintf(buf+strlen(buf), ": %s", strerror(errno_save)); </p>
<p>strcat(buf, "\n"); </p>
<p>if (debug) { </p>
<p>fflush(stdout); </p>
<p>fputs(buf, stderr); </p>
<p>fflush(stderr); </p>
<p>} else </p>
<p>syslog(priority, buf); </p>
<p>return; </p>
<p>} </p>
<p>程序B.3 用于精灵进程的处理函数 </p>
<p>-</font></p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -