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

📄 appendix_b.htm

📁 UNIX环境下C编程的详细详细介绍
💻 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>因为大多数程序序包含下列头文件:&lt;stdio.h&gt;、&lt;stdlib.h&gt;(其中有exit</p>

<p>函数原 </p>

<p>型),以及&lt;unistd.h&gt;(其中包含所有标准Unix函数的原型),所以</p>

<p>ourhdr.h包含 </p>

<p>了这些系统头文件,同时还包含了&lt;string.h&gt;。这样就减少了本书正文中所</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 &lt;sys/types.h&gt; /* required for some of our</p>

<p>prototypes */ </p>

<p>#include &lt;stdio.h&gt; /* for convenience */ </p>

<p>#include &lt;stdlib.h&gt; /* for convenience */ </p>

<p>#include &lt;string.h&gt; /* for convenience */ </p>

<p>#include &lt;unistd.h&gt; /* 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 &lt;signal.h&gt; doesn't define </p>

<p>SIG_ERR */ </p>

<p>#if defined(SIG_IGN) &amp;&amp; !defined(SIG_ERR) </p>

<p>#define SIG_ERR ((Sigfunc *)-1) </p>

<p>#endif </p>

<p>#define min(a,b) ((a) &lt; (b) ? (a) : (b)) </p>

<p>#define max(a,b) ((a) &gt; (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 &lt;termios.h&gt; 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 &lt;errno.h&gt; /* for definition of errno */ </p>

<p>#include &lt;stdarg.h&gt; /* ANSI C header file */ </p>

<p>#include &quot;ourhdr.h&quot; </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 &quot;errnoflag&quot;. */ </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), &quot;: %s&quot;, strerror(errno_save)); </p>

<p>strcat(buf, &quot;\n&quot;); </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 &lt;errno.h&gt; /* for definition of errno */ </p>

<p>#include &lt;stdarg.h&gt; /* ANSI C header file */ </p>

<p>#include &lt;syslog.h&gt; </p>

<p>#include &quot;ourhdr.h&quot; </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 &quot;errnoflag&quot; and &quot;priority&quot;. */ </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), &quot;: %s&quot;, strerror(errno_save)); </p>

<p>strcat(buf, &quot;\n&quot;); </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 + -