├── .gitignore ├── APUE_S1.xmind ├── APUE_S2.xmind ├── Advanced Programming in the UNIX Environment, 3rd Edition.pdf ├── README.md ├── UNIX环境高级编程(中文第三版).pdf └── src ├── 01_UNIX_Introduction ├── Makefile ├── getcputc ├── getcputc.c ├── hello ├── hello.c ├── ls1 ├── ls1.c ├── mycat ├── mycat.c ├── shell1 ├── shell1.c ├── shell2 ├── shell2.c ├── testerror ├── testerror.c ├── uidgid └── uidgid.c ├── 02_UNIX_Standard ├── Makefile ├── conf ├── conf.c ├── makeconf.awk ├── makeopt.awk ├── options ├── options.c ├── pathconf-lim.sym ├── pathconf-opt.sym ├── pathconf.sym ├── pathopt.sym ├── sysconf-lim.sym ├── sysconf-opt.sym ├── sysconf.sym └── sysopt.sym ├── 03_Unbuffered_IO ├── Makefile ├── dup ├── dup.c ├── fcntl ├── fcntl.c ├── file.nohole ├── fileflags ├── fileflags.c ├── hole ├── hole.c ├── mycat ├── mycat.c ├── open ├── open.c ├── seek └── seek.c ├── 04_FILE_DIR ├── Makefile ├── access ├── access.c ├── bar ├── cdpwd ├── cdpwd.c ├── changemod ├── changemod.c ├── changeown ├── changeown.c ├── devrdev ├── devrdev.c ├── filetype ├── filetype.c ├── foo ├── ftw8 ├── ftw8.c ├── link ├── link.c ├── mycd ├── mycd.c ├── umask ├── umask.c ├── unlink ├── unlink.c ├── zap └── zap.c ├── 05_Standard_IO ├── Makefile ├── buf ├── buf.c ├── fgetsfputs ├── fgetsfputs.c ├── fwide ├── fwide.c ├── getcharbug ├── getcharbug.c ├── getcputc ├── getcputc.c ├── memstr ├── memstr.c ├── mkstemp ├── mkstemp.c ├── tempfiles └── tempfiles.c ├── 06_System_Info ├── Makefile ├── getpwnam ├── getpwnam.c ├── getshadow ├── getshadow.c ├── strftime ├── strftime.c ├── uname └── uname.c ├── 07_Process_Env ├── Makefile ├── doatexit ├── doatexit.c ├── echoall ├── echoall.c ├── echoarg ├── echoarg.c ├── getrlimit ├── getrlimit.c ├── testenv ├── testenv.c ├── testjmp └── testjmp.c ├── 08_Process_Ctl ├── Makefile ├── exec1 ├── exec1.c ├── exec2 ├── exec2.c ├── fork1 ├── fork1.c ├── fork1.log ├── fork2 ├── fork2.c ├── nice ├── nice.c ├── pruids ├── pruids.c ├── system ├── system.c ├── systest ├── systest.c ├── tellwait1 ├── tellwait1.c ├── tellwait2 ├── tellwait2.c ├── test1 ├── test1.c ├── times1 ├── times1.c ├── tsys ├── tsys.c ├── vfork1 ├── vfork1.c ├── wait1 └── wait1.c ├── 09_Process_Rel ├── Makefile ├── orphan3 ├── orphan3.c ├── printid └── printid.c ├── 09_Signals ├── Makefile ├── abort ├── abort.c ├── abort.o ├── critical ├── critical.c ├── read1 ├── read1.c ├── read2 ├── read2.c ├── reenter ├── reenter.c ├── setops.c ├── sigint ├── sigint.c ├── sigtstp ├── sigtstp.c ├── sigusr ├── sigusr.c ├── sleep1.c ├── sleep1.o ├── sleep2.c ├── sleep2.o ├── suspend1 ├── suspend1.c ├── suspend2 ├── suspend2.c ├── system.c ├── system.o ├── systest2 ├── systest2.c ├── systest2.o ├── tsleep2 ├── tsleep2.c └── tsleep2.o ├── 10_Process_Rel ├── Makefile ├── orphan3 ├── orphan3.c ├── printid └── printid.c ├── 10_Signals ├── Makefile ├── abort.c ├── abort.o ├── critical ├── critical.c ├── read1 ├── read1.c ├── read2 ├── read2.c ├── reenter ├── reenter.c ├── setops.c ├── sigint ├── sigint.c ├── sigtstp ├── sigtstp.c ├── sigusr ├── sigusr.c ├── sleep1.c ├── sleep1.o ├── sleep2.c ├── sleep2.o ├── suspend1 ├── suspend1.c ├── suspend2 ├── suspend2.c ├── system.c ├── system.o ├── systest2 ├── systest2.c ├── systest2.o ├── tsleep2 ├── tsleep2.c └── tsleep2.o ├── 11_Threads ├── Makefile ├── badexit2 ├── badexit2.c ├── barrier ├── barrier.c ├── cleanup ├── cleanup.c ├── condvar.c ├── condvar.o ├── exitstatus ├── exitstatus.c ├── maketimeout.c ├── maketimeout.o ├── mutex1.c ├── mutex1.o ├── mutex2.c ├── mutex2.o ├── mutex3.c ├── mutex3.o ├── rwlock.c ├── rwlock.o ├── threadid ├── threadid.c ├── timedlock └── timedlock.c ├── 12_ThreadCtl ├── Makefile ├── detach.c ├── detach.o ├── getenv1.c ├── getenv1.o ├── getenv2.c ├── getenv2.o ├── getenv3.c ├── getenv3.o ├── suspend ├── suspend.c ├── timeout ├── timeout.c └── timeout.o ├── 13_Daemons ├── Makefile ├── init.c ├── init.o ├── reread.c ├── reread.o ├── reread2.c ├── reread2.o ├── single.c └── single.o ├── 14_Advanced_IO ├── Makefile ├── deadlock ├── deadlock.c ├── lockfile.c ├── lockfile.o ├── mandatory ├── mandatory.c ├── mcopy2 ├── mcopy2.c ├── nonblockw └── nonblockw.c ├── 15_IPC ├── Makefile ├── add2 ├── add2.c ├── add2stdio ├── add2stdio.c ├── common_shm.h ├── devzero ├── devzero.c ├── fifo ├── fifo.c ├── mq_client ├── mq_client.c ├── mq_common.h ├── mq_server ├── mq_server.c ├── myuclc ├── myuclc.c ├── pipe1 ├── pipe1.c ├── pipe2 ├── pipe2.c ├── pipe3 ├── pipe3.c ├── pipe4 ├── pipe4.c ├── popen.c ├── popen.o ├── popen1 ├── popen1.c ├── popen2 ├── popen2.c ├── read_fifo ├── read_fifo.c ├── read_shm ├── read_shm.c ├── shm_fifo.c ├── shm_fifo.h ├── shm_fifo.o ├── shm_get ├── shm_get.c ├── shm_get.o ├── shm_put ├── shm_put.c ├── shm_put.o ├── slock.c ├── slock.h ├── slock.o ├── tellwait.c ├── tellwait.o ├── tshm ├── tshm.c ├── write_fifo ├── write_fifo.c ├── write_shm └── write_shm.c ├── Make.defines.freebsd ├── Make.defines.linux ├── Make.defines.macos ├── Make.defines.solaris ├── Make.libapue.inc ├── Makefile ├── include └── apue.h ├── lib ├── Makefile ├── clrfl.c ├── clrfl.o ├── error.c ├── error.o ├── libapue.a ├── lockreg.c ├── lockreg.o ├── locktest.c ├── locktest.o ├── openmax.c ├── openmax.o ├── pathalloc.c ├── pathalloc.o ├── prexit.c ├── prexit.o ├── prmask.c ├── prmask.o ├── readn.c ├── readn.o ├── setfd.c ├── setfd.o ├── setfl.c ├── setfl.o ├── tellwait.c ├── tellwait.o ├── writen.c └── writen.o └── systype.sh /.gitignore: -------------------------------------------------------------------------------- 1 | src/.vscode/ 2 | src/.idea/ 3 | -------------------------------------------------------------------------------- /APUE_S1.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/APUE_S1.xmind -------------------------------------------------------------------------------- /APUE_S2.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/APUE_S2.xmind -------------------------------------------------------------------------------- /Advanced Programming in the UNIX Environment, 3rd Edition.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/Advanced Programming in the UNIX Environment, 3rd Edition.pdf -------------------------------------------------------------------------------- /UNIX环境高级编程(中文第三版).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/UNIX环境高级编程(中文第三版).pdf -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = ls1 hello getcputc mycat shell1 shell2 uidgid testerror 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | clean: 13 | rm -f $(PROGS) $(TEMPFILES) *.o 14 | 15 | include $(ROOT)/Make.libapue.inc -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/getcputc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/getcputc -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/getcputc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试getc和putc 3 | * 4 | * apue示例程序 - getcputc.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main() 12 | { 13 | int c; 14 | 15 | while((c = getc(stdin)) != EOF) 16 | if(putc(c, stdout) == EOF) 17 | err_sys("output error"); 18 | 19 | if(ferror(stdin)) 20 | err_sys("input error"); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/hello -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/hello.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 打印当前进程pid 3 | * 4 | * apue示例程序 - hello.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main() 12 | { 13 | printf("hello world from process ID %ld\n", (long)getpid()); 14 | exit(0); 15 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/ls1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/ls1 -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/ls1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 模拟ls命令 3 | * 4 | * apue示例程序 - ls1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | DIR *dp; 15 | struct dirent *dirp; 16 | 17 | if(argc != 2) 18 | err_quit("usage: %s directory_name", argv[0]); 19 | 20 | if((dp = opendir(argv[1])) == NULL) 21 | err_sys("can't open %s", argv[1]); 22 | 23 | while((dirp = readdir(dp)) != NULL) 24 | printf("%s\n", dirp->d_name); 25 | 26 | closedir(dp); 27 | return 0; 28 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/mycat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/mycat -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/mycat.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 模拟cat命令 3 | * 4 | * apue示例程序 - mycat.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | #define BUFSIZE 4096 12 | 13 | int main() 14 | { 15 | int n; 16 | char buf[BUFSIZE]; 17 | 18 | while((n = read(STDIN_FILENO, buf, BUFSIZE)) > 0) 19 | if(write(STDOUT_FILENO, buf, n) != n) 20 | err_sys("write error"); 21 | 22 | if(n < 0) 23 | err_sys("read error"); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/shell1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/shell1 -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/shell1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 模拟shell 3 | * 4 | * apue示例程序 - shell1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main() 13 | { 14 | char buf[MAXLINE]; 15 | pid_t pid; 16 | int status; 17 | 18 | printf("%% "); // 提示符 19 | while(fgets(buf, MAXLINE, stdin) != NULL) { 20 | if(buf[strlen(buf)-1] == '\n') 21 | buf[strlen(buf)-1] = 0; 22 | 23 | if((pid = fork()) < 0) { 24 | err_sys("fork error"); 25 | } else if(pid == 0) { // child 26 | execlp(buf, buf, (char *)0); 27 | err_ret("couldn't execute: %s", buf); 28 | exit(127); 29 | } 30 | 31 | // parent 32 | if(pid = waitpid(pid, &status, 0) < 0) 33 | err_sys("waitpid error"); 34 | printf("%% "); 35 | } 36 | return 0; 37 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/shell2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/shell2 -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/shell2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 模拟shell,处理SIGINT信号 3 | * 4 | * apue示例程序 - shell2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void sig_int(int); // SIGINT catching handler 13 | 14 | int main() 15 | { 16 | char buf[MAXLINE]; 17 | pid_t pid; 18 | int status; 19 | 20 | if(signal(SIGINT, sig_int) == SIG_ERR) 21 | err_sys("signal error"); 22 | 23 | printf("%% "); // 提示符 24 | while(fgets(buf, MAXLINE, stdin) != NULL) { 25 | if(buf[strlen(buf)-1] == '\n') 26 | buf[strlen(buf)-1] = 0; 27 | 28 | if((pid = fork()) < 0) { 29 | err_sys("fork error"); 30 | } else if(pid == 0) { // child 31 | execlp(buf, buf, (char *)0); 32 | err_ret("couldn't execute: %s", buf); 33 | exit(127); 34 | } 35 | 36 | // parent 37 | if(pid = waitpid(pid, &status, 0) < 0) 38 | err_sys("waitpid error"); 39 | printf("%% "); 40 | } 41 | return 0; 42 | } 43 | 44 | void sig_int(int signo) 45 | { 46 | printf("interrupt\n%% "); 47 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/testerror: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/testerror -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/testerror.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试errno,strerror 3 | * 4 | * apue示例程序 - testerror.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | fprintf(stderr, "EACCES: %s\n", strerror(EACCES)); 15 | errno = ENOENT; 16 | perror(argv[0]); 17 | exit(0); 18 | } -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/uidgid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/01_UNIX_Introduction/uidgid -------------------------------------------------------------------------------- /src/01_UNIX_Introduction/uidgid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取uid和gid 3 | * 4 | * apue示例程序 - uidigd.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | int main() 10 | { 11 | printf("uid = %d, gid = %d\n", getuid(), getgid()); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /src/02_UNIX_Standard/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = conf options 6 | 7 | all: $(PROGS) 8 | 9 | %: %.c $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | conf: conf.c 13 | 14 | conf.c: makeconf.awk sysconf.sym pathconf.sym 15 | $(AWK) -f makeconf.awk >conf.c 16 | 17 | sysconf.sym: sysconf-lim.sym 18 | grep -v "^#" sysconf-lim.sym >sysconf.sym 19 | 20 | pathconf.sym: pathconf-lim.sym 21 | grep -v "^#" pathconf-lim.sym >pathconf.sym 22 | 23 | options: options.c 24 | 25 | options.c: makeopt.awk sysopt.sym pathopt.sym 26 | $(AWK) -f makeopt.awk >options.c 27 | 28 | sysopt.sym: sysconf-opt.sym 29 | grep -v "^#" sysconf-opt.sym >sysopt.sym 30 | 31 | pathopt.sym: pathconf-opt.sym 32 | grep -v "^#" pathconf-opt.sym >pathopt.sym 33 | 34 | clean: 35 | rm -f $(PROGS) $(TEMPFILES) *.o conf.c options.c \ 36 | pathconf.sym pathopt.sym sysconf.sym sysopt.sym 37 | 38 | include $(ROOT)/Make.libapue.inc 39 | -------------------------------------------------------------------------------- /src/02_UNIX_Standard/conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/02_UNIX_Standard/conf -------------------------------------------------------------------------------- /src/02_UNIX_Standard/options: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/02_UNIX_Standard/options -------------------------------------------------------------------------------- /src/02_UNIX_Standard/pathconf-lim.sym: -------------------------------------------------------------------------------- 1 | FILESIZEBITS _PC_FILESIZEBITS 2 | LINK_MAX _PC_LINK_MAX 3 | MAX_CANON _PC_MAX_CANON 4 | MAX_INPUT _PC_MAX_INPUT 5 | NAME_MAX _PC_NAME_MAX 6 | PATH_MAX _PC_PATH_MAX 7 | PIPE_BUF _PC_PIPE_BUF 8 | SYMLINK_MAX _PC_SYMLINK_MAX 9 | _POSIX_TIMESTAMP_RESOLUTION _PC_TIMESTAMP_RESOLUTION 10 | -------------------------------------------------------------------------------- /src/02_UNIX_Standard/pathconf-opt.sym: -------------------------------------------------------------------------------- 1 | _POSIX_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED 2 | _POSIX_NO_TRUNC _PC_NO_TRUNC 3 | _POSIX_VDISABLE _PC_VDISABLE 4 | _POSIX_ASYNC_IO _PC_ASYNC_IO 5 | _POSIX_PRIO_IO _PC_PRIO_IO 6 | _POSIX_SYNC_IO _PC_SYNC_IO 7 | _POSIX2_SYMLINKS _PC_2_SYMLINKS 8 | -------------------------------------------------------------------------------- /src/02_UNIX_Standard/pathconf.sym: -------------------------------------------------------------------------------- 1 | FILESIZEBITS _PC_FILESIZEBITS 2 | LINK_MAX _PC_LINK_MAX 3 | MAX_CANON _PC_MAX_CANON 4 | MAX_INPUT _PC_MAX_INPUT 5 | NAME_MAX _PC_NAME_MAX 6 | PATH_MAX _PC_PATH_MAX 7 | PIPE_BUF _PC_PIPE_BUF 8 | SYMLINK_MAX _PC_SYMLINK_MAX 9 | _POSIX_TIMESTAMP_RESOLUTION _PC_TIMESTAMP_RESOLUTION 10 | -------------------------------------------------------------------------------- /src/02_UNIX_Standard/pathopt.sym: -------------------------------------------------------------------------------- 1 | _POSIX_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED 2 | _POSIX_NO_TRUNC _PC_NO_TRUNC 3 | _POSIX_VDISABLE _PC_VDISABLE 4 | _POSIX_ASYNC_IO _PC_ASYNC_IO 5 | _POSIX_PRIO_IO _PC_PRIO_IO 6 | _POSIX_SYNC_IO _PC_SYNC_IO 7 | _POSIX2_SYMLINKS _PC_2_SYMLINKS 8 | -------------------------------------------------------------------------------- /src/02_UNIX_Standard/sysconf-lim.sym: -------------------------------------------------------------------------------- 1 | # AIO_LISTIO_MAX _SC_AIO_LISTIO_MAX ; defer to chapter 14 2 | # AIO_MAX _SC_AIO_MAX ; defer to chapter 14 3 | # AIO_PRIO_DELTA_MAX _SC_AIO_PRIO_DELTA_MAX ; defer to chapter 14 4 | ARG_MAX _SC_ARG_MAX 5 | ATEXIT_MAX _SC_ATEXIT_MAX 6 | CHARCLASS_NAME_MAX _SC_CHARCLASS_NAME_MAX 7 | CHILD_MAX _SC_CHILD_MAX 8 | CLOCKTICKSPERSECOND /*clock ticks/second*/ _SC_CLK_TCK 9 | COLL_WEIGHTS_MAX _SC_COLL_WEIGHTS_MAX 10 | DELAYTIMER_MAX _SC_DELAYTIMER_MAX 11 | HOST_NAME_MAX _SC_HOST_NAME_MAX 12 | IOV_MAX _SC_IOV_MAX 13 | LINE_MAX _SC_LINE_MAX 14 | LOGIN_NAME_MAX _SC_LOGIN_NAME_MAX 15 | NGROUPS_MAX _SC_NGROUPS_MAX 16 | # initial size of getgrgid_r() _SC_GETGR_R_SIZE_MAX 17 | # initial size of getpwuid_r() _SC_GETPW_R_SIZE_MAX 18 | OPEN_MAX _SC_OPEN_MAX 19 | PAGESIZE _SC_PAGESIZE 20 | PAGE_SIZE _SC_PAGE_SIZE 21 | # PTHREAD_DESTRUCTOR_ITERATIONS _SC_THREAD_DESTRUCTOR_ITERATIONS ; defer to chapter 12 22 | # PTHREAD_KEYS_MAX _SC_THREAD_KEYS_MAX ; defer to chapter 12 23 | # PTHREAD_STACK_MIN _SC_THREAD_STACK_MIN ; defer to chapter 12 24 | # PTHREAD_THREADS_MAX _SC_THREAD_THREADS_MAX ; defer to chapter 12 25 | RE_DUP_MAX _SC_RE_DUP_MAX 26 | RTSIG_MAX _SC_RTSIG_MAX 27 | SEM_NSEMS_MAX _SC_SEM_NSEMS_MAX 28 | SEM_VALUE_MAX _SC_SEM_VALUE_MAX 29 | SIGQUEUE_MAX _SC_SIGQUEUE_MAX 30 | STREAM_MAX _SC_STREAM_MAX 31 | SYMLOOP_MAX _SC_SYMLOOP_MAX 32 | TIMER_MAX _SC_TIMER_MAX 33 | TTY_NAME_MAX _SC_TTY_NAME_MAX 34 | TZNAME_MAX _SC_TZNAME_MAX 35 | -------------------------------------------------------------------------------- /src/02_UNIX_Standard/sysconf.sym: -------------------------------------------------------------------------------- 1 | ARG_MAX _SC_ARG_MAX 2 | ATEXIT_MAX _SC_ATEXIT_MAX 3 | CHARCLASS_NAME_MAX _SC_CHARCLASS_NAME_MAX 4 | CHILD_MAX _SC_CHILD_MAX 5 | CLOCKTICKSPERSECOND /*clock ticks/second*/ _SC_CLK_TCK 6 | COLL_WEIGHTS_MAX _SC_COLL_WEIGHTS_MAX 7 | DELAYTIMER_MAX _SC_DELAYTIMER_MAX 8 | HOST_NAME_MAX _SC_HOST_NAME_MAX 9 | IOV_MAX _SC_IOV_MAX 10 | LINE_MAX _SC_LINE_MAX 11 | LOGIN_NAME_MAX _SC_LOGIN_NAME_MAX 12 | NGROUPS_MAX _SC_NGROUPS_MAX 13 | OPEN_MAX _SC_OPEN_MAX 14 | PAGESIZE _SC_PAGESIZE 15 | PAGE_SIZE _SC_PAGE_SIZE 16 | RE_DUP_MAX _SC_RE_DUP_MAX 17 | RTSIG_MAX _SC_RTSIG_MAX 18 | SEM_NSEMS_MAX _SC_SEM_NSEMS_MAX 19 | SEM_VALUE_MAX _SC_SEM_VALUE_MAX 20 | SIGQUEUE_MAX _SC_SIGQUEUE_MAX 21 | STREAM_MAX _SC_STREAM_MAX 22 | SYMLOOP_MAX _SC_SYMLOOP_MAX 23 | TIMER_MAX _SC_TIMER_MAX 24 | TTY_NAME_MAX _SC_TTY_NAME_MAX 25 | TZNAME_MAX _SC_TZNAME_MAX 26 | -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = fileflags hole mycat seek open dup fcntl 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | clean: 13 | rm -f $(PROGS) $(TEMPFILES) *.o file.hole 14 | 15 | include $(ROOT)/Make.libapue.inc -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/dup: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/dup -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/dup.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 练习dup/dup2 3 | * 4 | * apue示例程序 - dup.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main() 12 | { 13 | int fd = dup(STDIN_FILENO); //复制stdin,理应返回3 14 | if(-1 == fd) 15 | err_sys("dup stdin failed!"); 16 | printf("fd:%d\n",fd); 17 | 18 | int result = dup2(STDERR_FILENO, fd); // 理应atomic{close(fd) + fcntl(100, F_DUPFD, fd)},但100是未打开的fd 19 | if(-1 == result) 20 | err_sys("dup2 100 failed!"); 21 | printf("fd:%d\n", fd); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/fcntl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/fcntl -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/fcntl.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试fcntl 3 | * 4 | * apue示例程序 - fcntl.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int fcntl_dupfd(int fd, int arg, int cloexec_flag) 13 | { 14 | int result; 15 | 16 | if(cloexec_flag == 0) 17 | result = fcntl(fd, F_DUPFD, arg); 18 | else 19 | result = fcntl(fd, F_DUPFD_CLOEXEC, arg); 20 | 21 | if(result == -1) 22 | { 23 | err_ret("fcntl_dupfd failed, param fd:%d\targ:%d", fd, arg); 24 | return -1; 25 | } 26 | return result; 27 | } 28 | 29 | int fcntl_getfd(int fd) 30 | { 31 | int result = fcntl(fd, F_GETFD); 32 | if(result == -1) 33 | { 34 | err_ret("fcntl_getfd failed, param fd:%d", fd); 35 | return -1; 36 | } 37 | return result; 38 | } 39 | 40 | int fcntl_setfd(int fd, int arg) 41 | { 42 | int result = fcntl(fd, F_SETFD, arg); 43 | if(result == -1) 44 | { 45 | err_ret("fcntl_setfl failed, param fd:%d\targ:%d", fd, arg); 46 | return -1; 47 | } 48 | return result; 49 | } 50 | 51 | int main() 52 | { 53 | int fd = fcntl_dupfd(STDIN_FILENO, 10, 0); 54 | 55 | if(fd != -1) 56 | { 57 | printf("Duplicated fd %d from stdin\n", fd); 58 | fcntl_setfd(fd, ~fcntl_getfd(fd)); 59 | } 60 | 61 | getchar(); 62 | return 0; 63 | } -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/fileflags: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/fileflags -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/fileflags.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 检视文件flags 3 | * 4 | * apue示例程序 - fileflags.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int val; 15 | 16 | if(argc != 2) 17 | err_quit("usage: %s ", argv[0]); 18 | 19 | if((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0) 20 | err_sys("fcntl error for fd %d", atoi(argv[1])); 21 | 22 | switch(val & O_ACCMODE) { 23 | case O_RDONLY: 24 | printf("read only"); 25 | break; 26 | case O_WRONLY: 27 | printf("write only"); 28 | break; 29 | case O_RDWR: 30 | printf("read write"); 31 | break; 32 | default: 33 | err_dump("unknown access mode"); 34 | } 35 | 36 | if(val & O_APPEND) 37 | printf(", append"); 38 | if(val & O_NONBLOCK) 39 | printf(", nonblocking"); 40 | if(val & O_SYNC) 41 | printf(", synchronous writes"); 42 | 43 | putchar('\n'); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/hole: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/hole -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/hole.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 生成空洞文件 3 | * 4 | * apue示例程序 - hole.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | char buf1[] = "abcdefghij"; 13 | char buf2[] = "ABCDEFGHIJ"; 14 | 15 | int main(void) 16 | { 17 | int fd, fd2; 18 | int count = 0; 19 | 20 | if((fd = creat("file.hole", FILE_MODE)) < 0) 21 | err_sys("creat error"); 22 | 23 | if(write(fd, buf1, 10) != 10) 24 | err_sys("buf1 write error"); 25 | /* offset now = 10_Process_Rel */ 26 | 27 | if(lseek(fd, 16384, SEEK_SET) == -1) 28 | err_sys("lseek error"); 29 | /* offset now = 16384 */ 30 | 31 | if(write(fd, buf2, 10) != 10) 32 | err_sys("buf2 write error"); 33 | /* offset now = 16394 */ 34 | // abcdefghij ......... ABCDEFGHIJ 35 | 36 | if((fd2 = creat("file.nohole", FILE_MODE)) < 0) 37 | err_sys("creat error"); 38 | 39 | while(count < 16390) 40 | { 41 | if(write(fd2, buf1, 10) != 10) 42 | err_sys("buf1 write error"); 43 | count += 10; 44 | } 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/mycat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/mycat -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/mycat.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 简易cat,测试read/write 3 | * 4 | * apue示例程序 - mycat.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | #define BUFFSIZE 4096 12 | 13 | int main() 14 | { 15 | int n; 16 | char buf[BUFFSIZE]; 17 | 18 | while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) 19 | if(write(STDOUT_FILENO, buf, n) != n) 20 | err_sys("write error"); 21 | 22 | if(n < 0) 23 | err_sys("read error"); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/open: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/open -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/open.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试open 3 | * 4 | * apue示例程序 - open.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int result; 15 | 16 | if(argc != 2) 17 | err_sys("usage: %s ", argv[0]); 18 | 19 | result = open(argv[1], O_RDWR); 20 | if(result == -1) 21 | err_sys("open %s failed\n", argv[1]); 22 | 23 | result = open(argv[1], O_RDWR, S_IRUSR | S_IWUSR); 24 | if(result == -1) 25 | err_sys("open %s with mode S_IRUSR|S_IWUSR failed\n", argv[1]); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/seek: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/03_Unbuffered_IO/seek -------------------------------------------------------------------------------- /src/03_Unbuffered_IO/seek.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试lseek 3 | * 4 | * apue示例程序 - seek.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main() 12 | { 13 | if(lseek(STDIN_FILENO, 0, SEEK_CUR) == -1) 14 | printf("cannot seek\n"); 15 | else 16 | printf("seek OK\n"); 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "linux" 6 | ZAP = zap 7 | else 8 | ZAP = 9 | endif 10 | 11 | 12 | PROGS = access cdpwd changemod changeown devrdev filetype mycd umask link unlink $(ZAP) 13 | MOREPROGS = ftw8 14 | 15 | all: $(PROGS) $(MOREPROGS) 16 | 17 | $(PROGS): $(LIBAPUE) 18 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 19 | 20 | ftw8: ftw8.c $(LIBAPUE) 21 | $(CC) $(CFLAGS) $(NAMEMAX) ftw8.c -o ftw8 $(LDFLAGS) $(LDLIBS) 22 | 23 | clean: 24 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o $(ZAP) 25 | 26 | include $(ROOT)/Make.libapue.inc -------------------------------------------------------------------------------- /src/04_FILE_DIR/access: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/access -------------------------------------------------------------------------------- /src/04_FILE_DIR/access.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试access 3 | * 4 | * apue示例程序 - access.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | if (argc != 2) 15 | err_quit("usage: %s ", argv[0]); 16 | if (access(argv[1], W_OK) < 0) 17 | err_ret("access error for %s", argv[1]); 18 | else 19 | printf("read access OK\n"); 20 | if (open(argv[1], O_RDONLY) < 0) 21 | err_ret("open error for %s", argv[1]); 22 | else 23 | printf("open for reading OK\n"); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/bar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/bar -------------------------------------------------------------------------------- /src/04_FILE_DIR/cdpwd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/cdpwd -------------------------------------------------------------------------------- /src/04_FILE_DIR/cdpwd.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试chdir&getcwd 3 | * 4 | * apue示例程序 - cdpwd.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main() 12 | { 13 | char *ptr; 14 | size_t size; 15 | 16 | if (chdir("/usr/spool/uucppublic") < 0) 17 | err_sys("chdir failed"); 18 | 19 | ptr = path_alloc(&size); /* our own function */ 20 | if (getcwd(ptr, size) == NULL) 21 | err_sys("getcwd failed"); 22 | 23 | printf("cwd = %s\n", ptr); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/changemod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/changemod -------------------------------------------------------------------------------- /src/04_FILE_DIR/changemod.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试chmod 3 | * 4 | * apue示例程序 - changemod.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main() 13 | { 14 | struct stat statbuf; 15 | 16 | /* turn on set-group-ID and turn off group-execute */ 17 | 18 | if (stat("foo", &statbuf) < 0) 19 | err_sys("stat error for foo"); 20 | if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0) 21 | err_sys("chmod error for foo"); 22 | 23 | /* set absolute mode to "rw-r--r--" */ 24 | 25 | if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) 26 | err_sys("chmod error for bar"); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/changeown: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/changeown -------------------------------------------------------------------------------- /src/04_FILE_DIR/changeown.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试chown,需root权限 3 | * 4 | * apue示例程序 - changeown.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main() 13 | { 14 | struct stat statbuf; 15 | 16 | if (stat("foo", &statbuf) < 0) 17 | err_sys("stat error for foo"); 18 | if (chown("foo", 1000, 1000) < 0) 19 | err_sys("chown error for foo"); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/devrdev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/devrdev -------------------------------------------------------------------------------- /src/04_FILE_DIR/devrdev.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试字符设备和块设备文件 3 | * 4 | * apue示例程序 - devrdev.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #ifdef SOLARIS 11 | #include 12 | #endif 13 | #include 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | int i; 18 | struct stat buf; 19 | 20 | for (i = 1; i < argc; i++) { 21 | printf("%s: ", argv[i]); 22 | if (stat(argv[i], &buf) < 0) { 23 | err_ret("stat error"); 24 | continue; 25 | } 26 | 27 | printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev)); 28 | 29 | if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) { 30 | printf(" (%s) rdev = %d/%d", 31 | (S_ISCHR(buf.st_mode)) ? "character" : "block", 32 | major(buf.st_rdev), minor(buf.st_rdev)); 33 | } 34 | printf("\n"); 35 | } 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/filetype: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/filetype -------------------------------------------------------------------------------- /src/04_FILE_DIR/filetype.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试lstat 3 | * 4 | * apue示例程序 - filetype.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int i; 15 | struct stat buf; 16 | char *ptr; 17 | 18 | for (i = 1; i < argc; i++) { 19 | printf("%s: ", argv[i]); 20 | if (lstat(argv[i], &buf) < 0) { 21 | err_ret("lstat error"); 22 | continue; 23 | } 24 | if (S_ISREG(buf.st_mode)) 25 | ptr = "regular"; 26 | else if (S_ISDIR(buf.st_mode)) 27 | ptr = "directory"; 28 | else if (S_ISCHR(buf.st_mode)) 29 | ptr = "character special"; 30 | else if (S_ISBLK(buf.st_mode)) 31 | ptr = "block special"; 32 | else if (S_ISFIFO(buf.st_mode)) 33 | ptr = "fifo"; 34 | else if (S_ISLNK(buf.st_mode)) 35 | ptr = "symbolic link"; 36 | else if (S_ISSOCK(buf.st_mode)) 37 | ptr = "socket"; 38 | else 39 | ptr = "** unknown mode **"; 40 | printf("%s\n", ptr); 41 | } 42 | return 0; 43 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/foo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/foo -------------------------------------------------------------------------------- /src/04_FILE_DIR/ftw8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/ftw8 -------------------------------------------------------------------------------- /src/04_FILE_DIR/link: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/link -------------------------------------------------------------------------------- /src/04_FILE_DIR/link.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试link 3 | * 4 | * apue示例程序 - link.c 5 | * 创建硬链接 6 | * 7 | * @author r00tk1t 8 | * 9 | */ 10 | #include "apue.h" 11 | #include 12 | 13 | int main() 14 | { 15 | int fd; 16 | char buf[] = "hello world"; 17 | if ((fd = open("tempfile", O_RDWR | O_CREAT)) < 0) 18 | err_sys("open error"); 19 | if (write(fd, buf, strlen(buf)+1) != strlen(buf)+1) 20 | err_sys("write error"); 21 | if (link("tempfile", "tempfile2") < 0) 22 | err_sys("link error"); 23 | if (unlink("tempfile") < 0) 24 | err_sys("unlink error"); 25 | return 0; 26 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/mycd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/mycd -------------------------------------------------------------------------------- /src/04_FILE_DIR/mycd.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试chdir 3 | * 4 | * apue示例程序 - mycd.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main() 12 | { 13 | char buf[128]; 14 | printf("%s\n", getcwd(buf, sizeof(buf))); 15 | if (chdir("/tmp") < 0) 16 | err_sys("chdir failed"); 17 | printf("chdir to /tmp succeeded\n"); 18 | printf("%s\n", getcwd(buf, sizeof(buf))); 19 | return 0; 20 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/umask: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/umask -------------------------------------------------------------------------------- /src/04_FILE_DIR/umask.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试umask 3 | * 4 | * apue示例程序 - umask.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 14 | 15 | int main() 16 | { 17 | umask(0); 18 | if (creat("foo", RWRWRW) < 0) 19 | err_sys("creat error for foo"); 20 | umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 21 | if (creat("bar", RWRWRW) < 0) 22 | err_sys("creat error for bar"); 23 | exit(0); 24 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/unlink: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/unlink -------------------------------------------------------------------------------- /src/04_FILE_DIR/unlink.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试unlink 3 | * 4 | * apue示例程序 - unlink.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main() 13 | { 14 | if (open("tempfile", O_RDWR) < 0) 15 | err_sys("open error"); 16 | if (unlink("tempfile") < 0) 17 | err_sys("unlink error"); 18 | printf("file unlinked\n"); 19 | sleep(15); 20 | printf("done\n"); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /src/04_FILE_DIR/zap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/04_FILE_DIR/zap -------------------------------------------------------------------------------- /src/04_FILE_DIR/zap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试futimens 3 | * 4 | * apue示例程序 - zap.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int i, fd; 16 | struct stat statbuf; 17 | struct timespec times[2]; 18 | 19 | for (i = 1; i < argc; i++) { 20 | if (stat(argv[i], &statbuf) < 0) { /* fetch current times */ 21 | err_ret("%s: stat error", argv[i]); 22 | continue; 23 | } 24 | if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) { /* truncate */ 25 | err_ret("%s: open error", argv[i]); 26 | continue; 27 | } 28 | #ifdef __USE_XOPEN2K8 29 | times[0] = statbuf.st_atim; 30 | times[1] = statbuf.st_mtim; 31 | #else 32 | times[0].tv_sec = statbuf.st_atime; 33 | times[0].tv_nsec = statbuf.st_atimensec; 34 | times[1].tv_sec = statbuf.st_mtime; 35 | times[1].tv_nsec = statbuf.st_mtimensec; 36 | #endif 37 | if (futimens(fd, times) < 0) /* reset times */ 38 | err_ret("%s: futimens error", argv[i]); 39 | close(fd); 40 | } 41 | exit(0); 42 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "linux" 6 | MEMSTR = memstr 7 | else 8 | MEMSTR = 9 | endif 10 | 11 | PROGS = buf fgetsfputs getcharbug getcputc mkstemp tempfiles fwide 12 | 13 | all: $(PROGS) $(MEMSTR) 14 | 15 | $(PROGS): $(LIBAPUE) 16 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 17 | 18 | clean: 19 | rm -f $(PROGS) $(TEMPFILES) *.o $(MEMSTR) 20 | 21 | include $(ROOT)/Make.libapue.inc -------------------------------------------------------------------------------- /src/05_Standard_IO/buf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/buf -------------------------------------------------------------------------------- /src/05_Standard_IO/fgetsfputs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/fgetsfputs -------------------------------------------------------------------------------- /src/05_Standard_IO/fgetsfputs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试fgets和fputs 3 | * 4 | * apue示例程序 - fgetsfputs.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(void) 12 | { 13 | char buf[MAXLINE]; 14 | 15 | while (fgets(buf, MAXLINE, stdin) != NULL) 16 | if (fputs(buf, stdout) == EOF) 17 | err_sys("output error"); 18 | 19 | if (ferror(stdin)) 20 | err_sys("input error"); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/fwide: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/fwide -------------------------------------------------------------------------------- /src/05_Standard_IO/fwide.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试fwide 3 | * 4 | * apue示例程序 - fwide.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int fwide_help(FILE *fp, int mode) 13 | { 14 | if(!fp) 15 | return 0; 16 | 17 | int result = fwide(fp, mode); 18 | if(result > 0) 19 | printf("fp(%p) is wide-byte-flow\n", fp); 20 | else if(result < 0) 21 | printf("fp(%p) is byte-flow\n", fp); 22 | else 23 | printf("fp(%p) is unordered\n", fp); 24 | 25 | return result; 26 | } 27 | 28 | int main() 29 | { 30 | fwide_help(stdin, 0); // 打印stdin/stdout/stderr的流向 31 | fwide_help(stdout, 0); 32 | fwide_help(stderr, 0); 33 | 34 | FILE *fp = fopen("Makefile", "r"); 35 | if(fp != NULL) 36 | { 37 | fwide_help(fp, 0); 38 | fwide_help(fp, -1); // 修改为字节流 39 | fwide_help(fp, 1); // 尝试修改为宽字节流,但不会成功,因为一旦指定了流向就不能再改变 40 | } 41 | return 0; 42 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/getcharbug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/getcharbug -------------------------------------------------------------------------------- /src/05_Standard_IO/getcharbug.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试getchar和putchar 3 | * 4 | * apue示例程序 - getcharbug.c 5 | * https://stackoverflow.com/questions/10720821/im-trying-to-understand-getchar-eof 6 | * 7 | * @author Steve & r00tk1t 8 | * 9 | */ 10 | #include 11 | 12 | int main(void) 13 | { 14 | char c; 15 | 16 | while ((c = getchar()) != EOF) 17 | putchar(c); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/getcputc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/getcputc -------------------------------------------------------------------------------- /src/05_Standard_IO/getcputc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试putc和getc 3 | * 4 | * apue示例程序 - getcputc.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int 12 | main(void) 13 | { 14 | int c; 15 | 16 | while ((c = getc(stdin)) != EOF) 17 | if (putc(c, stdout) == EOF) 18 | err_sys("output error"); 19 | 20 | if (ferror(stdin)) 21 | err_sys("input error"); 22 | 23 | exit(0); 24 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/memstr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/memstr -------------------------------------------------------------------------------- /src/05_Standard_IO/memstr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试fmemopen 3 | * 4 | * apue示例程序 - memstr.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | #define BSZ 48 12 | 13 | int main() 14 | { 15 | FILE *fp; 16 | char buf[BSZ]; 17 | 18 | memset(buf, 'a', BSZ-2); 19 | buf[BSZ-2] = '\0'; 20 | buf[BSZ-1] = 'X'; 21 | if ((fp = fmemopen(buf, BSZ, "w+")) == NULL) 22 | err_sys("fmemopen failed"); 23 | printf("initial buffer contents: %s\n", buf); 24 | fprintf(fp, "hello, world"); 25 | printf("before flush: %s\n", buf); 26 | fflush(fp); 27 | printf("after fflush: %s\n", buf); 28 | printf("len of string in buf = %ld\n", (long)strlen(buf)); 29 | 30 | memset(buf, 'b', BSZ-2); 31 | buf[BSZ-2] = '\0'; 32 | buf[BSZ-1] = 'X'; 33 | fprintf(fp, "hello, world"); 34 | fseek(fp, 0, SEEK_SET); 35 | printf("after fseek: %s\n", buf); 36 | printf("len of string in buf = %ld\n", (long)strlen(buf)); 37 | 38 | memset(buf, 'c', BSZ-2); 39 | buf[BSZ-2] = '\0'; 40 | buf[BSZ-1] = 'X'; 41 | fprintf(fp, "hello, world"); 42 | fclose(fp); 43 | printf("after fclose: %s\n", buf); 44 | printf("len of string in buf = %ld\n", (long)strlen(buf)); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/mkstemp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/mkstemp -------------------------------------------------------------------------------- /src/05_Standard_IO/mkstemp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试mkstemp 3 | * 4 | * apue示例程序 - mkstemp.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | void make_temp(char *template); 14 | 15 | int main() 16 | { 17 | char good_template[] = "/tmp/dirXXXXXX"; /* right way */ 18 | char *bad_template = "/tmp/dirXXXXXX"; /* wrong way*/ 19 | 20 | printf("trying to create first temp file...\n"); 21 | make_temp(good_template); 22 | printf("trying to create second temp file...\n"); 23 | make_temp(bad_template); 24 | return 0; 25 | } 26 | 27 | void make_temp(char *template) 28 | { 29 | int fd; 30 | struct stat sbuf; 31 | 32 | if ((fd = mkstemp(template)) < 0) 33 | err_sys("can't create temp file"); 34 | printf("temp name = %s\n", template); 35 | close(fd); 36 | if (stat(template, &sbuf) < 0) { 37 | if (errno == ENOENT) 38 | printf("file doesn't exist\n"); 39 | else 40 | err_sys("stat failed"); 41 | } else { 42 | printf("file exists\n"); 43 | unlink(template); 44 | } 45 | } -------------------------------------------------------------------------------- /src/05_Standard_IO/tempfiles: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/05_Standard_IO/tempfiles -------------------------------------------------------------------------------- /src/05_Standard_IO/tempfiles.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试tmpfile 3 | * 4 | * apue示例程序 - tempfiles.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(void) 12 | { 13 | char name[L_tmpnam], line[MAXLINE]; 14 | FILE *fp; 15 | 16 | printf("%s\n", tmpnam(NULL)); /* first temp name */ 17 | 18 | tmpnam(name); /* second temp name */ 19 | printf("%s\n", name); 20 | 21 | if ((fp = tmpfile()) == NULL) /* create temp file */ 22 | err_sys("tmpfile error"); 23 | fputs("one line of output\n", fp); /* write to temp file */ 24 | rewind(fp); /* then read it back */ 25 | if (fgets(line, sizeof(line), fp) == NULL) 26 | err_sys("fgets error"); 27 | fputs(line, stdout); /* print the line we wrote */ 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /src/06_System_Info/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = strftime getpwnam uname getshadow 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | clean: 13 | rm -f $(PROGS) $(TEMPFILES) *.o 14 | 15 | include $(ROOT)/Make.libapue.inc -------------------------------------------------------------------------------- /src/06_System_Info/getpwnam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/06_System_Info/getpwnam -------------------------------------------------------------------------------- /src/06_System_Info/getpwnam.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试getpwent 3 | * 4 | * apue示例程序 - getpwnam.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | struct passwd * 14 | getpwnam(const char *name) 15 | { 16 | struct passwd *ptr; 17 | 18 | setpwent(); 19 | while ((ptr = getpwent()) != NULL) 20 | if (strcmp(name, ptr->pw_name) == 0) 21 | break; /* found a match */ 22 | endpwent(); 23 | return ptr; /* ptr is NULL if no match found */ 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | struct passwd *ptr; 29 | if(argc != 2) 30 | { 31 | err_quit("usage: %s name", argv[0]); 32 | } 33 | ptr = getpwnam(argv[1]); 34 | if(ptr) 35 | { 36 | printf("Get %s : %u\n", argv[1], ptr->pw_uid); 37 | } 38 | else 39 | { 40 | printf("Invalid parameter!\n"); 41 | } 42 | return 0; 43 | } -------------------------------------------------------------------------------- /src/06_System_Info/getshadow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/06_System_Info/getshadow -------------------------------------------------------------------------------- /src/06_System_Info/getshadow.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 从shadow文件中获取r00tk1t用户的信息 3 | * 4 | * apue示例程序 - getshadow.c 5 | * 需要root权限 6 | * 7 | * @author r00tk1t 8 | * 9 | */ 10 | #include"apue.h" 11 | #include 12 | 13 | int main() 14 | { 15 | struct spwd *ptr; 16 | if((ptr=getspnam("r00tk1t"))==NULL) 17 | err_sys("getspnam error"); 18 | printf("sp_pwdp=%s\n", (ptr->sp_pwdp == NULL || ptr->sp_pwdp[0] == '\0') 19 | ? "(null)" : ptr->sp_pwdp); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /src/06_System_Info/strftime: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/06_System_Info/strftime -------------------------------------------------------------------------------- /src/06_System_Info/strftime.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取时间并格式化打印字符串 3 | * 4 | * apue示例程序 - strftime.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | int main() 14 | { 15 | time_t t; 16 | struct tm *tmp; 17 | char buf1[16]; 18 | char buf2[64]; 19 | 20 | time(&t); 21 | tmp = localtime(&t); 22 | if (strftime(buf1, 16, "time and date: %r, %a %b %d, %Y", tmp) == 0) 23 | printf("buffer length 16 is too small\n"); 24 | else 25 | printf("%s\n", buf1); 26 | if (strftime(buf2, 64, "time and date: %r, %a %b %d, %Y", tmp) == 0) 27 | printf("buffer length 64 is too small\n"); 28 | else 29 | printf("%s\n", buf2); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/06_System_Info/uname: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/06_System_Info/uname -------------------------------------------------------------------------------- /src/06_System_Info/uname.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试uname/gethostname 3 | * 4 | * apue示例程序 - uname.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include"apue.h" 10 | #include 11 | #include 12 | 13 | int main(void) 14 | { 15 | int ret; 16 | struct utsname myuname; 17 | if((ret = uname(&myuname)) < 0) 18 | err_sys("uname error"); 19 | else 20 | printf("%s\t%s\t%s\t%s\t%s\n", myuname.sysname, myuname.nodename, myuname.version, myuname.release, myuname.machine); 21 | 22 | char buf[64]; 23 | if(gethostname(buf,sizeof(buf)) < 0) 24 | err_sys("gethostname error"); 25 | printf("hostname:%s\n", buf); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /src/07_Process_Env/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = doatexit echoarg getrlimit testjmp testenv echoall 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | clean: 12 | rm -f $(PROGS) $(TEMPFILES) *.o 13 | 14 | include $(ROOT)/Make.libapue.inc 15 | -------------------------------------------------------------------------------- /src/07_Process_Env/doatexit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/07_Process_Env/doatexit -------------------------------------------------------------------------------- /src/07_Process_Env/doatexit.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 注册终止处理程序 3 | * 4 | * apue示例程序 - doatexit.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void my_exit1(void); 12 | static void my_exit2(void); 13 | 14 | int main(void) 15 | { 16 | if (atexit(my_exit1) != 0) 17 | err_sys("can't register my_exit1"); 18 | 19 | if (atexit(my_exit2) != 0) 20 | err_sys("can't register my_exit2"); 21 | 22 | if (atexit(my_exit1) != 0) 23 | err_sys("can't register my_exit1"); 24 | 25 | printf("main is done\n"); 26 | return 0; 27 | } 28 | 29 | static void my_exit1(void) 30 | { 31 | printf("first exit handler\n"); 32 | } 33 | 34 | static void my_exit2(void) 35 | { 36 | printf("second exit handler\n"); 37 | } 38 | -------------------------------------------------------------------------------- /src/07_Process_Env/echoall: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/07_Process_Env/echoall -------------------------------------------------------------------------------- /src/07_Process_Env/echoall.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 全局变量environ测试 3 | * 4 | * apue示例程序 - echoall.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int i; 14 | char **ptr; 15 | extern char **environ; 16 | 17 | for (i = 0; i < argc; i++) /* echo all command-line args */ 18 | printf("argv[%d]: %s\n", i, argv[i]); 19 | 20 | for (ptr = environ; *ptr != 0; ptr++) /* and all env strings */ 21 | printf("%s\n", *ptr); 22 | 23 | exit(0); 24 | } 25 | -------------------------------------------------------------------------------- /src/07_Process_Env/echoarg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/07_Process_Env/echoarg -------------------------------------------------------------------------------- /src/07_Process_Env/echoarg.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 遍历argv参数 3 | * 4 | * apue示例程序 - echoarg.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[], char *env[]) 12 | { 13 | int i; 14 | 15 | for (i = 0; i < argc; i++) /* echo all command-line args */ 16 | printf("argv[%d]: %s\n", i, argv[i]); 17 | 18 | for (i=0; ;++i) 19 | { 20 | if(env[i] == NULL) 21 | break; 22 | printf("env[%d]:%s\n", i, env[i]); 23 | } 24 | exit(0); 25 | } 26 | -------------------------------------------------------------------------------- /src/07_Process_Env/getrlimit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/07_Process_Env/getrlimit -------------------------------------------------------------------------------- /src/07_Process_Env/getrlimit.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取进程资源限制 3 | * 4 | * apue示例程序 - getrlimit.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | #define doit(name) pr_limits(#name, name) 13 | 14 | static void pr_limits(char *, int); 15 | 16 | int main(void) 17 | { 18 | #ifdef RLIMIT_AS 19 | doit(RLIMIT_AS); 20 | #endif 21 | 22 | doit(RLIMIT_CORE); 23 | doit(RLIMIT_CPU); 24 | doit(RLIMIT_DATA); 25 | doit(RLIMIT_FSIZE); 26 | 27 | #ifdef RLIMIT_MEMLOCK 28 | doit(RLIMIT_MEMLOCK); 29 | #endif 30 | 31 | #ifdef RLIMIT_MSGQUEUE 32 | doit(RLIMIT_MSGQUEUE); 33 | #endif 34 | 35 | #ifdef RLIMIT_NICE 36 | doit(RLIMIT_NICE); 37 | #endif 38 | 39 | doit(RLIMIT_NOFILE); 40 | 41 | #ifdef RLIMIT_NPROC 42 | doit(RLIMIT_NPROC); 43 | #endif 44 | 45 | #ifdef RLIMIT_NPTS 46 | doit(RLIMIT_NPTS); 47 | #endif 48 | 49 | #ifdef RLIMIT_RSS 50 | doit(RLIMIT_RSS); 51 | #endif 52 | 53 | #ifdef RLIMIT_SBSIZE 54 | doit(RLIMIT_SBSIZE); 55 | #endif 56 | 57 | #ifdef RLIMIT_SIGPENDING 58 | doit(RLIMIT_SIGPENDING); 59 | #endif 60 | 61 | doit(RLIMIT_STACK); 62 | 63 | #ifdef RLIMIT_SWAP 64 | doit(RLIMIT_SWAP); 65 | #endif 66 | 67 | #ifdef RLIMIT_VMEM 68 | doit(RLIMIT_VMEM); 69 | #endif 70 | 71 | exit(0); 72 | } 73 | 74 | static void pr_limits(char *name, int resource) 75 | { 76 | struct rlimit limit; 77 | unsigned long long lim; 78 | 79 | if (getrlimit(resource, &limit) < 0) 80 | err_sys("getrlimit error for %s", name); 81 | printf("%-14s ", name); 82 | if (limit.rlim_cur == RLIM_INFINITY) { 83 | printf("(infinite) "); 84 | } else { 85 | lim = limit.rlim_cur; 86 | printf("%10lld ", lim); 87 | } 88 | if (limit.rlim_max == RLIM_INFINITY) { 89 | printf("(infinite)"); 90 | } else { 91 | lim = limit.rlim_max; 92 | printf("%10lld", lim); 93 | } 94 | putchar((int)'\n'); 95 | } 96 | -------------------------------------------------------------------------------- /src/07_Process_Env/testenv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/07_Process_Env/testenv -------------------------------------------------------------------------------- /src/07_Process_Env/testenv.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试环境变量 3 | * 4 | * apue示例程序 - testenv.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | char *p; 15 | if(p = getenv("USER")) 16 | printf("USER=%s\n", p); 17 | // overwrite 18 | if(setenv("USER", "test", 1) != 0) 19 | err_sys("setenv error"); 20 | if(p = getenv("USER")) 21 | printf("USER=%s\n", p); 22 | if(putenv("USER=root") != 0) 23 | err_sys("putenv error"); 24 | if(p = getenv("USER")) 25 | printf("USER=%s\n", p); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /src/07_Process_Env/testjmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/07_Process_Env/testjmp -------------------------------------------------------------------------------- /src/07_Process_Env/testjmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试setjmp/longjmp 3 | * 4 | * apue示例程序 - testjmp.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void f1(int, int, int, int); 13 | static void f2(void); 14 | 15 | static jmp_buf jmpbuffer; 16 | static int globval; 17 | 18 | int main(void) 19 | { 20 | int autoval; 21 | register int regival; 22 | volatile int volaval; 23 | static int statval; 24 | 25 | globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5; 26 | 27 | if (setjmp(jmpbuffer) != 0) { 28 | printf("after longjmp:\n"); 29 | printf("globval = %d, autoval = %d, regival = %d," 30 | " volaval = %d, statval = %d\n", 31 | globval, autoval, regival, volaval, statval); 32 | exit(0); 33 | } 34 | 35 | /* 36 | * Change variables after setjmp, but before longjmp. 37 | */ 38 | globval = 95; autoval = 96; regival = 97; volaval = 98; 39 | statval = 99; 40 | 41 | f1(autoval, regival, volaval, statval); /* never returns */ 42 | exit(0); 43 | } 44 | 45 | static void f1(int i, int j, int k, int l) 46 | { 47 | printf("in f1():\n"); 48 | printf("globval = %d, autoval = %d, regival = %d," 49 | " volaval = %d, statval = %d\n", globval, i, j, k, l); 50 | f2(); 51 | } 52 | 53 | static void f2(void) 54 | { 55 | longjmp(jmpbuffer, 1); 56 | } 57 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = exec1 exec2 fork1 fork2 nice pruids system systest tellwait1 tellwait2 test1 times1 tsys vfork1 wait1 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | clean: 12 | rm -f $(PROGS) $(TEMPFILES) *.o 13 | 14 | include $(ROOT)/Make.libapue.inc 15 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/exec1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/exec1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/exec1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file exec测试用例1 3 | * 4 | * apue示例程序 - exec1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | char* env_init[] = { "USER=unknown", "PATH=/tmp", NULL }; 13 | 14 | int main(void) 15 | { 16 | pid_t pid; 17 | 18 | if ((pid = fork()) < 0) { 19 | err_sys("fork error"); 20 | } else if (pid == 0) { /* specify pathname, specify environment */ 21 | if (execle("/home/r00tk1t/apue/src/07_Process_Env/echoall", "echoall", "myarg1", 22 | "MY ARG2", (char *)0, env_init) < 0) 23 | err_sys("execle error"); 24 | } 25 | 26 | if (waitpid(pid, NULL, 0) < 0) 27 | err_sys("wait error"); 28 | 29 | if ((pid = fork()) < 0) { 30 | err_sys("fork error"); 31 | } else if (pid == 0) { /* specify filename, inherit environment */ 32 | if (execlp("/home/r00tk1t/apue/src/07_Process_Env/echoall", "echoall", "only 1 arg", (char *)0) < 0) 33 | err_sys("execlp error"); 34 | } 35 | 36 | exit(0); 37 | } 38 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/exec2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/exec2 -------------------------------------------------------------------------------- /src/08_Process_Ctl/exec2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file exec测试用例2 3 | * 4 | * apue示例程序 - exec2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(void) 13 | { 14 | pid_t pid; 15 | 16 | if ((pid = fork()) < 0) { 17 | err_sys("fork error"); 18 | } else if (pid == 0) { /* child */ 19 | if (execl("/home/sar/bin/testinterp", 20 | "testinterp", "myarg1", "MY ARG2", (char *)0) < 0) 21 | err_sys("execl error"); 22 | } 23 | if (waitpid(pid, NULL, 0) < 0) /* parent */ 24 | err_sys("waitpid error"); 25 | exit(0); 26 | } 27 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/fork1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/fork1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/fork1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fork测试用例1 3 | * 4 | * apue示例程序 - fork1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int globvar = 6; /* external variable in initialized data */ 12 | char buf[] = "a write to stdout\n"; 13 | 14 | int main(void) 15 | { 16 | int var; /* automatic variable on the stack */ 17 | pid_t pid; 18 | 19 | var = 88; 20 | if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) 21 | err_sys("write error"); 22 | printf("before fork\n"); /* we don't flush stdout */ 23 | 24 | if ((pid = fork()) < 0) { 25 | err_sys("fork error"); 26 | } else if (pid == 0) { /* child */ 27 | globvar++; /* modify variables */ 28 | var++; 29 | } else { 30 | sleep(2); /* parent */ 31 | } 32 | 33 | printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, 34 | var); 35 | exit(0); 36 | } 37 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/fork1.log: -------------------------------------------------------------------------------- 1 | a write to stdout 2 | before fork 3 | pid = 61584, glob = 7, var = 89 4 | before fork 5 | pid = 61583, glob = 6, var = 88 6 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/fork2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/fork2 -------------------------------------------------------------------------------- /src/08_Process_Ctl/fork2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fork测试用例2 3 | * 4 | * apue示例程序 - fork2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(void) 13 | { 14 | pid_t pid; 15 | 16 | if ((pid = fork()) < 0) { 17 | err_sys("fork error"); 18 | } else if (pid == 0) { /* first child */ 19 | if ((pid = fork()) < 0) 20 | err_sys("fork error"); 21 | else if (pid > 0) 22 | exit(0); /* parent from second fork == first child */ 23 | 24 | /* 25 | * We're the second child; our parent becomes init as soon 26 | * as our real parent calls exit() in the statement above. 27 | * Here's where we'd continue executing, knowing that when 28 | * we're done, init will reap our status. 29 | */ 30 | sleep(2); 31 | printf("second child, parent pid = %ld\n", (long)getppid()); 32 | exit(0); 33 | } 34 | 35 | if (waitpid(pid, NULL, 0) != pid) /* wait for first child */ 36 | err_sys("waitpid error"); 37 | 38 | /* 39 | * We're the parent (the original process); we continue executing, 40 | * knowing that we're not the parent of the second child. 41 | */ 42 | exit(0); 43 | } 44 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/nice: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/nice -------------------------------------------------------------------------------- /src/08_Process_Ctl/nice.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 跨平台nice测试 3 | * 4 | * apue示例程序 - nice.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | #if defined(MACOS) 14 | #include 15 | #elif defined(SOLARIS) 16 | #include 17 | #elif defined(BSD) 18 | #include 19 | #endif 20 | 21 | unsigned long long count; 22 | struct timeval end; 23 | 24 | void checktime(char *str) 25 | { 26 | struct timeval tv; 27 | 28 | gettimeofday(&tv, NULL); 29 | if (tv.tv_sec >= end.tv_sec && tv.tv_usec >= end.tv_usec) { 30 | printf("%s count = %lld\n", str, count); 31 | exit(0); 32 | } 33 | } 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | pid_t pid; 38 | char *s; 39 | int nzero, ret; 40 | int adj = 0; 41 | 42 | setbuf(stdout, NULL); 43 | #if defined(NZERO) 44 | nzero = NZERO; 45 | #elif defined(_SC_NZERO) 46 | nzero = sysconf(_SC_NZERO); 47 | #else 48 | #error NZERO undefined 49 | #endif 50 | printf("NZERO = %d\n", nzero); 51 | if (argc == 2) 52 | adj = strtol(argv[1], NULL, 10); 53 | gettimeofday(&end, NULL); 54 | end.tv_sec += 10; /* run for 10_Process_Rel seconds */ 55 | 56 | if ((pid = fork()) < 0) { 57 | err_sys("fork failed"); 58 | } else if (pid == 0) { /* child */ 59 | s = "child"; 60 | printf("current nice value in child is %d, adjusting by %d\n", 61 | nice(0)+nzero, adj); 62 | errno = 0; 63 | if ((ret = nice(adj)) == -1 && errno != 0) 64 | err_sys("child set scheduling priority"); 65 | printf("now child nice value is %d\n", ret+nzero); 66 | } else { /* parent */ 67 | s = "parent"; 68 | printf("current nice value in parent is %d\n", nice(0)+nzero); 69 | } 70 | for(;;) { 71 | if (++count == 0) 72 | err_quit("%s counter wrap", s); 73 | checktime(s); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/pruids: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/pruids -------------------------------------------------------------------------------- /src/08_Process_Ctl/pruids.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取实际用户id和有效用户id 3 | * 4 | * apue示例程序 - pruids.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(void) 12 | { 13 | printf("real uid = %d, effective uid = %d\n", getuid(), geteuid()); 14 | exit(0); 15 | } 16 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/system: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/system -------------------------------------------------------------------------------- /src/08_Process_Ctl/system.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 模拟system实现 3 | * 4 | * apue示例程序 - system.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | int system(const char *cmdstring) /* version without signal handling */ 14 | { 15 | pid_t pid; 16 | int status; 17 | 18 | if (cmdstring == NULL) 19 | return(1); /* always a command processor with UNIX */ 20 | 21 | if ((pid = fork()) < 0) { 22 | status = -1; /* probably out of processes */ 23 | } else if (pid == 0) { /* child */ 24 | execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 25 | _exit(127); /* execl error */ 26 | } else { /* parent */ 27 | while (waitpid(pid, &status, 0) < 0) { 28 | if (errno != EINTR) { 29 | status = -1; /* error other than EINTR from waitpid() */ 30 | break; 31 | } 32 | } 33 | } 34 | 35 | return(status); 36 | } 37 | 38 | int main(void) 39 | { 40 | int status; 41 | 42 | if ((status = system("date")) < 0) 43 | err_sys("system() error"); 44 | 45 | pr_exit(status); 46 | 47 | if ((status = system("nosuchcommand")) < 0) 48 | err_sys("system() error"); 49 | 50 | pr_exit(status); 51 | 52 | if ((status = system("who; exit 44")) < 0) 53 | err_sys("system() error"); 54 | 55 | pr_exit(status); 56 | 57 | exit(0); 58 | } -------------------------------------------------------------------------------- /src/08_Process_Ctl/systest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/systest -------------------------------------------------------------------------------- /src/08_Process_Ctl/systest.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 原生system测试 3 | * 4 | * apue示例程序 - systest.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(void) 13 | { 14 | int status; 15 | 16 | if ((status = system("date")) < 0) 17 | err_sys("system() error"); 18 | 19 | pr_exit(status); 20 | 21 | if ((status = system("nosuchcommand")) < 0) 22 | err_sys("system() error"); 23 | 24 | pr_exit(status); 25 | 26 | if ((status = system("who; exit 44")) < 0) 27 | err_sys("system() error"); 28 | 29 | pr_exit(status); 30 | 31 | exit(0); 32 | } 33 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/tellwait1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/tellwait1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/tellwait1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试父子进程调用顺序 3 | * 4 | * apue示例程序 - tellwait1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void charatatime(char *); 12 | 13 | int main(void) 14 | { 15 | pid_t pid; 16 | 17 | if ((pid = fork()) < 0) { 18 | err_sys("fork error"); 19 | } else if (pid == 0) { 20 | charatatime("output from child\n"); 21 | } else { 22 | charatatime("output from parent\n"); 23 | } 24 | exit(0); 25 | } 26 | 27 | static void charatatime(char *str) 28 | { 29 | char *ptr; 30 | int c; 31 | 32 | setbuf(stdout, NULL); /* set unbuffered */ 33 | for (ptr = str; (c = *ptr++) != 0; ) 34 | putc(c, stdout); 35 | } 36 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/tellwait2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/tellwait2 -------------------------------------------------------------------------------- /src/08_Process_Ctl/tellwait2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void charatatime(char *); 4 | 5 | int main(void) 6 | { 7 | pid_t pid; 8 | 9 | TELL_WAIT(); 10 | 11 | if ((pid = fork()) < 0) { 12 | err_sys("fork error"); 13 | } else if (pid == 0) { 14 | WAIT_PARENT(); /* parent goes first */ 15 | charatatime("output from child\n"); 16 | } else { 17 | charatatime("output from parent\n"); 18 | TELL_CHILD(pid); 19 | } 20 | exit(0); 21 | } 22 | 23 | static void charatatime(char *str) 24 | { 25 | char *ptr; 26 | int c; 27 | 28 | setbuf(stdout, NULL); /* set unbuffered */ 29 | for (ptr = str; (c = *ptr++) != 0; ) 30 | putc(c, stdout); 31 | } 32 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/test1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/test1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/test1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 花式测试 3 | * 4 | * apue示例程序 - test1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(void) 12 | { 13 | pid_t pid; 14 | 15 | if ((pid = fork()) < 0) 16 | err_sys("fork error"); 17 | else if (pid != 0) { /* parent */ 18 | sleep(2); 19 | exit(2); /* terminate with exit status 2 */ 20 | } 21 | 22 | if ((pid = fork()) < 0) 23 | err_sys("fork error"); 24 | else if (pid != 0) { /* first child */ 25 | sleep(4); 26 | abort(); /* terminate with core dump */ 27 | } 28 | 29 | if ((pid = fork()) < 0) 30 | err_sys("fork error"); 31 | else if (pid != 0) { /* second child */ 32 | execl("/bin/dd", "dd", "if=/etc/passwd", "of=/dev/null", NULL); 33 | exit(7); /* shouldn't get here */ 34 | } 35 | 36 | if ((pid = fork()) < 0) 37 | err_sys("fork error"); 38 | else if (pid != 0) { /* third child */ 39 | sleep(8); 40 | exit(0); /* normal exit */ 41 | } 42 | 43 | sleep(6); /* fourth child */ 44 | kill(getpid(), SIGKILL); /* terminate w/signal, no core dump */ 45 | exit(6); /* shouldn't get here */ 46 | } 47 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/times1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/times1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/times1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file times测试用例 3 | * 4 | * apue示例程序 - times1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void pr_times(clock_t, struct tms *, struct tms *); 13 | static void do_cmd(char *); 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | int i; 18 | 19 | setbuf(stdout, NULL); 20 | for (i = 1; i < argc; i++) 21 | do_cmd(argv[i]); /* once for each command-line arg */ 22 | exit(0); 23 | } 24 | 25 | static void do_cmd(char *cmd) /* execute and time the "cmd" */ 26 | { 27 | struct tms tmsstart, tmsend; 28 | clock_t start, end; 29 | int status; 30 | 31 | printf("\ncommand: %s\n", cmd); 32 | 33 | if ((start = times(&tmsstart)) == -1) /* starting values */ 34 | err_sys("times error"); 35 | 36 | if ((status = system(cmd)) < 0) /* execute command */ 37 | err_sys("system() error"); 38 | 39 | if ((end = times(&tmsend)) == -1) /* ending values */ 40 | err_sys("times error"); 41 | 42 | pr_times(end-start, &tmsstart, &tmsend); 43 | pr_exit(status); 44 | } 45 | 46 | static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) 47 | { 48 | static long clktck = 0; 49 | 50 | if (clktck == 0) /* fetch clock ticks per second first time */ 51 | if ((clktck = sysconf(_SC_CLK_TCK)) < 0) 52 | err_sys("sysconf error"); 53 | 54 | printf(" real: %7.2f\n", real / (double) clktck); 55 | printf(" user: %7.2f\n", 56 | (tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck); 57 | printf(" sys: %7.2f\n", 58 | (tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck); 59 | printf(" child user: %7.2f\n", 60 | (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck); 61 | printf(" child sys: %7.2f\n", 62 | (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck); 63 | } 64 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/tsys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/tsys -------------------------------------------------------------------------------- /src/08_Process_Ctl/tsys.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 设置用户ID下测试system,配合pruids 3 | * 4 | * apue示例程序 - system.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int status; 14 | 15 | if (argc < 2) 16 | err_quit("command-line argument required"); 17 | 18 | if ((status = system(argv[1])) < 0) 19 | err_sys("system() error"); 20 | 21 | pr_exit(status); 22 | 23 | exit(0); 24 | } 25 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/vfork1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/vfork1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/vfork1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file vfork测试用例 3 | * 4 | * apue示例程序 - vfork1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int globvar = 6; /* external variable in initialized data */ 12 | 13 | int main(void) 14 | { 15 | int var; /* automatic variable on the stack */ 16 | pid_t pid; 17 | 18 | var = 88; 19 | printf("before vfork\n"); /* we don't flush stdio */ 20 | if ((pid = vfork()) < 0) { 21 | err_sys("vfork error"); 22 | } else if (pid == 0) { /* child */ 23 | globvar++; /* modify parent's variables */ 24 | var++; 25 | _exit(0); /* child terminates */ 26 | } 27 | 28 | /* parent continues here */ 29 | printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, 30 | var); 31 | exit(0); 32 | } 33 | -------------------------------------------------------------------------------- /src/08_Process_Ctl/wait1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/08_Process_Ctl/wait1 -------------------------------------------------------------------------------- /src/08_Process_Ctl/wait1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file wait测试用例 3 | * 4 | * apue示例程序 - wait1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(void) 13 | { 14 | pid_t pid; 15 | int status; 16 | 17 | if ((pid = fork()) < 0) 18 | err_sys("fork error"); 19 | else if (pid == 0) /* child */ 20 | exit(7); 21 | 22 | if (wait(&status) != pid) /* wait for child */ 23 | err_sys("wait error"); 24 | pr_exit(status); /* and print its status */ 25 | 26 | if ((pid = fork()) < 0) 27 | err_sys("fork error"); 28 | else if (pid == 0) /* child */ 29 | abort(); /* generates SIGABRT */ 30 | 31 | if (wait(&status) != pid) /* wait for child */ 32 | err_sys("wait error"); 33 | pr_exit(status); /* and print its status */ 34 | 35 | if ((pid = fork()) < 0) 36 | err_sys("fork error"); 37 | else if (pid == 0) /* child */ 38 | status /= 0; /* divide by 0 generates SIGFPE */ 39 | 40 | if (wait(&status) != pid) /* wait for child */ 41 | err_sys("wait error"); 42 | pr_exit(status); /* and print its status */ 43 | 44 | exit(0); 45 | } 46 | -------------------------------------------------------------------------------- /src/09_Process_Rel/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = orphan3 printid 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | clean: 13 | rm -f $(PROGS) $(TEMPFILES) *.o 14 | 15 | include $(ROOT)/Make.libapue.inc 16 | -------------------------------------------------------------------------------- /src/09_Process_Rel/orphan3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Process_Rel/orphan3 -------------------------------------------------------------------------------- /src/09_Process_Rel/orphan3.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 孤儿进程组SIGHUP|SIGCONT 3 | * 4 | * apue示例程序 - orphan3.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void sig_hup(int signo) 13 | { 14 | printf("SIGHUP received, pid = %ld\n", (long)getpid()); 15 | } 16 | 17 | static void pr_ids(char *name) 18 | { 19 | printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n", 20 | name, (long)getpid(), (long)getppid(), (long)getpgrp(), 21 | (long)tcgetpgrp(STDIN_FILENO)); 22 | fflush(stdout); 23 | } 24 | 25 | static void sig_cont(int signo) 26 | { 27 | printf("SIGCONT received, pid = %ld\n", (long)getpid()); 28 | } 29 | 30 | int main(void) 31 | { 32 | char c; 33 | pid_t pid; 34 | 35 | pr_ids("parent"); 36 | if ((pid = fork()) < 0) { 37 | err_sys("fork error"); 38 | } else if (pid > 0) { /* parent */ 39 | sleep(5); /* sleep to let child stop itself */ 40 | } else { /* child */ 41 | pr_ids("child"); 42 | signal(SIGHUP, sig_hup); /* establish signal handler */ 43 | //signal(SIGCONT, sig_cont); 44 | kill(getpid(), SIGTSTP); /* stop ourself */ 45 | pr_ids("child"); /* prints only if we're continued */ 46 | if (read(STDIN_FILENO, &c, 1) != 1) 47 | printf("read error %d on controlling TTY\n", errno); 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/09_Process_Rel/printid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Process_Rel/printid -------------------------------------------------------------------------------- /src/09_Process_Rel/printid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 打印相关id 3 | * 4 | * apue示例程序 - printid.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | void pr_ids(char *name) 13 | { 14 | printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n", 15 | name, (long)getpid(), (long)getppid(), (long)getpgrp(), 16 | (long)tcgetpgrp(STDIN_FILENO)); 17 | } 18 | 19 | int main() 20 | { 21 | pid_t pid; 22 | int status; 23 | 24 | pr_ids("parent"); 25 | if ((pid = fork()) < 0) { 26 | err_sys("fork error"); 27 | } else if (pid > 0) { /* parent */ 28 | if (wait(&status) != pid) /* wait for child */ 29 | err_sys("wait error"); 30 | } else { /* child */ 31 | pr_ids("child"); 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /src/09_Signals/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = critical read1 read2 reenter sigtstp sigusr suspend1 suspend2 abort sigint 6 | MOREPROGS = systest2 tsleep2 7 | 8 | all: $(PROGS) $(MOREPROGS) sleep1.o sleep2.o system.o abort.o 9 | 10 | $(PROGS): $(LIBAPUE) 11 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 12 | 13 | tsleep2: tsleep2.o sleep2.o 14 | $(CC) $(CFLAGS) -o tsleep2 tsleep2.o sleep2.o $(LDFLAGS) $(LDLIBS) 15 | 16 | systest2: systest2.o system.o 17 | $(CC) $(CFLAGS) -o systest2 systest2.o system.o $(LDFLAGS) $(LDLIBS) 18 | 19 | clean: 20 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o file.hole 21 | 22 | include $(ROOT)/Make.libapue.inc 23 | -------------------------------------------------------------------------------- /src/09_Signals/abort: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/abort -------------------------------------------------------------------------------- /src/09_Signals/abort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file abort模拟实现 3 | * 4 | * apue示例程序 - abort.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void abort() 15 | { 16 | sigset_t mask; 17 | struct sigaction action; 18 | 19 | /* Caller can't ignore SIGABRT, if so reset to default */ 20 | sigaction(SIGABRT, NULL, &action); 21 | if (action.sa_handler == SIG_IGN) { 22 | action.sa_handler = SIG_DFL; 23 | sigaction(SIGABRT, &action, NULL); 24 | } 25 | if (action.sa_handler == SIG_DFL) 26 | fflush(NULL); /* flush all open stdio streams */ 27 | 28 | /* Caller can't block SIGABRT; make sure it's unblocked */ 29 | sigfillset(&mask); 30 | sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ 31 | sigprocmask(SIG_SETMASK, &mask, NULL); 32 | kill(getpid(), SIGABRT); /* send the signal */ 33 | 34 | /* If we're here, process caught SIGABRT and returned */ 35 | fflush(NULL); /* flush all open stdio streams */ 36 | action.sa_handler = SIG_DFL; 37 | sigaction(SIGABRT, &action, NULL); /* reset to default */ 38 | sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */ 39 | kill(getpid(), SIGABRT); /* and one more time */ 40 | exit(1); /* this should never be executed ... */ 41 | } -------------------------------------------------------------------------------- /src/09_Signals/abort.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/abort.o -------------------------------------------------------------------------------- /src/09_Signals/critical: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/critical -------------------------------------------------------------------------------- /src/09_Signals/critical.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SIGQUIT捕获测试 3 | * 4 | * apue示例程序 - critical.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_quit(int); 12 | 13 | int main() 14 | { 15 | sigset_t newmask, oldmask, pendmask; 16 | 17 | if (signal(SIGQUIT, sig_quit) == SIG_ERR) 18 | err_sys("can't catch SIGQUIT"); 19 | 20 | /* 21 | * Block SIGQUIT and save current signal mask. 22 | */ 23 | sigemptyset(&newmask); 24 | sigaddset(&newmask, SIGQUIT); 25 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 26 | err_sys("SIG_BLOCK error"); 27 | 28 | sleep(5); /* SIGQUIT here will remain pending */ 29 | 30 | if (sigpending(&pendmask) < 0) 31 | err_sys("sigpending error"); 32 | if (sigismember(&pendmask, SIGQUIT)) 33 | printf("\nSIGQUIT pending\n"); 34 | 35 | /* 36 | * Restore signal mask which unblocks SIGQUIT. 37 | */ 38 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 39 | err_sys("SIG_SETMASK error"); 40 | printf("SIGQUIT unblocked\n"); 41 | 42 | sleep(5); /* SIGQUIT here will terminate with core file */ 43 | exit(0); 44 | } 45 | 46 | static void sig_quit(int signo) 47 | { 48 | printf("caught SIGQUIT\n"); 49 | if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) 50 | err_sys("can't reset SIGQUIT"); 51 | } 52 | -------------------------------------------------------------------------------- /src/09_Signals/read1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/read1 -------------------------------------------------------------------------------- /src/09_Signals/read1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 低速系统调用打断测试 3 | * 4 | * apue示例程序 - read1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_alrm(int); 12 | 13 | int main() 14 | { 15 | int n; 16 | char line[MAXLINE]; 17 | 18 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 19 | err_sys("signal(SIGALRM) error"); 20 | 21 | /* 22 | * 1.alarm和read不是原子的,中间可能会被调度出去,如果调度出去的时间超过了定时器的时间, 23 | * 那么read就可能永久阻塞,alarm定时器无法达到停止read的效果 24 | * 2.如果read实现是自动重启的,SIGALRM中断程序返回是不会打断read的 25 | */ 26 | alarm(5); 27 | if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) 28 | err_sys("read error"); 29 | alarm(0); 30 | 31 | write(STDOUT_FILENO, line, n); 32 | exit(0); 33 | } 34 | 35 | static void sig_alrm(int signo) 36 | { 37 | /* nothing to do, just return to interrupt the read */ 38 | } 39 | -------------------------------------------------------------------------------- /src/09_Signals/read2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/read2 -------------------------------------------------------------------------------- /src/09_Signals/read2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file setjmp/longjmp解决自动重启问题,但依然蹩脚 3 | * 4 | * apue示例程序 - read2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void sig_alrm(int); 13 | static jmp_buf env_alrm; 14 | 15 | int main(void) 16 | { 17 | int n; 18 | char line[MAXLINE]; 19 | 20 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 21 | err_sys("signal(SIGALRM) error"); 22 | if (setjmp(env_alrm) != 0) 23 | err_quit("read timeout"); 24 | 25 | alarm(10); 26 | if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) 27 | err_sys("read error"); 28 | alarm(0); 29 | 30 | write(STDOUT_FILENO, line, n); 31 | exit(0); 32 | } 33 | 34 | static void sig_alrm(int signo) 35 | { 36 | longjmp(env_alrm, 1); 37 | } 38 | -------------------------------------------------------------------------------- /src/09_Signals/reenter: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/reenter -------------------------------------------------------------------------------- /src/09_Signals/reenter.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试中断调用不可重入函数引起的负面效果 3 | * 4 | * apue示例程序 - reenter.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void my_alarm(int signo) 13 | { 14 | struct passwd *rootptr; 15 | 16 | printf("in signal handler\n"); 17 | // ubuntu x64 16.04会死锁 18 | if ((rootptr = getpwnam("root")) == NULL) 19 | err_sys("getpwnam(root) error"); 20 | printf("finish"); 21 | alarm(1); 22 | } 23 | 24 | int main(void) 25 | { 26 | struct passwd *ptr; 27 | 28 | signal(SIGALRM, my_alarm); 29 | alarm(1); 30 | for ( ; ; ) { 31 | if ((ptr = getpwnam("r00tk1t")) == NULL) 32 | err_sys("getpwnam error"); 33 | if (strcmp(ptr->pw_name, "r00tk1t") != 0) 34 | printf("return value corrupted!, pw_name = %s\n", 35 | ptr->pw_name); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/09_Signals/setops.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 信号屏蔽字/阻塞集模拟实现 3 | * 4 | * apue示例程序 - setops.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | /* 13 | * usually defines NSIG to include signal number 0. 14 | */ 15 | #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG) 16 | 17 | int sigaddset(sigset_t *set, int signo) 18 | { 19 | if (SIGBAD(signo)) { 20 | errno = EINVAL; 21 | return(-1); 22 | } 23 | *set |= 1 << (signo - 1); /* turn bit on */ 24 | return(0); 25 | } 26 | 27 | int sigdelset(sigset_t *set, int signo) 28 | { 29 | if (SIGBAD(signo)) { 30 | errno = EINVAL; 31 | return(-1); 32 | } 33 | *set &= ~(1 << (signo - 1)); /* turn bit off */ 34 | return(0); 35 | } 36 | 37 | int sigismember(const sigset_t *set, int signo) 38 | { 39 | if (SIGBAD(signo)) { 40 | errno = EINVAL; 41 | return(-1); 42 | } 43 | return((*set & (1 << (signo - 1))) != 0); 44 | } 45 | -------------------------------------------------------------------------------- /src/09_Signals/sigint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/sigint -------------------------------------------------------------------------------- /src/09_Signals/sigint.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试sigint 3 | * 4 | * apue示例程序 - sigint.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_int(int signo) 12 | { 13 | printf("caught SIGINT\n"); 14 | } 15 | 16 | static void sig_quit() 17 | { 18 | printf("caught SIGQUIT\n"); 19 | } 20 | 21 | int main(void) 22 | { 23 | if (signal(SIGINT, sig_int) == SIG_ERR) 24 | err_sys("signal(SIGINT) error"); 25 | if (signal(SIGQUIT, sig_quit) == SIG_ERR) 26 | err_sys("signal(SIGQUIT) error"); 27 | while(1); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /src/09_Signals/sigtstp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/sigtstp -------------------------------------------------------------------------------- /src/09_Signals/sigtstp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试SIGTSTP 3 | * 4 | * apue示例程序 - sigtstp.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | #define BUFFSIZE 1024 12 | 13 | static void sig_tstp(int signo) /* signal handler for SIGTSTP */ 14 | { 15 | sigset_t mask; 16 | 17 | /* ... move cursor to lower left corner, reset tty mode ... */ 18 | 19 | /* 20 | * Unblock SIGTSTP, since it's blocked while we're handling it. 21 | */ 22 | sigemptyset(&mask); 23 | sigaddset(&mask, SIGTSTP); 24 | sigprocmask(SIG_UNBLOCK, &mask, NULL); 25 | 26 | signal(SIGTSTP, SIG_DFL); /* reset disposition to default */ 27 | 28 | kill(getpid(), SIGTSTP); /* and send the signal to ourself */ 29 | 30 | /* we won't return from the kill until we're continued */ 31 | 32 | signal(SIGTSTP, sig_tstp); /* reestablish signal handler */ 33 | 34 | /* ... reset tty mode, redraw screen ... */ 35 | } 36 | 37 | int main() 38 | { 39 | int n; 40 | char buf[BUFFSIZE]; 41 | 42 | /* 43 | * Only catch SIGTSTP if we're running with a job-control shell. 44 | */ 45 | if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) 46 | signal(SIGTSTP, sig_tstp); 47 | 48 | while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) 49 | if (write(STDOUT_FILENO, buf, n) != n) 50 | err_sys("write error"); 51 | 52 | if (n < 0) 53 | err_sys("read error"); 54 | 55 | exit(0); 56 | } 57 | -------------------------------------------------------------------------------- /src/09_Signals/sigusr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/sigusr -------------------------------------------------------------------------------- /src/09_Signals/sigusr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 自定义信号测试 3 | * 4 | * apue示例程序 - sigusr.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_usr(int); /* one handler for both signals */ 12 | 13 | int main() 14 | { 15 | if (signal(SIGUSR1, sig_usr) == SIG_ERR) 16 | err_sys("can't catch SIGUSR1"); 17 | if (signal(SIGUSR2, sig_usr) == SIG_ERR) 18 | err_sys("can't catch SIGUSR2"); 19 | for ( ; ; ) 20 | pause(); 21 | } 22 | 23 | static void sig_usr(int signo) /* argument is signal number */ 24 | { 25 | if (signo == SIGUSR1) 26 | printf("received SIGUSR1\n"); 27 | else if (signo == SIGUSR2) 28 | printf("received SIGUSR2\n"); 29 | else 30 | err_dump("received signal %d\n", signo); 31 | } 32 | -------------------------------------------------------------------------------- /src/09_Signals/sleep1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sleep模拟实现1 3 | * 4 | * apue示例程序 - sleep1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | static void sig_alrm(int signo) 13 | { 14 | /* nothing to do, just return to wake up the pause */ 15 | } 16 | 17 | unsigned int sleep1(unsigned int seconds) 18 | { 19 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 20 | return(seconds); 21 | /* 22 | * 1. alarm和pause非原子,如果alarm后被调度出去,seconds后才会来调用pause,则可能会永久阻塞 23 | * 2. 如果用户设置过定时器,会破坏现状,sig_alrm也被内部消化掉了,外部不知这一事实 24 | */ 25 | alarm(seconds); /* start the timer */ 26 | pause(); /* next caught signal wakes us up */ 27 | return(alarm(0)); /* turn off timer, return unslept time */ 28 | } 29 | -------------------------------------------------------------------------------- /src/09_Signals/sleep1.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/sleep1.o -------------------------------------------------------------------------------- /src/09_Signals/sleep2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sleep模拟实现2,解决了原子问题,但依然蹩脚 3 | * 4 | * apue示例程序 - sleep2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | static jmp_buf env_alrm; 14 | 15 | static void sig_alrm(int signo) 16 | { 17 | longjmp(env_alrm, 1); 18 | } 19 | 20 | unsigned int sleep2(unsigned int seconds) 21 | { 22 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 23 | return(seconds); 24 | if (setjmp(env_alrm) == 0) { 25 | alarm(seconds); /* start the timer */ 26 | pause(); /* next caught signal wakes us up */ 27 | } 28 | return(alarm(0)); /* turn off timer, return unslept time */ 29 | } 30 | -------------------------------------------------------------------------------- /src/09_Signals/sleep2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/sleep2.o -------------------------------------------------------------------------------- /src/09_Signals/suspend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/suspend1 -------------------------------------------------------------------------------- /src/09_Signals/suspend1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 阻塞信号测试 3 | * 4 | * apue示例程序 - suspend1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_int(int); 12 | 13 | int main() 14 | { 15 | sigset_t newmask, oldmask, waitmask; 16 | 17 | pr_mask("program start: "); 18 | 19 | if (signal(SIGINT, sig_int) == SIG_ERR) 20 | err_sys("signal(SIGINT) error"); 21 | sigemptyset(&waitmask); 22 | sigaddset(&waitmask, SIGUSR1); 23 | sigemptyset(&newmask); 24 | sigaddset(&newmask, SIGINT); 25 | 26 | /* 27 | * Block SIGINT and save current signal mask. 28 | */ 29 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 30 | err_sys("SIG_BLOCK error"); 31 | 32 | /* 33 | * Critical region of code. 34 | */ 35 | pr_mask("in critical region: "); 36 | 37 | /* 38 | * Pause, allowing all signals except SIGUSR1. 39 | */ 40 | if (sigsuspend(&waitmask) != -1) 41 | err_sys("sigsuspend error"); 42 | 43 | pr_mask("after return from sigsuspend: "); 44 | 45 | /* 46 | * Reset signal mask which unblocks SIGINT. 47 | */ 48 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 49 | err_sys("SIG_SETMASK error"); 50 | 51 | /* 52 | * And continue processing ... 53 | */ 54 | pr_mask("program exit: "); 55 | 56 | exit(0); 57 | } 58 | 59 | static void sig_int(int signo) 60 | { 61 | pr_mask("\nin sig_int: "); 62 | } 63 | -------------------------------------------------------------------------------- /src/09_Signals/suspend2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/suspend2 -------------------------------------------------------------------------------- /src/09_Signals/suspend2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sigsuspend另一应用:等待信号处理程序设置一个全局量 3 | * 4 | * apue示例程序 - suspend2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | volatile sig_atomic_t quitflag; /* set nonzero by signal handler */ 12 | 13 | static void sig_int(int signo) /* one signal handler for SIGINT and SIGQUIT */ 14 | { 15 | if (signo == SIGINT) 16 | printf("\ninterrupt\n"); 17 | else if (signo == SIGQUIT) 18 | quitflag = 1; /* set flag for main loop */ 19 | } 20 | 21 | int main(void) 22 | { 23 | sigset_t newmask, oldmask, zeromask; 24 | 25 | if (signal(SIGINT, sig_int) == SIG_ERR) 26 | err_sys("signal(SIGINT) error"); 27 | if (signal(SIGQUIT, sig_int) == SIG_ERR) 28 | err_sys("signal(SIGQUIT) error"); 29 | 30 | sigemptyset(&zeromask); 31 | sigemptyset(&newmask); 32 | sigaddset(&newmask, SIGQUIT); 33 | 34 | /* 35 | * Block SIGQUIT and save current signal mask. 36 | */ 37 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 38 | err_sys("SIG_BLOCK error"); 39 | 40 | while (quitflag == 0) 41 | sigsuspend(&zeromask); 42 | 43 | /* 44 | * SIGQUIT has been caught and is now blocked; do whatever. 45 | */ 46 | quitflag = 0; 47 | 48 | /* 49 | * Reset signal mask which unblocks SIGQUIT. 50 | */ 51 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 52 | err_sys("SIG_SETMASK error"); 53 | 54 | exit(0); 55 | } 56 | -------------------------------------------------------------------------------- /src/09_Signals/system.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file system模拟实现(处理信号版本) 3 | * 4 | * apue示例程序 - system.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int system(const char *cmdstring) /* with appropriate signal handling */ 15 | { 16 | pid_t pid; 17 | int status; 18 | struct sigaction ignore, saveintr, savequit; 19 | sigset_t chldmask, savemask; 20 | 21 | if (cmdstring == NULL) 22 | return(1); /* always a command processor with UNIX */ 23 | 24 | ignore.sa_handler = SIG_IGN; /* ignore SIGINT and SIGQUIT */ 25 | sigemptyset(&ignore.sa_mask); 26 | ignore.sa_flags = 0; 27 | if (sigaction(SIGINT, &ignore, &saveintr) < 0) 28 | return(-1); 29 | if (sigaction(SIGQUIT, &ignore, &savequit) < 0) 30 | return(-1); 31 | sigemptyset(&chldmask); /* now block SIGCHLD */ 32 | sigaddset(&chldmask, SIGCHLD); 33 | if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) 34 | return(-1); 35 | 36 | if ((pid = fork()) < 0) { 37 | status = -1; /* probably out of processes */ 38 | } else if (pid == 0) { /* child */ 39 | /* restore previous signal actions & reset signal mask */ 40 | sigaction(SIGINT, &saveintr, NULL); 41 | sigaction(SIGQUIT, &savequit, NULL); 42 | sigprocmask(SIG_SETMASK, &savemask, NULL); 43 | 44 | execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 45 | _exit(127); /* exec error */ 46 | } else { /* parent */ 47 | while (waitpid(pid, &status, 0) < 0) 48 | if (errno != EINTR) { 49 | status = -1; /* error other than EINTR from waitpid() */ 50 | break; 51 | } 52 | } 53 | 54 | /* restore previous signal actions & reset signal mask */ 55 | if (sigaction(SIGINT, &saveintr, NULL) < 0) 56 | return(-1); 57 | if (sigaction(SIGQUIT, &savequit, NULL) < 0) 58 | return(-1); 59 | if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) 60 | return(-1); 61 | 62 | return(status); 63 | } 64 | -------------------------------------------------------------------------------- /src/09_Signals/system.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/system.o -------------------------------------------------------------------------------- /src/09_Signals/systest2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/systest2 -------------------------------------------------------------------------------- /src/09_Signals/systest2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 自定义system测试 3 | * 4 | * apue示例程序 - systest2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_int(int signo) 12 | { 13 | printf("caught SIGINT\n"); 14 | } 15 | 16 | static void sig_chld(int signo) 17 | { 18 | printf("caught SIGCHLD\n"); 19 | } 20 | 21 | int main(void) 22 | { 23 | if (signal(SIGINT, sig_int) == SIG_ERR) 24 | err_sys("signal(SIGINT) error"); 25 | if (signal(SIGCHLD, sig_chld) == SIG_ERR) 26 | err_sys("signal(SIGCHLD) error"); 27 | if (system("/bin/ed") < 0) 28 | err_sys("system() error"); 29 | exit(0); 30 | } 31 | -------------------------------------------------------------------------------- /src/09_Signals/systest2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/systest2.o -------------------------------------------------------------------------------- /src/09_Signals/tsleep2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/tsleep2 -------------------------------------------------------------------------------- /src/09_Signals/tsleep2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试sleep2.c模拟实现的sleep 3 | * 4 | * apue示例程序 - tsleep.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | unsigned int sleep2(unsigned int); 12 | static void sig_int(int); 13 | 14 | int main() 15 | { 16 | unsigned int unslept; 17 | 18 | if (signal(SIGINT, sig_int) == SIG_ERR) 19 | err_sys("signal(SIGINT) error"); 20 | unslept = sleep2(5); 21 | printf("sleep2 returned: %u\n", unslept); 22 | exit(0); 23 | } 24 | 25 | static void sig_int(int signo) 26 | { 27 | int i, j; 28 | volatile int k; 29 | 30 | /* 31 | * Tune these loops to run for more than 5 seconds 32 | * on whatever system this test program is run. 33 | */ 34 | printf("\nsig_int starting\n"); 35 | for (i = 0; i < 300000; i++) 36 | for (j = 0; j < 4000; j++) 37 | k += i * j; 38 | printf("sig_int finished\n"); 39 | } 40 | -------------------------------------------------------------------------------- /src/09_Signals/tsleep2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/09_Signals/tsleep2.o -------------------------------------------------------------------------------- /src/10_Process_Rel/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = orphan3 printid 6 | 7 | all: $(PROGS) 8 | 9 | $(PROGS): $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | clean: 13 | rm -f $(PROGS) $(TEMPFILES) *.o 14 | 15 | include $(ROOT)/Make.libapue.inc 16 | -------------------------------------------------------------------------------- /src/10_Process_Rel/orphan3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Process_Rel/orphan3 -------------------------------------------------------------------------------- /src/10_Process_Rel/orphan3.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 孤儿进程组SIGHUP|SIGCONT 3 | * 4 | * apue示例程序 - orphan3.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void sig_hup(int signo) 13 | { 14 | printf("SIGHUP received, pid = %ld\n", (long)getpid()); 15 | } 16 | 17 | static void pr_ids(char *name) 18 | { 19 | printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n", 20 | name, (long)getpid(), (long)getppid(), (long)getpgrp(), 21 | (long)tcgetpgrp(STDIN_FILENO)); 22 | fflush(stdout); 23 | } 24 | 25 | static void sig_cont(int signo) 26 | { 27 | printf("SIGCONT received, pid = %ld\n", (long)getpid()); 28 | } 29 | 30 | int main(void) 31 | { 32 | char c; 33 | pid_t pid; 34 | 35 | pr_ids("parent"); 36 | if ((pid = fork()) < 0) { 37 | err_sys("fork error"); 38 | } else if (pid > 0) { /* parent */ 39 | sleep(5); /* sleep to let child stop itself */ 40 | } else { /* child */ 41 | pr_ids("child"); 42 | signal(SIGHUP, sig_hup); /* establish signal handler */ 43 | //signal(SIGCONT, sig_cont); 44 | kill(getpid(), SIGTSTP); /* stop ourself */ 45 | pr_ids("child"); /* prints only if we're continued */ 46 | if (read(STDIN_FILENO, &c, 1) != 1) 47 | printf("read error %d on controlling TTY\n", errno); 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/10_Process_Rel/printid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Process_Rel/printid -------------------------------------------------------------------------------- /src/10_Process_Rel/printid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 打印相关id 3 | * 4 | * apue示例程序 - printid.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | void pr_ids(char *name) 13 | { 14 | printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n", 15 | name, (long)getpid(), (long)getppid(), (long)getpgrp(), 16 | (long)tcgetpgrp(STDIN_FILENO)); 17 | } 18 | 19 | int main() 20 | { 21 | pid_t pid; 22 | int status; 23 | 24 | pr_ids("parent"); 25 | if ((pid = fork()) < 0) { 26 | err_sys("fork error"); 27 | } else if (pid > 0) { /* parent */ 28 | if (wait(&status) != pid) /* wait for child */ 29 | err_sys("wait error"); 30 | } else { /* child */ 31 | pr_ids("child"); 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /src/10_Signals/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = critical read1 read2 reenter sigtstp sigusr suspend1 suspend2 sigint 6 | MOREPROGS = systest2 tsleep2 7 | 8 | all: $(PROGS) $(MOREPROGS) sleep1.o sleep2.o system.o abort.o 9 | 10 | $(PROGS): $(LIBAPUE) 11 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 12 | 13 | tsleep2: tsleep2.o sleep2.o 14 | $(CC) $(CFLAGS) -o tsleep2 tsleep2.o sleep2.o $(LDFLAGS) $(LDLIBS) 15 | 16 | systest2: systest2.o system.o 17 | $(CC) $(CFLAGS) -o systest2 systest2.o system.o $(LDFLAGS) $(LDLIBS) 18 | 19 | clean: 20 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o file.hole 21 | 22 | include $(ROOT)/Make.libapue.inc 23 | -------------------------------------------------------------------------------- /src/10_Signals/abort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file abort模拟实现 3 | * 4 | * apue示例程序 - abort.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void abort() 15 | { 16 | sigset_t mask; 17 | struct sigaction action; 18 | 19 | /* Caller can't ignore SIGABRT, if so reset to default */ 20 | sigaction(SIGABRT, NULL, &action); 21 | if (action.sa_handler == SIG_IGN) { 22 | action.sa_handler = SIG_DFL; 23 | sigaction(SIGABRT, &action, NULL); 24 | } 25 | if (action.sa_handler == SIG_DFL) 26 | fflush(NULL); /* flush all open stdio streams */ 27 | 28 | /* Caller can't block SIGABRT; make sure it's unblocked */ 29 | sigfillset(&mask); 30 | sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ 31 | sigprocmask(SIG_SETMASK, &mask, NULL); 32 | kill(getpid(), SIGABRT); /* send the signal */ 33 | 34 | /* If we're here, process caught SIGABRT and returned */ 35 | fflush(NULL); /* flush all open stdio streams */ 36 | action.sa_handler = SIG_DFL; 37 | sigaction(SIGABRT, &action, NULL); /* reset to default */ 38 | sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */ 39 | kill(getpid(), SIGABRT); /* and one more time */ 40 | exit(1); /* this should never be executed ... */ 41 | } -------------------------------------------------------------------------------- /src/10_Signals/abort.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/abort.o -------------------------------------------------------------------------------- /src/10_Signals/critical: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/critical -------------------------------------------------------------------------------- /src/10_Signals/critical.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SIGQUIT捕获测试 3 | * 4 | * apue示例程序 - critical.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_quit(int); 12 | 13 | int main() 14 | { 15 | sigset_t newmask, oldmask, pendmask; 16 | 17 | if (signal(SIGQUIT, sig_quit) == SIG_ERR) 18 | err_sys("can't catch SIGQUIT"); 19 | 20 | /* 21 | * Block SIGQUIT and save current signal mask. 22 | */ 23 | sigemptyset(&newmask); 24 | sigaddset(&newmask, SIGQUIT); 25 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 26 | err_sys("SIG_BLOCK error"); 27 | 28 | sleep(5); /* SIGQUIT here will remain pending */ 29 | 30 | if (sigpending(&pendmask) < 0) 31 | err_sys("sigpending error"); 32 | if (sigismember(&pendmask, SIGQUIT)) 33 | printf("\nSIGQUIT pending\n"); 34 | 35 | /* 36 | * Restore signal mask which unblocks SIGQUIT. 37 | */ 38 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 39 | err_sys("SIG_SETMASK error"); 40 | printf("SIGQUIT unblocked\n"); 41 | 42 | sleep(5); /* SIGQUIT here will terminate with core file */ 43 | exit(0); 44 | } 45 | 46 | static void sig_quit(int signo) 47 | { 48 | printf("caught SIGQUIT\n"); 49 | if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) 50 | err_sys("can't reset SIGQUIT"); 51 | } 52 | -------------------------------------------------------------------------------- /src/10_Signals/read1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/read1 -------------------------------------------------------------------------------- /src/10_Signals/read1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 低速系统调用打断测试 3 | * 4 | * apue示例程序 - read1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_alrm(int); 12 | 13 | int main() 14 | { 15 | int n; 16 | char line[MAXLINE]; 17 | 18 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 19 | err_sys("signal(SIGALRM) error"); 20 | 21 | /* 22 | * 1.alarm和read不是原子的,中间可能会被调度出去,如果调度出去的时间超过了定时器的时间, 23 | * 那么read就可能永久阻塞,alarm定时器无法达到停止read的效果 24 | * 2.如果read实现是自动重启的,SIGALRM中断程序返回是不会打断read的 25 | */ 26 | alarm(5); 27 | if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) 28 | err_sys("read error"); 29 | alarm(0); 30 | 31 | write(STDOUT_FILENO, line, n); 32 | exit(0); 33 | } 34 | 35 | static void sig_alrm(int signo) 36 | { 37 | /* nothing to do, just return to interrupt the read */ 38 | } 39 | -------------------------------------------------------------------------------- /src/10_Signals/read2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/read2 -------------------------------------------------------------------------------- /src/10_Signals/read2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file setjmp/longjmp解决自动重启问题,但依然蹩脚 3 | * 4 | * apue示例程序 - read2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void sig_alrm(int); 13 | static jmp_buf env_alrm; 14 | 15 | int main(void) 16 | { 17 | int n; 18 | char line[MAXLINE]; 19 | 20 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 21 | err_sys("signal(SIGALRM) error"); 22 | if (setjmp(env_alrm) != 0) 23 | err_quit("read timeout"); 24 | 25 | alarm(10); 26 | if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) 27 | err_sys("read error"); 28 | alarm(0); 29 | 30 | write(STDOUT_FILENO, line, n); 31 | exit(0); 32 | } 33 | 34 | static void sig_alrm(int signo) 35 | { 36 | longjmp(env_alrm, 1); 37 | } 38 | -------------------------------------------------------------------------------- /src/10_Signals/reenter: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/reenter -------------------------------------------------------------------------------- /src/10_Signals/reenter.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试中断调用不可重入函数引起的负面效果 3 | * 4 | * apue示例程序 - reenter.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void my_alarm(int signo) 13 | { 14 | struct passwd *rootptr; 15 | 16 | printf("in signal handler\n"); 17 | // ubuntu x64 16.04会死锁 18 | if ((rootptr = getpwnam("root")) == NULL) 19 | err_sys("getpwnam(root) error"); 20 | printf("finish"); 21 | alarm(1); 22 | } 23 | 24 | int main(void) 25 | { 26 | struct passwd *ptr; 27 | 28 | signal(SIGALRM, my_alarm); 29 | alarm(1); 30 | for ( ; ; ) { 31 | if ((ptr = getpwnam("r00tk1t")) == NULL) 32 | err_sys("getpwnam error"); 33 | if (strcmp(ptr->pw_name, "r00tk1t") != 0) 34 | printf("return value corrupted!, pw_name = %s\n", 35 | ptr->pw_name); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/10_Signals/setops.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 信号屏蔽字/阻塞集模拟实现 3 | * 4 | * apue示例程序 - setops.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | /* 13 | * usually defines NSIG to include signal number 0. 14 | */ 15 | #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG) 16 | 17 | int sigaddset(sigset_t *set, int signo) 18 | { 19 | if (SIGBAD(signo)) { 20 | errno = EINVAL; 21 | return(-1); 22 | } 23 | *set |= 1 << (signo - 1); /* turn bit on */ 24 | return(0); 25 | } 26 | 27 | int sigdelset(sigset_t *set, int signo) 28 | { 29 | if (SIGBAD(signo)) { 30 | errno = EINVAL; 31 | return(-1); 32 | } 33 | *set &= ~(1 << (signo - 1)); /* turn bit off */ 34 | return(0); 35 | } 36 | 37 | int sigismember(const sigset_t *set, int signo) 38 | { 39 | if (SIGBAD(signo)) { 40 | errno = EINVAL; 41 | return(-1); 42 | } 43 | return((*set & (1 << (signo - 1))) != 0); 44 | } 45 | -------------------------------------------------------------------------------- /src/10_Signals/sigint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/sigint -------------------------------------------------------------------------------- /src/10_Signals/sigint.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试sigint 3 | * 4 | * apue示例程序 - sigint.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_int(int signo) 12 | { 13 | printf("caught SIGINT\n"); 14 | } 15 | 16 | static void sig_quit() 17 | { 18 | printf("caught SIGQUIT\n"); 19 | } 20 | 21 | int main(void) 22 | { 23 | if (signal(SIGINT, sig_int) == SIG_ERR) 24 | err_sys("signal(SIGINT) error"); 25 | if (signal(SIGQUIT, sig_quit) == SIG_ERR) 26 | err_sys("signal(SIGQUIT) error"); 27 | while(1); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /src/10_Signals/sigtstp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/sigtstp -------------------------------------------------------------------------------- /src/10_Signals/sigtstp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试SIGTSTP 3 | * 4 | * apue示例程序 - sigtstp.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | #define BUFFSIZE 1024 12 | 13 | static void sig_tstp(int signo) /* signal handler for SIGTSTP */ 14 | { 15 | sigset_t mask; 16 | 17 | /* ... move cursor to lower left corner, reset tty mode ... */ 18 | 19 | /* 20 | * Unblock SIGTSTP, since it's blocked while we're handling it. 21 | */ 22 | sigemptyset(&mask); 23 | sigaddset(&mask, SIGTSTP); 24 | sigprocmask(SIG_UNBLOCK, &mask, NULL); 25 | 26 | signal(SIGTSTP, SIG_DFL); /* reset disposition to default */ 27 | 28 | kill(getpid(), SIGTSTP); /* and send the signal to ourself */ 29 | 30 | /* we won't return from the kill until we're continued */ 31 | 32 | signal(SIGTSTP, sig_tstp); /* reestablish signal handler */ 33 | 34 | /* ... reset tty mode, redraw screen ... */ 35 | } 36 | 37 | int main() 38 | { 39 | int n; 40 | char buf[BUFFSIZE]; 41 | 42 | /* 43 | * Only catch SIGTSTP if we're running with a job-control shell. 44 | */ 45 | if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) 46 | signal(SIGTSTP, sig_tstp); 47 | 48 | while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) 49 | if (write(STDOUT_FILENO, buf, n) != n) 50 | err_sys("write error"); 51 | 52 | if (n < 0) 53 | err_sys("read error"); 54 | 55 | exit(0); 56 | } 57 | -------------------------------------------------------------------------------- /src/10_Signals/sigusr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/sigusr -------------------------------------------------------------------------------- /src/10_Signals/sigusr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 自定义信号测试 3 | * 4 | * apue示例程序 - sigusr.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_usr(int); /* one handler for both signals */ 12 | 13 | int main() 14 | { 15 | if (signal(SIGUSR1, sig_usr) == SIG_ERR) 16 | err_sys("can't catch SIGUSR1"); 17 | if (signal(SIGUSR2, sig_usr) == SIG_ERR) 18 | err_sys("can't catch SIGUSR2"); 19 | for ( ; ; ) 20 | pause(); 21 | } 22 | 23 | static void sig_usr(int signo) /* argument is signal number */ 24 | { 25 | if (signo == SIGUSR1) 26 | printf("received SIGUSR1\n"); 27 | else if (signo == SIGUSR2) 28 | printf("received SIGUSR2\n"); 29 | else 30 | err_dump("received signal %d\n", signo); 31 | } 32 | -------------------------------------------------------------------------------- /src/10_Signals/sleep1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sleep模拟实现1 3 | * 4 | * apue示例程序 - sleep1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | static void sig_alrm(int signo) 13 | { 14 | /* nothing to do, just return to wake up the pause */ 15 | } 16 | 17 | unsigned int sleep1(unsigned int seconds) 18 | { 19 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 20 | return(seconds); 21 | /* 22 | * 1. alarm和pause非原子,如果alarm后被调度出去,seconds后才会来调用pause,则可能会永久阻塞 23 | * 2. 如果用户设置过定时器,会破坏现状,sig_alrm也被内部消化掉了,外部不知这一事实 24 | */ 25 | alarm(seconds); /* start the timer */ 26 | pause(); /* next caught signal wakes us up */ 27 | return(alarm(0)); /* turn off timer, return unslept time */ 28 | } 29 | -------------------------------------------------------------------------------- /src/10_Signals/sleep1.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/sleep1.o -------------------------------------------------------------------------------- /src/10_Signals/sleep2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sleep模拟实现2,解决了原子问题,但依然蹩脚 3 | * 4 | * apue示例程序 - sleep2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | static jmp_buf env_alrm; 14 | 15 | static void sig_alrm(int signo) 16 | { 17 | longjmp(env_alrm, 1); 18 | } 19 | 20 | unsigned int sleep2(unsigned int seconds) 21 | { 22 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 23 | return(seconds); 24 | if (setjmp(env_alrm) == 0) { 25 | alarm(seconds); /* start the timer */ 26 | pause(); /* next caught signal wakes us up */ 27 | } 28 | return(alarm(0)); /* turn off timer, return unslept time */ 29 | } 30 | -------------------------------------------------------------------------------- /src/10_Signals/sleep2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/sleep2.o -------------------------------------------------------------------------------- /src/10_Signals/suspend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/suspend1 -------------------------------------------------------------------------------- /src/10_Signals/suspend1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 阻塞信号测试 3 | * 4 | * apue示例程序 - suspend1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_int(int); 12 | 13 | int main() 14 | { 15 | sigset_t newmask, oldmask, waitmask; 16 | 17 | pr_mask("program start: "); 18 | 19 | if (signal(SIGINT, sig_int) == SIG_ERR) 20 | err_sys("signal(SIGINT) error"); 21 | sigemptyset(&waitmask); 22 | sigaddset(&waitmask, SIGUSR1); 23 | sigemptyset(&newmask); 24 | sigaddset(&newmask, SIGINT); 25 | 26 | /* 27 | * Block SIGINT and save current signal mask. 28 | */ 29 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 30 | err_sys("SIG_BLOCK error"); 31 | 32 | /* 33 | * Critical region of code. 34 | */ 35 | pr_mask("in critical region: "); 36 | 37 | /* 38 | * Pause, allowing all signals except SIGUSR1. 39 | */ 40 | if (sigsuspend(&waitmask) != -1) 41 | err_sys("sigsuspend error"); 42 | 43 | pr_mask("after return from sigsuspend: "); 44 | 45 | /* 46 | * Reset signal mask which unblocks SIGINT. 47 | */ 48 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 49 | err_sys("SIG_SETMASK error"); 50 | 51 | /* 52 | * And continue processing ... 53 | */ 54 | pr_mask("program exit: "); 55 | 56 | exit(0); 57 | } 58 | 59 | static void sig_int(int signo) 60 | { 61 | pr_mask("\nin sig_int: "); 62 | } 63 | -------------------------------------------------------------------------------- /src/10_Signals/suspend2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/suspend2 -------------------------------------------------------------------------------- /src/10_Signals/suspend2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sigsuspend另一应用:等待信号处理程序设置一个全局量 3 | * 4 | * apue示例程序 - suspend2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | volatile sig_atomic_t quitflag; /* set nonzero by signal handler */ 12 | 13 | static void sig_int(int signo) /* one signal handler for SIGINT and SIGQUIT */ 14 | { 15 | if (signo == SIGINT) 16 | printf("\ninterrupt\n"); 17 | else if (signo == SIGQUIT) 18 | quitflag = 1; /* set flag for main loop */ 19 | } 20 | 21 | int main(void) 22 | { 23 | sigset_t newmask, oldmask, zeromask; 24 | 25 | if (signal(SIGINT, sig_int) == SIG_ERR) 26 | err_sys("signal(SIGINT) error"); 27 | if (signal(SIGQUIT, sig_int) == SIG_ERR) 28 | err_sys("signal(SIGQUIT) error"); 29 | 30 | sigemptyset(&zeromask); 31 | sigemptyset(&newmask); 32 | sigaddset(&newmask, SIGQUIT); 33 | 34 | /* 35 | * Block SIGQUIT and save current signal mask. 36 | */ 37 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 38 | err_sys("SIG_BLOCK error"); 39 | 40 | while (quitflag == 0) 41 | sigsuspend(&zeromask); 42 | 43 | /* 44 | * SIGQUIT has been caught and is now blocked; do whatever. 45 | */ 46 | quitflag = 0; 47 | 48 | /* 49 | * Reset signal mask which unblocks SIGQUIT. 50 | */ 51 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 52 | err_sys("SIG_SETMASK error"); 53 | 54 | exit(0); 55 | } 56 | -------------------------------------------------------------------------------- /src/10_Signals/system.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file system模拟实现(处理信号版本) 3 | * 4 | * apue示例程序 - system.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int system(const char *cmdstring) /* with appropriate signal handling */ 15 | { 16 | pid_t pid; 17 | int status; 18 | struct sigaction ignore, saveintr, savequit; 19 | sigset_t chldmask, savemask; 20 | 21 | if (cmdstring == NULL) 22 | return(1); /* always a command processor with UNIX */ 23 | 24 | ignore.sa_handler = SIG_IGN; /* ignore SIGINT and SIGQUIT */ 25 | sigemptyset(&ignore.sa_mask); 26 | ignore.sa_flags = 0; 27 | if (sigaction(SIGINT, &ignore, &saveintr) < 0) 28 | return(-1); 29 | if (sigaction(SIGQUIT, &ignore, &savequit) < 0) 30 | return(-1); 31 | sigemptyset(&chldmask); /* now block SIGCHLD */ 32 | sigaddset(&chldmask, SIGCHLD); 33 | if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) 34 | return(-1); 35 | 36 | if ((pid = fork()) < 0) { 37 | status = -1; /* probably out of processes */ 38 | } else if (pid == 0) { /* child */ 39 | /* restore previous signal actions & reset signal mask */ 40 | sigaction(SIGINT, &saveintr, NULL); 41 | sigaction(SIGQUIT, &savequit, NULL); 42 | sigprocmask(SIG_SETMASK, &savemask, NULL); 43 | 44 | execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 45 | _exit(127); /* exec error */ 46 | } else { /* parent */ 47 | while (waitpid(pid, &status, 0) < 0) 48 | if (errno != EINTR) { 49 | status = -1; /* error other than EINTR from waitpid() */ 50 | break; 51 | } 52 | } 53 | 54 | /* restore previous signal actions & reset signal mask */ 55 | if (sigaction(SIGINT, &saveintr, NULL) < 0) 56 | return(-1); 57 | if (sigaction(SIGQUIT, &savequit, NULL) < 0) 58 | return(-1); 59 | if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) 60 | return(-1); 61 | 62 | return(status); 63 | } 64 | -------------------------------------------------------------------------------- /src/10_Signals/system.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/system.o -------------------------------------------------------------------------------- /src/10_Signals/systest2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/systest2 -------------------------------------------------------------------------------- /src/10_Signals/systest2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 自定义system测试 3 | * 4 | * apue示例程序 - systest2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_int(int signo) 12 | { 13 | printf("caught SIGINT\n"); 14 | } 15 | 16 | static void sig_chld(int signo) 17 | { 18 | printf("caught SIGCHLD\n"); 19 | } 20 | 21 | int main(void) 22 | { 23 | if (signal(SIGINT, sig_int) == SIG_ERR) 24 | err_sys("signal(SIGINT) error"); 25 | if (signal(SIGCHLD, sig_chld) == SIG_ERR) 26 | err_sys("signal(SIGCHLD) error"); 27 | if (system("/bin/ed") < 0) 28 | err_sys("system() error"); 29 | exit(0); 30 | } 31 | -------------------------------------------------------------------------------- /src/10_Signals/systest2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/systest2.o -------------------------------------------------------------------------------- /src/10_Signals/tsleep2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/tsleep2 -------------------------------------------------------------------------------- /src/10_Signals/tsleep2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 测试sleep2.c模拟实现的sleep 3 | * 4 | * apue示例程序 - tsleep.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | unsigned int sleep2(unsigned int); 12 | static void sig_int(int); 13 | 14 | int main() 15 | { 16 | unsigned int unslept; 17 | 18 | if (signal(SIGINT, sig_int) == SIG_ERR) 19 | err_sys("signal(SIGINT) error"); 20 | unslept = sleep2(5); 21 | printf("sleep2 returned: %u\n", unslept); 22 | exit(0); 23 | } 24 | 25 | static void sig_int(int signo) 26 | { 27 | int i, j; 28 | volatile int k; 29 | 30 | /* 31 | * Tune these loops to run for more than 5 seconds 32 | * on whatever system this test program is run. 33 | */ 34 | printf("\nsig_int starting\n"); 35 | for (i = 0; i < 300000; i++) 36 | for (j = 0; j < 4000; j++) 37 | k += i * j; 38 | printf("sig_int finished\n"); 39 | } 40 | -------------------------------------------------------------------------------- /src/10_Signals/tsleep2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/10_Signals/tsleep2.o -------------------------------------------------------------------------------- /src/11_Threads/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | EXTRALIBS=-pthread 3 | PLATFORM=$(shell $(ROOT)/systype.sh) 4 | include $(ROOT)/Make.defines.$(PLATFORM) 5 | 6 | BAR = 7 | ifeq "$(PLATFORM)" "macos" 8 | TLOCK = 9 | EXTRALIBS=-pthread 10 | else 11 | TLOCK = timedlock 12 | endif 13 | ifeq "$(PLATFORM)" "linux" 14 | BAR = barrier 15 | EXTRALIBS=-pthread -lrt -lbsd 16 | endif 17 | ifeq "$(PLATFORM)" "freebsd" 18 | BAR = barrier 19 | EXTRALIBS=-pthread 20 | endif 21 | ifeq "$(PLATFORM)" "solaris" 22 | BAR = barrier 23 | EXTRALIBS=-lpthread -lrt 24 | endif 25 | 26 | PROGS = badexit2 cleanup exitstatus threadid 27 | 28 | all: $(PROGS) condvar.o maketimeout.o mutex1.o mutex2.o mutex3.o rwlock.o $(TLOCK) $(BAR) 29 | 30 | $(PROGS): $(LIBAPUE) 31 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 32 | 33 | clean: 34 | rm -f $(PROGS) $(TEMPFILES) *.o $(TLOCK) $(BAR) 35 | 36 | include $(ROOT)/Make.libapue.inc 37 | -------------------------------------------------------------------------------- /src/11_Threads/badexit2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/badexit2 -------------------------------------------------------------------------------- /src/11_Threads/badexit2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file pthread create/join模型 3 | * 4 | * apue示例程序 - badexit2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | struct foo { 13 | int a, b, c, d; 14 | }; 15 | 16 | void printfoo(const char *s, const struct foo *fp) 17 | { 18 | printf("%s", s); 19 | printf(" structure at 0x%lx\n", (unsigned long)fp); 20 | printf(" foo.a = %d\n", fp->a); 21 | printf(" foo.b = %d\n", fp->b); 22 | printf(" foo.c = %d\n", fp->c); 23 | printf(" foo.d = %d\n", fp->d); 24 | } 25 | 26 | void *thr_fn1(void *arg) 27 | { 28 | struct foo foo = {1, 2, 3, 4}; 29 | 30 | printfoo("thread 1:\n", &foo); 31 | pthread_exit((void *)&foo); 32 | } 33 | 34 | void *thr_fn2(void *arg) 35 | { 36 | printf("thread 2: ID is %lu\n", (unsigned long)pthread_self()); 37 | pthread_exit((void *)0); 38 | } 39 | 40 | int main(void) 41 | { 42 | int err; 43 | pthread_t tid1, tid2; 44 | struct foo *fp; 45 | 46 | err = pthread_create(&tid1, NULL, thr_fn1, NULL); 47 | if (err != 0) 48 | err_exit(err, "can't create thread 1"); 49 | err = pthread_join(tid1, (void *)&fp); 50 | if (err != 0) 51 | err_exit(err, "can't join with thread 1"); 52 | sleep(1); 53 | printf("parent starting second thread\n"); 54 | err = pthread_create(&tid2, NULL, thr_fn2, NULL); 55 | if (err != 0) 56 | err_exit(err, "can't create thread 2"); 57 | sleep(1); 58 | printfoo("parent:\n", fp); 59 | exit(0); 60 | } 61 | -------------------------------------------------------------------------------- /src/11_Threads/barrier: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/barrier -------------------------------------------------------------------------------- /src/11_Threads/cleanup: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/cleanup -------------------------------------------------------------------------------- /src/11_Threads/cleanup.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 注册线程清理例程 3 | * 4 | * apue示例程序 - cleanup.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | void cleanup(void *arg) 13 | { 14 | printf("cleanup: %s\n", (char *)arg); 15 | } 16 | 17 | void *thr_fn1(void *arg) 18 | { 19 | printf("thread 1 start\n"); 20 | pthread_cleanup_push(cleanup, "thread 1 first handler"); 21 | pthread_cleanup_push(cleanup, "thread 1 second handler"); 22 | printf("thread 1 push complete\n"); 23 | //if (arg) 24 | // return((void *)1); 25 | pthread_cleanup_pop(1); 26 | pthread_cleanup_pop(1); 27 | printf("thread 1 pop complete\n"); 28 | return((void *)1); 29 | } 30 | 31 | void *thr_fn2(void *arg) 32 | { 33 | printf("thread 2 start\n"); 34 | pthread_cleanup_push(cleanup, "thread 2 first handler"); 35 | pthread_cleanup_push(cleanup, "thread 2 second handler"); 36 | printf("thread 2 push complete\n"); 37 | //if (arg) 38 | // pthread_exit((void *)2); 39 | pthread_cleanup_pop(1); 40 | pthread_cleanup_pop(1); 41 | pthread_exit((void *)2); 42 | } 43 | 44 | int main(void) 45 | { 46 | int err; 47 | pthread_t tid1, tid2; 48 | void *tret; 49 | 50 | err = pthread_create(&tid1, NULL, thr_fn1, (void *)1); 51 | if (err != 0) 52 | err_exit(err, "can't create thread 1"); 53 | err = pthread_create(&tid2, NULL, thr_fn2, (void *)1); 54 | if (err != 0) 55 | err_exit(err, "can't create thread 2"); 56 | err = pthread_join(tid1, &tret); 57 | if (err != 0) 58 | err_exit(err, "can't join with thread 1"); 59 | printf("thread 1 exit code %ld\n", (long)tret); 60 | err = pthread_join(tid2, &tret); 61 | if (err != 0) 62 | err_exit(err, "can't join with thread 2"); 63 | printf("thread 2 exit code %ld\n", (long)tret); 64 | exit(0); 65 | } 66 | -------------------------------------------------------------------------------- /src/11_Threads/condvar.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 条件变量的正确使用手法 3 | * 4 | * apue示例程序 - condvar.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | 11 | struct msg { 12 | struct msg *m_next; 13 | /* ... more stuff here ... */ 14 | }; 15 | 16 | struct msg *workq; 17 | 18 | pthread_cond_t qready = PTHREAD_COND_INITIALIZER; 19 | 20 | pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; 21 | 22 | void process_msg() 23 | { 24 | struct msg *mp; 25 | 26 | for (;;) { 27 | pthread_mutex_lock(&qlock); 28 | while (workq == NULL) 29 | pthread_cond_wait(&qready, &qlock); // 1-> thread wait on qready ,2-> unlock qlock, 3->relock qlock before return 30 | mp = workq; 31 | workq = mp->m_next; 32 | pthread_mutex_unlock(&qlock); 33 | /* now process the message mp */ 34 | } 35 | } 36 | 37 | void enqueue_msg(struct msg *mp) 38 | { 39 | pthread_mutex_lock(&qlock); 40 | mp->m_next = workq; 41 | workq = mp; 42 | pthread_mutex_unlock(&qlock); 43 | pthread_cond_signal(&qready); 44 | } 45 | -------------------------------------------------------------------------------- /src/11_Threads/condvar.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/condvar.o -------------------------------------------------------------------------------- /src/11_Threads/exitstatus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/exitstatus -------------------------------------------------------------------------------- /src/11_Threads/exitstatus.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 查看线程退出码 3 | * 4 | * apue示例程序 - exitstatus.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | void *thr_fn1(void *arg) 13 | { 14 | printf("thread 1 returning\n"); 15 | return((void *)1); 16 | } 17 | 18 | void *thr_fn2(void *arg) 19 | { 20 | printf("thread 2 exiting\n"); 21 | pthread_exit((void *)2); 22 | } 23 | 24 | int main(void) 25 | { 26 | int err; 27 | pthread_t tid1, tid2; 28 | void *tret; 29 | 30 | err = pthread_create(&tid1, NULL, thr_fn1, NULL); 31 | if (err != 0) 32 | err_exit(err, "can't create thread 1"); 33 | err = pthread_create(&tid2, NULL, thr_fn2, NULL); 34 | if (err != 0) 35 | err_exit(err, "can't create thread 2"); 36 | err = pthread_join(tid1, &tret); 37 | if (err != 0) 38 | err_exit(err, "can't join with thread 1"); 39 | printf("thread 1 exit code %ld\n", (long)tret); 40 | err = pthread_join(tid2, &tret); 41 | if (err != 0) 42 | err_exit(err, "can't join with thread 2"); 43 | printf("thread 2 exit code %ld\n", (long)tret); 44 | exit(0); 45 | } 46 | -------------------------------------------------------------------------------- /src/11_Threads/maketimeout.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file timeval到timespec的手动转换 3 | * 4 | * apue示例程序 - maketimeout.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | void maketimeout(struct timespec *tsp, long minutes) 13 | { 14 | struct timeval now; 15 | 16 | /* get the current time */ 17 | gettimeofday(&now, NULL); 18 | tsp->tv_sec = now.tv_sec; 19 | tsp->tv_nsec = now.tv_usec * 1000; /* usec to nsec */ 20 | /* add the offset to get timeout value */ 21 | tsp->tv_sec += minutes * 60; 22 | } 23 | -------------------------------------------------------------------------------- /src/11_Threads/maketimeout.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/maketimeout.o -------------------------------------------------------------------------------- /src/11_Threads/mutex1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 互斥量应用于引用计数 3 | * 4 | * apue示例程序 - mutex1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | struct foo { 13 | int f_count; 14 | pthread_mutex_t f_lock; 15 | int f_id; 16 | /* ... more stuff here ... */ 17 | }; 18 | 19 | struct foo *foo_alloc(int id) /* allocate the object */ 20 | { 21 | struct foo *fp; 22 | 23 | if ((fp = malloc(sizeof(struct foo))) != NULL) { 24 | fp->f_count = 1; 25 | fp->f_id = id; 26 | if (pthread_mutex_init(&fp->f_lock, NULL) != 0) { 27 | free(fp); 28 | return(NULL); 29 | } 30 | /* ... continue initialization ... */ 31 | } 32 | return(fp); 33 | } 34 | 35 | void foo_hold(struct foo *fp) /* add a reference to the object */ 36 | { 37 | pthread_mutex_lock(&fp->f_lock); 38 | fp->f_count++; 39 | pthread_mutex_unlock(&fp->f_lock); 40 | } 41 | 42 | void foo_rele(struct foo *fp) /* release a reference to the object */ 43 | { 44 | pthread_mutex_lock(&fp->f_lock); 45 | if (--fp->f_count == 0) { /* last reference */ 46 | pthread_mutex_unlock(&fp->f_lock); 47 | pthread_mutex_destroy(&fp->f_lock); 48 | free(fp); 49 | } else { 50 | pthread_mutex_unlock(&fp->f_lock); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/11_Threads/mutex1.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/mutex1.o -------------------------------------------------------------------------------- /src/11_Threads/mutex2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/mutex2.o -------------------------------------------------------------------------------- /src/11_Threads/mutex3.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/mutex3.o -------------------------------------------------------------------------------- /src/11_Threads/rwlock.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/rwlock.o -------------------------------------------------------------------------------- /src/11_Threads/threadid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/threadid -------------------------------------------------------------------------------- /src/11_Threads/threadid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 打印线程ID 3 | * 4 | * apue示例程序 - threadid.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | pthread_t ntid; 13 | 14 | void printids(const char *s) 15 | { 16 | pid_t pid; 17 | pthread_t tid; 18 | 19 | pid = getpid(); 20 | tid = pthread_self(); 21 | printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid, 22 | (unsigned long)tid, (unsigned long)tid); 23 | } 24 | 25 | void *thr_fn(void *arg) 26 | { 27 | printids("new thread: "); 28 | return((void *)0); 29 | } 30 | 31 | int main(void) 32 | { 33 | int err; 34 | 35 | err = pthread_create(&ntid, NULL, thr_fn, NULL); 36 | if (err != 0) 37 | err_exit(err, "can't create thread"); 38 | printids("main thread:"); 39 | sleep(1); 40 | exit(0); 41 | } 42 | -------------------------------------------------------------------------------- /src/11_Threads/timedlock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/11_Threads/timedlock -------------------------------------------------------------------------------- /src/11_Threads/timedlock.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file timedlock的一种应用 3 | * 4 | * apue示例程序 - timedlock.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(void) 13 | { 14 | int err; 15 | struct timespec tout; 16 | struct tm *tmp; 17 | char buf[64]; 18 | pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 19 | 20 | pthread_mutex_lock(&lock); 21 | printf("mutex is locked\n"); 22 | clock_gettime(CLOCK_REALTIME, &tout); 23 | tmp = localtime(&tout.tv_sec); 24 | strftime(buf, sizeof(buf), "%r", tmp); 25 | printf("current time is %s\n", buf); 26 | tout.tv_sec += 10; /* 10 seconds from now */ 27 | /* caution: this could lead to deadlock */ 28 | err = pthread_mutex_timedlock(&lock, &tout); 29 | clock_gettime(CLOCK_REALTIME, &tout); 30 | tmp = localtime(&tout.tv_sec); 31 | strftime(buf, sizeof(buf), "%r", tmp); 32 | printf("the time is now %s\n", buf); 33 | if (err == 0) 34 | printf("mutex locked again!\n"); 35 | else 36 | printf("can't lock mutex again: %s\n", strerror(err)); 37 | exit(0); 38 | } 39 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | TOUT = 6 | ifeq "$(PLATFORM)" "freebsd" 7 | EXTRALIBS = -pthread 8 | endif 9 | ifeq "$(PLATFORM)" "linux" 10 | EXTRALIBS = -pthread 11 | TOUT = timeout 12 | endif 13 | ifeq "$(PLATFORM)" "solaris" 14 | EXTRALIBS = -lpthread 15 | TOUT = timeout.o 16 | endif 17 | 18 | PROGS = suspend 19 | 20 | all: $(PROGS) detach.o getenv1.o getenv2.o getenv3.o $(TOUT) 21 | 22 | $(PROGS): $(LIBAPUE) 23 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 24 | 25 | clean: 26 | rm -f $(PROGS) $(TEMPFILES) *.o 27 | 28 | include $(ROOT)/Make.libapue.inc 29 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/detach.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 初始态置为detach的线程创建demo 3 | * 4 | * apue示例程序 - detach.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int makethread(void *(*fn)(void *), void *arg) 13 | { 14 | int err; 15 | pthread_t tid; 16 | pthread_attr_t attr; 17 | 18 | err = pthread_attr_init(&attr); 19 | if (err != 0) 20 | return(err); 21 | err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 22 | if (err == 0) 23 | err = pthread_create(&tid, &attr, fn, arg); 24 | pthread_attr_destroy(&attr); 25 | return(err); 26 | } 27 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/detach.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/detach.o -------------------------------------------------------------------------------- /src/12_ThreadCtl/getenv1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取指定的env变量 3 | * 4 | * apue示例程序 - getenv1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | #define MAXSTRINGSZ 4096 13 | 14 | static char envbuf[MAXSTRINGSZ]; 15 | 16 | extern char **environ; 17 | 18 | char *getenv(const char *name) 19 | { 20 | int i, len; 21 | 22 | len = strlen(name); 23 | for (i = 0; environ[i] != NULL; i++) { 24 | if ((strncmp(name, environ[i], len) == 0) && 25 | (environ[i][len] == '=')) { 26 | strncpy(envbuf, &environ[i][len+1], MAXSTRINGSZ-1); 27 | return(envbuf); 28 | } 29 | } 30 | return(NULL); 31 | } 32 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/getenv1.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/getenv1.o -------------------------------------------------------------------------------- /src/12_ThreadCtl/getenv2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取指定的env变量-可重入版本 3 | * 4 | * apue示例程序 - getenv2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | extern char **environ; 15 | 16 | pthread_mutex_t env_mutex; 17 | 18 | static pthread_once_t init_done = PTHREAD_ONCE_INIT; 19 | 20 | static void thread_init(void) 21 | { 22 | pthread_mutexattr_t attr; 23 | 24 | pthread_mutexattr_init(&attr); 25 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); // 防止信号处理程序调用getenv_r而死锁 26 | pthread_mutex_init(&env_mutex, &attr); 27 | pthread_mutexattr_destroy(&attr); 28 | } 29 | 30 | int getenv_r(const char *name, char *buf, int buflen) 31 | { 32 | int i, len, olen; 33 | 34 | pthread_once(&init_done, thread_init); 35 | len = strlen(name); 36 | pthread_mutex_lock(&env_mutex); 37 | for (i = 0; environ[i] != NULL; i++) { 38 | if ((strncmp(name, environ[i], len) == 0) && 39 | (environ[i][len] == '=')) { 40 | olen = strlen(&environ[i][len+1]); 41 | if (olen >= buflen) { 42 | pthread_mutex_unlock(&env_mutex); 43 | return(ENOSPC); 44 | } 45 | strcpy(buf, &environ[i][len+1]); 46 | pthread_mutex_unlock(&env_mutex); 47 | return(0); 48 | } 49 | } 50 | pthread_mutex_unlock(&env_mutex); 51 | return(ENOENT); 52 | } 53 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/getenv2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/getenv2.o -------------------------------------------------------------------------------- /src/12_ThreadCtl/getenv3.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取指定的env变量-线程私有数据存储 3 | * 4 | * apue示例程序 - getenv3.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAXSTRINGSZ 4096 15 | 16 | static pthread_key_t key; 17 | static pthread_once_t init_done = PTHREAD_ONCE_INIT; 18 | pthread_mutex_t env_mutex = PTHREAD_MUTEX_INITIALIZER; 19 | 20 | extern char **environ; 21 | 22 | static void thread_init(void) 23 | { 24 | pthread_key_create(&key, free); 25 | } 26 | 27 | char *getenv(const char *name) 28 | { 29 | int i, len; 30 | char *envbuf; 31 | 32 | pthread_once(&init_done, thread_init); 33 | pthread_mutex_lock(&env_mutex); 34 | envbuf = (char *)pthread_getspecific(key); 35 | if (envbuf == NULL) { 36 | envbuf = malloc(MAXSTRINGSZ); 37 | if (envbuf == NULL) { 38 | pthread_mutex_unlock(&env_mutex); 39 | return(NULL); 40 | } 41 | pthread_setspecific(key, envbuf); 42 | } 43 | len = strlen(name); 44 | for (i = 0; environ[i] != NULL; i++) { 45 | if ((strncmp(name, environ[i], len) == 0) && 46 | (environ[i][len] == '=')) { 47 | strncpy(envbuf, &environ[i][len+1], MAXSTRINGSZ-1); 48 | pthread_mutex_unlock(&env_mutex); 49 | return(envbuf); 50 | } 51 | } 52 | pthread_mutex_unlock(&env_mutex); 53 | return(NULL); 54 | } 55 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/getenv3.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/getenv3.o -------------------------------------------------------------------------------- /src/12_ThreadCtl/suspend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/suspend -------------------------------------------------------------------------------- /src/12_ThreadCtl/suspend.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 线程的阻塞信号集测试,可以类比10_Signals/suspend2.c 3 | * 4 | * apue示例程序 - suspend.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int quitflag; /* set nonzero by thread */ 13 | sigset_t mask; 14 | 15 | pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 16 | pthread_cond_t waitloc = PTHREAD_COND_INITIALIZER; 17 | 18 | void *thr_fn(void *arg) 19 | { 20 | int err, signo; 21 | 22 | for (;;) { 23 | err = sigwait(&mask, &signo); 24 | if (err != 0) 25 | err_exit(err, "sigwait failed"); 26 | switch (signo) { 27 | case SIGINT: 28 | printf("\ninterrupt\n"); 29 | break; 30 | 31 | case SIGQUIT: 32 | pthread_mutex_lock(&lock); 33 | quitflag = 1; 34 | pthread_mutex_unlock(&lock); 35 | pthread_cond_signal(&waitloc); 36 | return(0); 37 | 38 | default: 39 | printf("unexpected signal %d\n", signo); 40 | exit(1); 41 | } 42 | } 43 | } 44 | 45 | int main(void) 46 | { 47 | int err; 48 | sigset_t oldmask; 49 | pthread_t tid; 50 | 51 | sigemptyset(&mask); 52 | sigaddset(&mask, SIGINT); 53 | sigaddset(&mask, SIGQUIT); 54 | if ((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0) 55 | err_exit(err, "SIG_BLOCK error"); 56 | 57 | err = pthread_create(&tid, NULL, thr_fn, 0); 58 | if (err != 0) 59 | err_exit(err, "can't create thread"); 60 | 61 | pthread_mutex_lock(&lock); 62 | while (quitflag == 0) 63 | pthread_cond_wait(&waitloc, &lock); 64 | pthread_mutex_unlock(&lock); 65 | 66 | /* SIGQUIT has been caught and is now blocked; do whatever */ 67 | quitflag = 0; 68 | 69 | /* reset signal mask which unblocks SIGQUIT */ 70 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 71 | err_sys("SIG_SETMASK error"); 72 | exit(0); 73 | } 74 | -------------------------------------------------------------------------------- /src/12_ThreadCtl/timeout: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/timeout -------------------------------------------------------------------------------- /src/12_ThreadCtl/timeout.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/12_ThreadCtl/timeout.o -------------------------------------------------------------------------------- /src/13_Daemons/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | all: init.o reread.o reread2.o single.o 6 | 7 | clean: 8 | rm -f $(TEMPFILES) *.o 9 | -------------------------------------------------------------------------------- /src/13_Daemons/init.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 守护进程封装函数示例 3 | * 4 | * apue示例程序 - init.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | #include 13 | 14 | void daemonize(const char *cmd) 15 | { 16 | int i, fd0, fd1, fd2; 17 | pid_t pid; 18 | struct rlimit rl; 19 | struct sigaction sa; 20 | 21 | /* 22 | * Clear file creation mask. 23 | */ 24 | umask(0); 25 | 26 | /* 27 | * Get maximum number of file descriptors. 28 | */ 29 | if (getrlimit(RLIMIT_NOFILE, &rl) < 0) 30 | err_quit("%s: can't get file limit", cmd); 31 | 32 | /* 33 | * Become a session leader to lose controlling TTY. 34 | */ 35 | if ((pid = fork()) < 0) 36 | err_quit("%s: can't fork", cmd); 37 | else if (pid != 0) /* parent */ 38 | exit(0); 39 | setsid(); 40 | 41 | /* 42 | * Ensure future opens won't allocate controlling TTYs. 43 | */ 44 | sa.sa_handler = SIG_IGN; 45 | sigemptyset(&sa.sa_mask); 46 | sa.sa_flags = 0; 47 | if (sigaction(SIGHUP, &sa, NULL) < 0) 48 | err_quit("%s: can't ignore SIGHUP", cmd); 49 | if ((pid = fork()) < 0) 50 | err_quit("%s: can't fork", cmd); 51 | else if (pid != 0) /* parent */ 52 | exit(0); 53 | 54 | /* 55 | * Change the current working directory to the root so 56 | * we won't prevent file systems from being unmounted. 57 | */ 58 | if (chdir("/") < 0) 59 | err_quit("%s: can't change directory to /", cmd); 60 | 61 | /* 62 | * Close all open file descriptors. 63 | */ 64 | if (rl.rlim_max == RLIM_INFINITY) 65 | rl.rlim_max = 1024; 66 | for (i = 0; i < rl.rlim_max; i++) 67 | close(i); 68 | 69 | /* 70 | * Attach file descriptors 0, 1, and 2 to /dev/null. 71 | */ 72 | fd0 = open("/dev/null", O_RDWR); 73 | fd1 = dup(0); 74 | fd2 = dup(0); 75 | 76 | /* 77 | * Initialize the log file. 78 | */ 79 | openlog(cmd, LOG_CONS, LOG_DAEMON); 80 | if (fd0 != 0 || fd1 != 1 || fd2 != 2) { 81 | syslog(LOG_ERR, "unexpected file descriptors %d %d %d", 82 | fd0, fd1, fd2); 83 | exit(1); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/13_Daemons/init.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/13_Daemons/init.o -------------------------------------------------------------------------------- /src/13_Daemons/reread.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/13_Daemons/reread.o -------------------------------------------------------------------------------- /src/13_Daemons/reread2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SIGHUP处理 3 | * 4 | * apue示例程序 - reread2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | extern int lockfile(int); 14 | extern int already_running(void); 15 | 16 | void reread(void) 17 | { 18 | /* ... */ 19 | } 20 | 21 | void sigterm(int signo) 22 | { 23 | syslog(LOG_INFO, "got SIGTERM; exiting"); 24 | exit(0); 25 | } 26 | 27 | void sighup(int signo) 28 | { 29 | syslog(LOG_INFO, "Re-reading configuration file"); 30 | reread(); 31 | } 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | char *cmd; 36 | struct sigaction sa; 37 | 38 | if ((cmd = strrchr(argv[0], '/')) == NULL) 39 | cmd = argv[0]; 40 | else 41 | cmd++; 42 | 43 | /* 44 | * Become a daemon. 45 | */ 46 | daemonize(cmd); 47 | 48 | /* 49 | * Make sure only one copy of the daemon is running. 50 | */ 51 | if (already_running()) { 52 | syslog(LOG_ERR, "daemon already running"); 53 | exit(1); 54 | } 55 | 56 | /* 57 | * Handle signals of interest. 58 | */ 59 | sa.sa_handler = sigterm; 60 | sigemptyset(&sa.sa_mask); 61 | sigaddset(&sa.sa_mask, SIGHUP); 62 | sa.sa_flags = 0; 63 | if (sigaction(SIGTERM, &sa, NULL) < 0) { 64 | syslog(LOG_ERR, "can't catch SIGTERM: %s", strerror(errno)); 65 | exit(1); 66 | } 67 | sa.sa_handler = sighup; 68 | sigemptyset(&sa.sa_mask); 69 | sigaddset(&sa.sa_mask, SIGTERM); 70 | sa.sa_flags = 0; 71 | if (sigaction(SIGHUP, &sa, NULL) < 0) { 72 | syslog(LOG_ERR, "can't catch SIGHUP: %s", strerror(errno)); 73 | exit(1); 74 | } 75 | 76 | /* 77 | * Proceed with the rest of the daemon. 78 | */ 79 | /* ... */ 80 | exit(0); 81 | } 82 | -------------------------------------------------------------------------------- /src/13_Daemons/reread2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/13_Daemons/reread2.o -------------------------------------------------------------------------------- /src/13_Daemons/single.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 单例进程实现 3 | * 4 | * apue示例程序 - single.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define LOCKFILE "/var/run/daemon.pid" 19 | #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 20 | 21 | extern int lockfile(int); 22 | 23 | int already_running(void) 24 | { 25 | int fd; 26 | char buf[16]; 27 | 28 | fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE); 29 | if (fd < 0) { 30 | syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno)); 31 | exit(1); 32 | } 33 | if (lockfile(fd) < 0) { 34 | if (errno == EACCES || errno == EAGAIN) { 35 | close(fd); 36 | return(1); 37 | } 38 | syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno)); 39 | exit(1); 40 | } 41 | ftruncate(fd, 0); 42 | sprintf(buf, "%ld", (long)getpid()); 43 | write(fd, buf, strlen(buf)+1); 44 | return(0); 45 | } 46 | -------------------------------------------------------------------------------- /src/13_Daemons/single.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/13_Daemons/single.o -------------------------------------------------------------------------------- /src/14_Advanced_IO/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "linux" 6 | EXTRALIBS=-lrt 7 | endif 8 | ifeq "$(PLATFORM)" "solaris" 9 | EXTRALIBS=-lrt 10 | endif 11 | 12 | PROGS = deadlock mandatory mcopy2 nonblockw 13 | 14 | all: $(PROGS) $(MOREPROGS) lockfile.o 15 | 16 | $(PROGS): $(LIBAPUE) 17 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 18 | 19 | clean: 20 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o 21 | 22 | include $(ROOT)/Make.libapue.inc 23 | -------------------------------------------------------------------------------- /src/14_Advanced_IO/deadlock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/14_Advanced_IO/deadlock -------------------------------------------------------------------------------- /src/14_Advanced_IO/deadlock.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file A/B锁顺序引起的死锁 3 | * 4 | * apue示例程序 - deadlock.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | static void lockabyte(const char *name, int fd, off_t offset) 13 | { 14 | if (write_lock(fd, offset, SEEK_SET, 1) < 0) 15 | err_sys("%s: writew_lock error", name); 16 | printf("%s: got the lock, byte %lld\n", name, (long long)offset); 17 | } 18 | 19 | int main(void) 20 | { 21 | int fd; 22 | pid_t pid; 23 | 24 | /* 25 | * Create a file and write two bytes to it. 26 | */ 27 | if ((fd = creat("templock", FILE_MODE)) < 0) 28 | err_sys("creat error"); 29 | if (write(fd, "ab", 2) != 2) 30 | err_sys("write error"); 31 | 32 | TELL_WAIT(); 33 | if ((pid = fork()) < 0) { 34 | err_sys("fork error"); 35 | } else if (pid == 0) { /* child */ 36 | lockabyte("child", fd, 0); 37 | TELL_PARENT(getppid()); 38 | WAIT_PARENT(); 39 | lockabyte("child", fd, 1); 40 | } else { /* parent */ 41 | lockabyte("parent", fd, 1); 42 | TELL_CHILD(pid); 43 | WAIT_CHILD(); 44 | lockabyte("parent", fd, 0); 45 | } 46 | exit(0); 47 | } 48 | -------------------------------------------------------------------------------- /src/14_Advanced_IO/lockfile.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 写锁整个文件demo 3 | * 4 | * apue示例程序 - lockfile.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | int lockfile(int fd) 13 | { 14 | struct flock fl; 15 | 16 | fl.l_type = F_WRLCK; 17 | fl.l_start = 0; 18 | fl.l_whence = SEEK_SET; 19 | fl.l_len = 0; 20 | return(fcntl(fd, F_SETLK, &fl)); 21 | } 22 | -------------------------------------------------------------------------------- /src/14_Advanced_IO/lockfile.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/14_Advanced_IO/lockfile.o -------------------------------------------------------------------------------- /src/14_Advanced_IO/mandatory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/14_Advanced_IO/mandatory -------------------------------------------------------------------------------- /src/14_Advanced_IO/mandatory.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 记录读写锁的尝试使用demo 3 | * 4 | * apue示例程序 - mandatory.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int fd; 17 | pid_t pid; 18 | char buf[5]; 19 | struct stat statbuf; 20 | 21 | if (argc != 2) { 22 | fprintf(stderr, "usage: %s filename\n", argv[0]); 23 | exit(1); 24 | } 25 | if ((fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0) 26 | err_sys("open error"); 27 | if (write(fd, "abcdef", 6) != 6) 28 | err_sys("write error"); 29 | 30 | /* turn on set-group-ID and turn off group-execute */ 31 | if (fstat(fd, &statbuf) < 0) 32 | err_sys("fstat error"); 33 | if (fchmod(fd, (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0) 34 | err_sys("fchmod error"); 35 | 36 | TELL_WAIT(); 37 | 38 | if ((pid = fork()) < 0) { 39 | err_sys("fork error"); 40 | } else if (pid > 0) { /* parent */ 41 | /* write lock entire file */ 42 | if (write_lock(fd, 0, SEEK_SET, 0) < 0) 43 | err_sys("write_lock error"); 44 | 45 | TELL_CHILD(pid); 46 | 47 | if (waitpid(pid, NULL, 0) < 0) 48 | err_sys("waitpid error"); 49 | } else { /* child */ 50 | WAIT_PARENT(); /* wait for parent to set lock */ 51 | 52 | set_fl(fd, O_NONBLOCK); 53 | 54 | /* first let's see what error we get if region is locked */ 55 | if (read_lock(fd, 0, SEEK_SET, 0) != -1) /* no wait */ 56 | err_sys("child: read_lock succeeded"); 57 | printf("read_lock of already-locked region returns %d\n", 58 | errno); 59 | 60 | /* now try to read the mandatory locked file */ 61 | if (lseek(fd, 0, SEEK_SET) == -1) 62 | err_sys("lseek error"); 63 | if (read(fd, buf, 2) < 0) 64 | err_ret("read failed (mandatory locking works)"); 65 | else 66 | printf("read OK (no mandatory locking), buf = %2.2s\n", 67 | buf); 68 | } 69 | exit(0); 70 | } 71 | -------------------------------------------------------------------------------- /src/14_Advanced_IO/mcopy2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/14_Advanced_IO/mcopy2 -------------------------------------------------------------------------------- /src/14_Advanced_IO/mcopy2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mmap拷贝文件demo 3 | * 4 | * apue示例程序 - mcopy2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | #define COPYINCR (1024*1024*1024) /* 1 GB */ 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | int fdin, fdout; 18 | void *src, *dst; 19 | size_t copysz; 20 | struct stat sbuf; 21 | off_t fsz = 0; 22 | 23 | if (argc != 3) 24 | err_quit("usage: %s ", argv[0]); 25 | 26 | if ((fdin = open(argv[1], O_RDONLY)) < 0) 27 | err_sys("can't open %s for reading", argv[1]); 28 | 29 | if ((fdout = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 30 | FILE_MODE)) < 0) 31 | err_sys("can't creat %s for writing", argv[2]); 32 | 33 | if (fstat(fdin, &sbuf) < 0) /* need size of input file */ 34 | err_sys("fstat error"); 35 | 36 | if (ftruncate(fdout, sbuf.st_size) < 0) /* set output file size */ 37 | err_sys("ftruncate error"); 38 | 39 | while (fsz < sbuf.st_size) { 40 | if ((sbuf.st_size - fsz) > COPYINCR) 41 | copysz = COPYINCR; 42 | else 43 | copysz = sbuf.st_size - fsz; 44 | 45 | if ((src = mmap(0, copysz, PROT_READ, MAP_SHARED, 46 | fdin, fsz)) == MAP_FAILED) 47 | err_sys("mmap error for input"); 48 | if ((dst = mmap(0, copysz, PROT_READ | PROT_WRITE, 49 | MAP_SHARED, fdout, fsz)) == MAP_FAILED) 50 | err_sys("mmap error for output"); 51 | 52 | memcpy(dst, src, copysz); /* does the file copy */ 53 | 54 | munmap(src, copysz); 55 | munmap(dst, copysz); 56 | fsz += copysz; 57 | } 58 | exit(0); 59 | } 60 | -------------------------------------------------------------------------------- /src/14_Advanced_IO/nonblockw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/14_Advanced_IO/nonblockw -------------------------------------------------------------------------------- /src/14_Advanced_IO/nonblockw.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 非阻塞I/O写demo 3 | * 4 | * apue示例程序 - nonblockw.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | char buf[500000]; 14 | 15 | int main(void) 16 | { 17 | int ntowrite, nwrite; 18 | char *ptr; 19 | 20 | ntowrite = read(STDIN_FILENO, buf, sizeof(buf)); 21 | fprintf(stderr, "read %d bytes\n", ntowrite); 22 | 23 | set_fl(STDOUT_FILENO, O_NONBLOCK); /* set nonblocking */ 24 | 25 | ptr = buf; 26 | while (ntowrite > 0) { 27 | errno = 0; 28 | nwrite = write(STDOUT_FILENO, ptr, ntowrite); 29 | fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno); 30 | 31 | if (nwrite > 0) { 32 | ptr += nwrite; 33 | ntowrite -= nwrite; 34 | } 35 | } 36 | 37 | clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */ 38 | 39 | exit(0); 40 | } 41 | -------------------------------------------------------------------------------- /src/15_IPC/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "linux" 6 | EXTRALIBS=-lrt 7 | endif 8 | ifeq "$(PLATFORM)" "solaris" 9 | EXTRALIBS=-lrt 10 | endif 11 | 12 | PROGS = add2 add2stdio devzero myuclc pipe1 pipe2 pipe3 pipe4 popen1 popen2 tshm fifo read_fifo write_fifo \ 13 | read_shm write_shm mq_client mq_server 14 | MOREPROGS = shm_put shm_get 15 | all: $(PROGS) $(MOREPROGS) popen.o slock.o tellwait.o shm_fifo.o 16 | 17 | shm_get: shm_get.o shm_fifo.o 18 | $(CC) $(CFLAGS) -o shm_get shm_get.o shm_fifo.o $(LDFLAGS) $(LDLIBS) 19 | 20 | shm_put: shm_put.o shm_fifo.o 21 | $(CC) $(CFLAGS) -o shm_put shm_put.o shm_fifo.o $(LDFLAGS) $(LDLIBS) 22 | 23 | slock.o: slock.c slock.h 24 | 25 | $(PROGS): $(LIBAPUE) 26 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 27 | 28 | clean: 29 | rm -f $(PROGS) $(TEMPFILES) *.o 30 | 31 | include $(ROOT)/Make.libapue.inc 32 | -------------------------------------------------------------------------------- /src/15_IPC/add2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/add2 -------------------------------------------------------------------------------- /src/15_IPC/add2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 协同进程add2 3 | * 4 | * apue示例程序 - add2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int n, int1, int2; 14 | char line[MAXLINE]; 15 | 16 | while ((n = read(STDIN_FILENO, line, MAXLINE)) > 0) { 17 | line[n] = 0; /* null terminate */ 18 | if (sscanf(line, "%d%d", &int1, &int2) == 2) { 19 | sprintf(line, "%d\n", int1 + int2); 20 | n = strlen(line); 21 | if (write(STDOUT_FILENO, line, n) != n) 22 | err_sys("write error"); 23 | } else { 24 | if (write(STDOUT_FILENO, "invalid args\n", 13) != 13) 25 | err_sys("write error"); 26 | } 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/15_IPC/add2stdio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/add2stdio -------------------------------------------------------------------------------- /src/15_IPC/add2stdio.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 协同进程add2stdio 3 | * 4 | * apue示例程序 - add2stdio.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int int1, int2; 14 | char line[MAXLINE]; 15 | 16 | /* 17 | if (setvbuf(stdin, NULL, _IOLBF, 0) != 0) { 18 | err_sys("setvbuf error"); 19 | } 20 | if (setvbuf(stdout, NULL, _IOLBF, 0) != 0) { 21 | err_sys("setvbuf error"); 22 | } 23 | */ 24 | while (fgets(line, MAXLINE, stdin) != NULL) { 25 | if (sscanf(line, "%d%d", &int1, &int2) == 2) { 26 | if (printf("%d\n", int1 + int2) == EOF) 27 | err_sys("printf error"); 28 | } else { 29 | if (printf("invalid args\n") == EOF) 30 | err_sys("printf error"); 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /src/15_IPC/common_shm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 共享存储公共头 3 | * 4 | * apue示例程序 - common_shm.h 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #pragma once 10 | 11 | #define SHM_ID 1234 12 | 13 | typedef struct Student { 14 | int age; 15 | char name[10]; 16 | }Student; -------------------------------------------------------------------------------- /src/15_IPC/devzero: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/devzero -------------------------------------------------------------------------------- /src/15_IPC/devzero.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 对比mmap, mmap是文件与内存的关联 3 | * 4 | * apue示例程序 - devzero.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | #define NLOOPS 1000 14 | #define SIZE sizeof(long) /* size of shared memory area */ 15 | 16 | static int update(long *ptr) 17 | { 18 | return((*ptr)++); /* return value before increment */ 19 | } 20 | 21 | int main() 22 | { 23 | int fd, i, counter; 24 | pid_t pid; 25 | void *area; 26 | 27 | if ((fd = open("/dev/zero", O_RDWR)) < 0) 28 | err_sys("open error"); 29 | if ((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 30 | fd, 0)) == MAP_FAILED) 31 | err_sys("mmap error"); 32 | close(fd); /* can close /dev/zero now that it's mapped */ 33 | 34 | TELL_WAIT(); 35 | 36 | if ((pid = fork()) < 0) { 37 | err_sys("fork error"); 38 | } else if (pid > 0) { /* parent */ 39 | for (i = 0; i < NLOOPS; i += 2) { 40 | if ((counter = update((long *)area)) != i) 41 | err_quit("parent: expected %d, got %d", i, counter); 42 | 43 | TELL_CHILD(pid); 44 | WAIT_CHILD(); 45 | } 46 | } else { /* child */ 47 | for (i = 1; i < NLOOPS + 1; i += 2) { 48 | WAIT_PARENT(); 49 | 50 | if ((counter = update((long *)area)) != i) 51 | err_quit("child: expected %d, got %d", i, counter); 52 | 53 | TELL_PARENT(getppid()); 54 | } 55 | } 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /src/15_IPC/fifo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/fifo -------------------------------------------------------------------------------- /src/15_IPC/fifo.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 创建FIFO 3 | * 4 | * apue示例程序 - fifo.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "apue.h" 15 | 16 | int main() 17 | { 18 | if(mkfifo("my_fifo", 0777) == -1) 19 | { 20 | err_sys("mkfifo"); 21 | } 22 | return 0; 23 | } -------------------------------------------------------------------------------- /src/15_IPC/mq_client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/mq_client -------------------------------------------------------------------------------- /src/15_IPC/mq_client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MQ-Client 3 | * 4 | * apue示例程序 - mq_client.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "mq_common.h" 16 | #include "apue.h" 17 | 18 | int main() 19 | { 20 | int id = msgget(MQ_KEY, 0); 21 | if(id == -1) err_sys("msgget"); 22 | while(1) { 23 | msgbuf_t mb,rcv; 24 | memset(&mb, 0x00, sizeof(mb)); 25 | while(fgets(mb.mtext+sizeof(long), 100- sizeof(long), stdin) != NULL) { 26 | *(long*)mb.mtext = getpid(); 27 | mb.channel = 1; 28 | 29 | msgsnd(id, &mb, strlen(mb.mtext+ sizeof(long))+sizeof(long), 0); 30 | printf("send ok!\n"); 31 | 32 | memset(&rcv, 0x00, sizeof(rcv)); 33 | if(msgrcv(id, &rcv, 100, (long)getpid(), 0) == -1) { 34 | err_sys("msgrcv"); 35 | } 36 | printf("Message back: %s\n", rcv.mtext + sizeof(long)); 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /src/15_IPC/mq_common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by r00tk1t on 2020/12/27. 3 | // 4 | 5 | #ifndef APUE_MQ_COMMON_H 6 | #define APUE_MQ_COMMON_H 7 | 8 | #define MQ_KEY 11111 9 | 10 | typedef struct msg_buf{ 11 | long channel; 12 | char mtext[100]; 13 | }msgbuf_t; 14 | 15 | #endif //APUE_MQ_COMMON_H 16 | -------------------------------------------------------------------------------- /src/15_IPC/mq_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/mq_server -------------------------------------------------------------------------------- /src/15_IPC/mq_server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MQ-Server 3 | * 4 | * apue示例程序 - mq_server.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "mq_common.h" 16 | #include "apue.h" 17 | 18 | int main() 19 | { 20 | int id = msgget(MQ_KEY, IPC_CREAT|0644); //创建消息队列 21 | if(id == -1) err_sys("msgget"); 22 | 23 | while(1) { 24 | msgbuf_t mb; 25 | memset(&mb, 0x00, sizeof(mb)); 26 | if(msgrcv(id ,&mb, 100,1, 0) == -1) 27 | err_sys("msgrcv"); 28 | 29 | printf("Get from Client:%s\n", mb.mtext+ sizeof(long)); 30 | mb.channel = *(long*)(mb.mtext); 31 | msgsnd(id, &mb, strlen(mb.mtext+sizeof(long)) + sizeof(long), 0); 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /src/15_IPC/myuclc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/myuclc -------------------------------------------------------------------------------- /src/15_IPC/myuclc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file popen测试辅助过滤程序 3 | * 4 | * apue示例程序 - myuclc.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int c; 15 | 16 | while ((c = getchar()) != EOF) { 17 | if (isupper(c)) 18 | c = tolower(c); 19 | if (putchar(c) == EOF) 20 | err_sys("output error"); 21 | if (c == '\n') 22 | fflush(stdout); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/15_IPC/pipe1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/pipe1 -------------------------------------------------------------------------------- /src/15_IPC/pipe1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 创建管道 3 | * 4 | * apue示例程序 - pipe1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int n; 14 | int fd[2]; 15 | pid_t pid; 16 | char line[MAXLINE]; 17 | 18 | if (pipe(fd) < 0) 19 | err_sys("pipe error"); 20 | if ((pid = fork()) < 0) { 21 | err_sys("fork error"); 22 | } else if (pid > 0) { /* parent */ 23 | close(fd[0]); 24 | write(fd[1], "hello world\n", 12); 25 | } else { /* child */ 26 | close(fd[1]); 27 | n = read(fd[0], line, MAXLINE); 28 | write(STDOUT_FILENO, line, n); 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/15_IPC/pipe2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/pipe2 -------------------------------------------------------------------------------- /src/15_IPC/pipe2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 管道与PAGER交互 3 | * 4 | * apue示例程序 - pipe2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | #define DEF_PAGER "/bin/more" /* default pager program */ 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int n; 17 | int fd[2]; 18 | pid_t pid; 19 | char *pager, *argv0; 20 | char line[MAXLINE]; 21 | FILE *fp; 22 | 23 | if (argc != 2) 24 | err_quit("usage: pipe2 "); 25 | 26 | if ((fp = fopen(argv[1], "r")) == NULL) 27 | err_sys("can't open %s", argv[1]); 28 | if (pipe(fd) < 0) 29 | err_sys("pipe error"); 30 | 31 | if ((pid = fork()) < 0) { 32 | err_sys("fork error"); 33 | } else if (pid > 0) { /* parent */ 34 | close(fd[0]); /* close read end */ 35 | 36 | /* parent copies argv[1] to pipe */ 37 | while (fgets(line, MAXLINE, fp) != NULL) { 38 | n = strlen(line); 39 | if (write(fd[1], line, n) != n) 40 | err_sys("write error to pipe"); 41 | } 42 | if (ferror(fp)) 43 | err_sys("fgets error"); 44 | 45 | close(fd[1]); /* close write end of pipe for reader */ 46 | 47 | if (waitpid(pid, NULL, 0) < 0) 48 | err_sys("waitpid error"); 49 | return 0; 50 | } else { /* child */ 51 | close(fd[1]); /* close write end */ 52 | if (fd[0] != STDIN_FILENO) { 53 | if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) 54 | err_sys("dup2 error to stdin"); 55 | close(fd[0]); /* don't need this after dup2 */ 56 | } 57 | 58 | /* get arguments for execl() */ 59 | if ((pager = getenv("PAGER")) == NULL) 60 | pager = DEF_PAGER; 61 | if ((argv0 = strrchr(pager, '/')) != NULL) 62 | argv0++; /* step past rightmost slash */ 63 | else 64 | argv0 = pager; /* no slash in pager */ 65 | 66 | if (execlp(pager, argv0, (char *)0) < 0) 67 | err_sys("execl error for %s", pager); 68 | } 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/15_IPC/pipe3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/pipe3 -------------------------------------------------------------------------------- /src/15_IPC/pipe3.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 管道模拟`ls -l|wc -l` 3 | * 4 | * apue示例程序 - pipe3.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int n; 14 | int fd[2]; 15 | pid_t pid; 16 | char line[MAXLINE]; 17 | 18 | if (pipe(fd) < 0) 19 | err_sys("pipe error"); 20 | if ((pid = fork()) < 0) { 21 | err_sys("fork error"); 22 | } else if (pid == 0) { /* child */ 23 | close(fd[0]); 24 | if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) 25 | err_sys("dup2 error to stdout"); 26 | execlp("ls", "ls", "-l", NULL); 27 | close(fd[1]); 28 | exit(127); 29 | } else { /* parent */ 30 | close(fd[1]); 31 | if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) 32 | err_sys("dup2 error to stdin"); 33 | execlp("wc", "wc", "-l", NULL); 34 | close(fd[0]); 35 | exit(127); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/15_IPC/pipe4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/pipe4 -------------------------------------------------------------------------------- /src/15_IPC/pipe4.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 协同进程 3 | * 4 | * apue示例程序 - pipe4.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static void sig_pipe(int); /* our signal handler */ 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int n, fd1[2], fd2[2]; 16 | pid_t pid; 17 | char line[MAXLINE]; 18 | 19 | if (signal(SIGPIPE, sig_pipe) == SIG_ERR) 20 | err_sys("signal error"); 21 | 22 | if (pipe(fd1) < 0 || pipe(fd2) < 0) 23 | err_sys("pipe error"); 24 | 25 | if ((pid = fork()) < 0) { 26 | err_sys("fork error"); 27 | } else if (pid > 0) { /* parent */ 28 | close(fd1[0]); 29 | close(fd2[1]); 30 | 31 | while (fgets(line, MAXLINE, stdin) != NULL) { 32 | n = strlen(line); 33 | if (write(fd1[1], line, n) != n) 34 | err_sys("write error to pipe"); 35 | if ((n = read(fd2[0], line, MAXLINE)) < 0) 36 | err_sys("read error from pipe"); 37 | if (n == 0) { 38 | err_msg("child closed pipe"); 39 | break; 40 | } 41 | line[n] = 0; /* null terminate */ 42 | if (fputs(line, stdout) == EOF) 43 | err_sys("fputs error"); 44 | } 45 | 46 | if (ferror(stdin)) 47 | err_sys("fgets error on stdin"); 48 | return 0; 49 | } else { /* child */ 50 | close(fd1[1]); 51 | close(fd2[0]); 52 | if (fd1[0] != STDIN_FILENO) { 53 | if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) 54 | err_sys("dup2 error to stdin"); 55 | close(fd1[0]); 56 | } 57 | 58 | if (fd2[1] != STDOUT_FILENO) { 59 | if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO) 60 | err_sys("dup2 error to stdout"); 61 | close(fd2[1]); 62 | } 63 | if (execl("./add2", "add2", (char *)0) < 0) 64 | err_sys("execl error"); 65 | } 66 | return 0; 67 | } 68 | 69 | static void sig_pipe(int signo) 70 | { 71 | printf("SIGPIPE caught\n"); 72 | exit(1); 73 | } 74 | -------------------------------------------------------------------------------- /src/15_IPC/popen.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/popen.o -------------------------------------------------------------------------------- /src/15_IPC/popen1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/popen1 -------------------------------------------------------------------------------- /src/15_IPC/popen1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file popen读取测试 3 | * 4 | * apue示例程序 - popen1.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | char line[MAXLINE]; 15 | FILE *fpin; 16 | 17 | if ((fpin = popen("./myuclc", "r")) == NULL) 18 | err_sys("popen error"); 19 | for ( ; ; ) { 20 | fputs("prompt> ", stdout); 21 | fflush(stdout); 22 | if (fgets(line, MAXLINE, fpin) == NULL) /* read from pipe */ 23 | break; 24 | if (fputs(line, stdout) == EOF) 25 | err_sys("fputs error to pipe"); 26 | } 27 | if (pclose(fpin) == -1) 28 | err_sys("pclose error"); 29 | putchar('\n'); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/15_IPC/popen2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/popen2 -------------------------------------------------------------------------------- /src/15_IPC/popen2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PAGER交互-popen版 3 | * 4 | * apue示例程序 - popen2.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | #define PAGER "${PAGER:-more}" /* environment variable, or default */ 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | char line[MAXLINE]; 17 | FILE *fpin, *fpout; 18 | 19 | if (argc != 2) 20 | err_quit("usage: a.out "); 21 | if ((fpin = fopen(argv[1], "r")) == NULL) 22 | err_sys("can't open %s", argv[1]); 23 | 24 | if ((fpout = popen(PAGER, "w")) == NULL) 25 | err_sys("popen error"); 26 | 27 | /* copy argv[1] to pager */ 28 | while (fgets(line, MAXLINE, fpin) != NULL) { 29 | if (fputs(line, fpout) == EOF) 30 | err_sys("fputs error to pipe"); 31 | } 32 | if (ferror(fpin)) 33 | err_sys("fgets error"); 34 | if (pclose(fpout) == -1) 35 | err_sys("pclose error"); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/15_IPC/read_fifo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/read_fifo -------------------------------------------------------------------------------- /src/15_IPC/read_fifo.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 读FIFO 3 | * 4 | * apue示例程序 - read_fifo.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "apue.h" 15 | 16 | int main() 17 | { 18 | int fd; 19 | char buf[MAXLINE]; 20 | fd = open("my_fifo", O_RDONLY); 21 | 22 | while(1) 23 | { 24 | read(fd, buf, sizeof(buf)); 25 | printf("%s\n", buf); 26 | sleep(1); 27 | } 28 | return 0; 29 | } -------------------------------------------------------------------------------- /src/15_IPC/read_shm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/read_shm -------------------------------------------------------------------------------- /src/15_IPC/read_shm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 读共享存储 3 | * 4 | * apue示例程序 - read_shm.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "common_shm.h" 16 | 17 | int main() 18 | { 19 | int id = shmget(SHM_ID, 8, 0); 20 | if (id == -1) err_sys("shmget"); 21 | 22 | Student *p = (Student*)shmat(id, NULL, 0); 23 | while(1) { 24 | printf(" age=%d, name=%s\n", p->age, p->name); 25 | sleep(2); 26 | } 27 | return 0; 28 | } -------------------------------------------------------------------------------- /src/15_IPC/shm_fifo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 共享存储信息 3 | * 4 | * apue示例程序 - shm_fifo.h 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #ifndef __SHMFIFO_H__ 10 | #define __SHMFIFO_H__ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | typedef struct shmhead { 21 | int rd_idx; // 读入数据索引 22 | int wr_idx; // 写数据索引 23 | int blocks; // 存数据块数量 24 | int blksz; // 每个数据块大小 25 | } shmhead_t; 26 | 27 | typedef struct shmfifo { 28 | shmhead_t *p_head; // 共享内存的起始地址 29 | char * p_payload; // 有效数据的起始地址 30 | int shmid; // 打开的共享内存id 31 | int sem_mutex; // 互斥量 32 | int sem_empty; // 还剩多少个地方可以生产 33 | int sem_full; // 剩余多少个地方可以消费 34 | } shmfifo_t; 35 | 36 | // 初始化函数 37 | shmfifo_t *shmfifo_init(key_t key, int blocks, int blksz); 38 | // 放入数据 39 | void shmfifo_put(shmfifo_t *fifo, const void *buf); 40 | // 取得数据 41 | void shmfifo_get(shmfifo_t *fifo, void *buf); 42 | // 结构销毁 43 | void shmfifo_destroy(shmfifo_t *fifo); 44 | 45 | #endif //__SHMFIFO_H__ -------------------------------------------------------------------------------- /src/15_IPC/shm_fifo.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/shm_fifo.o -------------------------------------------------------------------------------- /src/15_IPC/shm_get: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/shm_get -------------------------------------------------------------------------------- /src/15_IPC/shm_get.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 共享存储FIFO-GET端 3 | * 4 | * apue示例程序 - shm_get.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "shm_fifo.h" 10 | #include 11 | 12 | typedef struct Products{ 13 | int id; 14 | char pro_name[10]; 15 | }Pro; 16 | 17 | int main() 18 | { 19 | shmfifo_t* fifo = shmfifo_init(12345, 3, sizeof(Pro)); 20 | Pro p; 21 | 22 | for(int i=0; i<20; i++) { 23 | memset(&p, 0x00, sizeof(p)); 24 | shmfifo_get(fifo, &p); 25 | printf("id:%d, 产品名:%s\n", p.id, p.pro_name); 26 | sleep(1); 27 | } 28 | shmfifo_destroy(fifo); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /src/15_IPC/shm_get.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/shm_get.o -------------------------------------------------------------------------------- /src/15_IPC/shm_put: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/shm_put -------------------------------------------------------------------------------- /src/15_IPC/shm_put.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 共享存储FIFO-PUT端 3 | * 4 | * apue示例程序 - shm_put.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include "shm_fifo.h" 10 | 11 | typedef struct Product 12 | { 13 | int id; 14 | char pro_name[10]; 15 | }Pro; 16 | 17 | int main() 18 | { 19 | shmfifo_t *fifo = shmfifo_init(12345, 4, sizeof(Pro)); 20 | Pro p; 21 | 22 | for (int i=0; i<20; ++i) { 23 | memset(&p, 0x00, sizeof(p)); 24 | sprintf(p.pro_name, "iphone%d", i); 25 | p.id = i+1; 26 | shmfifo_put(fifo, &p); 27 | printf("put %d ok\n", i); 28 | } 29 | return 0; 30 | } -------------------------------------------------------------------------------- /src/15_IPC/shm_put.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/shm_put.o -------------------------------------------------------------------------------- /src/15_IPC/slock.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file POSIX信号量-互斥锁实现 3 | * 4 | * apue示例程序 - slock.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "slock.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct slock *s_alloc() 16 | { 17 | struct slock *sp; 18 | static int cnt; 19 | 20 | if ((sp = malloc(sizeof(struct slock))) == NULL) 21 | return(NULL); 22 | do { 23 | snprintf(sp->name, sizeof(sp->name), "/%ld.%d", (long)getpid(), cnt++); 24 | sp->semp = sem_open(sp->name, O_CREAT|O_EXCL, S_IRWXU, 1); 25 | } while ((sp->semp == SEM_FAILED) && (errno == EEXIST)); 26 | if (sp->semp == SEM_FAILED) { 27 | free(sp); 28 | return(NULL); 29 | } 30 | sem_unlink(sp->name); 31 | return(sp); 32 | } 33 | 34 | void s_free(struct slock *sp) 35 | { 36 | sem_close(sp->semp); 37 | free(sp); 38 | } 39 | 40 | int s_lock(struct slock *sp) 41 | { 42 | return(sem_wait(sp->semp)); 43 | } 44 | 45 | int s_trylock(struct slock *sp) 46 | { 47 | return(sem_trywait(sp->semp)); 48 | } 49 | 50 | int s_unlock(struct slock *sp) 51 | { 52 | return(sem_post(sp->semp)); 53 | } 54 | -------------------------------------------------------------------------------- /src/15_IPC/slock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file POSIX信号量-互斥锁实现 3 | * 4 | * apue示例程序 - slock.h 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | struct slock { 15 | sem_t *semp; 16 | char name[_POSIX_NAME_MAX]; 17 | }; 18 | 19 | struct slock * s_alloc(); 20 | void s_free(struct slock *); 21 | int s_lock(struct slock *); 22 | int s_trylock(struct slock *); 23 | int s_unlock(struct slock *); 24 | -------------------------------------------------------------------------------- /src/15_IPC/slock.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/slock.o -------------------------------------------------------------------------------- /src/15_IPC/tellwait.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file TELL/WAIT语义管道实现版本 3 | * 4 | * apue示例程序 - tellwait.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | 11 | static int pfd1[2], pfd2[2]; 12 | 13 | void 14 | TELL_WAIT(void) 15 | { 16 | if (pipe(pfd1) < 0 || pipe(pfd2) < 0) 17 | err_sys("pipe error"); 18 | } 19 | 20 | void 21 | TELL_PARENT(pid_t pid) 22 | { 23 | if (write(pfd2[1], "c", 1) != 1) 24 | err_sys("write error"); 25 | } 26 | 27 | void 28 | WAIT_PARENT(void) 29 | { 30 | char c; 31 | 32 | if (read(pfd1[0], &c, 1) != 1) 33 | err_sys("read error"); 34 | 35 | if (c != 'p') 36 | err_quit("WAIT_PARENT: incorrect data"); 37 | } 38 | 39 | void 40 | TELL_CHILD(pid_t pid) 41 | { 42 | if (write(pfd1[1], "p", 1) != 1) 43 | err_sys("write error"); 44 | } 45 | 46 | void 47 | WAIT_CHILD(void) 48 | { 49 | char c; 50 | 51 | if (read(pfd2[0], &c, 1) != 1) 52 | err_sys("read error"); 53 | 54 | if (c != 'c') 55 | err_quit("WAIT_CHILD: incorrect data"); 56 | } 57 | -------------------------------------------------------------------------------- /src/15_IPC/tellwait.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/tellwait.o -------------------------------------------------------------------------------- /src/15_IPC/tshm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/tshm -------------------------------------------------------------------------------- /src/15_IPC/tshm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 创建共享存储demo 3 | * 4 | * apue示例程序 - tshm.c 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | #define ARRAY_SIZE 40000 13 | #define MALLOC_SIZE 100000 14 | #define SHM_SIZE 100000 15 | #define SHM_MODE 0600 /* user read/write */ 16 | 17 | char array[ARRAY_SIZE]; /* uninitialized data = bss */ 18 | 19 | int main() 20 | { 21 | int shmid; 22 | char *ptr, *shmptr; 23 | 24 | printf("array[] from %p to %p\n", (void *)&array[0], 25 | (void *)&array[ARRAY_SIZE]); 26 | printf("stack around %p\n", (void *)&shmid); 27 | 28 | if ((ptr = malloc(MALLOC_SIZE)) == NULL) 29 | err_sys("malloc error"); 30 | printf("malloced from %p to %p\n", (void *)ptr, 31 | (void *)ptr+MALLOC_SIZE); 32 | 33 | if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0) 34 | err_sys("shmget error"); 35 | if ((shmptr = shmat(shmid, 0, 0)) == (void *)-1) 36 | err_sys("shmat error"); 37 | printf("shared memory attached from %p to %p\n", (void *)shmptr, 38 | (void *)shmptr+SHM_SIZE); 39 | 40 | if (shmctl(shmid, IPC_RMID, 0) < 0) 41 | err_sys("shmctl error"); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /src/15_IPC/write_fifo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/write_fifo -------------------------------------------------------------------------------- /src/15_IPC/write_fifo.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 写FIFO 3 | * 4 | * apue示例程序 - write_fifo.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main() 16 | { 17 | int fd; 18 | char buf[] = "6666"; 19 | fd = open("my_fifo", O_WRONLY); 20 | 21 | while(1) 22 | { 23 | write(fd, buf, sizeof(buf)); 24 | sleep(1); 25 | } 26 | return 0; 27 | } -------------------------------------------------------------------------------- /src/15_IPC/write_shm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/15_IPC/write_shm -------------------------------------------------------------------------------- /src/15_IPC/write_shm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 写共享存储 3 | * 4 | * apue示例程序 - write_shm.c 5 | * 6 | * @author r00tk1t 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "common_shm.h" 16 | 17 | int main() 18 | { 19 | Student s; 20 | strcpy(s.name, "Jack"); 21 | 22 | int id = shmget(SHM_ID, 8, IPC_CREAT|0644); 23 | if (id == -1) err_sys("shmget"); 24 | 25 | Student *p = (Student*)shmat(id, NULL, 0); 26 | 27 | int i = 0; 28 | while(1) { 29 | s.age = i++; 30 | memcpy(p, &s, sizeof(Student)); 31 | sleep(2); 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /src/Make.defines.freebsd: -------------------------------------------------------------------------------- 1 | # Common make definitions, customized for each platform 2 | 3 | # Definitions required in all program directories to compile and link 4 | # C programs using gcc. 5 | 6 | CC=gcc 7 | COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c 8 | LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 9 | LDFLAGS= 10 | LDDIR=-L$(ROOT)/lib 11 | LDLIBS=$(LDDIR) -lapue $(EXTRALIBS) 12 | CFLAGS=-ansi -I$(ROOT)/include -Wall -DBSD -D__BSD_VISIBLE $(EXTRA) 13 | RANLIB=ranlib 14 | AR=ar 15 | AWK=awk 16 | LIBAPUE=$(ROOT)/lib/libapue.a 17 | 18 | # Common temp files to delete from each directory. 19 | TEMPFILES=core core.* *.o temp.* *.out 20 | -------------------------------------------------------------------------------- /src/Make.defines.linux: -------------------------------------------------------------------------------- 1 | # Common make definitions, customized for each platform 2 | 3 | # Definitions required in all program directories to compile and link 4 | # C programs using gcc. 5 | 6 | CC=gcc 7 | COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c 8 | LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 9 | LDFLAGS= 10 | LDDIR=-L$(ROOT)/lib 11 | LDLIBS=$(LDDIR) -lapue $(EXTRALIBS) 12 | CFLAGS=-I$(ROOT)/include -Wall -DLINUX -D_GNU_SOURCE $(EXTRA) 13 | RANLIB=echo 14 | AR=ar 15 | AWK=awk 16 | LIBAPUE=$(ROOT)/lib/libapue.a 17 | 18 | # Common temp files to delete from each directory. 19 | TEMPFILES=core core.* *.o temp.* *.out 20 | -------------------------------------------------------------------------------- /src/Make.defines.macos: -------------------------------------------------------------------------------- 1 | # Common make definitions, customized for each platform 2 | 3 | # Definitions required in all program directories to compile and link 4 | # C programs using gcc. 5 | 6 | CC=gcc 7 | COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c 8 | LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 9 | LDFLAGS= 10 | LDDIR=-L$(ROOT)/lib 11 | LDLIBS=$(LDDIR) -lapue $(EXTRALIBS) 12 | CFLAGS=-ansi -I$(ROOT)/include -Wall -DMACOS -D_DARWIN_C_SOURCE $(EXTRA) 13 | RANLIB=ranlib 14 | AR=ar 15 | AWK=awk 16 | LIBAPUE=$(ROOT)/lib/libapue.a 17 | 18 | # Common temp files to delete from each directory. 19 | TEMPFILES=core core.* *.o temp.* *.out 20 | -------------------------------------------------------------------------------- /src/Make.defines.solaris: -------------------------------------------------------------------------------- 1 | # Common make definitions, customized for each platform 2 | 3 | # Definitions required in all program directories to compile and link 4 | # C programs using gcc. 5 | 6 | CC=gcc 7 | COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c 8 | LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 9 | LDFLAGS= 10 | LDDIR=-L$(ROOT)/lib 11 | LDLIBS=$(LDDIR) -lapue $(EXTRALIBS) 12 | CFLAGS=-std=c99 -m64 -I$(ROOT)/include -Wall -DSOLARIS -D__EXTENSIONS__ $(EXTRA) 13 | RANLIB=echo 14 | AR=ar 15 | AWK=nawk 16 | LIBAPUE=$(ROOT)/lib/libapue.a 17 | NAMEMAX=-DNAME_MAX=_XOPEN_NAME_MAX 18 | 19 | # Common temp files to delete from each directory. 20 | TEMPFILES=core core.* *.o temp.* *.out 21 | -------------------------------------------------------------------------------- /src/Make.libapue.inc: -------------------------------------------------------------------------------- 1 | $(LIBAPUE): 2 | (cd $(ROOT)/lib && $(MAKE)) -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | DIRS = lib 01_UNIX_Introduction 02_UNIX_Standard 03_Unbuffered_IO 04_FILE_DIR 05_Standard_IO \ 2 | 06_System_Info 07_Process_Env 08_Process_Ctl 09_Process_Rel 10_Signals 11_Threads 12_ThreadCtl 13_Daemons \ 3 | 14_Advanced_IO 15_IPC 4 | 5 | all: 6 | for i in $(DIRS); do \ 7 | (cd $$i && echo "making &&i" && $(MAKE) ) || exit 1; \ 8 | done 9 | 10 | clean: 11 | for i in $(DIRS); do \ 12 | (cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \ 13 | done 14 | -------------------------------------------------------------------------------- /src/lib/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for misc library 'libapue'. 3 | # 4 | ROOT=.. 5 | PLATFORM=$(shell $(ROOT)/systype.sh) 6 | include $(ROOT)/Make.defines.$(PLATFORM) 7 | 8 | LIBMISC = libapue.a 9 | OBJS = error.o pathalloc.o tellwait.o prexit.o prmask.o lockreg.o locktest.o writen.o readn.o setfl.o setfd.o clrfl.o \ 10 | openmax.o 11 | 12 | all: $(LIBMISC) 13 | 14 | $(LIBMISC): $(OBJS) 15 | $(AR) rv $(LIBMISC) $? 16 | $(RANLIB) $(LIBMISC) 17 | 18 | clean: 19 | rm -rf *.o a.out core temp.* $(LIBMISC) 20 | 21 | include $(ROOT)/Make.libapue.inc -------------------------------------------------------------------------------- /src/lib/clrfl.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void clr_fl(int fd, int flags) 5 | /* flags are the file status flags to turn off */ 6 | { 7 | int val; 8 | 9 | if ((val = fcntl(fd, F_GETFL, 0)) < 0) 10 | err_sys("fcntl F_GETFL error"); 11 | 12 | val &= ~flags; /* turn flags off */ 13 | 14 | if (fcntl(fd, F_SETFL, val) < 0) 15 | err_sys("fcntl F_SETFL error"); 16 | } 17 | -------------------------------------------------------------------------------- /src/lib/clrfl.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/clrfl.o -------------------------------------------------------------------------------- /src/lib/error.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/error.o -------------------------------------------------------------------------------- /src/lib/libapue.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/libapue.a -------------------------------------------------------------------------------- /src/lib/lockreg.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 封装的文件记录锁函数,源于libapue 3 | * 4 | * 封装了更加友好的文件记录锁调用接口 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) 13 | { 14 | struct flock lock; 15 | 16 | lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */ 17 | lock.l_start = offset; /* byte offset, relative to l_whence */ 18 | lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ 19 | lock.l_len = len; /* #bytes (0 means to EOF) */ 20 | 21 | return(fcntl(fd, cmd, &lock)); 22 | } 23 | -------------------------------------------------------------------------------- /src/lib/lockreg.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/lockreg.o -------------------------------------------------------------------------------- /src/lib/locktest.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 文件记录锁探测接口,源于libapue 3 | * 4 | * 封装了更加友好的文件记录锁探测接口 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | 12 | pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len) 13 | { 14 | struct flock lock; 15 | 16 | lock.l_type = type; /* F_RDLCK or F_WRLCK */ 17 | lock.l_start = offset; /* byte offset, relative to l_whence */ 18 | lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ 19 | lock.l_len = len; /* #bytes (0 means to EOF) */ 20 | 21 | if (fcntl(fd, F_GETLK, &lock) < 0) 22 | err_sys("fcntl error"); 23 | 24 | if (lock.l_type == F_UNLCK) 25 | return(0); /* false, region isn't locked by another proc */ 26 | return(lock.l_pid); /* true, return pid of lock owner */ 27 | } -------------------------------------------------------------------------------- /src/lib/locktest.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/locktest.o -------------------------------------------------------------------------------- /src/lib/openmax.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 获取可以打开的最大文件数 3 | * 4 | * 通过sysconf获取 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | #ifdef OPEN_MAX 14 | static long openmax = OPEN_MAX; 15 | #else 16 | static long openmax = 0; 17 | #endif 18 | 19 | /* 20 | * If OPEN_MAX is indeterminate, this might be inadequate. 21 | */ 22 | #define OPEN_MAX_GUESS 256 23 | 24 | long open_max(void) 25 | { 26 | if (openmax == 0) { /* first time through */ 27 | errno = 0; 28 | if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) { 29 | if (errno == 0) 30 | openmax = OPEN_MAX_GUESS; /* it's indeterminate */ 31 | else 32 | err_sys("sysconf error for _SC_OPEN_MAX"); 33 | } 34 | } 35 | return(openmax); 36 | } 37 | -------------------------------------------------------------------------------- /src/lib/openmax.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/openmax.o -------------------------------------------------------------------------------- /src/lib/pathalloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file path_alloc通用函数,源于libapue 3 | * 4 | * path_alloc用于堆上分配路径,且会检查进程的限制 5 | * 6 | * @author Steve & r00tk1t 7 | * 8 | */ 9 | #include "apue.h" 10 | #include 11 | #include 12 | 13 | #ifdef PATH_MAX 14 | static long pathmax = PATH_MAX; 15 | #else 16 | static long pathmax = 0; 17 | #endif 18 | 19 | static long posix_version = 0; 20 | static long xsi_version = 0; 21 | 22 | /* If PATH_MAX is indeterminate, no guarantee this is adequate */ 23 | #define PATH_MAX_GUESS 1024 24 | 25 | char * 26 | path_alloc(size_t *sizep) /* also return allocated size, if nonnull */ 27 | { 28 | char *ptr; 29 | size_t size; 30 | 31 | if (posix_version == 0) 32 | posix_version = sysconf(_SC_VERSION); 33 | 34 | if (xsi_version == 0) 35 | xsi_version = sysconf(_SC_XOPEN_VERSION); 36 | 37 | if (pathmax == 0) { /* first time through */ 38 | errno = 0; 39 | if ((pathmax = pathconf("/", _PC_PATH_MAX)) < 0) { 40 | if (errno == 0) 41 | pathmax = PATH_MAX_GUESS; /* it's indeterminate */ 42 | else 43 | err_sys("pathconf error for _PC_PATH_MAX"); 44 | } else { 45 | pathmax++; /* add one since it's relative to root */ 46 | } 47 | } 48 | 49 | /* 50 | * Before POSIX.1-2001, we aren't guaranteed that PATH_MAX includes 51 | * the terminating null byte. Same goes for XPG3. 52 | */ 53 | if ((posix_version < 200112L) && (xsi_version < 4)) 54 | size = pathmax + 1; 55 | else 56 | size = pathmax; 57 | 58 | if ((ptr = malloc(size)) == NULL) 59 | err_sys("malloc error for pathname"); 60 | 61 | if (sizep != NULL) 62 | *sizep = size; 63 | return(ptr); 64 | } -------------------------------------------------------------------------------- /src/lib/pathalloc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/pathalloc.o -------------------------------------------------------------------------------- /src/lib/prexit.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | pr_exit(int status) 6 | { 7 | if (WIFEXITED(status)) 8 | printf("normal termination, exit status = %d\n", 9 | WEXITSTATUS(status)); 10 | else if (WIFSIGNALED(status)) 11 | printf("abnormal termination, signal number = %d%s\n", 12 | WTERMSIG(status), 13 | #ifdef WCOREDUMP 14 | WCOREDUMP(status) ? " (core file generated)" : ""); 15 | #else 16 | ""); 17 | #endif 18 | else if (WIFSTOPPED(status)) 19 | printf("child stopped, signal number = %d\n", 20 | WSTOPSIG(status)); 21 | } 22 | -------------------------------------------------------------------------------- /src/lib/prexit.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/prexit.o -------------------------------------------------------------------------------- /src/lib/prmask.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void pr_mask(const char *str) 5 | { 6 | sigset_t sigset; 7 | int errno_save; 8 | 9 | errno_save = errno; /* we can be called by signal handlers */ 10 | if (sigprocmask(SIG_BLOCK, NULL, &sigset) < 0) { 11 | err_ret("sigprocmask error"); 12 | } else { 13 | printf("%s", str); 14 | if (sigismember(&sigset, SIGINT)) 15 | printf(" SIGINT"); 16 | if (sigismember(&sigset, SIGQUIT)) 17 | printf(" SIGQUIT"); 18 | if (sigismember(&sigset, SIGUSR1)) 19 | printf(" SIGUSR1"); 20 | if (sigismember(&sigset, SIGALRM)) 21 | printf(" SIGALRM"); 22 | 23 | /* remaining signals can go here */ 24 | 25 | printf("\n"); 26 | } 27 | 28 | errno = errno_save; /* restore errno */ 29 | } 30 | -------------------------------------------------------------------------------- /src/lib/prmask.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/prmask.o -------------------------------------------------------------------------------- /src/lib/readn.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | ssize_t /* Read "n" bytes from a descriptor */ 4 | readn(int fd, void *ptr, size_t n) 5 | { 6 | size_t nleft; 7 | ssize_t nread; 8 | 9 | nleft = n; 10 | while (nleft > 0) { 11 | if ((nread = read(fd, ptr, nleft)) < 0) { 12 | if (nleft == n) 13 | return(-1); /* error, return -1 */ 14 | else 15 | break; /* error, return amount read so far */ 16 | } else if (nread == 0) { 17 | break; /* EOF */ 18 | } 19 | nleft -= nread; 20 | ptr += nread; 21 | } 22 | return(n - nleft); /* return >= 0 */ 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/readn.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/readn.o -------------------------------------------------------------------------------- /src/lib/setfd.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int set_cloexec(int fd) 5 | { 6 | int val; 7 | 8 | if ((val = fcntl(fd, F_GETFD, 0)) < 0) 9 | return(-1); 10 | 11 | val |= FD_CLOEXEC; /* enable close-on-exec */ 12 | 13 | return(fcntl(fd, F_SETFD, val)); 14 | } 15 | -------------------------------------------------------------------------------- /src/lib/setfd.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/setfd.o -------------------------------------------------------------------------------- /src/lib/setfl.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void set_fl(int fd, int flags) /* flags are file status flags to turn on */ 5 | { 6 | int val; 7 | 8 | if ((val = fcntl(fd, F_GETFL, 0)) < 0) 9 | err_sys("fcntl F_GETFL error"); 10 | 11 | val |= flags; /* turn on flags */ 12 | 13 | if (fcntl(fd, F_SETFL, val) < 0) 14 | err_sys("fcntl F_SETFL error"); 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/setfl.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/setfl.o -------------------------------------------------------------------------------- /src/lib/tellwait.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */ 4 | static sigset_t newmask, oldmask, zeromask; 5 | 6 | static void 7 | sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */ 8 | { 9 | sigflag = 1; 10 | } 11 | 12 | void 13 | TELL_WAIT(void) 14 | { 15 | if (signal(SIGUSR1, sig_usr) == SIG_ERR) 16 | err_sys("signal(SIGUSR1) error"); 17 | if (signal(SIGUSR2, sig_usr) == SIG_ERR) 18 | err_sys("signal(SIGUSR2) error"); 19 | sigemptyset(&zeromask); 20 | sigemptyset(&newmask); 21 | sigaddset(&newmask, SIGUSR1); 22 | sigaddset(&newmask, SIGUSR2); 23 | 24 | /* Block SIGUSR1 and SIGUSR2, and save current signal mask */ 25 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 26 | err_sys("SIG_BLOCK error"); 27 | } 28 | 29 | void 30 | TELL_PARENT(pid_t pid) 31 | { 32 | kill(pid, SIGUSR2); /* tell parent we're done */ 33 | } 34 | 35 | void 36 | WAIT_PARENT(void) 37 | { 38 | while (sigflag == 0) 39 | sigsuspend(&zeromask); /* and wait for parent */ 40 | sigflag = 0; 41 | 42 | /* Reset signal mask to original value */ 43 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 44 | err_sys("SIG_SETMASK error"); 45 | } 46 | 47 | void 48 | TELL_CHILD(pid_t pid) 49 | { 50 | kill(pid, SIGUSR1); /* tell child we're done */ 51 | } 52 | 53 | void 54 | WAIT_CHILD(void) 55 | { 56 | while (sigflag == 0) 57 | sigsuspend(&zeromask); /* and wait for child */ 58 | sigflag = 0; 59 | 60 | /* Reset signal mask to original value */ 61 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 62 | err_sys("SIG_SETMASK error"); 63 | } 64 | -------------------------------------------------------------------------------- /src/lib/tellwait.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/tellwait.o -------------------------------------------------------------------------------- /src/lib/writen.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | ssize_t /* Write "n" bytes to a descriptor */ 4 | writen(int fd, const void *ptr, size_t n) 5 | { 6 | size_t nleft; 7 | ssize_t nwritten; 8 | 9 | nleft = n; 10 | while (nleft > 0) { 11 | if ((nwritten = write(fd, ptr, nleft)) < 0) { 12 | if (nleft == n) 13 | return(-1); /* error, return -1 */ 14 | else 15 | break; /* error, return amount written so far */ 16 | } else if (nwritten == 0) { 17 | break; 18 | } 19 | nleft -= nwritten; 20 | ptr += nwritten; 21 | } 22 | return(n - nleft); /* return >= 0 */ 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/writen.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tk1ts/apue/926f6c126a43c50f408f279aae028bfa7059ee00/src/lib/writen.o -------------------------------------------------------------------------------- /src/systype.sh: -------------------------------------------------------------------------------- 1 | # (leading space required for Xenix /bin/sh) 2 | 3 | # 4 | # Determine the type of *ix operating system that we're 5 | # running on, and echo an appropriate value. 6 | # This script is intended to be used in Makefiles. 7 | # (This is a kludge. Gotta be a better way.) 8 | # 9 | 10 | case `uname -s` in 11 | "FreeBSD") 12 | PLATFORM="freebsd" 13 | ;; 14 | "Linux") 15 | PLATFORM="linux" 16 | ;; 17 | "Darwin") 18 | PLATFORM="macos" 19 | ;; 20 | "SunOS") 21 | PLATFORM="solaris" 22 | ;; 23 | *) 24 | echo "Unknown platform" >&2 25 | exit 1 26 | esac 27 | echo $PLATFORM 28 | exit 0 29 | --------------------------------------------------------------------------------