一、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 != ) {
err_quit("usage: mycat <pathname>");
}
if ( (fd = my_open(argv[], O_RDONLY)) < ) {
err_sys("cannot open %s", argv[]);
}
while ( (n = read(fd, buff, BUFFSIZE)) > ) {
write(STDOUT_FILENO, buff, n);
}
exit();
}
#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[], status;
pid_t childpid;
char c, argsockfd[], argmode[];
socketpair:
if (socketpair(AF_LOCAL, SOCK_STREAM, , sockfd) == -) {
if (errno == EINTR) {
goto socketpair;
} else {
err_quit("socketpair failed to create stream pipe");
}
}
if ( (childpid = fork()) == ) { /* child process */
close(sockfd[]);
snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[]);
snprintf(argmode, sizeof(argmode), "%d", mode);
execl("../openfile/openfile", "openfile", argsockfd,
pathname, argmode,(char *) NULL);
err_sys("execl error");
}
close(sockfd[]); /* close the end we don't use */
waitpid(childpid, &status, );
if (WIFEXITED(status) == ) {
err_quit("child did not terminate");
}
if ( (status = WEXITSTATUS(status)) == ) {
Read_fd(sockfd[], &c, , &fd);
} else {
errno = status; /* set errno value from child's status */
fd = -;
}
close(sockfd[]);
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[];
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 = ;
iov[].iov_base = ptr;
iov[].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = ;
if ( (n = recvmsg(fd, &msg, )) <= ) {
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 = -; /* 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)) < ) {
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(, 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(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
}
/* 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(, LOG_ERR, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(); /* 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(, 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(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
}
/* 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 + ];
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 != ) {
err_quit("openfile <sockfd> <filename> <mode>");
}
if ( (fd = open(argv[], atoi(argv[]))) < ) {
exit( (errno > ) ? errno : );
}
if (Write_fd(atoi(argv[]), "", , fd) < ) {
exit( (errno > ) ? errno : );
}
exit();
}
#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[];
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 = ;
iov[].iov_base = ptr;
iov[].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = ;
return (sendmsg(fd, &msg, ));
}
ssize_t Write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
ssize_t n;
if ( (n = write_fd(fd, ptr, nbytes, sendfd)) < ) {
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(, 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(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
}
/* 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(, LOG_ERR, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(); /* 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(, 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(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
}
/* 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 + ];
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;
}