《UNIX 环境高级编程》第一个例子

UNIX 环境高级编程第一个例子

我的博客
本文是对《UNIX 环境高级编程》这本书的第一章第一个例子进行的实现,本文给出了 myls.c 源码,Makefile 源码,以及后续所有章节都会用到的附录中的头文件以及头文件函数实现源码。
我的目录结构是这样的:

# myls.c 源码放在如下目录下
arv@arv-OptiPlex-7090:~/advanced_UNIX_PRO/src/1_test$ ls
Makefile  myls.c
# 头文件与错误、日志记录源码放在如下目录下
arv@arv-OptiPlex-7090:~/advanced_UNIX_PRO/inc$ ls
apue.h  error_a.c  error_b.c

对本文例子,在 Makefile 同级目录下执行:

arv@arv-OptiPlex-7090:~/advanced_UNIX_PRO/src/1_test$ make
gcc -Wall   -c -o error_a.o /home/arv/advanced_UNIX_PRO/inc/error_a.c
gcc -Wall   -c -o error_b.o /home/arv/advanced_UNIX_PRO/inc/error_b.c
gcc -Wall   -c -o myls.o myls.c
gcc -o myls *.o -lm

运行结果:

arv@arv-OptiPlex-7090:~/advanced_UNIX_PRO/src/1_test$ ./myls ./
error_b.o
myls
Makefile
myls.c
.
..
myls.o
error_a.o

myls.c 源码

#include "../../inc/apue.h"
#include <dirent.h>

int main(int argc, char *argv[])
{
        DIR     *dp;
        struct dirent *dirp;

        if(argc != 2)
                err_quit("usage: lsdirectory_name");

        if((dp = opendir(argv[1])) == NULL)
        {
                err_sys("can't open %s", argv[1]);
        }
        while((dirp = readdir(dp)) != NULL)
                printf("%s\r\n", dirp->d_name);

        closedir(dp);
        exit(0);
}

Makefile

CC      = gcc
CFLAGS  = -Wall
LDFLAGS = -lm

VPATH   = /home/arv/advanced_UNIX_PRO/inc (PWD)#/home/arv/advanced_UNIX_PRO/src/1_test
EXENAME = myls
OBJECTS = error_a.o error_b.o myls.o

# make target
all:${OBJECTS}
        ${CC} -o ${EXENAME} *.o ${LDFLAGS}

# make clean
clean:
        rm -rf ${EXENAME} ${OBJECTS}

# dependence

头文件 apue.h

/*
 * @Author: Arvin
 * @Date: 2022-03-23 21:04:49
 * @LastEditTime: 2022-03-23 21:45:12
 * @LastEditors: Please set LastEditors
 * @Description: This is for Advanced Unix Program
 * @FilePath: \undefinedc:\Users\XDD\Desktop\apue.h
 */

#ifndef _APUE_H
#define _APUE_H

#define _POSIX_C_SOURCE 200809L

#if defined(SOLARIS)    /* Solaris 10 */
#define _XOPEN_SOURCE   600
#else
#define _XOPEN_SOURCE   700
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/termios.h>

#if defined(MACOS) || !defined(TIOCGWINSZ)
#include <sys/ioctl.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

#define MAXLINE 4096    /* max line length */

/* Default file access permissions for new files */
#define FILE_MODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

/* Default permissions for new directories */
#define DIR_MODE    (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)

typedef void Sigfunc(int);  /* for signal handlers */
#define min(a,b)    ((a) < (b) ? (a) : (b))
#define max(a,b)    ((a) > (b) ? (a) : (b))

/* Prototypes for our own functions */
char    *path_alloc(size_t *);                                      /* Figure 2.16 */
long    open_max(void);                                             /* Figure 2.17 */

int     set_cloexec(int);                                           /* Figure 13.9 */
void    clr_fl(int, int);
void    set_fl(int, int);                                           /* Figure 3.12 */

void    pr_exit(int);                                               /* Figure 8.5 */

void    pr_mask(const char *);                                      /* Figure 10.14 */
Sigfunc *signal_intr(int, Sigfunc *);                               /* Figure 10.19 */

void    daemonize(const char *);                                    /* Figure 13.1 */

void    sleep_us(unsigned int);                                     /* Exercise 14.5 */
ssize_t readn(int, void *, size_t);                                 /* Figure 14.24 */
ssize_t writen(int, const void *, size_t);                          /* Figure 14.24 */

int     fd_pipe(int *);                                             /* Figure 17.2 */
int     recv_fd(int, ssize_t (*func)(int, const void *, size_t));  /* Figure 17.14 */
int     send_fd(int, int);                                          /* Figure 17.13 */
int     send_err(int, int, const char *);                           /* Figure 17.12 */
int     serv_listen(const char *);          /* Figure 17.8 */
int     serc_accept(int, uid_t *);          /* Figure 17.9 */
int     cli_conn(const char *);             /* Figure 17.10 */
int     buf_args(char *, int (*func)(int, char **));                /* Figure 17.23 */

int     tty_cbreak(int);                    /* Figure 18.20 */
int     tty_raw(int);                       /* Figure 18.20 */
int     tty_reset(int);                     /* Figure 18.20 */
int     tty_atexit(void);                   /* Figure 18.20 */
struct termios *tty_termios(void);          /* Figure 18.20 */

int     ptym_open(char *, int);             /* Figure 19.9 */
int     ptys_open(char *);                  /* Figure 19.9 */

#ifdef  TIOCGWINSZ
pid_t   pty_fork(int *, char *, int, const struct termios *, const struct winsize *);   /* Figure 19.10 */
#endif

int     lock_reg(int, int, int, off_t, int, off_t); /* Figure 14.5 */
#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);     /* Figure 14.6 */

#define is_read_lockable(fd, offset, whence, len) \
            (lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)
#define is_write_lockable(fd, offset, whence, len) \
            (lock_test((fd), FWRLCK, (offset), (whence), (len)) == 0)

void    err_msg(const char *, ...);         /* Appendix B */
void    err_dump(const char *, ...) __attribute__((noreturn));
void    err_quit(const char *, ...) __attribute__((noreturn));
void    err_cont(int, const char *, ...);
void    err_exit(int, const char *, ...)    __attribute__((noreturn));
void    err_ret(const char *, ...);
void    err_sys(const char *, ...)  __attribute__((noreturn));

void    log_msg(const char *, ...);         /* Appendix B */
void    log_open(const char *, int, int);
void    log_quit(const char *, ...) __attribute__((noreturn));
void    log_ret(const char *, ...);
void    log_sys(const char *, ...)  __attribute__((noreturn));
void    log_exit(int, const char *, ...)    __attribute__((noreturn));

void    TELL_WAIT(void);            /* parent/child/from Section 8.9 */
void    TELL_PARENT(pid_t);
void    TELL_CHILD(pid_t);
void    WAIT_PARENT(void);
void    WAIT_CHILD(void);

#endif  /* _APUE_H */

错误处理函数

/*
 * @Author: Arvin
 * @Date: 2022-03-23 21:46:36
 * @LastEditTime: 2022-03-23 22:03:59
 * @LastEditors: Please set LastEditors
 * @Description: 
 * @FilePath: \undefinedc:\Users\XDD\Desktop\error_a.c
 */
#include "apue.h"
#include <errno.h>
#include <stdarg.h>

static void err_doit(int, int, const char *, va_list);

/**
 * @brief  Prit a message and return 
 * @note   Nonfatal error related to a system call
 * @param  *fmt: 
 * @retval None
 */
void err_ret(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);
}

/**
 * @brief  Print a message and terminate
 * @note   Fatal error related to a system call
 * @param  *fmt: 
 * @retval None
 */
void err_sys(const char *fmt, ...)
{
    va_list ap;
    
    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);
    exit(1);
}

/**
 * @brief  Prit a message and return
 * @note   Nonfatal error unrelated to a system call
 * @param  error: Error code passed as explict parameter
 * @param  *fmt: 
 * @retval None
 */
void err_cont(int error, const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, error, fmt, ap);
    va_end(ap);
}

/**
 * @brief  Print a message and terminate
 * @note   Fatal error unrelated to a system call
 * @param  error: Error code passed as explict parameter
 * @param  *fmt: 
 * @retval None
 */
void err_exit(int error, const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, error, fmt, ap);
    va_end(ap);
    exit(1);
}

/**
 * @brief  Print a message, dump core, and terminate
 * @note   Fatal error related to a system call
 * @param  *fmt: 
 * @retval None
 */
void err_dump(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);
    abort();    /* dump core and terminate */
    exit(1);    /* shouldn;t get here */
}

/**
 * @brief  Print a message and return
 * @note   Nonfatal error unrelated to a system call
 * @param  *fmt: 
 * @retval None
 */
void err_msg(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(0, 0, fmt, ap);
    va_end(ap);
}

/**
 * @brief  Print a message and terminate
 * @note   Fatal error unrelated to a system call
 * @param  *fmt: 
 * @retval None
 */
void err_quit(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(0, 0, fmt, ap);
    va_end(ap);
    exit(1);
}

/**
 * @brief  Caller specifies "errnoflag"
 * @note   Print a message and return to caller
 * @param  errnoflag: 
 * @param  error: 
 * @param  fmt: 
 * @param  ap: 
 * @retval None
 */
static void err_doit(int errnoflag, int error, const char * fmt, va_list ap)
{
    char    buf[MAXLINE];

    vsnprintf(buf, MAXLINE-1, fmt, ap);
    if(errnoflag)
    {
        snprintf(buf+strlen(buf), MAXLINE-strlen(buf) - 1, ": %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 */
}

错误记录函数

/*
 * @Author: Arvin
 * @Date: 2022-03-23 22:04:31
 * @LastEditTime: 2022-03-24 21:35:17
 * @LastEditors: Please set LastEditors
 * @Description: 
 * @FilePath: \undefinedc:\Users\XDD\Desktop\error_b.c
 */

#include "apue.h"
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>

static void log_doit(int, int, int, const char *, va_list ap);

/**
 * @brief  Caller must define and set this: nonzero if interactive, zero if daemon
 * @note   
 * @retval None
 */
//extern int log_to_stderr;

/**
 * @brief  Initialize syslog(), if runing as daemon
 * @note   
 * @param  *ident: 
 * @param  option: 
 * @param  facility: 
 * @retval None
 */
void log_open(const char *ident, int option, int facility)
{
    if(1)//(log_to_stderr == 0)
    {
        openlog(ident, option, facility);
    }
}

/**
 * @brief  Print a message with the system's errno value and return
 * @note   Nonfatal error related to a system call
 * @param  *fmt: 
 * @retval None
 */
void log_ret(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    log_doit(1, errno, LOG_ERR, fmt, ap);
    va_end(ap);
}

/**
 * @brief  Print a message and terminate
 * @note   Fatal error related to a system call
 * @param  *fmt: 
 * @retval None
 */
void log_sys(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    log_doit(1, errno, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(2);
}

/**
 * @brief  Print a message and return
 * @note   Nonfatal error unrelated to a system call
 * @param  *fmt: 
 * @retval None
 */
void log_msg(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    log_doit(0, 0, LOG_ERR, fmt, ap);
    va_end(ap);
}

/**
 * @brief  Print a message and terminate
 * @note   Fatal error unrelated to a system call
 * @param  *fmt: 
 * @retval None
 */
void log_quit(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    log_doit(0, 0, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(2);
}

/**
 * @brief  Print a message and terminate
 * @note   Fatal error related to a system call
 * @param  error: Error number passed as an explicit parameter
 * @param  fmt: 
 * @retval None
 */
void log_exit(int error, const char * fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    log_doit(1, error, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(2);
}

/**
 * @brief  Print a message and return to caller
 * @note   Caller specifies "errnoflag" and "priority"
 * @param  errnoflag: 
 * @param  error: 
 * @param  priority: 
 * @param  *fmt: 
 * @param  ap: 
 * @retval None
 */
static void log_doit(int errnoflag, int error, int priority, const char *fmt, va_list ap)
{
    char buf[MAXLINE];

    vsnprintf(buf, MAXLINE - 1, fmt, ap);
    if(errnoflag)
    {
        snprintf(buf + strlen(buf), MAXLINE - strlen(buf) - 1, ": %s", strerror(error));
    }
    strcat(buf, "\n");
    if(1)//(log_to_stderr)
    {
        fflush(stdout);
        fputs(buf, stderr);
        fflush(stderr);
    }
    else
    {
        syslog(priority, "%s", buf);
    }
}

剩下的书内源码不再给出,可以以本例作为参考,实现后续的内容。

posted @ 2022-03-27 13:46  ArvinDu  阅读(129)  评论(0编辑  收藏  举报