歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

附錄 B

其它源代碼 B.1我們的頭文件 在書正文中的大多數程序都包含頭文件ourhdr.h,這示於程序B.1中。其中定義了 常數(例如MAXLINE)和我們自編函數的原型。 因為大多數程序序包含下列頭文件:s td io.h、stdlib.h(其中有exit函數原 型),以及unistd.h(其中包含   

其它源代碼  
B.1 我們的頭文件  
        在書正文中的大多數程序都包含頭文件ourhdr.h,這示於程序B.1中。其中定義了  
常數(例如MAXLINE)和我們自編函數的原型。  
        因為大多數程序序包含下列頭文件:<stdio.h>、<stdlib.h>(其中有exit函數原  
型),以及<unistd.h>(其中包含所有標准Unix函數的原型),所以ourhdr.h包含  
了這些系統頭文件,同時還包含了<string.h>。這樣就減少了本書正文中所有程序  
的長度。  
/* Our own header, to be included *after* all standard system headers *  
/  
#ifndef __ourhdr_h  
#define __ourhdr_h  
#include        <sys/types.h>   /* required for some of our prototypes */  
#include        <stdio.h>               /* for convenience */  
#include        <stdlib.h>              /* for convenience */  
#include        <string.h>              /* for convenience */  
#include        <unistd.h>              /* for convenience */  
#define MAXLINE 4096                    /* max line length */  
#define FILE_MODE       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)  
                                        /* default file aclearcase/" target="_blank" >ccess permissions for n  
w files */  
#define DIR_MODE        (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)  
                                        /* default permissions for new directori  
s */  
typedef void    Sigfunc(int);   /* for signal handlers */  
                                        /* 4.3BSD Reno <signal.h> doesn't define  
SIG_ERR */  
#if     defined(SIG_IGN) && !defined(SIG_ERR)  
#define SIG_ERR ((Sigfunc *)-1)  
#endif  
#define min(a,b)        ((a) < (b) ? (a) : (b))  
#define max(a,b)        ((a) > (b) ? (a) : (b))  
                                        /* prototypes for our own functions */  
char    *path_alloc(int *);                     /*  */  
int              open_max(void);                        /*  */  
void     clr_fl(int, int);                      /*  */  
void     set_fl(int, int);                      /*  */  
void     pr_exit(int);                          /*  */  
void     pr_mask(const char *);         /*  */  
Sigfunc *signal_intr(int, Sigfunc *);/*  */  
int              tty_cbreak(int);                       /*  */  
int              tty_raw(int);                          /*  */  
int              tty_reset(int);                        /*  */  
void     tty_atexit(void);                      /*  */  
#ifdef  ECHO    /* only if <termios.h> has been included */  
struct termios  *tty_termios(void);     /*  */  
#endif  
void     sleep_us(unsigned int);        /*  */  
ssize_t  readn(int, void *, size_t);/*  */  
ssize_t  writen(int, const void *, size_t);/*  */  
int              daemon_init(void);                     /*  */  
int              s_pipe(int *);                         /* {Progs svr4_spipe bsd  
spipe} */  
int              recv_fd(int, ssize_t (*func)(int, const void *, size_t));  
                                                                        /* {Prog  
 recvfd_svr4 recvfd_43bsd} */  
int              send_fd(int, int);                     /* {Progs sendfd_svr4 se  
dfd_43bsd} */  
int              send_err(int, int, const char *);/*  */  
int              serv_listen(const char *);     /* {Progs servlisten_svr4 servli  
ten_4  
4bsd} */  
int              serv_accept(int, uid_t *);     /* {Progs servaccept_svr4 servac  
ept_4  
4bsd} */  
int              cli_conn(const char *);        /* {Progs cliconn_svr4 cliconn_4  
bsd} */  
int              buf_args(char *, int (*func)(int, char **));  
                                                                        /* {Prog  
bufargs} */  
int              ptym_open(char *);                     /* {Progs ptyopen_svr4 p  
yopen_44bsd} */  
int              ptys_open(int, char *);        /* {Progs ptyopen_svr4 ptyopen_4  
bsd} */  
#ifdef  TIOCGWINSZ  
pid_t    pty_fork(int *, char *, const struct termios *,  
                                  const struct winsize *);      /* {Prog ptyfork  
 */  
#endif  
int             lock_reg(int, int, int, off_t, int, off_t);  
                                                                        /* {Prog  
lockreg} */  
#define read_lock(fd, offset, whence, len) \  
                        lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)  
#define readw_lock(fd, offset, whence, len) \  
                        lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len)  
#define write_lock(fd, offset, whence, len) \  
                        lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)  
#define writew_lock(fd, offset, whence, len) \  
                        lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)  
#define un_lock(fd, offset, whence, len) \  
                        lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)  
pid_t   lock_test(int, int, off_t, int, off_t);  
                                                                        /* {Prog  
locktest} */  
#define is_readlock(fd, offset, whence, len) \  
                        lock_test(fd, F_RDLCK, offset, whence, len)  
#define is_writelock(fd, offset, whence, len) \  
                        lock_test(fd, F_WRLCK, offset, whence, len)  
void    err_dump(const char *, ...);    /*  */  
void    err_msg(const char *, ...);  
void    err_quit(const char *, ...);  
void    err_ret(const char *, ...);  
void    err_sys(const char *, ...);  
void    log_msg(const char *, ...);             /*  */  
void    log_open(const char *, int, int);  
void    log_quit(const char *, ...);  
void    log_ret(const char *, ...);  
void    log_sys(const char *, ...);  
void    TELL_WAIT(void);                /* parent/child from {Sec race_condition  
} */  
void    TELL_PARENT(pid_t);  
void    TELL_CHILD(pid_t);  
void    WAIT_PARENT(void);  
void    WAIT_CHILD(void);  
#endif  /* __ourhdr_h */  
程序B.1 我們的頭文件ourhdr.h  
        在程序中先包括一般系統頭文件,然後再包括ourhdr.h,這樣就能解決某些系統  
之間的差別(例如4.3BSDReno中沒有定義SIG_ERR),並且也可定義一些我們的函  
數原型,而這些僅當包括一般系統頭文件之後才是需要的。當尚未定義某個結構就  
在原型中引用該結構時,某些ANSI C編譯會認為不正常。  
B.2 標准出錯處理例程  
        我們提供了兩套出錯處理例程,它們用於本書中大多數實例以處理各種出錯情況  
。一套例程以err_開頭,並向標准出錯文件輸出一條出錯消息。另一套例程以log  
_開頭,用於精靈進程(第十三章),它們多半沒有控制終端。  
        提供了這些出錯處理函數後,只要在程序中寫一行代碼就可以進行出錯處理,例  
如:  
                if (出錯條件)  
                        err_dump(帶任意參數的printf格式);  
這樣也就不再需要使用下列代碼:  
                if (出錯條件) {  
                        char    buff[200];  
                        sprintf(buff, 帶任意參數的printf格式);  
                        perror(buff);  
                        abort( );  
                }  
        我們的出錯處理函數使用了ANSI C的變長參數表功能。其詳細說明見Kernighan和  
Ritchie[1998]的7.3接。應當注意的是這一ANSI C功能與較早系統(例如SVR3和4  
.3BSD)提供的varargs功能不同。宏的名字相同,但更改了某些宏的參數。  
        圖B.1列出了各個出錯處理函數之間的區別。  
Function        strerror(errno)?        Teerminate?  
Err_ret         yes                     return;  
Err_sys         yes                     exit(0);  
Err_dump        yes                     abort();  
Err_msg         no                      return;  
Err_quit        no                      exit(1);  
Log_ret         yes                     return;  
Log_sys         yes                     exit(2);  
Log_msg         no                      return;  
                if (出錯條件)  
                        err_dump(帶任意參數的printf格式);  
這樣也就不再需要使用下列代碼:  
                if (出錯條件) {  
                        char    buff[200];  
                        sprintf(buff, 帶任意參數的printf格式);  
                        perror(buff);  
                        abort( );  
                }  
        我們的出錯處理函數使用了ANSI C的變長參數表功能。其詳細說明見Kernighan和  
Ritchie[1998]的7.3接。應當注意的是這一ANSI C功能與較早系統(例如SVR3和4  
.3BSD)提供的varargs功能不同。宏的名字相同,但更改了某些宏的參數。  
        圖B.1列出了各個出錯處理函數之間的區別。  
Function        strerror(errno)?        Teerminate?  
Err_ret         yes                     return;  
Err_sys         yes                     exit(0);  
Err_dump        yes                     abort();  
Err_msg         no                      return;  
Err_quit        no                      exit(1);  
Log_ret         yes                     return;  
Log_sys         yes                     exit(2);  
Log_msg         no                      return;  
Log_quit        no                      exit(2);  
   
圖B.1  我們的標准出錯處理函數  
程序B.2包括了輸出至標准出錯文件的各個出錯處理函數。  
#include <errno.h>  /* for definition of errno */  
#include <stdarg.h>  /* ANSI C header file */  
#include "ourhdr.h"  
static void err_doit(int, const char *, va_list);  
char *pname = NULL;  /* caller can set this from argv[0] */  
/* Nonfatal error related to a system call.  
 * Print a message and return. */  
void  
err_ret(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 err_doit(1, fmt, ap);  
 va_end(ap);  
 return;  
}  
/* Fatal error related to a system call.  
 * Print a message and terminate. */  
void  
err_sys(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 err_doit(1, fmt, ap);  
 va_end(ap);  
 exit(1);  
}  
/* Fatal error related to a system call.  
 * Print a message, dump core, and terminate. */  
void  
err_dump(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 err_doit(1, fmt, ap);  
 va_end(ap);  
 abort();  /* dump core and terminate */  
 exit(1);  /* shouldn't get here */  
}  
/* Nonfatal error unrelated to a system call.  
 * Caller specifies "errnoflag". */  
static void  
err_doit(int errnoflag, const char *fmt, va_list ap)  
{  
 int  errno_save;  
 char buf[MAXLINE];  
 errno_save = errno;  /* value caller might want printed */  
 vsprintf(buf, fmt, ap);  
 if (errnoflag)  
  sprintf(buf+strlen(buf), ": %s", strerror(errno_save));  
 strcat(buf, "\n");  
 fflush(stdout);  /* in case stdout and stderr are the same */  
 fputs(buf, stderr);  
 fflush(stderr);  /* SunOS 4.1.* doesn't grok NULL argument */  
 return;  
}  
程序B.2  輸出至標准出錯文件的出錯處理函數  
 程序B.3包括了各log_xxx出錯處理函數。若進程不以精靈進程方式進行,那麼調  
用者應當定義變量debug,並將其設置為非0值。在這種情況下,出錯消息被送至標  
准出錯文件。若debug標志為0,則使用syslog功能(見13.4.2節)。  
/* Error routines for programs that can run as a daemon. */  
#include <errno.h>  /* for definition of errno */  
#include <stdarg.h>  /* ANSI C header file */  
#include <syslog.h>  
#include "ourhdr.h"  
static void log_doit(int, int, const char *, va_list ap);  
extern int debug;  /* caller must define and set this:  
         nonzero if interactive, zero if daemon */  
/* Initialize syslog(), if running as daemon. */  
void  
log_open(const char *ident, int option, int facility)  
{  
 if (debug == 0)  
  openlog(ident, option, facility);  
}  
/* Nonfatal error related to a system call.  
 * Print a message with the system's errno value and return. */  
void  
log_ret(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 log_doit(1, LOG_ERR, fmt, ap);  
 va_end(ap);  
 return;  
}  
/* Fatal error related to a system call.  
 * Print a message and terminate. */  
void  
log_sys(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 log_doit(1, LOG_ERR, fmt, ap);  
 va_end(ap);  
 exit(2);  
}  
/* Nonfatal error unrelated to a system call.  
 * Print a message and return. */  
void  
log_msg(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 log_doit(0, LOG_ERR, fmt, ap);  
 va_end(ap);  
 return;  
}  
/* Fatal error unrelated to a system call.  
 * Print a message and terminate. */  
void  
log_quit(const char *fmt, ...)  
{  
 va_list  ap;  
 va_start(ap, fmt);  
 log_doit(0, LOG_ERR, fmt, ap);  
 va_end(ap);  
 exit(2);  
}  
/* Print a message and return to caller.  
 * Caller specifies "errnoflag" and "priority". */  
static void  
log_doit(int errnoflag, int priority, const char *fmt, va_list ap)  
{  
 int  errno_save;  
 char buf[MAXLINE];  
 errno_save = errno;  /* value caller might want printed */  
 vsprintf(buf, fmt, ap);  
 
 if (errnoflag)  
  sprintf(buf+strlen(buf), ": %s", strerror(errno_save));  
 strcat(buf, "\n");  
 if (debug) {  
  fflush(stdout);  
  fputs(buf, stderr);  
  fflush(stderr);  
 } else  
  syslog(priority, buf);  
 return;  
}  
程序B.3  用於精靈進程的處理函數 

Copyright © Linux教程網 All Rights Reserved