一、mycat程序
#include <fcntl.h> #include <stdlib.h> #include <unistd.h> #define BUFFSIZE 4096 int my_open(const char *, int); void err_sys(const char *, ...); void err_quit(const char *, ...); int main(int argc, char **argv) { int fd, n; char buff[BUFFSIZE]; if (argc != 2) { err_quit("usage: mycat <pathname>"); } if ( (fd = my_open(argv[1], O_RDONLY)) < 0) { err_sys("cannot open %s", argv[1]); } while ( (n = read(fd, buff, BUFFSIZE)) > 0) { write(STDOUT_FILENO, buff, n); } exit(0); }
#include <errno.h> #include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <sys/socket.h> void err_sys(const char *, ...); void err_quit(const char *, ...); ssize_t Read_fd(int, void *, size_t, int *); int my_open(const char *pathname, int mode) { int fd, sockfd[2], status; pid_t childpid; char c, argsockfd[10], argmode[10]; socketpair: if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) == -1) { if (errno == EINTR) { goto socketpair; } else { err_quit("socketpair failed to create stream pipe"); } } if ( (childpid = fork()) == 0) { /* child process */ close(sockfd[0]); snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]); snprintf(argmode, sizeof(argmode), "%d", mode); execl("../openfile/openfile", "openfile", argsockfd, pathname, argmode,(char *) NULL); err_sys("execl error"); } close(sockfd[1]); /* close the end we don't use */ waitpid(childpid, &status, 0); if (WIFEXITED(status) == 0) { err_quit("child did not terminate"); } if ( (status = WEXITSTATUS(status)) == 0) { Read_fd(sockfd[0], &c, 1, &fd); } else { errno = status; /* set errno value from child's status */ fd = -1; } close(sockfd[0]); return (fd); }
#include <stddef.h> #include <sys/socket.h> void err_sys(const char *, ...); void err_quit(const char *, ...); ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd) { struct msghdr msg; struct iovec iov[1]; ssize_t n; union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; if ( (n = recvmsg(fd, &msg, 0)) <= 0) { return (n); } if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmptr->cmsg_level != SOL_SOCKET) { err_quit("control level != SOL_SOCKET"); } if (cmptr->cmsg_type != SCM_RIGHTS) { err_quit("control type != SCM_RIGHTS"); } *recvfd = *((int *) CMSG_DATA(cmptr)); } else { *recvfd = -1; /* descriptor was not passed */ } return(n); } ssize_t Read_fd(int fd, void *ptr, size_t nbytes, int *recvfd) { ssize_t n; if ( (n = read_fd(fd, ptr, nbytes, recvfd)) < 0) { err_sys("read_fd error"); } return (n); }
#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> /* ANSI C header file */ #include <syslog.h> /* for syslog() */ #define MAXLINE 4096 int daemon_proc; /* set nonzero by daemon_init() */ static void err_doit(int, int, const char *, va_list); /* Nonfatal error related to system call * Print message and return */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_INFO, fmt, ap); va_end(ap); return; } /* Fatal error related to system call * Print message and terminate */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Fatal error related to system call * Print message, dump core, and terminate */ void err_dump(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); abort(); /* dump core and terminate */ exit(1); /* shouldn't get here */ } /* Nonfatal error unrelated to system call * Print message and return */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_INFO, fmt, ap); va_end(ap); return; } /* Fatal error unrelated to system call * Print message and terminate */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Print message and return to caller * Caller specifies "errnoflag" and "level" */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n; char buf[MAXLINE + 1]; errno_save = errno; /* value caller might want printed */ #ifdef HAVE_VSNPRINTF vsnprintf(buf, MAXLINE, fmt, ap); /* safe */ #else vsprintf(buf, fmt, ap); /* not safe */ #endif n = strlen(buf); if (errnoflag) snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save)); strcat(buf, "\n"); if (daemon_proc) { syslog(level, buf); } else { fflush(stdout); /* in case stdout and stderr are the same */ fputs(buf, stderr); fflush(stderr); } return; }
二、openfile程序
#include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <sys/types.h> void err_quit(const char *, ...); ssize_t Write_fd(int, void *, size_t, int); int main(int argc, char **argv) { int fd; if (argc != 4) { err_quit("openfile <sockfd> <filename> <mode>"); } if ( (fd = open(argv[2], atoi(argv[3]))) < 0) { exit( (errno > 0) ? errno : 255 ); } if (Write_fd(atoi(argv[1]), "", 1, fd) < 0) { exit( (errno > 0) ? errno : 255 ); } exit(0); }
#include <stddef.h> #include <sys/socket.h> void err_sys(const char *, ...); ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd) { struct msghdr msg; struct iovec iov[1]; union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = sendfd; msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; return (sendmsg(fd, &msg, 0)); } ssize_t Write_fd(int fd, void *ptr, size_t nbytes, int sendfd) { ssize_t n; if ( (n = write_fd(fd, ptr, nbytes, sendfd)) < 0) { err_sys("write_fd error"); } return (n); }
#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> /* ANSI C header file */ #include <syslog.h> /* for syslog() */ #define MAXLINE 4096 int daemon_proc; /* set nonzero by daemon_init() */ static void err_doit(int, int, const char *, va_list); /* Nonfatal error related to system call * Print message and return */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_INFO, fmt, ap); va_end(ap); return; } /* Fatal error related to system call * Print message and terminate */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Fatal error related to system call * Print message, dump core, and terminate */ void err_dump(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); abort(); /* dump core and terminate */ exit(1); /* shouldn't get here */ } /* Nonfatal error unrelated to system call * Print message and return */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_INFO, fmt, ap); va_end(ap); return; } /* Fatal error unrelated to system call * Print message and terminate */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Print message and return to caller * Caller specifies "errnoflag" and "level" */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n; char buf[MAXLINE + 1]; errno_save = errno; /* value caller might want printed */ #ifdef HAVE_VSNPRINTF vsnprintf(buf, MAXLINE, fmt, ap); /* safe */ #else vsprintf(buf, fmt, ap); /* not safe */ #endif n = strlen(buf); if (errnoflag) snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save)); strcat(buf, "\n"); if (daemon_proc) { syslog(level, buf); } else { fflush(stdout); /* in case stdout and stderr are the same */ fputs(buf, stderr); fflush(stderr); } return; }