1. Configuration
Apue. H is a file written by the author. It contains common header files and is not provided by the system. This includes common header files and definitions of error handling functions. It is really convenient to use.
To use it, perform the following operations to complete the configuration.
Download the compressed src.tar.gzsource code package at http://www.apuebook.com.
1. decompress the package to the/home/user/directory.
2. Modify wkdir =/home/XXX/apue.2e in make. Defines. Linux to wkdir =/home/user/apue.2e.
3. Return to the directory apue.2e, modify Linux. mk, and change all nawk in to awk. You can use this command: % S/nawk/awk/g.
4. Make
5. Copy/home/user/apue.2e/include/apue. h and/home/user/apue.2e/lib/error. C to the/usr/include directory.
2. The apue. h and error. c files to be copied are as follows: (you can copy them directly to/usr/include)
Apue. H (added a line # include <error. c>)
/* Our own header, to be included before all standard system headers */#ifndef_APUE_H#define_APUE_H#if defined(SOLARIS)#define _XOPEN_SOURCE500/* Single UNIX Specification, Version 2 for Solaris 9 */#define CMSG_LEN(x)_CMSG_DATA_ALIGN(sizeof(struct cmsghdr)+(x))#elif !defined(BSD)#define _XOPEN_SOURCE600/* Single UNIX Specification, Version 3 */#endif#include <sys/types.h>/* some systems still require this */#include <sys/stat.h>#include <sys/termios.h>/* for winsize */#ifndef TIOCGWINSZ#include <sys/ioctl.h>#endif#include <stdio.h>/* for convenience */#include <stdlib.h>/* for convenience */#include <stddef.h>/* for offsetof */#include <string.h>/* for convenience */#include <unistd.h>/* for convenience */#include <signal.h>/* for SIG_ERR */#defineMAXLINE4096/* max line length *//* * Default file access permissions for new files. */#defineFILE_MODE(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)/* * Default permissions for new directories. */#defineDIR_MODE(FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)typedefvoidSigfunc(int);/* for signal handlers */#ifdefined(SIG_IGN) && !defined(SIG_ERR)#defineSIG_ERR((Sigfunc *)-1)#endif#definemin(a,b)((a) < (b) ? (a) : (b))#definemax(a,b)((a) > (b) ? (a) : (b))/* * Prototypes for our own functions. */char*path_alloc(int *);/* {Prog pathalloc} */long open_max(void);/* {Prog openmax} */void clr_fl(int, int);/* {Prog setfl} */void set_fl(int, int);/* {Prog setfl} */void pr_exit(int);/* {Prog prexit} */void pr_mask(const char *);/* {Prog prmask} */Sigfunc*signal_intr(int, Sigfunc *);/* {Prog signal_intr_function} */int tty_cbreak(int);/* {Prog raw} */int tty_raw(int);/* {Prog raw} */int tty_reset(int);/* {Prog raw} */void tty_atexit(void);/* {Prog raw} */#ifdefECHO/* only if <termios.h> has been included */struct termios*tty_termios(void);/* {Prog raw} */#endifvoid sleep_us(unsigned int);/* {Ex sleepus} */ssize_t readn(int, void *, size_t);/* {Prog readn_writen} */ssize_t writen(int, const void *, size_t);/* {Prog readn_writen} */void daemonize(const char *);/* {Prog daemoninit} */int s_pipe(int *);/* {Progs streams_spipe sock_spipe} */int recv_fd(int, ssize_t (*func)(int, const void *, size_t));/* {Progs recvfd_streams recvfd_sockets} */int send_fd(int, int);/* {Progs sendfd_streams sendfd_sockets} */int send_err(int, int, const char *);/* {Prog senderr} */int serv_listen(const char *);/* {Progs servlisten_streams servlisten_sockets} */int serv_accept(int, uid_t *);/* {Progs servaccept_streams servaccept_sockets} */int cli_conn(const char *);/* {Progs cliconn_streams cliconn_sockets} */int buf_args(char *, int (*func)(int, char **));/* {Prog bufargs} */int ptym_open(char *, int);/* {Progs3 ptyopen_streams ptyopen_bsd ptyopen_linux} */int ptys_open(char *);/* {Progs3 ptyopen_streams ptyopen_bsd ptyopen_linux} */#ifdefTIOCGWINSZpid_t pty_fork(int *, char *, int, const struct termios *, const struct winsize *);/* {Prog ptyfork} */#endifintlock_reg(int, int, int, off_t, int, off_t); /* {Prog lockreg} */#defineread_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))#definereadw_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))#definewrite_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))#definewritew_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))#defineun_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))pid_tlock_test(int, int, off_t, int, off_t);/* {Prog locktest} */#defineis_read_lockable(fd, offset, whence, len) \(lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)#defineis_write_lockable(fd, offset, whence, len) \(lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)voiderr_dump(const char *, ...);/* {App misc_source} */voiderr_msg(const char *, ...);voiderr_quit(const char *, ...);voiderr_exit(int, const char *, ...);voiderr_ret(const char *, ...);voiderr_sys(const char *, ...);voidlog_msg(const char *, ...);/* {App misc_source} */voidlog_open(const char *, int, int);voidlog_quit(const char *, ...);voidlog_ret(const char *, ...);voidlog_sys(const char *, ...);voidTELL_WAIT(void);/* parent/child from {Sec race_conditions} */voidTELL_PARENT(pid_t);voidTELL_CHILD(pid_t);voidWAIT_PARENT(void);voidWAIT_CHILD(void);#include "error.c" #endif/* _APUE_H */
Error. c
#include "apue.h"#include <errno.h>/* for definition of errno */#include <stdarg.h>/* ISO C variable aruments */static voiderr_doit(int, int, const char *, va_list);/* * Nonfatal error related to a system call. * Print a message and return. */voiderr_ret(const char *fmt, ...){va_listap;va_start(ap, fmt);err_doit(1, errno, fmt, ap);va_end(ap);}/* * Fatal error related to a system call. * Print a message and terminate. */voiderr_sys(const char *fmt, ...){va_listap;va_start(ap, fmt);err_doit(1, errno, fmt, ap);va_end(ap);exit(1);}/* * Fatal error unrelated to a system call. * Error code passed as explict parameter. * Print a message and terminate. */voiderr_exit(int error, const char *fmt, ...){va_listap;va_start(ap, fmt);err_doit(1, error, fmt, ap);va_end(ap);exit(1);}/* * Fatal error related to a system call. * Print a message, dump core, and terminate. */voiderr_dump(const char *fmt, ...){va_listap;va_start(ap, fmt);err_doit(1, errno, fmt, ap);va_end(ap);abort();/* dump core and terminate */exit(1);/* shouldn't get here */}/* * Nonfatal error unrelated to a system call. * Print a message and return. */voiderr_msg(const char *fmt, ...){va_listap;va_start(ap, fmt);err_doit(0, 0, fmt, ap);va_end(ap);}/* * Fatal error unrelated to a system call. * Print a message and terminate. */voiderr_quit(const char *fmt, ...){va_listap;va_start(ap, fmt);err_doit(0, 0, fmt, ap);va_end(ap);exit(1);}/* * Print a message and return to caller. * Caller specifies "errnoflag". */static voiderr_doit(int errnoflag, int error, const char *fmt, va_list ap){charbuf[MAXLINE];vsnprintf(buf, MAXLINE, fmt, ap);if (errnoflag)snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s", strerror(error));strcat(buf, "\n");fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(NULL);/* flushes all stdio output streams */}
3. Example:
#include <stdio.h>#include <dirent.h>int main(int argc, char *argv[]){ DIR *dp; struct dirent *dirp; if(argc!=2) { printf("Usage: ls directory_name\n"); return -1; } if((dp=opendir(argv[1]))==NULL) printf("can't open %s\n", argv[1]); while((dirp = readdir(dp))!=NULL) printf("%s\n", dirp->d_name); closedir(dp); return 0;}