一、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;
}