├── apue.3e ├── figlinks │ ├── fig1.3 │ ├── fig13.9 │ ├── fig17.2 │ ├── fig19.11 │ ├── fig19.12 │ ├── fig20.3 │ ├── fig5.11 │ ├── fig8.1 │ ├── fig8.30 │ ├── fig8.5 │ ├── fig8.6 │ ├── fig8.8 │ ├── figB.3 │ ├── fig1.10 │ ├── fig1.4 │ ├── fig1.5 │ ├── fig1.6 │ ├── fig1.7 │ ├── fig1.8 │ ├── fig1.9 │ ├── fig10.10 │ ├── fig10.11 │ ├── fig10.14 │ ├── fig10.18 │ ├── fig10.2 │ ├── fig10.20 │ ├── fig10.24 │ ├── fig10.25 │ ├── fig10.29 │ ├── fig10.6 │ ├── fig10.7 │ ├── fig10.8 │ ├── fig13.1 │ ├── fig13.6 │ ├── fig13.7 │ ├── fig14.20 │ ├── fig14.21 │ ├── fig14.24 │ ├── fig14.27 │ ├── fig14.5 │ ├── fig14.6 │ ├── fig14.7 │ ├── fig14.9 │ ├── fig15.11 │ ├── fig15.12 │ ├── fig15.14 │ ├── fig15.15 │ ├── fig15.17 │ ├── fig15.18 │ ├── fig15.31 │ ├── fig15.33 │ ├── fig15.35 │ ├── fig15.5 │ ├── fig15.6 │ ├── fig15.7 │ ├── fig17.10 │ ├── fig17.12 │ ├── fig17.13 │ ├── fig17.14 │ ├── fig17.15 │ ├── fig17.16 │ ├── fig17.23 │ ├── fig17.3 │ ├── fig17.4 │ ├── fig17.5 │ ├── fig17.8 │ ├── fig17.9 │ ├── fig18.11 │ ├── fig18.20 │ ├── fig18.21 │ ├── fig18.22 │ ├── fig19.10 │ ├── fig19.16 │ ├── fig19.9 │ ├── fig2.16 │ ├── fig2.17 │ ├── fig3.1 │ ├── fig3.12 │ ├── fig3.2 │ ├── fig3.5 │ ├── fig4.16 │ ├── fig4.21 │ ├── fig4.22 │ ├── fig4.23 │ ├── fig4.24 │ ├── fig4.8 │ ├── fig4.9 │ ├── fig5.13 │ ├── fig5.15 │ ├── fig5.4 │ ├── fig7.1 │ ├── fig7.11 │ ├── fig7.4 │ ├── fig7.9 │ ├── fig8.12 │ ├── fig8.13 │ ├── fig8.16 │ ├── fig8.17 │ ├── fig8.20 │ ├── fig8.21 │ ├── fig8.22 │ ├── fig8.23 │ ├── fig8.24 │ ├── fig8.25 │ ├── fig8.28 │ ├── fig8.29 │ ├── fig8.3 │ ├── fig8.31 │ ├── figB.1 │ ├── figB.4 │ ├── figC.22 │ ├── fig10.12 │ ├── fig10.15 │ ├── fig10.19 │ ├── fig10.22 │ ├── fig10.23 │ ├── fig10.26 │ ├── fig10.28 │ ├── fig10.31 │ ├── fig10.5 │ ├── fig10.9 │ ├── fig11.10 │ ├── fig11.11 │ ├── fig11.12 │ ├── fig11.14 │ ├── fig11.15 │ ├── fig11.16 │ ├── fig11.2 │ ├── fig11.3 │ ├── fig11.4 │ ├── fig11.5 │ ├── fig12.11 │ ├── fig12.12 │ ├── fig12.13 │ ├── fig12.16 │ ├── fig12.17 │ ├── fig12.4 │ ├── fig12.8 │ ├── fig13.8 │ ├── fig14.1 │ ├── fig14.12 │ ├── fig15.19 │ ├── fig16.10 │ ├── fig16.11 │ ├── fig16.12 │ ├── fig16.16 │ ├── fig16.17 │ ├── fig16.19 │ ├── fig16.22 │ ├── fig16.9 │ ├── fig17.17 │ ├── fig17.18 │ ├── fig17.19 │ ├── fig17.21 │ ├── fig17.25 │ ├── fig17.26 │ ├── fig17.27 │ ├── fig17.28 │ ├── fig17.31 │ ├── fig18.10 │ ├── fig18.12 │ ├── fig18.13 │ ├── fig18.14 │ ├── fig18.15 │ ├── fig18.16 │ ├── fig18.17 │ ├── fig18.18 │ ├── fig3.11 │ ├── fig4.12 │ ├── fig4.25 │ ├── fig4.3 │ ├── fig5.12 │ ├── fig5.5 │ ├── fig6.11 │ ├── fig6.2 │ ├── fig7.13 │ ├── fig7.14 │ ├── fig7.16 │ ├── fig7.3 │ ├── fig9.12 │ ├── figC.1 │ ├── figC.10 │ ├── figC.12 │ ├── figC.13 │ ├── figC.14 │ ├── figC.15 │ ├── figC.18 │ ├── figC.20 │ ├── figC.24 │ ├── figC.3 │ ├── figC.4 │ ├── figC.5 │ ├── figC.6 │ ├── figC.7 │ ├── figC.8 │ ├── fig16.18 │ ├── fig16.20 │ ├── fig17.20 │ ├── fig17.22 │ ├── fig17.24 │ ├── fig17.29 │ ├── fig17.30 │ ├── fig2.13 │ ├── fig2.14 │ ├── figC.16 │ ├── figC.17 │ └── figC.23 ├── Make.libapue.inc ├── environ │ ├── hello1.c │ ├── scope.c │ ├── echoarg.c │ ├── opendata.c │ ├── Makefile │ ├── cmd2.c │ ├── doatexit.c │ ├── cmd1.c │ └── testjmp.c ├── Readme.md ├── intro │ ├── uidgid.c │ ├── hello.c │ ├── testerror.c │ ├── getcputc.c │ ├── mycat.c │ ├── Makefile │ ├── ls1.c │ ├── shell1.c │ └── shell2.c ├── proc │ ├── pruids.c │ ├── awkexample │ ├── systest3.c │ ├── echoall.c │ ├── exec2.c │ ├── systest1.c │ ├── tellwait1.c │ ├── vfork1.c │ ├── tellwait2.c │ ├── fork1.c │ ├── system.c │ ├── exec1.c │ ├── wait1.c │ ├── test1.c │ ├── fork2.c │ └── Makefile ├── stdio │ ├── getcharbug.c │ ├── getcputc.c │ ├── fgetsfputs.c │ ├── Makefile │ ├── tempfiles.c │ ├── mkstemp.c │ └── memstr.c ├── ipc2 │ ├── open.fe │ │ ├── open.h │ │ ├── Makefile │ │ └── main.c │ ├── open │ │ ├── open.h │ │ ├── Makefile │ │ ├── main.c │ │ └── open.c │ ├── opend.fe │ │ ├── opend.h │ │ ├── Makefile │ │ ├── main.c │ │ ├── cliargs.c │ │ └── request.c │ ├── opend │ │ ├── cliargs.c │ │ ├── main.c │ │ ├── Makefile │ │ ├── opend.h │ │ └── request.c │ ├── bindunix.c │ ├── sendmsg.c │ └── Makefile ├── termios │ ├── isatty.c │ ├── t_isatty.c │ ├── ctermid.c │ ├── Makefile │ ├── t_getpass.c │ ├── t_ttyname.c │ ├── settty.c │ ├── csize.c │ ├── winch.c │ └── getpass.c ├── filedir │ ├── mycd.c │ ├── unlink.c │ ├── cdpwd.c │ ├── umask.c │ ├── access.c │ ├── changemod.c │ ├── Makefile │ ├── devrdev.c │ ├── zap.c │ └── filetype.c ├── daemons │ ├── Makefile │ └── single.c ├── fileio │ ├── seek.c │ ├── mycat.c │ ├── Makefile │ ├── setfl.c │ ├── hole.c │ └── fileflags.c ├── exercises │ ├── sleepus_poll.c │ ├── sleepus_select.c │ ├── getpwsvr4.c │ ├── getlogin.c │ ├── bo.c │ ├── getpw44bsd.c │ ├── zombie.c │ ├── prtime.c │ ├── sizepipe.c │ ├── fifo1.c │ ├── sleep.c │ ├── vfork3.c │ ├── openmax.c │ ├── asyncsocket.c │ ├── Makefile │ ├── goodexit.c │ └── longpath.c ├── standards │ ├── pathconf-opt.sym │ ├── pathconf-lim.sym │ └── Makefile ├── advio │ ├── fixup.awk │ ├── lockfile.c │ ├── readn.c │ ├── writen.c │ ├── nonblockw.c │ ├── Makefile │ ├── deadlock.c │ └── rot13a.c ├── lib │ ├── sleepus.c │ ├── setfd.c │ ├── spipe.c │ ├── strerror.c │ ├── setfl.c │ ├── clrfl.c │ ├── signalintr.c │ ├── lockreg.c │ ├── signal.c │ ├── prexit.c │ ├── senderr.c │ ├── readn.c │ ├── writen.c │ ├── locktest.c │ ├── openmax.c │ ├── prmask.c │ ├── Makefile │ ├── nspipe.c │ ├── bufargs.c │ ├── sleep.c │ └── servlisten.c ├── ipc1 │ ├── myuclc.c │ ├── slock.h │ ├── add2stdio.c │ ├── Makefile │ ├── pipe1.c │ ├── popen1.c │ ├── add2.c │ ├── popen2.c │ ├── tellwait.c │ ├── slock.c │ ├── tshm.c │ └── devzero.c ├── relation │ ├── Makefile │ └── orphan3.c ├── README ├── datafiles │ ├── Makefile │ ├── getpwnam.c │ └── strftime.c ├── threads │ ├── maketimeout.c │ ├── threadid.c │ ├── condvar.c │ ├── Makefile │ ├── timedlock.c │ ├── exitstatus.c │ └── mutex1.c ├── Makefile ├── pty │ ├── Makefile │ └── driver.c ├── threadctl │ ├── detach.c │ ├── getenv1.c │ ├── Makefile │ ├── getenv2.c │ └── getenv3.c ├── signals │ ├── sleep1.c │ ├── systest2.c │ ├── read1.c │ ├── sleep2.c │ ├── read2.c │ ├── sigusr.c │ ├── reenter.c │ ├── tsleep2.c │ ├── child.c │ ├── setops.c │ ├── Makefile │ ├── critical.c │ ├── abort.c │ ├── suspend2.c │ ├── suspend1.c │ ├── sigtstp.c │ └── mask.c ├── sockets │ ├── initsrv1.c │ ├── clconn.c │ ├── initsrv2.c │ ├── clconn2.c │ ├── makefile │ └── ruptime.c ├── systype.sh ├── Make.defines.linux ├── db │ ├── t4.c │ ├── apue_db.h │ └── Makefile ├── Make.defines.freebsd ├── Make.defines.macos ├── Make.defines.solaris ├── DISCLAIMER └── printer │ └── Makefile ├── Chapter03 ├── 3.3.pdf ├── exercise_6.input └── exercise_6.c ├── Chapter08 ├── 8.2.pdf ├── exercise_5.c ├── exercise_1.c ├── exercise_6.c └── exercise_2.c ├── Chapter10 ├── 10.3.pdf ├── exercise_10.c └── exercise_12.c ├── Chapter15 ├── add2 ├── exercise_3.c ├── exercise_8.c ├── exercise_12a.c └── exercise_12b.c ├── Chapter06 ├── exercise_2.c ├── exercise_4.c ├── exercise_3.c └── exercise_5.c ├── Chapter16 ├── exercise_1.c ├── exercise_2.c └── exercise_4_client.c ├── README.md ├── Chapter04 ├── exercise_17.c ├── exercise_4.c ├── exercise_16.c ├── create_sparse_file.c └── exercise_1.c ├── Chapter05 └── exercise_2.c ├── Chapter14 ├── exercise_5.c └── exercise_7.c ├── Chapter09 └── exercise_2.c ├── .gitignore ├── Chapter18 └── figure_18.11.c ├── Chapter17 └── figure_17.4.c └── Chapter12 └── exercise_2.c /apue.3e/figlinks/fig1.3: -------------------------------------------------------------------------------- 1 | ../intro/ls1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig13.9: -------------------------------------------------------------------------------- 1 | ../lib/setfd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.2: -------------------------------------------------------------------------------- 1 | ../lib/spipe.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig19.11: -------------------------------------------------------------------------------- 1 | ../pty/main.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig19.12: -------------------------------------------------------------------------------- 1 | ../pty/loop.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig20.3: -------------------------------------------------------------------------------- 1 | ../db/t4.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig5.11: -------------------------------------------------------------------------------- 1 | ../stdio/buf.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.1: -------------------------------------------------------------------------------- 1 | ../proc/fork1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.30: -------------------------------------------------------------------------------- 1 | ../proc/nice.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.5: -------------------------------------------------------------------------------- 1 | ../lib/prexit.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.6: -------------------------------------------------------------------------------- 1 | ../proc/wait1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.8: -------------------------------------------------------------------------------- 1 | ../proc/fork2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figB.3: -------------------------------------------------------------------------------- 1 | ../lib/error.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.10: -------------------------------------------------------------------------------- 1 | ../intro/shell2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.4: -------------------------------------------------------------------------------- 1 | ../intro/mycat.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.5: -------------------------------------------------------------------------------- 1 | ../intro/getcputc.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.6: -------------------------------------------------------------------------------- 1 | ../intro/hello.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.7: -------------------------------------------------------------------------------- 1 | ../intro/shell1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.8: -------------------------------------------------------------------------------- 1 | ../intro/testerror.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig1.9: -------------------------------------------------------------------------------- 1 | ../intro/uidgid.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.10: -------------------------------------------------------------------------------- 1 | ../signals/read1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.11: -------------------------------------------------------------------------------- 1 | ../signals/read2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.14: -------------------------------------------------------------------------------- 1 | ../lib/prmask.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.18: -------------------------------------------------------------------------------- 1 | ../lib/signal.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.2: -------------------------------------------------------------------------------- 1 | ../signals/sigusr.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.20: -------------------------------------------------------------------------------- 1 | ../signals/mask.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.24: -------------------------------------------------------------------------------- 1 | ../lib/tellwait.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.25: -------------------------------------------------------------------------------- 1 | ../signals/abort.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.29: -------------------------------------------------------------------------------- 1 | ../lib/sleep.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.6: -------------------------------------------------------------------------------- 1 | ../signals/child.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.7: -------------------------------------------------------------------------------- 1 | ../signals/sleep1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.8: -------------------------------------------------------------------------------- 1 | ../signals/sleep2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig13.1: -------------------------------------------------------------------------------- 1 | ../daemons/init.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig13.6: -------------------------------------------------------------------------------- 1 | ../daemons/single.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig13.7: -------------------------------------------------------------------------------- 1 | ../daemons/reread.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.20: -------------------------------------------------------------------------------- 1 | ../advio/rot13a.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.21: -------------------------------------------------------------------------------- 1 | ../advio/rot13c2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.24: -------------------------------------------------------------------------------- 1 | ../advio/writen.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.27: -------------------------------------------------------------------------------- 1 | ../advio/mcopy2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.5: -------------------------------------------------------------------------------- 1 | ../lib/lockreg.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.6: -------------------------------------------------------------------------------- 1 | ../lib/locktest.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.7: -------------------------------------------------------------------------------- 1 | ../advio/deadlock.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.9: -------------------------------------------------------------------------------- 1 | ../advio/lockfile.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.11: -------------------------------------------------------------------------------- 1 | ../ipc1/popen2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.12: -------------------------------------------------------------------------------- 1 | ../ipc1/popen.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.14: -------------------------------------------------------------------------------- 1 | ../ipc1/myuclc.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.15: -------------------------------------------------------------------------------- 1 | ../ipc1/popen1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.17: -------------------------------------------------------------------------------- 1 | ../ipc1/add2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.18: -------------------------------------------------------------------------------- 1 | ../ipc1/pipe4.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.31: -------------------------------------------------------------------------------- 1 | ../ipc1/tshm.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.33: -------------------------------------------------------------------------------- 1 | ../ipc1/devzero.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.35: -------------------------------------------------------------------------------- 1 | ../ipc1/slock.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.5: -------------------------------------------------------------------------------- 1 | ../ipc1/pipe1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.6: -------------------------------------------------------------------------------- 1 | ../ipc1/pipe2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.7: -------------------------------------------------------------------------------- 1 | ../ipc1/tellwait.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.10: -------------------------------------------------------------------------------- 1 | ../lib/cliconn.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.12: -------------------------------------------------------------------------------- 1 | ../lib/senderr.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.13: -------------------------------------------------------------------------------- 1 | ../lib/sendfd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.14: -------------------------------------------------------------------------------- 1 | ../lib/recvfd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.15: -------------------------------------------------------------------------------- 1 | ../ipc2/sendfd2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.16: -------------------------------------------------------------------------------- 1 | ../ipc2/recvfd2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.23: -------------------------------------------------------------------------------- 1 | ../lib/bufargs.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.3: -------------------------------------------------------------------------------- 1 | ../ipc2/pollmsg.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.4: -------------------------------------------------------------------------------- 1 | ../ipc2/sendmsg.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.5: -------------------------------------------------------------------------------- 1 | ../ipc2/bindunix.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.8: -------------------------------------------------------------------------------- 1 | ../lib/servlisten.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.9: -------------------------------------------------------------------------------- 1 | ../lib/servaccept.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.11: -------------------------------------------------------------------------------- 1 | ../termios/csize.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.20: -------------------------------------------------------------------------------- 1 | ../lib/ttymodes.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.21: -------------------------------------------------------------------------------- 1 | ../termios/t_raw.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.22: -------------------------------------------------------------------------------- 1 | ../termios/winch.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig19.10: -------------------------------------------------------------------------------- 1 | ../lib/ptyfork.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig19.16: -------------------------------------------------------------------------------- 1 | ../pty/driver.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig19.9: -------------------------------------------------------------------------------- 1 | ../lib/ptyopen.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig2.16: -------------------------------------------------------------------------------- 1 | ../lib/pathalloc.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig2.17: -------------------------------------------------------------------------------- 1 | ../lib/openmax.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig3.1: -------------------------------------------------------------------------------- 1 | ../fileio/seek.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig3.12: -------------------------------------------------------------------------------- 1 | ../fileio/setfl.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig3.2: -------------------------------------------------------------------------------- 1 | ../fileio/hole.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig3.5: -------------------------------------------------------------------------------- 1 | ../fileio/mycat.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.16: -------------------------------------------------------------------------------- 1 | ../filedir/unlink.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.21: -------------------------------------------------------------------------------- 1 | ../filedir/zap.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.22: -------------------------------------------------------------------------------- 1 | ../filedir/ftw8.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.23: -------------------------------------------------------------------------------- 1 | ../filedir/mycd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.24: -------------------------------------------------------------------------------- 1 | ../filedir/cdpwd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.8: -------------------------------------------------------------------------------- 1 | ../filedir/access.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.9: -------------------------------------------------------------------------------- 1 | ../filedir/umask.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig5.13: -------------------------------------------------------------------------------- 1 | ../stdio/mkstemp.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig5.15: -------------------------------------------------------------------------------- 1 | ../stdio/memstr.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig5.4: -------------------------------------------------------------------------------- 1 | ../stdio/getcputc.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.1: -------------------------------------------------------------------------------- 1 | ../environ/hello1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.11: -------------------------------------------------------------------------------- 1 | ../environ/cmd2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.4: -------------------------------------------------------------------------------- 1 | ../environ/echoarg.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.9: -------------------------------------------------------------------------------- 1 | ../environ/cmd1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.12: -------------------------------------------------------------------------------- 1 | ../proc/tellwait1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.13: -------------------------------------------------------------------------------- 1 | ../proc/tellwait2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.16: -------------------------------------------------------------------------------- 1 | ../proc/exec1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.17: -------------------------------------------------------------------------------- 1 | ../proc/echoall.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.20: -------------------------------------------------------------------------------- 1 | ../proc/exec2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.21: -------------------------------------------------------------------------------- 1 | ../proc/awkexample -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.22: -------------------------------------------------------------------------------- 1 | ../proc/system.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.23: -------------------------------------------------------------------------------- 1 | ../proc/systest1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.24: -------------------------------------------------------------------------------- 1 | ../proc/systest3.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.25: -------------------------------------------------------------------------------- 1 | ../proc/pruids.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.28: -------------------------------------------------------------------------------- 1 | ../proc/test1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.29: -------------------------------------------------------------------------------- 1 | ../proc/pracct.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.3: -------------------------------------------------------------------------------- 1 | ../proc/vfork1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig8.31: -------------------------------------------------------------------------------- 1 | ../proc/times1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figB.1: -------------------------------------------------------------------------------- 1 | ../include/apue.h -------------------------------------------------------------------------------- /apue.3e/figlinks/figB.4: -------------------------------------------------------------------------------- 1 | ../lib/errorlog.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.22: -------------------------------------------------------------------------------- 1 | ../exercises/bo.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.12: -------------------------------------------------------------------------------- 1 | ../signals/setops.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.15: -------------------------------------------------------------------------------- 1 | ../signals/critical.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.19: -------------------------------------------------------------------------------- 1 | ../lib/signalintr.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.22: -------------------------------------------------------------------------------- 1 | ../signals/suspend1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.23: -------------------------------------------------------------------------------- 1 | ../signals/suspend2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.26: -------------------------------------------------------------------------------- 1 | ../signals/systest2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.28: -------------------------------------------------------------------------------- 1 | ../signals/system.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.31: -------------------------------------------------------------------------------- 1 | ../signals/sigtstp.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.5: -------------------------------------------------------------------------------- 1 | ../signals/reenter.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig10.9: -------------------------------------------------------------------------------- 1 | ../signals/tsleep2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.10: -------------------------------------------------------------------------------- 1 | ../threads/mutex1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.11: -------------------------------------------------------------------------------- 1 | ../threads/mutex2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.12: -------------------------------------------------------------------------------- 1 | ../threads/mutex3.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.14: -------------------------------------------------------------------------------- 1 | ../threads/rwlock.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.15: -------------------------------------------------------------------------------- 1 | ../threads/condvar.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.16: -------------------------------------------------------------------------------- 1 | ../threads/barrier.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.2: -------------------------------------------------------------------------------- 1 | ../threads/threadid.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.3: -------------------------------------------------------------------------------- 1 | ../threads/exitstatus.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.4: -------------------------------------------------------------------------------- 1 | ../threads/badexit2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig11.5: -------------------------------------------------------------------------------- 1 | ../threads/cleanup.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.11: -------------------------------------------------------------------------------- 1 | ../threadctl/getenv1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.12: -------------------------------------------------------------------------------- 1 | ../threadctl/getenv2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.13: -------------------------------------------------------------------------------- 1 | ../threadctl/getenv3.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.16: -------------------------------------------------------------------------------- 1 | ../threadctl/suspend.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.17: -------------------------------------------------------------------------------- 1 | ../threadctl/atfork.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.4: -------------------------------------------------------------------------------- 1 | ../threadctl/detach.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig12.8: -------------------------------------------------------------------------------- 1 | ../threadctl/timeout.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig13.8: -------------------------------------------------------------------------------- 1 | ../daemons/reread2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.1: -------------------------------------------------------------------------------- 1 | ../advio/nonblockw.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig14.12: -------------------------------------------------------------------------------- 1 | ../advio/mandatory.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig15.19: -------------------------------------------------------------------------------- 1 | ../ipc1/add2stdio.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.10: -------------------------------------------------------------------------------- 1 | ../sockets/clconn.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.11: -------------------------------------------------------------------------------- 1 | ../sockets/clconn2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.12: -------------------------------------------------------------------------------- 1 | ../sockets/initsrv1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.16: -------------------------------------------------------------------------------- 1 | ../sockets/ruptime.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.17: -------------------------------------------------------------------------------- 1 | ../sockets/ruptimed.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.19: -------------------------------------------------------------------------------- 1 | ../sockets/ruptime-dg.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.22: -------------------------------------------------------------------------------- 1 | ../sockets/initsrv2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.9: -------------------------------------------------------------------------------- 1 | ../sockets/findsvc.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.17: -------------------------------------------------------------------------------- 1 | ../ipc2/open.fe/open.h -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.18: -------------------------------------------------------------------------------- 1 | ../ipc2/open.fe/main.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.19: -------------------------------------------------------------------------------- 1 | ../ipc2/open.fe/open.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.21: -------------------------------------------------------------------------------- 1 | ../ipc2/opend.fe/main.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.25: -------------------------------------------------------------------------------- 1 | ../ipc2/open/open.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.26: -------------------------------------------------------------------------------- 1 | ../ipc2/opend/opend.h -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.27: -------------------------------------------------------------------------------- 1 | ../ipc2/opend/client.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.28: -------------------------------------------------------------------------------- 1 | ../ipc2/opend/main.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.31: -------------------------------------------------------------------------------- 1 | ../ipc2/opend/request.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.10: -------------------------------------------------------------------------------- 1 | ../termios/settty.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.12: -------------------------------------------------------------------------------- 1 | ../termios/ctermid.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.13: -------------------------------------------------------------------------------- 1 | ../termios/isatty.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.14: -------------------------------------------------------------------------------- 1 | ../termios/t_isatty.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.15: -------------------------------------------------------------------------------- 1 | ../termios/ttyname.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.16: -------------------------------------------------------------------------------- 1 | ../termios/t_ttyname.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.17: -------------------------------------------------------------------------------- 1 | ../termios/getpass.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig18.18: -------------------------------------------------------------------------------- 1 | ../termios/t_getpass.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig3.11: -------------------------------------------------------------------------------- 1 | ../fileio/fileflags.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.12: -------------------------------------------------------------------------------- 1 | ../filedir/changemod.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.25: -------------------------------------------------------------------------------- 1 | ../filedir/devrdev.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig4.3: -------------------------------------------------------------------------------- 1 | ../filedir/filetype.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig5.12: -------------------------------------------------------------------------------- 1 | ../stdio/tempfiles.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig5.5: -------------------------------------------------------------------------------- 1 | ../stdio/fgetsfputs.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig6.11: -------------------------------------------------------------------------------- 1 | ../datafiles/strftime.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig6.2: -------------------------------------------------------------------------------- 1 | ../datafiles/getpwnam.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.13: -------------------------------------------------------------------------------- 1 | ../environ/testjmp.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.14: -------------------------------------------------------------------------------- 1 | ../environ/opendata.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.16: -------------------------------------------------------------------------------- 1 | ../environ/getrlimit.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig7.3: -------------------------------------------------------------------------------- 1 | ../environ/doatexit.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig9.12: -------------------------------------------------------------------------------- 1 | ../relation/orphan3.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.1: -------------------------------------------------------------------------------- 1 | ../exercises/openmax.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.10: -------------------------------------------------------------------------------- 1 | ../exercises/zombie.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.12: -------------------------------------------------------------------------------- 1 | ../exercises/goodexit.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.13: -------------------------------------------------------------------------------- 1 | ../exercises/sleep.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.14: -------------------------------------------------------------------------------- 1 | ../exercises/getlogin.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.15: -------------------------------------------------------------------------------- 1 | ../exercises/pendlock.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.18: -------------------------------------------------------------------------------- 1 | ../exercises/sizepipe.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.20: -------------------------------------------------------------------------------- 1 | ../exercises/fifo1.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.24: -------------------------------------------------------------------------------- 1 | ../exercises/pollmsg2.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.3: -------------------------------------------------------------------------------- 1 | ../exercises/longpath.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.4: -------------------------------------------------------------------------------- 1 | ../exercises/fmemopen.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.5: -------------------------------------------------------------------------------- 1 | ../exercises/getpwsvr4.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.6: -------------------------------------------------------------------------------- 1 | ../exercises/getpw44bsd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.7: -------------------------------------------------------------------------------- 1 | ../exercises/prtime.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.8: -------------------------------------------------------------------------------- 1 | ../exercises/vfork3.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.18: -------------------------------------------------------------------------------- 1 | ../sockets/ruptimed-fd.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig16.20: -------------------------------------------------------------------------------- 1 | ../sockets/ruptimed-dg.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.20: -------------------------------------------------------------------------------- 1 | ../ipc2/opend.fe/opend.h -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.22: -------------------------------------------------------------------------------- 1 | ../ipc2/opend.fe/request.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.24: -------------------------------------------------------------------------------- 1 | ../ipc2/opend.fe/cliargs.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.29: -------------------------------------------------------------------------------- 1 | ../ipc2/opend/loop.select.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig17.30: -------------------------------------------------------------------------------- 1 | ../ipc2/opend/loop.poll.c -------------------------------------------------------------------------------- /apue.3e/figlinks/fig2.13: -------------------------------------------------------------------------------- 1 | ../standards/makeconf.awk -------------------------------------------------------------------------------- /apue.3e/figlinks/fig2.14: -------------------------------------------------------------------------------- 1 | ../standards/conf.c.modified -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.16: -------------------------------------------------------------------------------- 1 | ../exercises/sleepus_select.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.17: -------------------------------------------------------------------------------- 1 | ../exercises/sleepus_poll.c -------------------------------------------------------------------------------- /apue.3e/figlinks/figC.23: -------------------------------------------------------------------------------- 1 | ../exercises/asyncsocket.c -------------------------------------------------------------------------------- /apue.3e/Make.libapue.inc: -------------------------------------------------------------------------------- 1 | $(LIBAPUE): 2 | (cd $(ROOT)/lib && $(MAKE)) 3 | -------------------------------------------------------------------------------- /Chapter03/3.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adalton/apue3/HEAD/Chapter03/3.3.pdf -------------------------------------------------------------------------------- /Chapter08/8.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adalton/apue3/HEAD/Chapter08/8.2.pdf -------------------------------------------------------------------------------- /Chapter10/10.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adalton/apue3/HEAD/Chapter10/10.3.pdf -------------------------------------------------------------------------------- /apue.3e/environ/hello1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | main() 4 | { 5 | printf("hello, world\n"); 6 | } 7 | -------------------------------------------------------------------------------- /apue.3e/Readme.md: -------------------------------------------------------------------------------- 1 | # The source code for the examples in the book; downloaded from: 2 | 3 | http://www.apuebook.com/src.3e.tar.gz 4 | -------------------------------------------------------------------------------- /apue.3e/intro/uidgid.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | printf("uid = %d, gid = %d\n", getuid(), getgid()); 7 | exit(0); 8 | } 9 | -------------------------------------------------------------------------------- /apue.3e/intro/hello.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | printf("hello world from process ID %ld\n", (long)getpid()); 7 | exit(0); 8 | } 9 | -------------------------------------------------------------------------------- /apue.3e/proc/pruids.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | printf("real uid = %d, effective uid = %d\n", getuid(), geteuid()); 7 | exit(0); 8 | } 9 | -------------------------------------------------------------------------------- /apue.3e/stdio/getcharbug.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | char c; 7 | 8 | while ((c = getchar()) != EOF) 9 | putchar(c); 10 | } 11 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open.fe/open.h: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define CL_OPEN "open" /* client's request for server */ 5 | 6 | int csopen(char *, int); 7 | -------------------------------------------------------------------------------- /apue.3e/proc/awkexample: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # Note: on Solaris, use nawk instead 3 | BEGIN { 4 | for (i = 0; i < ARGC; i++) 5 | printf "ARGV[%d] = %s\n", i, ARGV[i] 6 | exit 7 | } 8 | -------------------------------------------------------------------------------- /apue.3e/termios/isatty.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | isatty(int fd) 5 | { 6 | struct termios ts; 7 | 8 | return(tcgetattr(fd, &ts) != -1); /* true if no error (is a tty) */ 9 | } 10 | -------------------------------------------------------------------------------- /apue.3e/filedir/mycd.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | if (chdir("/tmp") < 0) 7 | err_sys("chdir failed"); 8 | printf("chdir to /tmp succeeded\n"); 9 | exit(0); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter03/exercise_6.input: -------------------------------------------------------------------------------- 1 | Four score and seven years ago our fathers brought fourth on this continent 2 | a new nation, conceived in liberty and dedicated to the proposition that all 3 | men are created equal. 4 | -------------------------------------------------------------------------------- /Chapter15/add2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while [[ true ]]; do 4 | read line 5 | x="$(echo "${line}" | awk '{ print $1 }')" 6 | y="$(echo "${line}" | awk '{ print $2 }')" 7 | echo "$((x + y))" 8 | done 9 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/environ/scope.c: -------------------------------------------------------------------------------- 1 | int 2 | f1(int val) 3 | { 4 | int num = 0; 5 | int *ptr = # 6 | 7 | if (val == 0) { 8 | int val; 9 | 10 | val = 5; 11 | ptr = &val; 12 | } 13 | return(*ptr + 1); 14 | } 15 | -------------------------------------------------------------------------------- /apue.3e/fileio/seek.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | if (lseek(STDIN_FILENO, 0, SEEK_CUR) == -1) 7 | printf("cannot seek\n"); 8 | else 9 | printf("seek OK\n"); 10 | exit(0); 11 | } 12 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open/open.h: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define CL_OPEN "open" /* client's request for server */ 5 | #define CS_OPEN "/tmp/opend.socket" /* server's well-known name */ 6 | 7 | int csopen(char *, int); 8 | -------------------------------------------------------------------------------- /apue.3e/intro/testerror.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(int argc, char *argv[]) 6 | { 7 | fprintf(stderr, "EACCES: %s\n", strerror(EACCES)); 8 | errno = ENOENT; 9 | perror(argv[0]); 10 | exit(0); 11 | } 12 | -------------------------------------------------------------------------------- /apue.3e/environ/echoarg.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(int argc, char *argv[]) 5 | { 6 | int i; 7 | 8 | for (i = 0; i < argc; i++) /* echo all command-line args */ 9 | printf("argv[%d]: %s\n", i, argv[i]); 10 | exit(0); 11 | } 12 | -------------------------------------------------------------------------------- /apue.3e/exercises/sleepus_poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void 4 | sleep_us(unsigned int nusecs) 5 | { 6 | struct pollfd dummy; 7 | int timeout; 8 | 9 | if ((timeout = nusecs / 1000) <= 0) 10 | timeout = 1; 11 | poll(&dummy, 0, timeout); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter15/exercise_3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | FILE* const file = popen("does-not-exist", "r"); 7 | 8 | if (file == NULL) { 9 | perror("popen"); 10 | return 1; 11 | } 12 | 13 | pclose(file); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/standards/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 | -------------------------------------------------------------------------------- /apue.3e/advio/fixup.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | BEGIN { 3 | ready = 0 4 | } 5 | /^translate/ { 6 | ready = 1 7 | next 8 | } 9 | /^{/ { 10 | next 11 | } 12 | /^}/ { 13 | ready = 0 14 | next 15 | } 16 | { 17 | if (ready) 18 | print $0 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/advio/lockfile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | lockfile(int fd) 6 | { 7 | struct flock fl; 8 | 9 | fl.l_type = F_WRLCK; 10 | fl.l_start = 0; 11 | fl.l_whence = SEEK_SET; 12 | fl.l_len = 0; 13 | return(fcntl(fd, F_SETLK, &fl)); 14 | } 15 | -------------------------------------------------------------------------------- /apue.3e/lib/sleepus.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | sleep_us(unsigned int nusecs) 6 | { 7 | struct timeval tval; 8 | 9 | tval.tv_sec = nusecs / 1000000; 10 | tval.tv_usec = nusecs % 1000000; 11 | select(0, NULL, NULL, NULL, &tval); 12 | } 13 | -------------------------------------------------------------------------------- /apue.3e/termios/t_isatty.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | printf("fd 0: %s\n", isatty(0) ? "tty" : "not a tty"); 7 | printf("fd 1: %s\n", isatty(1) ? "tty" : "not a tty"); 8 | printf("fd 2: %s\n", isatty(2) ? "tty" : "not a tty"); 9 | exit(0); 10 | } 11 | -------------------------------------------------------------------------------- /apue.3e/termios/ctermid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static char ctermid_name[L_ctermid]; 5 | 6 | char * 7 | ctermid(char *str) 8 | { 9 | if (str == NULL) 10 | str = ctermid_name; 11 | return(strcpy(str, "/dev/tty")); /* strcpy() returns str */ 12 | } 13 | -------------------------------------------------------------------------------- /apue.3e/intro/getcputc.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | int c; 7 | 8 | while ((c = getc(stdin)) != EOF) 9 | if (putc(c, stdout) == EOF) 10 | err_sys("output error"); 11 | 12 | if (ferror(stdin)) 13 | err_sys("input error"); 14 | 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/stdio/getcputc.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | int c; 7 | 8 | while ((c = getc(stdin)) != EOF) 9 | if (putc(c, stdout) == EOF) 10 | err_sys("output error"); 11 | 12 | if (ferror(stdin)) 13 | err_sys("input error"); 14 | 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/exercise_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | const struct spwd* const entry = getspnam("root"); 8 | 9 | if (entry != NULL) { 10 | printf("user/pass: %s/%s\n", entry->sp_namp, entry->sp_pwdp); 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /apue.3e/exercises/sleepus_select.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | sleep_us(unsigned int nusecs) 6 | { 7 | struct timeval tval; 8 | 9 | tval.tv_sec = nusecs / 1000000; 10 | tval.tv_usec = nusecs % 1000000; 11 | select(0, NULL, NULL, NULL, &tval); 12 | } 13 | -------------------------------------------------------------------------------- /apue.3e/lib/setfd.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | set_cloexec(int fd) 6 | { 7 | int val; 8 | 9 | if ((val = fcntl(fd, F_GETFD, 0)) < 0) 10 | return(-1); 11 | 12 | val |= FD_CLOEXEC; /* enable close-on-exec */ 13 | 14 | return(fcntl(fd, F_SETFD, val)); 15 | } 16 | -------------------------------------------------------------------------------- /apue.3e/lib/spipe.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | /* 5 | * Returns a full-duplex pipe (a UNIX domain socket) with 6 | * the two file descriptors returned in fd[0] and fd[1]. 7 | */ 8 | int 9 | fd_pipe(int fd[2]) 10 | { 11 | return(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)); 12 | } 13 | -------------------------------------------------------------------------------- /apue.3e/stdio/fgetsfputs.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | char buf[MAXLINE]; 7 | 8 | while (fgets(buf, MAXLINE, stdin) != NULL) 9 | if (fputs(buf, stdout) == EOF) 10 | err_sys("output error"); 11 | 12 | if (ferror(stdin)) 13 | err_sys("input error"); 14 | 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/proc/systest3.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(int argc, char *argv[]) 5 | { 6 | int status; 7 | 8 | if (argc < 2) 9 | err_quit("command-line argument required"); 10 | 11 | if ((status = system(argv[1])) < 0) 12 | err_sys("system() error"); 13 | 14 | pr_exit(status); 15 | 16 | exit(0); 17 | } 18 | -------------------------------------------------------------------------------- /apue.3e/standards/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 | -------------------------------------------------------------------------------- /Chapter16/exercise_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | const union { 8 | uint64_t number; 9 | char bytes[8]; 10 | } value = { 11 | .number = 1 12 | }; 13 | 14 | printf("%s Endian\n", 15 | (value.bytes[0] == 1) ? "Little" : "Big"); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/filedir/unlink.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | if (open("tempfile", O_RDWR) < 0) 8 | err_sys("open error"); 9 | if (unlink("tempfile") < 0) 10 | err_sys("unlink error"); 11 | printf("file unlinked\n"); 12 | sleep(15); 13 | printf("done\n"); 14 | exit(0); 15 | } 16 | -------------------------------------------------------------------------------- /apue.3e/ipc1/myuclc.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | int c; 8 | 9 | while ((c = getchar()) != EOF) { 10 | if (isupper(c)) 11 | c = tolower(c); 12 | if (putchar(c) == EOF) 13 | err_sys("output error"); 14 | if (c == '\n') 15 | fflush(stdout); 16 | } 17 | exit(0); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/relation/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = orphan3 6 | 7 | all: $(PROGS) 8 | 9 | %: %.c $(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 | -------------------------------------------------------------------------------- /apue.3e/README: -------------------------------------------------------------------------------- 1 | Read the file called DISCLAIMER. 2 | 3 | On Freebsd, type "gmake". 4 | On other platforms, type "make" (as long as this is gnu make). 5 | 6 | For FAQs, updated source code, and the lost chapter, see http://www.apuebook.com. 7 | Please direct questions, suggestions, and bug reports to sar@apuebook.com. 8 | 9 | Steve Rago 10 | January 2013 11 | -------------------------------------------------------------------------------- /apue.3e/environ/opendata.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | FILE * 4 | open_data(void) 5 | { 6 | FILE *fp; 7 | char databuf[BUFSIZ]; /* setvbuf makes this the stdio buffer */ 8 | 9 | if ((fp = fopen("datafile", "r")) == NULL) 10 | return(NULL); 11 | if (setvbuf(fp, databuf, _IOLBF, BUFSIZ) != 0) 12 | return(NULL); 13 | return(fp); /* error */ 14 | } 15 | -------------------------------------------------------------------------------- /apue.3e/datafiles/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = strftime 6 | 7 | all: $(PROGS) getpwnam.o 8 | 9 | %: %.c $(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 | -------------------------------------------------------------------------------- /apue.3e/fileio/mycat.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #define BUFFSIZE 4096 4 | 5 | int 6 | main(void) 7 | { 8 | int n; 9 | char buf[BUFFSIZE]; 10 | 11 | while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) 12 | if (write(STDOUT_FILENO, buf, n) != n) 13 | err_sys("write error"); 14 | 15 | if (n < 0) 16 | err_sys("read error"); 17 | 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/intro/mycat.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #define BUFFSIZE 4096 4 | 5 | int 6 | main(void) 7 | { 8 | int n; 9 | char buf[BUFFSIZE]; 10 | 11 | while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) 12 | if (write(STDOUT_FILENO, buf, n) != n) 13 | err_sys("write error"); 14 | 15 | if (n < 0) 16 | err_sys("read error"); 17 | 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/exercises/getpwsvr4.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) /* Linux/Solaris version */ 6 | { 7 | struct spwd *ptr; 8 | 9 | if ((ptr = getspnam("sar")) == NULL) 10 | err_sys("getspnam error"); 11 | printf("sp_pwdp = %s\n", ptr->sp_pwdp == NULL || 12 | ptr->sp_pwdp[0] == 0 ? "(null)" : ptr->sp_pwdp); 13 | exit(0); 14 | } 15 | -------------------------------------------------------------------------------- /apue.3e/ipc1/slock.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct slock { 7 | sem_t *semp; 8 | char name[_POSIX_NAME_MAX]; 9 | }; 10 | 11 | struct slock * s_alloc(); 12 | void s_free(struct slock *); 13 | int s_lock(struct slock *); 14 | int s_trylock(struct slock *); 15 | int s_unlock(struct slock *); 16 | -------------------------------------------------------------------------------- /apue.3e/exercises/getlogin.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | FILE *fp; 7 | char *p; 8 | 9 | daemonize("getlog"); 10 | p = getlogin(); 11 | fp = fopen("/tmp/getlog.out", "w"); 12 | if (fp != NULL) { 13 | if (p == NULL) 14 | fprintf(fp, "no login name\n"); 15 | else 16 | fprintf(fp, "login name: %s\n", p); 17 | } 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/exercises/bo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | uint32_t i = 0x04030201; 9 | unsigned char *cp = (unsigned char *)&i; 10 | 11 | if (*cp == 1) 12 | printf("little-endian\n"); 13 | else if (*cp == 4) 14 | printf("big-endian\n"); 15 | else 16 | printf("who knows?\n"); 17 | exit(0); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/exercises/getpw44bsd.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) /* FreeBSD/Mac OS X version */ 6 | { 7 | struct passwd *ptr; 8 | 9 | if ((ptr = getpwnam("sar")) == NULL) 10 | err_sys("getpwnam error"); 11 | printf("pw_passwd = %s\n", ptr->pw_passwd == NULL || 12 | ptr->pw_passwd[0] == 0 ? "(null)" : ptr->pw_passwd); 13 | exit(0); 14 | } 15 | -------------------------------------------------------------------------------- /apue.3e/filedir/cdpwd.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | char *ptr; 7 | size_t size; 8 | 9 | if (chdir("/usr/spool/uucppublic") < 0) 10 | err_sys("chdir failed"); 11 | 12 | ptr = path_alloc(&size); /* our own function */ 13 | if (getcwd(ptr, size) == NULL) 14 | err_sys("getcwd failed"); 15 | 16 | printf("cwd = %s\n", ptr); 17 | exit(0); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/fileio/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = fileflags hole mycat seek 6 | 7 | all: $(PROGS) setfl.o 8 | 9 | %: %.c $(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 16 | -------------------------------------------------------------------------------- /apue.3e/lib/strerror.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef LINUX 4 | extern char *sys_errlist[]; 5 | extern int sys_nerr; 6 | #endif 7 | 8 | char * 9 | strerror(int error) 10 | { 11 | static char mesg[30]; 12 | 13 | if (error >= 0 && error <= sys_nerr) 14 | return((char *)sys_errlist[error]); 15 | 16 | sprintf(mesg, "Unknown error (%d)", error); 17 | return(mesg); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/intro/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = getcputc hello ls1 mycat shell1 shell2 testerror uidgid 6 | 7 | all: $(PROGS) 8 | 9 | %: %.c $(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 | -------------------------------------------------------------------------------- /Chapter08/exercise_5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | main(const int argc, char* const argv[]) 6 | { 7 | if (argc == 1) { 8 | execlp(argv[0], argv[0], "myarg1", "MY ARG2", NULL); 9 | perror("execlp"); 10 | return 1; 11 | } 12 | int i; 13 | 14 | for (i = 0; i < argc; ++i) { 15 | printf("argv[%d] = %s\n", i, argv[i]); 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/fileio/setfl.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | set_fl(int fd, int flags) /* flags are file status flags to turn on */ 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 on flags */ 13 | 14 | if (fcntl(fd, F_SETFL, val) < 0) 15 | err_sys("fcntl F_SETFL error"); 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/lib/setfl.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | set_fl(int fd, int flags) /* flags are file status flags to turn on */ 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 on flags */ 13 | 14 | if (fcntl(fd, F_SETFL, val) < 0) 15 | err_sys("fcntl F_SETFL error"); 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/environ/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = doatexit echoarg getrlimit hello1 testjmp 6 | 7 | all: $(PROGS) opendata.o scope.o 8 | 9 | %: %.c $(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 | -------------------------------------------------------------------------------- /apue.3e/proc/echoall.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(int argc, char *argv[]) 5 | { 6 | int i; 7 | char **ptr; 8 | extern char **environ; 9 | 10 | for (i = 0; i < argc; i++) /* echo all command-line args */ 11 | printf("argv[%d]: %s\n", i, argv[i]); 12 | 13 | for (ptr = environ; *ptr != 0; ptr++) /* and all env strings */ 14 | printf("%s\n", *ptr); 15 | 16 | exit(0); 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solutions: Advanced Programming in the Unix Environment v3 2 | This repository contains my solutions to the exercises in _Advanced Programming 3 | in the Unix Environment v3_. I've tried to make each solution file 4 | self-sufficient; I do not use the "apue.h" header. When an exercise depends on 5 | pre-written functions, I copy the implementation of those functions into the 6 | solution source file. 7 | -------------------------------------------------------------------------------- /apue.3e/filedir/umask.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 5 | 6 | int 7 | main(void) 8 | { 9 | umask(0); 10 | if (creat("foo", RWRWRW) < 0) 11 | err_sys("creat error for foo"); 12 | umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 13 | if (creat("bar", RWRWRW) < 0) 14 | err_sys("creat error for bar"); 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/lib/clrfl.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | clr_fl(int fd, int flags) 6 | /* flags are the file status flags to turn off */ 7 | { 8 | int val; 9 | 10 | if ((val = fcntl(fd, F_GETFL, 0)) < 0) 11 | err_sys("fcntl F_GETFL error"); 12 | 13 | val &= ~flags; /* turn flags off */ 14 | 15 | if (fcntl(fd, F_SETFL, val) < 0) 16 | err_sys("fcntl F_SETFL error"); 17 | } 18 | -------------------------------------------------------------------------------- /apue.3e/lib/signalintr.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | Sigfunc * 4 | signal_intr(int signo, Sigfunc *func) 5 | { 6 | struct sigaction act, oact; 7 | 8 | act.sa_handler = func; 9 | sigemptyset(&act.sa_mask); 10 | act.sa_flags = 0; 11 | #ifdef SA_INTERRUPT 12 | act.sa_flags |= SA_INTERRUPT; 13 | #endif 14 | if (sigaction(signo, &act, &oact) < 0) 15 | return(SIG_ERR); 16 | return(oact.sa_handler); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter04/exercise_17.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int 8 | main(void) 9 | { 10 | const char* const path = "/dev/fd/1"; 11 | 12 | if (unlink(path) < 0) { 13 | perror("unlink"); 14 | } 15 | 16 | const int fd = creat(path, 0644); 17 | if (fd < 0) { 18 | perror("creat"); 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend.fe/opend.h: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define CL_OPEN "open" /* client's request for server */ 5 | 6 | extern char errmsg[]; /* error message string to return to client */ 7 | extern int oflag; /* open() flag: O_xxx ... */ 8 | extern char *pathname; /* of file to open() for client */ 9 | 10 | int cli_args(int, char **); 11 | void handle_request(char *, int, int); 12 | -------------------------------------------------------------------------------- /apue.3e/threads/maketimeout.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void 5 | maketimeout(struct timespec *tsp, long minutes) 6 | { 7 | struct timeval now; 8 | 9 | /* get the current time */ 10 | gettimeofday(&now, NULL); 11 | tsp->tv_sec = now.tv_sec; 12 | tsp->tv_nsec = now.tv_usec * 1000; /* usec to nsec */ 13 | /* add the offset to get timeout value */ 14 | tsp->tv_sec += minutes * 60; 15 | } 16 | -------------------------------------------------------------------------------- /apue.3e/termios/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = csize settty t_getpass t_isatty t_raw t_ttyname winch 6 | 7 | all: $(PROGS) ctermid.o getpass.o isatty.o ttyname.o 8 | 9 | %: %.c $(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 | -------------------------------------------------------------------------------- /apue.3e/datafiles/getpwnam.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct passwd * 6 | getpwnam(const char *name) 7 | { 8 | struct passwd *ptr; 9 | 10 | setpwent(); 11 | while ((ptr = getpwent()) != NULL) 12 | if (strcmp(name, ptr->pw_name) == 0) 13 | break; /* found a match */ 14 | endpwent(); 15 | return(ptr); /* ptr is NULL if no match found */ 16 | } 17 | -------------------------------------------------------------------------------- /apue.3e/termios/t_getpass.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | char *getpass(const char *); 4 | 5 | int 6 | main(void) 7 | { 8 | char *ptr; 9 | 10 | if ((ptr = getpass("Enter password:")) == NULL) 11 | err_sys("getpass error"); 12 | printf("password: %s\n", ptr); 13 | 14 | /* now use password (probably encrypt it) ... */ 15 | 16 | while (*ptr != 0) 17 | *ptr++ = 0; /* zero it out when we're done with it */ 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/Makefile: -------------------------------------------------------------------------------- 1 | DIRS = lib intro sockets advio daemons datafiles db environ \ 2 | fileio filedir ipc1 ipc2 proc pty relation signals standards \ 3 | stdio termios threadctl threads printer exercises 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 | -------------------------------------------------------------------------------- /Chapter05/exercise_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define err_sys(fmt, ...) fprintf(stderr, "" fmt "\n", ##__VA_ARGS__) 5 | 6 | #define MAXLINE 4 7 | 8 | int 9 | main(void) 10 | { 11 | char buf[MAXLINE]; 12 | 13 | while (fgets(buf, MAXLINE, stdin) != NULL) 14 | if (fputs(buf, stdout) == EOF) 15 | err_sys("output error"); 16 | 17 | if (ferror(stdin)) 18 | err_sys("input error"); 19 | 20 | exit(0); 21 | } 22 | -------------------------------------------------------------------------------- /apue.3e/intro/ls1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(int argc, char *argv[]) 6 | { 7 | DIR *dp; 8 | struct dirent *dirp; 9 | 10 | if (argc != 2) 11 | err_quit("usage: ls directory_name"); 12 | 13 | if ((dp = opendir(argv[1])) == NULL) 14 | err_sys("can't open %s", argv[1]); 15 | while ((dirp = readdir(dp)) != NULL) 16 | printf("%s\n", dirp->d_name); 17 | 18 | closedir(dp); 19 | exit(0); 20 | } 21 | -------------------------------------------------------------------------------- /apue.3e/ipc1/add2stdio.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | int int1, int2; 7 | char line[MAXLINE]; 8 | 9 | while (fgets(line, MAXLINE, stdin) != NULL) { 10 | if (sscanf(line, "%d%d", &int1, &int2) == 2) { 11 | if (printf("%d\n", int1 + int2) == EOF) 12 | err_sys("printf error"); 13 | } else { 14 | if (printf("invalid args\n") == EOF) 15 | err_sys("printf error"); 16 | } 17 | } 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/exercises/zombie.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #ifdef SOLARIS 4 | #define PSCMD "ps -a -o pid,ppid,s,tty,comm" 5 | #else 6 | #define PSCMD "ps -o pid,ppid,state,tty,command" 7 | #endif 8 | 9 | int 10 | main(void) 11 | { 12 | pid_t pid; 13 | 14 | if ((pid = fork()) < 0) 15 | err_sys("fork error"); 16 | else if (pid == 0) /* child */ 17 | exit(0); 18 | 19 | /* parent */ 20 | sleep(4); 21 | system(PSCMD); 22 | 23 | exit(0); 24 | } 25 | -------------------------------------------------------------------------------- /apue.3e/pty/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "solaris" 6 | EXTRALIBS=-lsocket -lnsl 7 | endif 8 | 9 | PROGS = pty 10 | 11 | all: $(PROGS) 12 | 13 | pty: main.o loop.o driver.o $(LIBAPUE) 14 | $(CC) $(CFLAGS) -o pty main.o loop.o driver.o $(LDFLAGS) $(LDLIBS) 15 | 16 | clean: 17 | rm -f $(PROGS) $(TEMPFILES) *.o 18 | 19 | include $(ROOT)/Make.libapue.inc 20 | -------------------------------------------------------------------------------- /apue.3e/filedir/access.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(int argc, char *argv[]) 6 | { 7 | if (argc != 2) 8 | err_quit("usage: a.out "); 9 | if (access(argv[1], R_OK) < 0) 10 | err_ret("access error for %s", argv[1]); 11 | else 12 | printf("read access OK\n"); 13 | if (open(argv[1], O_RDONLY) < 0) 14 | err_ret("open error for %s", argv[1]); 15 | else 16 | printf("open for reading OK\n"); 17 | exit(0); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/ipc1/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | PROGS = add2 add2stdio devzero myuclc pipe1 pipe2 pipe4 popen1 popen2 tshm 6 | 7 | all: $(PROGS) popen.o slock.o tellwait.o 8 | 9 | %: %.c $(LIBAPUE) 10 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 11 | 12 | slock.o: slock.c slock.h 13 | 14 | clean: 15 | rm -f $(PROGS) $(TEMPFILES) *.o 16 | 17 | include $(ROOT)/Make.libapue.inc 18 | -------------------------------------------------------------------------------- /Chapter06/exercise_4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | time_t max_time = 0; 8 | time_t mask = 1; 9 | size_t i; 10 | 11 | for (i = 0; i < ((8 * sizeof(time_t)) - 9); ++i) 12 | { 13 | max_time |= (mask << i); 14 | } 15 | 16 | const char* const str = asctime(gmtime(&max_time)); 17 | if (str == NULL) { 18 | perror("asctime"); 19 | return 1; 20 | } 21 | 22 | printf("%s\n", str); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=../.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "solaris" 6 | EXTRALIBS=-lsocket -lnsl 7 | endif 8 | 9 | PROGS = openclient 10 | 11 | all: $(PROGS) 12 | 13 | openclient: main.o open.o $(LIBAPUE) 14 | $(CC) $(CFLAGS) -o openclient main.o open.o $(LDFLAGS) $(LDLIBS) 15 | 16 | clean: 17 | rm -f $(PROGS) $(TEMPFILES) *.o 18 | 19 | include $(ROOT)/Make.libapue.inc 20 | -------------------------------------------------------------------------------- /apue.3e/exercises/prtime.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | time_t caltime; 8 | struct tm *tm; 9 | char line[MAXLINE]; 10 | 11 | if ((caltime = time(NULL)) == -1) 12 | err_sys("time error"); 13 | if ((tm = localtime(&caltime)) == NULL) 14 | err_sys("localtime error"); 15 | if (strftime(line, MAXLINE, "%a %b %d %X %Z %Y\n", tm) == 0) 16 | err_sys("strftime error"); 17 | fputs(line, stdout); 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open.fe/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=../.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "solaris" 6 | EXTRALIBS=-lsocket -lnsl 7 | endif 8 | 9 | PROGS = openclient 10 | 11 | all: $(PROGS) 12 | 13 | openclient: main.o open.o $(LIBAPUE) 14 | $(CC) $(CFLAGS) -o openclient main.o open.o $(LDFLAGS) $(LDLIBS) 15 | 16 | clean: 17 | rm -f $(PROGS) $(TEMPFILES) *.o 18 | 19 | include $(ROOT)/Make.libapue.inc 20 | -------------------------------------------------------------------------------- /apue.3e/proc/exec2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | pid_t pid; 8 | 9 | if ((pid = fork()) < 0) { 10 | err_sys("fork error"); 11 | } else if (pid == 0) { /* child */ 12 | if (execl("/home/sar/bin/testinterp", 13 | "testinterp", "myarg1", "MY ARG2", (char *)0) < 0) 14 | err_sys("execl error"); 15 | } 16 | if (waitpid(pid, NULL, 0) < 0) /* parent */ 17 | err_sys("waitpid error"); 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/lib/lockreg.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) 6 | { 7 | struct flock lock; 8 | 9 | lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */ 10 | lock.l_start = offset; /* byte offset, relative to l_whence */ 11 | lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ 12 | lock.l_len = len; /* #bytes (0 means to EOF) */ 13 | 14 | return(fcntl(fd, cmd, &lock)); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter04/exercise_4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 8 | 9 | int 10 | main(void) 11 | { 12 | umask(0); 13 | if (creat("foo", RWRWRW) < 0) 14 | perror("creat(foo)"); 15 | 16 | umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 17 | 18 | if (creat("bar", RWRWRW) < 0) 19 | perror("creat(bar)"); 20 | 21 | exit(0); 22 | } 23 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend.fe/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=../.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "solaris" 6 | EXTRALIBS=-lsocket -lnsl 7 | endif 8 | 9 | PROGS = opend 10 | 11 | all: $(PROGS) 12 | 13 | opend: main.o request.o cliargs.o $(LIBAPUE) 14 | $(CC) $(CFLAGS) -o opend main.o cliargs.o request.o $(LDFLAGS) $(LDLIBS) 15 | 16 | clean: 17 | rm -f $(PROGS) $(TEMPFILES) *.o 18 | 19 | include $(ROOT)/Make.libapue.inc 20 | -------------------------------------------------------------------------------- /apue.3e/threadctl/detach.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | makethread(void *(*fn)(void *), void *arg) 6 | { 7 | int err; 8 | pthread_t tid; 9 | pthread_attr_t attr; 10 | 11 | err = pthread_attr_init(&attr); 12 | if (err != 0) 13 | return(err); 14 | err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 15 | if (err == 0) 16 | err = pthread_create(&tid, &attr, fn, arg); 17 | pthread_attr_destroy(&attr); 18 | return(err); 19 | } 20 | -------------------------------------------------------------------------------- /apue.3e/exercises/sizepipe.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | int i, n; 8 | int fd[2]; 9 | 10 | if (pipe(fd) < 0) 11 | err_sys("pipe error"); 12 | set_fl(fd[1], O_NONBLOCK); 13 | 14 | /* write 1 byte at a time until pipe is full */ 15 | for (n = 0; ; n++) { 16 | if ((i = write(fd[1], "a", 1)) != 1) { 17 | printf("write ret %d, ", i); 18 | break; 19 | } 20 | } 21 | printf("pipe capacity = %d\n", n); 22 | exit(0); 23 | } 24 | -------------------------------------------------------------------------------- /apue.3e/proc/systest1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | int status; 8 | 9 | if ((status = system("date")) < 0) 10 | err_sys("system() error"); 11 | 12 | pr_exit(status); 13 | 14 | if ((status = system("nosuchcommand")) < 0) 15 | err_sys("system() error"); 16 | 17 | pr_exit(status); 18 | 19 | if ((status = system("who; exit 44")) < 0) 20 | err_sys("system() error"); 21 | 22 | pr_exit(status); 23 | 24 | exit(0); 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/signals/sleep1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void 5 | sig_alrm(int signo) 6 | { 7 | /* nothing to do, just return to wake up the pause */ 8 | } 9 | 10 | unsigned int 11 | sleep1(unsigned int seconds) 12 | { 13 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 14 | return(seconds); 15 | alarm(seconds); /* start the timer */ 16 | pause(); /* next caught signal wakes us up */ 17 | return(alarm(0)); /* turn off timer, return unslept time */ 18 | } 19 | -------------------------------------------------------------------------------- /Chapter15/exercise_8.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(const int argc, const char* const argv[]) 5 | { 6 | if (argc == 1) { 7 | char cmd[128]; 8 | snprintf(cmd, sizeof(cmd), "%s foo", argv[0]); 9 | FILE* proc = popen(cmd, "r"); 10 | if (proc == NULL) { 11 | perror("fopen"); 12 | return 1; 13 | } 14 | pclose(proc); 15 | } else { 16 | fprintf(stdout, "Writing to standard output\n"); 17 | fprintf(stderr, "Writing to standard error\n"); 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /apue.3e/exercises/fifo1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define FIFO "temp.fifo" 5 | 6 | int 7 | main(void) 8 | { 9 | int fdread, fdwrite; 10 | 11 | unlink(FIFO); 12 | if (mkfifo(FIFO, FILE_MODE) < 0) 13 | err_sys("mkfifo error"); 14 | if ((fdread = open(FIFO, O_RDONLY | O_NONBLOCK)) < 0) 15 | err_sys("open error for reading"); 16 | if ((fdwrite = open(FIFO, O_WRONLY)) < 0) 17 | err_sys("open error for writing"); 18 | clr_fl(fdread, O_NONBLOCK); 19 | exit(0); 20 | } 21 | -------------------------------------------------------------------------------- /apue.3e/stdio/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 12 | 13 | all: $(PROGS) $(MEMSTR) 14 | 15 | %: %.c $(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 22 | -------------------------------------------------------------------------------- /apue.3e/exercises/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | unsigned 6 | sleep(unsigned seconds) 7 | { 8 | int n; 9 | unsigned slept; 10 | time_t start, end; 11 | struct timeval tv; 12 | 13 | tv.tv_sec = seconds; 14 | tv.tv_usec = 0; 15 | time(&start); 16 | n = select(0, NULL, NULL, NULL, &tv); 17 | if (n == 0) 18 | return(0); 19 | time(&end); 20 | slept = end - start; 21 | if (slept >= seconds) 22 | return(0); 23 | return(seconds - slept); 24 | } 25 | -------------------------------------------------------------------------------- /apue.3e/exercises/vfork3.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void f1(void), f2(void); 4 | 5 | int 6 | main(void) 7 | { 8 | f1(); 9 | f2(); 10 | _exit(0); 11 | } 12 | 13 | static void 14 | f1(void) 15 | { 16 | pid_t pid; 17 | 18 | if ((pid = vfork()) < 0) 19 | err_sys("vfork error"); 20 | /* child and parent both return */ 21 | } 22 | 23 | static void 24 | f2(void) 25 | { 26 | char buf[1000]; /* automatic variables */ 27 | int i; 28 | 29 | for (i = 0; i < sizeof(buf); i++) 30 | buf[i] = 0; 31 | } 32 | -------------------------------------------------------------------------------- /Chapter14/exercise_5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | suseconds_t 5 | sleep_us(const suseconds_t microseconds) 6 | { 7 | struct timeval timeout = { .tv_usec = microseconds }; 8 | 9 | (void) select(0, NULL, NULL, NULL, &timeout); 10 | 11 | return timeout.tv_usec; 12 | } 13 | 14 | static suseconds_t 15 | seconds_to_microseconds(double seconds) 16 | { 17 | return seconds * 1000000U; 18 | } 19 | 20 | int 21 | main(void) 22 | { 23 | sleep_us(seconds_to_microseconds(5.25)); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/ipc1/pipe1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | int n; 7 | int fd[2]; 8 | pid_t pid; 9 | char line[MAXLINE]; 10 | 11 | if (pipe(fd) < 0) 12 | err_sys("pipe error"); 13 | if ((pid = fork()) < 0) { 14 | err_sys("fork error"); 15 | } else if (pid > 0) { /* parent */ 16 | close(fd[0]); 17 | write(fd[1], "hello world\n", 12); 18 | } else { /* child */ 19 | close(fd[1]); 20 | n = read(fd[0], line, MAXLINE); 21 | write(STDOUT_FILENO, line, n); 22 | } 23 | exit(0); 24 | } 25 | -------------------------------------------------------------------------------- /apue.3e/signals/systest2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void 4 | sig_int(int signo) 5 | { 6 | printf("caught SIGINT\n"); 7 | } 8 | 9 | static void 10 | sig_chld(int signo) 11 | { 12 | printf("caught SIGCHLD\n"); 13 | } 14 | 15 | int 16 | main(void) 17 | { 18 | if (signal(SIGINT, sig_int) == SIG_ERR) 19 | err_sys("signal(SIGINT) error"); 20 | if (signal(SIGCHLD, sig_chld) == SIG_ERR) 21 | err_sys("signal(SIGCHLD) error"); 22 | if (system("/bin/ed") < 0) 23 | err_sys("system() error"); 24 | exit(0); 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend.fe/main.c: -------------------------------------------------------------------------------- 1 | #include "opend.h" 2 | 3 | char errmsg[MAXLINE]; 4 | int oflag; 5 | char *pathname; 6 | 7 | int 8 | main(void) 9 | { 10 | int nread; 11 | char buf[MAXLINE]; 12 | 13 | for ( ; ; ) { /* read arg buffer from client, process request */ 14 | if ((nread = read(STDIN_FILENO, buf, MAXLINE)) < 0) 15 | err_sys("read error on stream pipe"); 16 | else if (nread == 0) 17 | break; /* client has closed the stream pipe */ 18 | handle_request(buf, nread, STDOUT_FILENO); 19 | } 20 | exit(0); 21 | } 22 | -------------------------------------------------------------------------------- /apue.3e/exercises/openmax.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | #define OPEN_MAX_GUESS 256 6 | 7 | long 8 | open_max(void) 9 | { 10 | long openmax; 11 | struct rlimit rl; 12 | 13 | if ((openmax = sysconf(_SC_OPEN_MAX)) < 0 || 14 | openmax == LONG_MAX) { 15 | if (getrlimit(RLIMIT_NOFILE, &rl) < 0) 16 | err_sys("can't get file limit"); 17 | if (rl.rlim_max == RLIM_INFINITY) 18 | openmax = OPEN_MAX_GUESS; 19 | else 20 | openmax = rl.rlim_max; 21 | } 22 | return(openmax); 23 | } 24 | -------------------------------------------------------------------------------- /apue.3e/filedir/changemod.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | struct stat statbuf; 7 | 8 | /* turn on set-group-ID and turn off group-execute */ 9 | 10 | if (stat("foo", &statbuf) < 0) 11 | err_sys("stat error for foo"); 12 | if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0) 13 | err_sys("chmod error for foo"); 14 | 15 | /* set absolute mode to "rw-r--r--" */ 16 | 17 | if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) 18 | err_sys("chmod error for bar"); 19 | 20 | exit(0); 21 | } 22 | -------------------------------------------------------------------------------- /apue.3e/threadctl/getenv1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXSTRINGSZ 4096 5 | 6 | static char envbuf[MAXSTRINGSZ]; 7 | 8 | extern char **environ; 9 | 10 | char * 11 | getenv(const char *name) 12 | { 13 | int i, len; 14 | 15 | len = strlen(name); 16 | for (i = 0; environ[i] != NULL; i++) { 17 | if ((strncmp(name, environ[i], len) == 0) && 18 | (environ[i][len] == '=')) { 19 | strncpy(envbuf, &environ[i][len+1], MAXSTRINGSZ-1); 20 | return(envbuf); 21 | } 22 | } 23 | return(NULL); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter06/exercise_3.c: -------------------------------------------------------------------------------- 1 | //#define _GNU_SOURCE 2 | #include 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | struct utsname info = {}; 9 | 10 | if (uname(&info) < 0) { 11 | perror("uname"); 12 | return 1; 13 | } 14 | 15 | printf("%s %s %s %s %s", 16 | info.sysname, 17 | info.nodename, 18 | info.release, 19 | info.version, 20 | info.machine); 21 | #if defined(_GNU_SOURCE) 22 | printf(" %s", info.domainname); 23 | #endif 24 | printf("\n"); 25 | 26 | return 0; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /apue.3e/lib/signal.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | /* Reliable version of signal(), using POSIX sigaction(). */ 4 | Sigfunc * 5 | signal(int signo, Sigfunc *func) 6 | { 7 | struct sigaction act, oact; 8 | 9 | act.sa_handler = func; 10 | sigemptyset(&act.sa_mask); 11 | act.sa_flags = 0; 12 | if (signo == SIGALRM) { 13 | #ifdef SA_INTERRUPT 14 | act.sa_flags |= SA_INTERRUPT; 15 | #endif 16 | } else { 17 | act.sa_flags |= SA_RESTART; 18 | } 19 | if (sigaction(signo, &act, &oact) < 0) 20 | return(SIG_ERR); 21 | return(oact.sa_handler); 22 | } 23 | -------------------------------------------------------------------------------- /apue.3e/signals/read1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void sig_alrm(int); 4 | 5 | int 6 | main(void) 7 | { 8 | int n; 9 | char line[MAXLINE]; 10 | 11 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 12 | err_sys("signal(SIGALRM) error"); 13 | 14 | alarm(10); 15 | if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) 16 | err_sys("read error"); 17 | alarm(0); 18 | 19 | write(STDOUT_FILENO, line, n); 20 | exit(0); 21 | } 22 | 23 | static void 24 | sig_alrm(int signo) 25 | { 26 | /* nothing to do, just return to interrupt the read */ 27 | } 28 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend/cliargs.c: -------------------------------------------------------------------------------- 1 | #include "opend.h" 2 | 3 | /* 4 | * This function is called by buf_args(), which is called by 5 | * handle_request(). buf_args() has broken up the client's 6 | * buffer into an argv[] style array, which we now process. 7 | */ 8 | int 9 | cli_args(int argc, char **argv) 10 | { 11 | if (argc != 3 || strcmp(argv[0], CL_OPEN) != 0) { 12 | strcpy(errmsg, "usage: \n"); 13 | return(-1); 14 | } 15 | pathname = argv[1]; /* save ptr to pathname to open */ 16 | oflag = atoi(argv[2]); 17 | return(0); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/ipc2/bindunix.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | int fd, size; 9 | struct sockaddr_un un; 10 | 11 | un.sun_family = AF_UNIX; 12 | strcpy(un.sun_path, "foo.socket"); 13 | if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 14 | err_sys("socket failed"); 15 | size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path); 16 | if (bind(fd, (struct sockaddr *)&un, size) < 0) 17 | err_sys("bind failed"); 18 | printf("UNIX domain socket bound\n"); 19 | exit(0); 20 | } 21 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend.fe/cliargs.c: -------------------------------------------------------------------------------- 1 | #include "opend.h" 2 | 3 | /* 4 | * This function is called by buf_args(), which is called by 5 | * handle_request(). buf_args() has broken up the client's 6 | * buffer into an argv[]-style array, which we now process. 7 | */ 8 | int 9 | cli_args(int argc, char **argv) 10 | { 11 | if (argc != 3 || strcmp(argv[0], CL_OPEN) != 0) { 12 | strcpy(errmsg, "usage: \n"); 13 | return(-1); 14 | } 15 | pathname = argv[1]; /* save ptr to pathname to open */ 16 | oflag = atoi(argv[2]); 17 | return(0); 18 | } 19 | -------------------------------------------------------------------------------- /apue.3e/signals/sleep2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static jmp_buf env_alrm; 6 | 7 | static void 8 | sig_alrm(int signo) 9 | { 10 | longjmp(env_alrm, 1); 11 | } 12 | 13 | unsigned int 14 | sleep2(unsigned int seconds) 15 | { 16 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 17 | return(seconds); 18 | if (setjmp(env_alrm) == 0) { 19 | alarm(seconds); /* start the timer */ 20 | pause(); /* next caught signal wakes us up */ 21 | } 22 | return(alarm(0)); /* turn off timer, return unslept time */ 23 | } 24 | -------------------------------------------------------------------------------- /apue.3e/ipc1/popen1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | char line[MAXLINE]; 8 | FILE *fpin; 9 | 10 | if ((fpin = popen("myuclc", "r")) == NULL) 11 | err_sys("popen error"); 12 | for ( ; ; ) { 13 | fputs("prompt> ", stdout); 14 | fflush(stdout); 15 | if (fgets(line, MAXLINE, fpin) == NULL) /* read from pipe */ 16 | break; 17 | if (fputs(line, stdout) == EOF) 18 | err_sys("fputs error to pipe"); 19 | } 20 | if (pclose(fpin) == -1) 21 | err_sys("pclose error"); 22 | putchar('\n'); 23 | exit(0); 24 | } 25 | -------------------------------------------------------------------------------- /apue.3e/ipc1/add2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | int n, int1, int2; 7 | char line[MAXLINE]; 8 | 9 | while ((n = read(STDIN_FILENO, line, MAXLINE)) > 0) { 10 | line[n] = 0; /* null terminate */ 11 | if (sscanf(line, "%d%d", &int1, &int2) == 2) { 12 | sprintf(line, "%d\n", int1 + int2); 13 | n = strlen(line); 14 | if (write(STDOUT_FILENO, line, n) != n) 15 | err_sys("write error"); 16 | } else { 17 | if (write(STDOUT_FILENO, "invalid args\n", 13) != 13) 18 | err_sys("write error"); 19 | } 20 | } 21 | exit(0); 22 | } 23 | -------------------------------------------------------------------------------- /apue.3e/proc/tellwait1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void charatatime(char *); 4 | 5 | int 6 | main(void) 7 | { 8 | pid_t pid; 9 | 10 | if ((pid = fork()) < 0) { 11 | err_sys("fork error"); 12 | } else if (pid == 0) { 13 | charatatime("output from child\n"); 14 | } else { 15 | charatatime("output from parent\n"); 16 | } 17 | exit(0); 18 | } 19 | 20 | static void 21 | charatatime(char *str) 22 | { 23 | char *ptr; 24 | int c; 25 | 26 | setbuf(stdout, NULL); /* set unbuffered */ 27 | for (ptr = str; (c = *ptr++) != 0; ) 28 | putc(c, stdout); 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/environ/cmd2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define TOK_ADD 5 5 | 6 | jmp_buf jmpbuffer; 7 | 8 | int 9 | main(void) 10 | { 11 | char line[MAXLINE]; 12 | 13 | if (setjmp(jmpbuffer) != 0) 14 | printf("error"); 15 | while (fgets(line, MAXLINE, stdin) != NULL) 16 | do_line(line); 17 | exit(0); 18 | } 19 | 20 | . . . 21 | 22 | void 23 | cmd_add(void) 24 | { 25 | int token; 26 | 27 | token = get_token(); 28 | if (token < 0) /* an error has occurred */ 29 | longjmp(jmpbuffer, 1); 30 | /* rest of processing for this command */ 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/lib/senderr.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | /* 4 | * Used when we had planned to send an fd using send_fd(), 5 | * but encountered an error instead. We send the error back 6 | * using the send_fd()/recv_fd() protocol. 7 | */ 8 | int 9 | send_err(int fd, int errcode, const char *msg) 10 | { 11 | int n; 12 | 13 | if ((n = strlen(msg)) > 0) 14 | if (writen(fd, msg, n) != n) /* send the error message */ 15 | return(-1); 16 | 17 | if (errcode >= 0) 18 | errcode = -1; /* must be negative */ 19 | 20 | if (send_fd(fd, errcode) < 0) 21 | return(-1); 22 | 23 | return(0); 24 | } 25 | -------------------------------------------------------------------------------- /apue.3e/datafiles/strftime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | time_t t; 9 | struct tm *tmp; 10 | char buf1[16]; 11 | char buf2[64]; 12 | 13 | time(&t); 14 | tmp = localtime(&t); 15 | if (strftime(buf1, 16, "time and date: %r, %a %b %d, %Y", tmp) == 0) 16 | printf("buffer length 16 is too small\n"); 17 | else 18 | printf("%s\n", buf1); 19 | if (strftime(buf2, 64, "time and date: %r, %a %b %d, %Y", tmp) == 0) 20 | printf("buffer length 64 is too small\n"); 21 | else 22 | printf("%s\n", buf2); 23 | exit(0); 24 | } 25 | -------------------------------------------------------------------------------- /apue.3e/sockets/initsrv1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | int 6 | initserver(int type, const struct sockaddr *addr, socklen_t alen, 7 | int qlen) 8 | { 9 | int fd; 10 | int err = 0; 11 | 12 | if ((fd = socket(addr->sa_family, type, 0)) < 0) 13 | return(-1); 14 | if (bind(fd, addr, alen) < 0) 15 | goto errout; 16 | if (type == SOCK_STREAM || type == SOCK_SEQPACKET) { 17 | if (listen(fd, qlen) < 0) 18 | goto errout; 19 | } 20 | return(fd); 21 | 22 | errout: 23 | err = errno; 24 | close(fd); 25 | errno = err; 26 | return(-1); 27 | } 28 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/advio/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 | -------------------------------------------------------------------------------- /apue.3e/advio/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 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/fileio/hole.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | char buf1[] = "abcdefghij"; 5 | char buf2[] = "ABCDEFGHIJ"; 6 | 7 | int 8 | main(void) 9 | { 10 | int fd; 11 | 12 | if ((fd = creat("file.hole", FILE_MODE)) < 0) 13 | err_sys("creat error"); 14 | 15 | if (write(fd, buf1, 10) != 10) 16 | err_sys("buf1 write error"); 17 | /* offset now = 10 */ 18 | 19 | if (lseek(fd, 16384, SEEK_SET) == -1) 20 | err_sys("lseek error"); 21 | /* offset now = 16384 */ 22 | 23 | if (write(fd, buf2, 10) != 10) 24 | err_sys("buf2 write error"); 25 | /* offset now = 16394 */ 26 | 27 | exit(0); 28 | } 29 | -------------------------------------------------------------------------------- /apue.3e/sockets/clconn.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define MAXSLEEP 128 5 | 6 | int 7 | connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen) 8 | { 9 | int numsec; 10 | 11 | /* 12 | * Try to connect with exponential backoff. 13 | */ 14 | for (numsec = 1; numsec <= MAXSLEEP; numsec <<= 1) { 15 | if (connect(sockfd, addr, alen) == 0) { 16 | /* 17 | * Connection accepted. 18 | */ 19 | return(0); 20 | } 21 | 22 | /* 23 | * Delay before trying again. 24 | */ 25 | if (numsec <= MAXSLEEP/2) 26 | sleep(numsec); 27 | } 28 | return(-1); 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/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=-ansi -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 | -------------------------------------------------------------------------------- /apue.3e/db/t4.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include "apue_db.h" 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | DBHANDLE db; 9 | 10 | if ((db = db_open("db4", O_RDWR | O_CREAT | O_TRUNC, 11 | FILE_MODE)) == NULL) 12 | err_sys("db_open error"); 13 | 14 | if (db_store(db, "Alpha", "data1", DB_INSERT) != 0) 15 | err_quit("db_store error for alpha"); 16 | if (db_store(db, "beta", "Data for beta", DB_INSERT) != 0) 17 | err_quit("db_store error for beta"); 18 | if (db_store(db, "gamma", "record3", DB_INSERT) != 0) 19 | err_quit("db_store error for gamma"); 20 | 21 | db_close(db); 22 | exit(0); 23 | } 24 | -------------------------------------------------------------------------------- /apue.3e/environ/doatexit.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void my_exit1(void); 4 | static void my_exit2(void); 5 | 6 | int 7 | main(void) 8 | { 9 | if (atexit(my_exit2) != 0) 10 | err_sys("can't register my_exit2"); 11 | 12 | if (atexit(my_exit1) != 0) 13 | err_sys("can't register my_exit1"); 14 | if (atexit(my_exit1) != 0) 15 | err_sys("can't register my_exit1"); 16 | 17 | printf("main is done\n"); 18 | return(0); 19 | } 20 | 21 | static void 22 | my_exit1(void) 23 | { 24 | printf("first exit handler\n"); 25 | } 26 | 27 | static void 28 | my_exit2(void) 29 | { 30 | printf("second exit handler\n"); 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/exercises/asyncsocket.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #if defined(BSD) || defined(MACOS) || defined(SOLARIS) 7 | #include 8 | #endif 9 | 10 | int 11 | setasync(int sockfd) 12 | { 13 | int n; 14 | 15 | if (fcntl(sockfd, F_SETOWN, getpid()) < 0) 16 | return(-1); 17 | n = 1; 18 | if (ioctl(sockfd, FIOASYNC, &n) < 0) 19 | return(-1); 20 | return(0); 21 | } 22 | 23 | int 24 | clrasync(int sockfd) 25 | { 26 | int n; 27 | 28 | n = 0; 29 | if (ioctl(sockfd, FIOASYNC, &n) < 0) 30 | return(-1); 31 | return(0); 32 | } 33 | -------------------------------------------------------------------------------- /apue.3e/signals/read2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void sig_alrm(int); 5 | static jmp_buf env_alrm; 6 | 7 | int 8 | main(void) 9 | { 10 | int n; 11 | char line[MAXLINE]; 12 | 13 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 14 | err_sys("signal(SIGALRM) error"); 15 | if (setjmp(env_alrm) != 0) 16 | err_quit("read timeout"); 17 | 18 | alarm(10); 19 | if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) 20 | err_sys("read error"); 21 | alarm(0); 22 | 23 | write(STDOUT_FILENO, line, n); 24 | exit(0); 25 | } 26 | 27 | static void 28 | sig_alrm(int signo) 29 | { 30 | longjmp(env_alrm, 1); 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/signals/sigusr.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void sig_usr(int); /* one handler for both signals */ 4 | 5 | int 6 | main(void) 7 | { 8 | if (signal(SIGUSR1, sig_usr) == SIG_ERR) 9 | err_sys("can't catch SIGUSR1"); 10 | if (signal(SIGUSR2, sig_usr) == SIG_ERR) 11 | err_sys("can't catch SIGUSR2"); 12 | for ( ; ; ) 13 | pause(); 14 | } 15 | 16 | static void 17 | sig_usr(int signo) /* argument is signal number */ 18 | { 19 | if (signo == SIGUSR1) 20 | printf("received SIGUSR1\n"); 21 | else if (signo == SIGUSR2) 22 | printf("received SIGUSR2\n"); 23 | else 24 | err_dump("received signal %d\n", signo); 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/filedir/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 devrdev filetype mycd umask unlink $(ZAP) 13 | MOREPROGS = ftw8 14 | 15 | all: $(PROGS) $(MOREPROGS) 16 | 17 | %: %.c $(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 27 | -------------------------------------------------------------------------------- /apue.3e/signals/reenter.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void 5 | my_alarm(int signo) 6 | { 7 | struct passwd *rootptr; 8 | 9 | printf("in signal handler\n"); 10 | if ((rootptr = getpwnam("root")) == NULL) 11 | err_sys("getpwnam(root) error"); 12 | alarm(1); 13 | } 14 | 15 | int 16 | main(void) 17 | { 18 | struct passwd *ptr; 19 | 20 | signal(SIGALRM, my_alarm); 21 | alarm(1); 22 | for ( ; ; ) { 23 | if ((ptr = getpwnam("sar")) == NULL) 24 | err_sys("getpwnam error"); 25 | if (strcmp(ptr->pw_name, "sar") != 0) 26 | printf("return value corrupted!, pw_name = %s\n", 27 | ptr->pw_name); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/stdio/tempfiles.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | char name[L_tmpnam], line[MAXLINE]; 7 | FILE *fp; 8 | 9 | printf("%s\n", tmpnam(NULL)); /* first temp name */ 10 | 11 | tmpnam(name); /* second temp name */ 12 | printf("%s\n", name); 13 | 14 | if ((fp = tmpfile()) == NULL) /* create temp file */ 15 | err_sys("tmpfile error"); 16 | fputs("one line of output\n", fp); /* write to temp file */ 17 | rewind(fp); /* then read it back */ 18 | if (fgets(line, sizeof(line), fp) == NULL) 19 | err_sys("fgets error"); 20 | fputs(line, stdout); /* print the line we wrote */ 21 | 22 | exit(0); 23 | } 24 | -------------------------------------------------------------------------------- /Chapter06/exercise_5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_LINE 256 5 | 6 | int 7 | main(void) 8 | { 9 | char date_string[MAX_LINE] = {}; 10 | 11 | const time_t current_time = time(NULL); 12 | if (current_time < 0) { 13 | perror("time"); 14 | return 1; 15 | } 16 | 17 | const struct tm* const tm = localtime(¤t_time); 18 | if (tm == NULL) { 19 | perror("localtime"); 20 | return 1; 21 | } 22 | 23 | if (strftime(date_string, sizeof(date_string), "%a %b %d %X %Z %Y\n", tm) == 0) { 24 | fprintf(stderr, "strftime failed\n"); 25 | return 1; 26 | } 27 | 28 | printf("%s", date_string); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /Chapter09/exercise_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int 8 | main(void) 9 | { 10 | const pid_t pid = fork(); 11 | 12 | if (pid < 0) { 13 | perror("fork"); 14 | return 1; 15 | } 16 | 17 | if (pid == 0) { 18 | char buffer[128]; 19 | 20 | if (setsid() < 0) { 21 | perror("setsid"); 22 | return 1; 23 | } 24 | 25 | snprintf(buffer, sizeof(buffer), "ps -p %d -opid,cmd,pgrp,tpgid,session", getpid()); 26 | system(buffer); 27 | } else { 28 | int status; 29 | 30 | // Wait for child to die 31 | wait(&status); 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /apue.3e/proc/vfork1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int globvar = 6; /* external variable in initialized data */ 4 | 5 | int 6 | main(void) 7 | { 8 | int var; /* automatic variable on the stack */ 9 | pid_t pid; 10 | 11 | var = 88; 12 | printf("before vfork\n"); /* we don't flush stdio */ 13 | if ((pid = vfork()) < 0) { 14 | err_sys("vfork error"); 15 | } else if (pid == 0) { /* child */ 16 | globvar++; /* modify parent's variables */ 17 | var++; 18 | _exit(0); /* child terminates */ 19 | } 20 | 21 | /* parent continues here */ 22 | printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, 23 | var); 24 | exit(0); 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/lib/locktest.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | pid_t 5 | lock_test(int fd, int type, off_t offset, int whence, off_t len) 6 | { 7 | struct flock lock; 8 | 9 | lock.l_type = type; /* F_RDLCK or F_WRLCK */ 10 | lock.l_start = offset; /* byte offset, relative to l_whence */ 11 | lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ 12 | lock.l_len = len; /* #bytes (0 means to EOF) */ 13 | 14 | if (fcntl(fd, F_GETLK, &lock) < 0) 15 | err_sys("fcntl error"); 16 | 17 | if (lock.l_type == F_UNLCK) 18 | return(0); /* false, region isn't locked by another proc */ 19 | return(lock.l_pid); /* true, return pid of lock owner */ 20 | } 21 | -------------------------------------------------------------------------------- /apue.3e/lib/openmax.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | #ifdef OPEN_MAX 6 | static long openmax = OPEN_MAX; 7 | #else 8 | static long openmax = 0; 9 | #endif 10 | 11 | /* 12 | * If OPEN_MAX is indeterminate, this might be inadequate. 13 | */ 14 | #define OPEN_MAX_GUESS 256 15 | 16 | long 17 | open_max(void) 18 | { 19 | if (openmax == 0) { /* first time through */ 20 | errno = 0; 21 | if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) { 22 | if (errno == 0) 23 | openmax = OPEN_MAX_GUESS; /* it's indeterminate */ 24 | else 25 | err_sys("sysconf error for _SC_OPEN_MAX"); 26 | } 27 | } 28 | return(openmax); 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/proc/tellwait2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void charatatime(char *); 4 | 5 | int 6 | main(void) 7 | { 8 | pid_t pid; 9 | 10 | TELL_WAIT(); 11 | 12 | if ((pid = fork()) < 0) { 13 | err_sys("fork error"); 14 | } else if (pid == 0) { 15 | WAIT_PARENT(); /* parent goes first */ 16 | charatatime("output from child\n"); 17 | } else { 18 | charatatime("output from parent\n"); 19 | TELL_CHILD(pid); 20 | } 21 | exit(0); 22 | } 23 | 24 | static void 25 | charatatime(char *str) 26 | { 27 | char *ptr; 28 | int c; 29 | 30 | setbuf(stdout, NULL); /* set unbuffered */ 31 | for (ptr = str; (c = *ptr++) != 0; ) 32 | putc(c, stdout); 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /apue.3e/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.o 12 | endif 13 | ifeq "$(PLATFORM)" "solaris" 14 | EXTRALIBS = -lpthread 15 | TOUT = timeout.o 16 | endif 17 | 18 | PROGS = atfork suspend 19 | 20 | all: $(PROGS) detach.o getenv1.o getenv2.o getenv3.o $(TOUT) 21 | 22 | %: %.c $(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 | -------------------------------------------------------------------------------- /apue.3e/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 | -------------------------------------------------------------------------------- /apue.3e/termios/t_ttyname.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | char *name; 7 | if (isatty(0)) { 8 | name = ttyname(0); 9 | if (name == NULL) 10 | name = "undefined"; 11 | } else { 12 | name = "not a tty"; 13 | } 14 | printf("fd 0: %s\n", name); 15 | 16 | if (isatty(1)) { 17 | name = ttyname(1); 18 | if (name == NULL) 19 | name = "undefined"; 20 | } else { 21 | name = "not a tty"; 22 | } 23 | printf("fd 1: %s\n", name); 24 | 25 | if (isatty(2)) { 26 | name = ttyname(2); 27 | if (name == NULL) 28 | name = "undefined"; 29 | } else { 30 | name = "not a tty"; 31 | } 32 | printf("fd 2: %s\n", name); 33 | 34 | exit(0); 35 | } 36 | -------------------------------------------------------------------------------- /Chapter08/exercise_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int globvar = 6; 6 | 7 | int 8 | main(void) 9 | { 10 | int var; 11 | pid_t pid; 12 | 13 | /* external variable in initialized data */ 14 | /* automatic variable on the stack */ 15 | var = 88; 16 | 17 | printf("before vfork\n"); 18 | if ((pid = vfork()) < 0) { 19 | perror("vfork error"); 20 | } else if (pid == 0) { 21 | globvar++; 22 | var++; 23 | /*_exit(0);*/ 24 | fclose(stdout); /* simulate possible behavior */ 25 | exit(0); 26 | } 27 | 28 | /* parent continues here */ 29 | printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var); 30 | exit(0); 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/sockets/initsrv2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | int 6 | initserver(int type, const struct sockaddr *addr, socklen_t alen, 7 | int qlen) 8 | { 9 | int fd, err; 10 | int reuse = 1; 11 | 12 | if ((fd = socket(addr->sa_family, type, 0)) < 0) 13 | return(-1); 14 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, 15 | sizeof(int)) < 0) 16 | goto errout; 17 | if (bind(fd, addr, alen) < 0) 18 | goto errout; 19 | if (type == SOCK_STREAM || type == SOCK_SEQPACKET) 20 | if (listen(fd, qlen) < 0) 21 | goto errout; 22 | return(fd); 23 | 24 | errout: 25 | err = errno; 26 | close(fd); 27 | errno = err; 28 | return(-1); 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/DISCLAIMER: -------------------------------------------------------------------------------- 1 | LIMITS OF LIABILITY AND DISCLAIMER OF WARRANTY 2 | 3 | The author and publisher of the book "Advanced Programming in the 4 | Unix Environment" have used their best efforts in preparing this 5 | software. These efforts include the development, research, and 6 | testing of the theories and programs to determine their effectiveness. 7 | The author and publisher make no warranty of any kind, express or 8 | implied, with regard to these programs or the documentation contained 9 | in the book. The author and publisher shall not be liable in any event 10 | for incidental or consequential damages in connection with, or arising 11 | out of, the furnishing, performance, or use of these programs. 12 | -------------------------------------------------------------------------------- /apue.3e/filedir/devrdev.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #ifdef SOLARIS 3 | #include 4 | #endif 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | int i; 10 | struct stat buf; 11 | 12 | for (i = 1; i < argc; i++) { 13 | printf("%s: ", argv[i]); 14 | if (stat(argv[i], &buf) < 0) { 15 | err_ret("stat error"); 16 | continue; 17 | } 18 | 19 | printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev)); 20 | 21 | if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) { 22 | printf(" (%s) rdev = %d/%d", 23 | (S_ISCHR(buf.st_mode)) ? "character" : "block", 24 | major(buf.st_rdev), minor(buf.st_rdev)); 25 | } 26 | printf("\n"); 27 | } 28 | 29 | exit(0); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /apue.3e/threads/threadid.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | pthread_t ntid; 5 | 6 | void 7 | printids(const char *s) 8 | { 9 | pid_t pid; 10 | pthread_t tid; 11 | 12 | pid = getpid(); 13 | tid = pthread_self(); 14 | printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid, 15 | (unsigned long)tid, (unsigned long)tid); 16 | } 17 | 18 | void * 19 | thr_fn(void *arg) 20 | { 21 | printids("new thread: "); 22 | return((void *)0); 23 | } 24 | 25 | int 26 | main(void) 27 | { 28 | int err; 29 | 30 | err = pthread_create(&ntid, NULL, thr_fn, NULL); 31 | if (err != 0) 32 | err_exit(err, "can't create thread"); 33 | printids("main thread:"); 34 | sleep(1); 35 | exit(0); 36 | } 37 | -------------------------------------------------------------------------------- /apue.3e/filedir/zap.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(int argc, char *argv[]) 6 | { 7 | int i, fd; 8 | struct stat statbuf; 9 | struct timespec times[2]; 10 | 11 | for (i = 1; i < argc; i++) { 12 | if (stat(argv[i], &statbuf) < 0) { /* fetch current times */ 13 | err_ret("%s: stat error", argv[i]); 14 | continue; 15 | } 16 | if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) { /* truncate */ 17 | err_ret("%s: open error", argv[i]); 18 | continue; 19 | } 20 | times[0] = statbuf.st_atim; 21 | times[1] = statbuf.st_mtim; 22 | if (futimens(fd, times) < 0) /* reset times */ 23 | err_ret("%s: futimens error", argv[i]); 24 | close(fd); 25 | } 26 | exit(0); 27 | } 28 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend/main.c: -------------------------------------------------------------------------------- 1 | #include "opend.h" 2 | #include 3 | 4 | int debug, oflag, client_size, log_to_stderr; 5 | char errmsg[MAXLINE]; 6 | char *pathname; 7 | Client *client = NULL; 8 | 9 | int 10 | main(int argc, char *argv[]) 11 | { 12 | int c; 13 | 14 | log_open("open.serv", LOG_PID, LOG_USER); 15 | 16 | opterr = 0; /* don't want getopt() writing to stderr */ 17 | while ((c = getopt(argc, argv, "d")) != EOF) { 18 | switch (c) { 19 | case 'd': /* debug */ 20 | debug = log_to_stderr = 1; 21 | break; 22 | 23 | case '?': 24 | err_quit("unrecognized option: -%c", optopt); 25 | } 26 | } 27 | 28 | if (debug == 0) 29 | daemonize("opend"); 30 | 31 | loop(); /* never returns */ 32 | } 33 | -------------------------------------------------------------------------------- /apue.3e/termios/settty.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | struct termios term; 8 | long vdisable; 9 | 10 | if (isatty(STDIN_FILENO) == 0) 11 | err_quit("standard input is not a terminal device"); 12 | 13 | if ((vdisable = fpathconf(STDIN_FILENO, _PC_VDISABLE)) < 0) 14 | err_quit("fpathconf error or _POSIX_VDISABLE not in effect"); 15 | 16 | if (tcgetattr(STDIN_FILENO, &term) < 0) /* fetch tty state */ 17 | err_sys("tcgetattr error"); 18 | 19 | term.c_cc[VINTR] = vdisable; /* disable INTR character */ 20 | term.c_cc[VEOF] = 2; /* EOF is Control-B */ 21 | 22 | if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term) < 0) 23 | err_sys("tcsetattr error"); 24 | 25 | exit(0); 26 | } 27 | -------------------------------------------------------------------------------- /apue.3e/advio/nonblockw.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | char buf[500000]; 6 | 7 | int 8 | main(void) 9 | { 10 | int ntowrite, nwrite; 11 | char *ptr; 12 | 13 | ntowrite = read(STDIN_FILENO, buf, sizeof(buf)); 14 | fprintf(stderr, "read %d bytes\n", ntowrite); 15 | 16 | set_fl(STDOUT_FILENO, O_NONBLOCK); /* set nonblocking */ 17 | 18 | ptr = buf; 19 | while (ntowrite > 0) { 20 | errno = 0; 21 | nwrite = write(STDOUT_FILENO, ptr, ntowrite); 22 | fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno); 23 | 24 | if (nwrite > 0) { 25 | ptr += nwrite; 26 | ntowrite -= nwrite; 27 | } 28 | } 29 | 30 | clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */ 31 | 32 | exit(0); 33 | } 34 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=../.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "solaris" 6 | EXTRALIBS=-lsocket -lnsl 7 | endif 8 | 9 | PROGS = opend.poll opend.select 10 | 11 | all: $(PROGS) 12 | 13 | opend.poll: main.o request.o cliargs.o client.o loop.poll.o $(LIBAPUE) 14 | $(CC) $(CFLAGS) -o opend.poll main.o cliargs.o client.o request.o loop.poll.o \ 15 | $(LDFLAGS) $(LDLIBS) 16 | 17 | opend.select: main.o request.o cliargs.o client.o loop.select.o $(LIBAPUE) 18 | $(CC) $(CFLAGS) -o opend.select main.o cliargs.o client.o request.o loop.select.o \ 19 | $(LDFLAGS) $(LDLIBS) 20 | 21 | clean: 22 | rm -f $(PROGS) $(TEMPFILES) *.o 23 | 24 | include $(ROOT)/Make.libapue.inc 25 | -------------------------------------------------------------------------------- /apue.3e/ipc2/sendmsg.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define MAXMSZ 512 5 | 6 | struct mymesg { 7 | long mtype; 8 | char mtext[MAXMSZ]; 9 | }; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | key_t key; 15 | long qid; 16 | size_t nbytes; 17 | struct mymesg m; 18 | 19 | if (argc != 3) { 20 | fprintf(stderr, "usage: sendmsg KEY message\n"); 21 | exit(1); 22 | } 23 | key = strtol(argv[1], NULL, 0); 24 | if ((qid = msgget(key, 0)) < 0) 25 | err_sys("can't open queue key %s", argv[1]); 26 | memset(&m, 0, sizeof(m)); 27 | strncpy(m.mtext, argv[2], MAXMSZ-1); 28 | nbytes = strlen(m.mtext); 29 | m.mtype = 1; 30 | if (msgsnd(qid, &m, nbytes, 0) < 0) 31 | err_sys("can't send message"); 32 | exit(0); 33 | } 34 | -------------------------------------------------------------------------------- /apue.3e/signals/tsleep2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | unsigned int sleep2(unsigned int); 4 | static void sig_int(int); 5 | 6 | int 7 | main(void) 8 | { 9 | unsigned int unslept; 10 | 11 | if (signal(SIGINT, sig_int) == SIG_ERR) 12 | err_sys("signal(SIGINT) error"); 13 | unslept = sleep2(5); 14 | printf("sleep2 returned: %u\n", unslept); 15 | exit(0); 16 | } 17 | 18 | static void 19 | sig_int(int signo) 20 | { 21 | int i, j; 22 | volatile int k; 23 | 24 | /* 25 | * Tune these loops to run for more than 5 seconds 26 | * on whatever system this test program is run. 27 | */ 28 | printf("\nsig_int starting\n"); 29 | for (i = 0; i < 300000; i++) 30 | for (j = 0; j < 4000; j++) 31 | k += i * j; 32 | printf("sig_int finished\n"); 33 | } 34 | -------------------------------------------------------------------------------- /apue.3e/sockets/clconn2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define MAXSLEEP 128 5 | 6 | int 7 | connect_retry(int domain, int type, int protocol, 8 | const struct sockaddr *addr, socklen_t alen) 9 | { 10 | int numsec, fd; 11 | 12 | /* 13 | * Try to connect with exponential backoff. 14 | */ 15 | for (numsec = 1; numsec <= MAXSLEEP; numsec <<= 1) { 16 | if ((fd = socket(domain, type, protocol)) < 0) 17 | return(-1); 18 | if (connect(fd, addr, alen) == 0) { 19 | /* 20 | * Connection accepted. 21 | */ 22 | return(fd); 23 | } 24 | close(fd); 25 | 26 | /* 27 | * Delay before trying again. 28 | */ 29 | if (numsec <= MAXSLEEP/2) 30 | sleep(numsec); 31 | } 32 | return(-1); 33 | } 34 | -------------------------------------------------------------------------------- /apue.3e/lib/prmask.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void 5 | pr_mask(const char *str) 6 | { 7 | sigset_t sigset; 8 | int errno_save; 9 | 10 | errno_save = errno; /* we can be called by signal handlers */ 11 | if (sigprocmask(0, NULL, &sigset) < 0) { 12 | err_ret("sigprocmask error"); 13 | } else { 14 | printf("%s", str); 15 | if (sigismember(&sigset, SIGINT)) 16 | printf(" SIGINT"); 17 | if (sigismember(&sigset, SIGQUIT)) 18 | printf(" SIGQUIT"); 19 | if (sigismember(&sigset, SIGUSR1)) 20 | printf(" SIGUSR1"); 21 | if (sigismember(&sigset, SIGALRM)) 22 | printf(" SIGALRM"); 23 | 24 | /* remaining signals can go here */ 25 | 26 | printf("\n"); 27 | } 28 | 29 | errno = errno_save; /* restore errno */ 30 | } 31 | -------------------------------------------------------------------------------- /apue.3e/proc/fork1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int globvar = 6; /* external variable in initialized data */ 4 | char buf[] = "a write to stdout\n"; 5 | 6 | int 7 | main(void) 8 | { 9 | int var; /* automatic variable on the stack */ 10 | pid_t pid; 11 | 12 | var = 88; 13 | if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) 14 | err_sys("write error"); 15 | printf("before fork\n"); /* we don't flush stdout */ 16 | 17 | if ((pid = fork()) < 0) { 18 | err_sys("fork error"); 19 | } else if (pid == 0) { /* child */ 20 | globvar++; /* modify variables */ 21 | var++; 22 | } else { 23 | sleep(2); /* parent */ 24 | } 25 | 26 | printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, 27 | var); 28 | exit(0); 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/lib/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for misc library. 3 | # 4 | ROOT=.. 5 | PLATFORM=$(shell $(ROOT)/systype.sh) 6 | include $(ROOT)/Make.defines.$(PLATFORM) 7 | 8 | LIBMISC = libapue.a 9 | OBJS = bufargs.o cliconn.o clrfl.o \ 10 | daemonize.o error.o errorlog.o lockreg.o locktest.o \ 11 | openmax.o pathalloc.o popen.o prexit.o prmask.o \ 12 | ptyfork.o ptyopen.o readn.o recvfd.o senderr.o sendfd.o \ 13 | servaccept.o servlisten.o setfd.o setfl.o signal.o signalintr.o \ 14 | sleepus.o spipe.o tellwait.o ttymodes.o writen.o 15 | 16 | all: $(LIBMISC) sleep.o 17 | 18 | $(LIBMISC): $(OBJS) 19 | $(AR) rv $(LIBMISC) $? 20 | $(RANLIB) $(LIBMISC) 21 | 22 | 23 | clean: 24 | rm -f *.o a.out core temp.* $(LIBMISC) 25 | 26 | include $(ROOT)/Make.libapue.inc 27 | -------------------------------------------------------------------------------- /Chapter15/exercise_12a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | const int NUM_ITERATIONS = 5; 9 | int i; 10 | 11 | for (i = 0; i < NUM_ITERATIONS; ++i) { 12 | /* picked /etc/passwd because it exists */ 13 | const key_t key = ftok("/etc/passwd", i); 14 | if (key < 0) { 15 | perror("ftok"); 16 | return 1; 17 | } 18 | 19 | const int queue_id = msgget(key, IPC_CREAT | 0666); 20 | /* Create the queue */ 21 | if (queue_id < 0) { 22 | perror("msgget"); 23 | return 1; 24 | } 25 | printf("queue_id: %d\n", queue_id); 26 | 27 | /* Delete the queue */ 28 | if (msgctl(queue_id, IPC_RMID, NULL) < 0) { 29 | perror("msgctl"); 30 | return 1; 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /apue.3e/termios/csize.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | struct termios term; 8 | 9 | if (tcgetattr(STDIN_FILENO, &term) < 0) 10 | err_sys("tcgetattr error"); 11 | 12 | switch (term.c_cflag & CSIZE) { 13 | case CS5: 14 | printf("5 bits/byte\n"); 15 | break; 16 | case CS6: 17 | printf("6 bits/byte\n"); 18 | break; 19 | case CS7: 20 | printf("7 bits/byte\n"); 21 | break; 22 | case CS8: 23 | printf("8 bits/byte\n"); 24 | break; 25 | default: 26 | printf("unknown bits/byte\n"); 27 | } 28 | 29 | term.c_cflag &= ~CSIZE; /* zero out the bits */ 30 | term.c_cflag |= CS8; /* set 8 bits/byte */ 31 | if (tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0) 32 | err_sys("tcsetattr error"); 33 | 34 | exit(0); 35 | } 36 | -------------------------------------------------------------------------------- /apue.3e/advio/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 rot13a 13 | MOREPROGS = rot13c2 14 | 15 | all: $(PROGS) $(MOREPROGS) lockfile.o 16 | 17 | rot13c2.c: rot13c2.c.in $(LIBAPUE) 18 | ./fixup.awk rot13a.c >xlate 19 | sed '/same/q' rot13c2.c.in >rot13c2.c 20 | cat xlate >>rot13c2.c 21 | sed '1,/same/d' rot13c2.c.in >>rot13c2.c 22 | 23 | %: %.c $(LIBAPUE) 24 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 25 | 26 | clean: 27 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o xlate rot13c2.c 28 | 29 | include $(ROOT)/Make.libapue.inc 30 | -------------------------------------------------------------------------------- /apue.3e/intro/shell1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | char buf[MAXLINE]; /* from apue.h */ 8 | pid_t pid; 9 | int status; 10 | 11 | printf("%% "); /* print prompt (printf requires %% to print %) */ 12 | while (fgets(buf, MAXLINE, stdin) != NULL) { 13 | if (buf[strlen(buf) - 1] == '\n') 14 | buf[strlen(buf) - 1] = 0; /* replace newline with null */ 15 | 16 | if ((pid = fork()) < 0) { 17 | err_sys("fork error"); 18 | } else if (pid == 0) { /* child */ 19 | execlp(buf, buf, (char *)0); 20 | err_ret("couldn't execute: %s", buf); 21 | exit(127); 22 | } 23 | 24 | /* parent */ 25 | if ((pid = waitpid(pid, &status, 0)) < 0) 26 | err_sys("waitpid error"); 27 | printf("%% "); 28 | } 29 | exit(0); 30 | } 31 | -------------------------------------------------------------------------------- /apue.3e/proc/system.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int 6 | system(const char *cmdstring) /* version without signal handling */ 7 | { 8 | pid_t pid; 9 | int status; 10 | 11 | if (cmdstring == NULL) 12 | return(1); /* always a command processor with UNIX */ 13 | 14 | if ((pid = fork()) < 0) { 15 | status = -1; /* probably out of processes */ 16 | } else if (pid == 0) { /* child */ 17 | execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 18 | _exit(127); /* execl error */ 19 | } else { /* parent */ 20 | while (waitpid(pid, &status, 0) < 0) { 21 | if (errno != EINTR) { 22 | status = -1; /* error other than EINTR from waitpid() */ 23 | break; 24 | } 25 | } 26 | } 27 | 28 | return(status); 29 | } 30 | -------------------------------------------------------------------------------- /apue.3e/termios/winch.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #ifndef TIOCGWINSZ 4 | #include 5 | #endif 6 | 7 | static void 8 | pr_winsize(int fd) 9 | { 10 | struct winsize size; 11 | 12 | if (ioctl(fd, TIOCGWINSZ, (char *) &size) < 0) 13 | err_sys("TIOCGWINSZ error"); 14 | printf("%d rows, %d columns\n", size.ws_row, size.ws_col); 15 | } 16 | 17 | static void 18 | sig_winch(int signo) 19 | { 20 | printf("SIGWINCH received\n"); 21 | pr_winsize(STDIN_FILENO); 22 | } 23 | 24 | int 25 | main(void) 26 | { 27 | if (isatty(STDIN_FILENO) == 0) 28 | exit(1); 29 | if (signal(SIGWINCH, sig_winch) == SIG_ERR) 30 | err_sys("signal error"); 31 | pr_winsize(STDIN_FILENO); /* print initial size */ 32 | for ( ; ; ) /* and sleep forever */ 33 | pause(); 34 | } 35 | -------------------------------------------------------------------------------- /apue.3e/ipc1/popen2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define PAGER "${PAGER:-more}" /* environment variable, or default */ 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | char line[MAXLINE]; 10 | FILE *fpin, *fpout; 11 | 12 | if (argc != 2) 13 | err_quit("usage: a.out "); 14 | if ((fpin = fopen(argv[1], "r")) == NULL) 15 | err_sys("can't open %s", argv[1]); 16 | 17 | if ((fpout = popen(PAGER, "w")) == NULL) 18 | err_sys("popen error"); 19 | 20 | /* copy argv[1] to pager */ 21 | while (fgets(line, MAXLINE, fpin) != NULL) { 22 | if (fputs(line, fpout) == EOF) 23 | err_sys("fputs error to pipe"); 24 | } 25 | if (ferror(fpin)) 26 | err_sys("fgets error"); 27 | if (pclose(fpout) == -1) 28 | err_sys("pclose error"); 29 | 30 | exit(0); 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open/main.c: -------------------------------------------------------------------------------- 1 | #include "open.h" 2 | #include 3 | 4 | #define BUFFSIZE 8192 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | int n, fd; 10 | char buf[BUFFSIZE], line[MAXLINE]; 11 | 12 | /* read filename to cat from stdin */ 13 | while (fgets(line, MAXLINE, stdin) != NULL) { 14 | if (line[strlen(line) - 1] == '\n') 15 | line[strlen(line) - 1] = 0; /* replace newline with null */ 16 | 17 | /* open the file */ 18 | if ((fd = csopen(line, O_RDONLY)) < 0) 19 | continue; /* csopen() prints error from server */ 20 | 21 | /* and cat to stdout */ 22 | while ((n = read(fd, buf, BUFFSIZE)) > 0) 23 | if (write(STDOUT_FILENO, buf, n) != n) 24 | err_sys("write error"); 25 | if (n < 0) 26 | err_sys("read error"); 27 | close(fd); 28 | } 29 | 30 | exit(0); 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/lib/nspipe.c: -------------------------------------------------------------------------------- 1 | /* Create a named stream pipe. Called by server on initialization. */ 2 | 3 | #include "apue.h" 4 | #include 5 | #include 6 | 7 | int /* returns 0 if all OK, -1 if error (with errno set) */ 8 | ns_pipe(const char *name, int fd[2]) 9 | { 10 | int len; 11 | struct sockaddr_un unix_addr; 12 | 13 | if (fd_pipe(fd) < 0) /* create unnamed stream pipe */ 14 | return(-1); 15 | 16 | unlink(name); /* remove the name, if it already exists */ 17 | 18 | memset(&unix_addr, 0, sizeof(unix_addr)); 19 | unix_addr.sun_family = AF_UNIX; 20 | strcpy(unix_addr.sun_path, name); 21 | len = strlen(unix_addr.sun_path) + sizeof(unix_addr.sun_family); 22 | 23 | return(bind(fd[0], (struct sockaddr *) &unix_addr, len)); 24 | /* fd[0] has the name bound to it */ 25 | } 26 | -------------------------------------------------------------------------------- /apue.3e/proc/exec1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | char *env_init[] = { "USER=unknown", "PATH=/tmp", NULL }; 5 | 6 | int 7 | main(void) 8 | { 9 | pid_t pid; 10 | 11 | if ((pid = fork()) < 0) { 12 | err_sys("fork error"); 13 | } else if (pid == 0) { /* specify pathname, specify environment */ 14 | if (execle("/home/sar/bin/echoall", "echoall", "myarg1", 15 | "MY ARG2", (char *)0, env_init) < 0) 16 | err_sys("execle error"); 17 | } 18 | 19 | if (waitpid(pid, NULL, 0) < 0) 20 | err_sys("wait error"); 21 | 22 | if ((pid = fork()) < 0) { 23 | err_sys("fork error"); 24 | } else if (pid == 0) { /* specify filename, inherit environment */ 25 | if (execlp("echoall", "echoall", "only 1 arg", (char *)0) < 0) 26 | err_sys("execlp error"); 27 | } 28 | 29 | exit(0); 30 | } 31 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open.fe/main.c: -------------------------------------------------------------------------------- 1 | #include "open.h" 2 | #include 3 | 4 | #define BUFFSIZE 8192 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | int n, fd; 10 | char buf[BUFFSIZE]; 11 | char line[MAXLINE]; 12 | 13 | /* read filename to cat from stdin */ 14 | while (fgets(line, MAXLINE, stdin) != NULL) { 15 | if (line[strlen(line) - 1] == '\n') 16 | line[strlen(line) - 1] = 0; /* replace newline with null */ 17 | 18 | /* open the file */ 19 | if ((fd = csopen(line, O_RDONLY)) < 0) 20 | continue; /* csopen() prints error from server */ 21 | 22 | /* and cat to stdout */ 23 | while ((n = read(fd, buf, BUFFSIZE)) > 0) 24 | if (write(STDOUT_FILENO, buf, n) != n) 25 | err_sys("write error"); 26 | if (n < 0) 27 | err_sys("read error"); 28 | close(fd); 29 | } 30 | 31 | exit(0); 32 | } 33 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend.fe/request.c: -------------------------------------------------------------------------------- 1 | #include "opend.h" 2 | #include 3 | 4 | void 5 | handle_request(char *buf, int nread, int fd) 6 | { 7 | int newfd; 8 | 9 | if (buf[nread-1] != 0) { 10 | snprintf(errmsg, MAXLINE-1, 11 | "request not null terminated: %*.*s\n", nread, nread, buf); 12 | send_err(fd, -1, errmsg); 13 | return; 14 | } 15 | if (buf_args(buf, cli_args) < 0) { /* parse args & set options */ 16 | send_err(fd, -1, errmsg); 17 | return; 18 | } 19 | if ((newfd = open(pathname, oflag)) < 0) { 20 | snprintf(errmsg, MAXLINE-1, "can't open %s: %s\n", pathname, 21 | strerror(errno)); 22 | send_err(fd, -1, errmsg); 23 | return; 24 | } 25 | if (send_fd(fd, newfd) < 0) /* send the descriptor */ 26 | err_sys("send_fd error"); 27 | close(newfd); /* we're done with descriptor */ 28 | } 29 | -------------------------------------------------------------------------------- /apue.3e/threads/condvar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct msg { 4 | struct msg *m_next; 5 | /* ... more stuff here ... */ 6 | }; 7 | 8 | struct msg *workq; 9 | 10 | pthread_cond_t qready = PTHREAD_COND_INITIALIZER; 11 | 12 | pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; 13 | 14 | void 15 | process_msg(void) 16 | { 17 | struct msg *mp; 18 | 19 | for (;;) { 20 | pthread_mutex_lock(&qlock); 21 | while (workq == NULL) 22 | pthread_cond_wait(&qready, &qlock); 23 | mp = workq; 24 | workq = mp->m_next; 25 | pthread_mutex_unlock(&qlock); 26 | /* now process the message mp */ 27 | } 28 | } 29 | 30 | void 31 | enqueue_msg(struct msg *mp) 32 | { 33 | pthread_mutex_lock(&qlock); 34 | mp->m_next = workq; 35 | workq = mp; 36 | pthread_mutex_unlock(&qlock); 37 | pthread_cond_signal(&qready); 38 | } 39 | -------------------------------------------------------------------------------- /Chapter10/exercise_10.c: -------------------------------------------------------------------------------- 1 | /* 2 | 10. Write a program that calls `sleep(60)` in an infinite loop. Every five 3 | times through the loop (every 5 minutes), fetch the current time of day 4 | and print the `tm_sec` field. Run the program overnight and explain the 5 | results. How would a program such as the `cron` daemon, which runs every 6 | minute on the minute, handle this situation? 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int 14 | main(void) 15 | { 16 | int i; 17 | for (i = 0;; ++i) { 18 | time_t current_time; 19 | 20 | time(¤t_time); 21 | const struct tm* const now = gmtime(¤t_time); 22 | 23 | if (i % 5 == 0) { 24 | printf("%d\n", now->tm_sec); 25 | fflush(stdout); 26 | } 27 | 28 | sleep(60); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apue.3e/signals/child.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void sig_cld(int); 5 | 6 | int 7 | main() 8 | { 9 | pid_t pid; 10 | 11 | if (signal(SIGCLD, sig_cld) == SIG_ERR) 12 | perror("signal error"); 13 | if ((pid = fork()) < 0) { 14 | perror("fork error"); 15 | } else if (pid == 0) { /* child */ 16 | sleep(2); 17 | _exit(0); 18 | } 19 | 20 | pause(); /* parent */ 21 | exit(0); 22 | } 23 | 24 | static void 25 | sig_cld(int signo) /* interrupts pause() */ 26 | { 27 | pid_t pid; 28 | int status; 29 | 30 | printf("SIGCLD received\n"); 31 | 32 | if (signal(SIGCLD, sig_cld) == SIG_ERR) /* reestablish handler */ 33 | perror("signal error"); 34 | 35 | if ((pid = wait(&status)) < 0) /* fetch child status */ 36 | perror("wait error"); 37 | 38 | printf("pid = %d\n", pid); 39 | } 40 | -------------------------------------------------------------------------------- /apue.3e/signals/setops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * usually defines NSIG to include signal number 0. 6 | */ 7 | #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG) 8 | 9 | int 10 | sigaddset(sigset_t *set, int signo) 11 | { 12 | if (SIGBAD(signo)) { 13 | errno = EINVAL; 14 | return(-1); 15 | } 16 | *set |= 1 << (signo - 1); /* turn bit on */ 17 | return(0); 18 | } 19 | 20 | int 21 | sigdelset(sigset_t *set, int signo) 22 | { 23 | if (SIGBAD(signo)) { 24 | errno = EINVAL; 25 | return(-1); 26 | } 27 | *set &= ~(1 << (signo - 1)); /* turn bit off */ 28 | return(0); 29 | } 30 | 31 | int 32 | sigismember(const sigset_t *set, int signo) 33 | { 34 | if (SIGBAD(signo)) { 35 | errno = EINVAL; 36 | return(-1); 37 | } 38 | return((*set & (1 << (signo - 1))) != 0); 39 | } 40 | -------------------------------------------------------------------------------- /Chapter18/figure_18.11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int 7 | main(void) 8 | { 9 | struct termios term; 10 | 11 | if (tcgetattr(STDIN_FILENO, &term) < 0) 12 | perror("tcgetattr error"); 13 | 14 | switch (term.c_cflag & CSIZE) { 15 | case CS5: 16 | printf("5 bits/byte\n"); 17 | break; 18 | case CS6: 19 | printf("6 bits/byte\n"); 20 | break; 21 | case CS7: 22 | printf("7 bits/byte\n"); 23 | break; 24 | case CS8: 25 | printf("8 bits/byte\n"); 26 | break; 27 | default: 28 | printf("unknown bits/byte\n"); 29 | } 30 | 31 | term.c_cflag &= ~CSIZE; /* zero out the bits */ 32 | term.c_cflag |= CS8; /* set 8 bits/byte */ 33 | 34 | if (tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0) 35 | perror("tcsetattr error"); 36 | 37 | exit(0); 38 | } 39 | -------------------------------------------------------------------------------- /apue.3e/ipc1/tellwait.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static int pfd1[2], pfd2[2]; 4 | 5 | void 6 | TELL_WAIT(void) 7 | { 8 | if (pipe(pfd1) < 0 || pipe(pfd2) < 0) 9 | err_sys("pipe error"); 10 | } 11 | 12 | void 13 | TELL_PARENT(pid_t pid) 14 | { 15 | if (write(pfd2[1], "c", 1) != 1) 16 | err_sys("write error"); 17 | } 18 | 19 | void 20 | WAIT_PARENT(void) 21 | { 22 | char c; 23 | 24 | if (read(pfd1[0], &c, 1) != 1) 25 | err_sys("read error"); 26 | 27 | if (c != 'p') 28 | err_quit("WAIT_PARENT: incorrect data"); 29 | } 30 | 31 | void 32 | TELL_CHILD(pid_t pid) 33 | { 34 | if (write(pfd1[1], "p", 1) != 1) 35 | err_sys("write error"); 36 | } 37 | 38 | void 39 | WAIT_CHILD(void) 40 | { 41 | char c; 42 | 43 | if (read(pfd2[0], &c, 1) != 1) 44 | err_sys("read error"); 45 | 46 | if (c != 'c') 47 | err_quit("WAIT_CHILD: incorrect data"); 48 | } 49 | -------------------------------------------------------------------------------- /apue.3e/filedir/filetype.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(int argc, char *argv[]) 5 | { 6 | int i; 7 | struct stat buf; 8 | char *ptr; 9 | 10 | for (i = 1; i < argc; i++) { 11 | printf("%s: ", argv[i]); 12 | if (lstat(argv[i], &buf) < 0) { 13 | err_ret("lstat error"); 14 | continue; 15 | } 16 | if (S_ISREG(buf.st_mode)) 17 | ptr = "regular"; 18 | else if (S_ISDIR(buf.st_mode)) 19 | ptr = "directory"; 20 | else if (S_ISCHR(buf.st_mode)) 21 | ptr = "character special"; 22 | else if (S_ISBLK(buf.st_mode)) 23 | ptr = "block special"; 24 | else if (S_ISFIFO(buf.st_mode)) 25 | ptr = "fifo"; 26 | else if (S_ISLNK(buf.st_mode)) 27 | ptr = "symbolic link"; 28 | else if (S_ISSOCK(buf.st_mode)) 29 | ptr = "socket"; 30 | else 31 | ptr = "** unknown mode **"; 32 | printf("%s\n", ptr); 33 | } 34 | exit(0); 35 | } 36 | -------------------------------------------------------------------------------- /Chapter14/exercise_7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static int 6 | make_non_blocking(const int fd) 7 | { 8 | const int flags = fcntl(fd, F_GETFL); 9 | if (flags < 0) { 10 | perror("fcntl"); 11 | return -1; 12 | } 13 | 14 | return fcntl(fd, F_SETFL, flags | O_NONBLOCK); 15 | } 16 | 17 | int 18 | main(void) 19 | { 20 | int retval = 1; 21 | int pipe_fds[2] = {}; 22 | 23 | if (pipe(pipe_fds) < 0) { 24 | perror("pipe"); 25 | return 1; 26 | } 27 | 28 | // Make the write-end of the pipe non-blocking 29 | if (make_non_blocking(pipe_fds[1]) < 0) { 30 | goto close_pipe; 31 | } 32 | 33 | 34 | int i; 35 | for (i = 0; write(pipe_fds[1], "a", 1) == 1; ++i); 36 | 37 | printf("pipe size: %d\n", i); 38 | 39 | retval = 0; 40 | 41 | close_pipe: 42 | close(pipe_fds[0]); 43 | close(pipe_fds[1]); 44 | 45 | return retval; 46 | } 47 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend/opend.h: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define CS_OPEN "/tmp/opend.socket" /* well-known name */ 5 | #define CL_OPEN "open" /* client's request for server */ 6 | 7 | extern int debug; /* nonzero if interactive (not daemon) */ 8 | extern char errmsg[]; /* error message string to return to client */ 9 | extern int oflag; /* open flag: O_xxx ... */ 10 | extern char *pathname; /* of file to open for client */ 11 | 12 | typedef struct { /* one Client struct per connected client */ 13 | int fd; /* fd, or -1 if available */ 14 | uid_t uid; 15 | } Client; 16 | 17 | extern Client *client; /* ptr to malloc'ed array */ 18 | extern int client_size; /* # entries in client[] array */ 19 | 20 | int cli_args(int, char **); 21 | int client_add(int, uid_t); 22 | void client_del(int); 23 | void loop(void); 24 | void handle_request(char *, int, int, uid_t); 25 | -------------------------------------------------------------------------------- /apue.3e/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 | %: %.c $(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 | -------------------------------------------------------------------------------- /Chapter04/exercise_16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define PATH_ELEMENT "./0123456789" 8 | 9 | int 10 | main(const int argc, const char* const argv[]) 11 | { 12 | printf("PATH_MAX: %d\n", PATH_MAX); 13 | 14 | char path[PATH_MAX + 20]; 15 | int len = strlen("/tmp"); 16 | 17 | if (chdir("/tmp") < 0) { 18 | perror("chdir"); 19 | return 1; 20 | } 21 | 22 | while (len < sizeof(path)) { 23 | if (mkdir(PATH_ELEMENT, 0755) < 0) { 24 | perror("mkdir"); 25 | return 1; 26 | } 27 | if (chdir(PATH_ELEMENT) < 0) { 28 | perror("chdir"); 29 | return 1; 30 | } 31 | if (getcwd(path, sizeof(path) - 1) < 0) { 32 | perror("getcwd"); 33 | } 34 | 35 | // -1 to elminate the leading dot 36 | len += strlen(PATH_ELEMENT) - 1; 37 | } 38 | 39 | printf("%s\n", path); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /apue.3e/exercises/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "freebsd" 6 | GETPW = getpw44bsd 7 | FMEM = fmemopen.o 8 | EXTRALIBS=-pthread 9 | endif 10 | ifeq "$(PLATFORM)" "linux" 11 | GETPW = getpwsvr4 12 | FMEM = 13 | EXTRALIBS=-pthread 14 | endif 15 | ifeq "$(PLATFORM)" "macos" 16 | GETPW = getpw44bsd 17 | FMEM = fmemopen.o 18 | endif 19 | ifeq "$(PLATFORM)" "solaris" 20 | GETPW = getpwsvr4 21 | FMEM = 22 | endif 23 | 24 | PROGS = bo fifo1 getlogin goodexit longpath pendlock prtime sizepipe vfork3 zombie 25 | 26 | all: $(PROGS) asyncsocket.o $(FMEM) openmax.o sleep.o sleepus_poll.o sleepus_select.o $(GETPW) 27 | 28 | %: %.c $(LIBAPUE) 29 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 30 | 31 | clean: 32 | rm -f $(PROGS) $(TEMPFILES) *.o $(GETPW) 33 | 34 | include $(ROOT)/Make.libapue.inc 35 | -------------------------------------------------------------------------------- /apue.3e/signals/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | CLD = 6 | 7 | ifeq "$(PLATFORM)" "linux" 8 | CLD = child 9 | endif 10 | ifeq "$(PLATFORM)" "solaris" 11 | CLD = child 12 | endif 13 | 14 | PROGS = critical mask read1 read2 reenter sigtstp sigusr suspend1 suspend2 15 | MOREPROGS = systest2 tsleep2 16 | 17 | all: $(PROGS) $(MOREPROGS) abort.o sleep1.o sleep2.o system.o $(CLD) 18 | 19 | %: %.c $(LIBAPUE) 20 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 21 | 22 | tsleep2: tsleep2.o sleep2.o $(LIBAPUE) 23 | $(CC) $(CFLAGS) -o tsleep2 tsleep2.o sleep2.o $(LDFLAGS) $(LDLIBS) 24 | 25 | systest2: systest2.o system.o $(LIBAPUE) 26 | $(CC) $(CFLAGS) -o systest2 systest2.o system.o $(LDFLAGS) $(LDLIBS) 27 | 28 | clean: 29 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o file.hole $(CLD) 30 | 31 | include $(ROOT)/Make.libapue.inc 32 | -------------------------------------------------------------------------------- /Chapter08/exercise_6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int 8 | main(void) 9 | { 10 | const pid_t pid = fork(); 11 | if (pid < 0) { 12 | perror("fork"); 13 | return 1; 14 | } 15 | 16 | if (pid == 0) { 17 | // Child terminates 18 | return 0; 19 | } 20 | 21 | // We could have registered for SIGCHLD and waited to receive that 22 | // signal, but for simplicity we'll just sleep "long enough" for 23 | // the child to start and terminate 24 | sleep(2); 25 | 26 | char buffer[80]; 27 | int status = 0; 28 | 29 | snprintf(buffer, sizeof(buffer), "ps -p %d", pid); 30 | system(buffer); 31 | 32 | // This will reap the zombie. If we didn't do this, when the process 33 | // terminated, the zombie would get re-parented to `init`, and `init` 34 | // would reap it. 35 | wait(&status); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Chapter17/figure_17.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define err_sys(fmt, ...) fprintf(stderr, (fmt "\n"), ##__VA_ARGS__) 7 | 8 | #define MAXMSZ 512 9 | 10 | struct mymesg { 11 | long mtype; 12 | char mtext[MAXMSZ]; 13 | }; 14 | 15 | int 16 | main(int argc, char* argv[]) 17 | { 18 | key_t key; 19 | long qid; 20 | size_t nbytes; 21 | struct mymesg m; 22 | 23 | if (argc != 3) { 24 | fprintf(stderr, "usage: %s \n", argv[0]); 25 | exit(1); 26 | } 27 | 28 | key = strtol(argv[1], NULL, 0); 29 | if ((qid = msgget(key, 0)) < 0) 30 | err_sys("Can't open queue key %s", argv[1]); 31 | 32 | memset(&m, 0, sizeof(m)); 33 | strncpy(m.mtext, argv[2], MAXMSZ - 1); 34 | nbytes = strlen(m.mtext); 35 | m.mtype = 1; 36 | 37 | if (msgsnd(qid, &m, nbytes, 0) < 0) 38 | err_sys("can't send message"); 39 | 40 | exit(0); 41 | } 42 | -------------------------------------------------------------------------------- /apue.3e/environ/cmd1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #define TOK_ADD 5 4 | 5 | void do_line(char *); 6 | void cmd_add(void); 7 | int get_token(void); 8 | 9 | int 10 | main(void) 11 | { 12 | char line[MAXLINE]; 13 | 14 | while (fgets(line, MAXLINE, stdin) != NULL) 15 | do_line(line); 16 | exit(0); 17 | } 18 | 19 | char *tok_ptr; /* global pointer for get_token() */ 20 | 21 | void 22 | do_line(char *ptr) /* process one line of input */ 23 | { 24 | int cmd; 25 | 26 | tok_ptr = ptr; 27 | while ((cmd = get_token()) > 0) { 28 | switch (cmd) { /* one case for each command */ 29 | case TOK_ADD: 30 | cmd_add(); 31 | break; 32 | } 33 | } 34 | } 35 | 36 | void 37 | cmd_add(void) 38 | { 39 | int token; 40 | 41 | token = get_token(); 42 | /* rest of processing for this command */ 43 | } 44 | 45 | int 46 | get_token(void) 47 | { 48 | /* fetch next token from line pointed to by tok_ptr */ 49 | } 50 | -------------------------------------------------------------------------------- /apue.3e/stdio/mkstemp.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void make_temp(char *template); 5 | 6 | int 7 | main() 8 | { 9 | char good_template[] = "/tmp/dirXXXXXX"; /* right way */ 10 | char *bad_template = "/tmp/dirXXXXXX"; /* wrong way*/ 11 | 12 | printf("trying to create first temp file...\n"); 13 | make_temp(good_template); 14 | printf("trying to create second temp file...\n"); 15 | make_temp(bad_template); 16 | exit(0); 17 | } 18 | 19 | void 20 | make_temp(char *template) 21 | { 22 | int fd; 23 | struct stat sbuf; 24 | 25 | if ((fd = mkstemp(template)) < 0) 26 | err_sys("can't create temp file"); 27 | printf("temp name = %s\n", template); 28 | close(fd); 29 | if (stat(template, &sbuf) < 0) { 30 | if (errno == ENOENT) 31 | printf("file doesn't exist\n"); 32 | else 33 | err_sys("stat failed"); 34 | } else { 35 | printf("file exists\n"); 36 | unlink(template); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /apue.3e/db/apue_db.h: -------------------------------------------------------------------------------- 1 | #ifndef _APUE_DB_H 2 | #define _APUE_DB_H 3 | 4 | typedef void * DBHANDLE; 5 | 6 | DBHANDLE db_open(const char *, int, ...); 7 | void db_close(DBHANDLE); 8 | char *db_fetch(DBHANDLE, const char *); 9 | int db_store(DBHANDLE, const char *, const char *, int); 10 | int db_delete(DBHANDLE, const char *); 11 | void db_rewind(DBHANDLE); 12 | char *db_nextrec(DBHANDLE, char *); 13 | 14 | /* 15 | * Flags for db_store(). 16 | */ 17 | #define DB_INSERT 1 /* insert new record only */ 18 | #define DB_REPLACE 2 /* replace existing record */ 19 | #define DB_STORE 3 /* replace or insert */ 20 | 21 | /* 22 | * Implementation limits. 23 | */ 24 | #define IDXLEN_MIN 6 /* key, sep, start, sep, length, \n */ 25 | #define IDXLEN_MAX 1024 /* arbitrary */ 26 | #define DATLEN_MIN 2 /* data byte, newline */ 27 | #define DATLEN_MAX 1024 /* arbitrary */ 28 | 29 | #endif /* _APUE_DB_H */ 30 | -------------------------------------------------------------------------------- /Chapter15/exercise_12b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct { 6 | long mtype; 7 | char mtext[32]; 8 | } message_t; 9 | 10 | int 11 | main(void) 12 | { 13 | const int NUM_ITERATIONS = 5; 14 | int i; 15 | 16 | for (i = 0; i < NUM_ITERATIONS; ++i) { 17 | /* picked /etc/passwd because it exists */ 18 | const key_t key = ftok("/etc/passwd", i); 19 | if (key < 0) { 20 | perror("ftok"); 21 | return 1; 22 | } 23 | 24 | const int queue_id = msgget(key, 25 | IPC_CREAT | IPC_PRIVATE | 0666); 26 | /* Create the queue */ 27 | if (queue_id < 0) { 28 | perror("msgget"); 29 | return 1; 30 | } 31 | 32 | const message_t msg = { 33 | .mtype = 1, 34 | .mtext = "Hello, world!", 35 | }; 36 | 37 | if (msgsnd(queue_id, &msg, sizeof(msg.mtext), 0) < 0) { 38 | perror("msgsnd"); 39 | return 1; 40 | } 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /apue.3e/daemons/single.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define LOCKFILE "/var/run/daemon.pid" 11 | #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 12 | 13 | extern int lockfile(int); 14 | 15 | int 16 | already_running(void) 17 | { 18 | int fd; 19 | char buf[16]; 20 | 21 | fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE); 22 | if (fd < 0) { 23 | syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno)); 24 | exit(1); 25 | } 26 | if (lockfile(fd) < 0) { 27 | if (errno == EACCES || errno == EAGAIN) { 28 | close(fd); 29 | return(1); 30 | } 31 | syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno)); 32 | exit(1); 33 | } 34 | ftruncate(fd, 0); 35 | sprintf(buf, "%ld", (long)getpid()); 36 | write(fd, buf, strlen(buf)+1); 37 | return(0); 38 | } 39 | -------------------------------------------------------------------------------- /apue.3e/threads/timedlock.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | int err; 8 | struct timespec tout; 9 | struct tm *tmp; 10 | char buf[64]; 11 | pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 12 | 13 | pthread_mutex_lock(&lock); 14 | printf("mutex is locked\n"); 15 | clock_gettime(CLOCK_REALTIME, &tout); 16 | tmp = localtime(&tout.tv_sec); 17 | strftime(buf, sizeof(buf), "%r", tmp); 18 | printf("current time is %s\n", buf); 19 | tout.tv_sec += 10; /* 10 seconds from now */ 20 | /* caution: this could lead to deadlock */ 21 | err = pthread_mutex_timedlock(&lock, &tout); 22 | clock_gettime(CLOCK_REALTIME, &tout); 23 | tmp = localtime(&tout.tv_sec); 24 | strftime(buf, sizeof(buf), "%r", tmp); 25 | printf("the time is now %s\n", buf); 26 | if (err == 0) 27 | printf("mutex locked again!\n"); 28 | else 29 | printf("can't lock mutex again: %s\n", strerror(err)); 30 | exit(0); 31 | } 32 | -------------------------------------------------------------------------------- /apue.3e/printer/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | EXTRA= 5 | 6 | ifeq "$(PLATFORM)" "solaris" 7 | EXTRALIBS=-lsocket -lnsl -lrt -lpthread 8 | else 9 | EXTRALIBS=-pthread 10 | endif 11 | 12 | PROGS = print printd 13 | HDRS = print.h ipp.h 14 | 15 | all: $(PROGS) 16 | 17 | util.o: util.c $(HDRS) 18 | 19 | print.o: print.c $(HDRS) 20 | 21 | printd.o: printd.c $(HDRS) 22 | 23 | print: print.o util.o $(ROOT)/sockets/clconn2.o $(LIBAPUE) 24 | $(CC) $(CFLAGS) -o print print.o util.o $(ROOT)/sockets/clconn2.o $(LDFLAGS) $(LDDIR) $(LDLIBS) 25 | 26 | printd: printd.o util.o $(ROOT)/sockets/clconn2.o $(ROOT)/sockets/initsrv2.o $(LIBAPUE) 27 | $(CC) $(CFLAGS) -o printd printd.o util.o $(ROOT)/sockets/clconn2.o $(ROOT)/sockets/initsrv2.o \ 28 | $(LDFLAGS) $(LDDIR) $(LDLIBS) 29 | 30 | clean: 31 | rm -f $(PROGS) $(TEMPFILES) *.o 32 | 33 | include $(ROOT)/Make.libapue.inc 34 | -------------------------------------------------------------------------------- /apue.3e/ipc2/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "freebsd" 6 | EXTRALIBS=-pthread 7 | endif 8 | ifeq "$(PLATFORM)" "linux" 9 | EXTRALIBS=-pthread 10 | endif 11 | ifeq "$(PLATFORM)" "solaris" 12 | EXTRALIBS=-lsocket -lnsl 13 | endif 14 | 15 | PROGS = bindunix pollmsg sendmsg 16 | FDPASS = 17 | 18 | ifeq "$(PLATFORM)" "linux" 19 | FDPASS = recvfd2.o sendfd2.o 20 | endif 21 | ifeq "$(PLATFORM)" "freebsd" 22 | FDPASS = recvfd2.o sendfd2.o 23 | endif 24 | 25 | all: $(PROGS) $(FDPASS) 26 | for i in open opend open.fe opend.fe; do \ 27 | (cd $$i && $(MAKE) ) || exit 1; \ 28 | done 29 | 30 | %: %.c $(LIBAPUE) 31 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 32 | 33 | clean: 34 | rm -f $(PROGS) $(TEMPFILES) *.o 35 | for i in open opend open.fe opend.fe; do \ 36 | (cd $$i && $(MAKE) clean) || exit 1; \ 37 | done 38 | 39 | include $(ROOT)/Make.libapue.inc 40 | -------------------------------------------------------------------------------- /Chapter04/create_sparse_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define FOUR_GB (1024UL * 1024UL * 1024UL * 4UL) 9 | 10 | int 11 | main(const int argc, const char* const argv[]) 12 | { 13 | int exit_status = 1; 14 | 15 | if (argc < 2) { 16 | fprintf(stderr, "Usage: %s \n", argv[0]); 17 | return 1; 18 | } 19 | 20 | const int fd = open(argv[1], O_CREAT | O_WRONLY, 0644); 21 | if (fd < 0) { 22 | perror("open"); 23 | return 1; 24 | } 25 | 26 | if (write(fd, "hi", strlen("hi")) < 0) { 27 | perror("write"); 28 | goto done; 29 | } 30 | 31 | if (lseek(fd, FOUR_GB, SEEK_CUR) < 0) { 32 | perror("lseek"); 33 | goto done; 34 | } 35 | 36 | if (write(fd, "ho", strlen("ho")) < 0) { 37 | perror("write"); 38 | goto done; 39 | } 40 | 41 | exit_status = 0; 42 | 43 | done: 44 | close(fd); 45 | return exit_status; 46 | } 47 | -------------------------------------------------------------------------------- /apue.3e/threads/exitstatus.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | void * 5 | thr_fn1(void *arg) 6 | { 7 | printf("thread 1 returning\n"); 8 | return((void *)1); 9 | } 10 | 11 | void * 12 | thr_fn2(void *arg) 13 | { 14 | printf("thread 2 exiting\n"); 15 | pthread_exit((void *)2); 16 | } 17 | 18 | int 19 | main(void) 20 | { 21 | int err; 22 | pthread_t tid1, tid2; 23 | void *tret; 24 | 25 | err = pthread_create(&tid1, NULL, thr_fn1, NULL); 26 | if (err != 0) 27 | err_exit(err, "can't create thread 1"); 28 | err = pthread_create(&tid2, NULL, thr_fn2, NULL); 29 | if (err != 0) 30 | err_exit(err, "can't create thread 2"); 31 | err = pthread_join(tid1, &tret); 32 | if (err != 0) 33 | err_exit(err, "can't join with thread 1"); 34 | printf("thread 1 exit code %ld\n", (long)tret); 35 | err = pthread_join(tid2, &tret); 36 | if (err != 0) 37 | err_exit(err, "can't join with thread 2"); 38 | printf("thread 2 exit code %ld\n", (long)tret); 39 | exit(0); 40 | } 41 | -------------------------------------------------------------------------------- /apue.3e/fileio/fileflags.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(int argc, char *argv[]) 6 | { 7 | int val; 8 | 9 | if (argc != 2) 10 | err_quit("usage: a.out "); 11 | 12 | if ((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0) 13 | err_sys("fcntl error for fd %d", atoi(argv[1])); 14 | 15 | switch (val & O_ACCMODE) { 16 | case O_RDONLY: 17 | printf("read only"); 18 | break; 19 | 20 | case O_WRONLY: 21 | printf("write only"); 22 | break; 23 | 24 | case O_RDWR: 25 | printf("read write"); 26 | break; 27 | 28 | default: 29 | err_dump("unknown access mode"); 30 | } 31 | 32 | if (val & O_APPEND) 33 | printf(", append"); 34 | if (val & O_NONBLOCK) 35 | printf(", nonblocking"); 36 | if (val & O_SYNC) 37 | printf(", synchronous writes"); 38 | 39 | #if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC) && (O_FSYNC != O_SYNC) 40 | if (val & O_FSYNC) 41 | printf(", synchronous writes"); 42 | #endif 43 | 44 | putchar('\n'); 45 | exit(0); 46 | } 47 | -------------------------------------------------------------------------------- /apue.3e/proc/wait1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | pid_t pid; 8 | int status; 9 | 10 | if ((pid = fork()) < 0) 11 | err_sys("fork error"); 12 | else if (pid == 0) /* child */ 13 | exit(7); 14 | 15 | if (wait(&status) != pid) /* wait for child */ 16 | err_sys("wait error"); 17 | pr_exit(status); /* and print its status */ 18 | 19 | if ((pid = fork()) < 0) 20 | err_sys("fork error"); 21 | else if (pid == 0) /* child */ 22 | abort(); /* generates SIGABRT */ 23 | 24 | if (wait(&status) != pid) /* wait for child */ 25 | err_sys("wait error"); 26 | pr_exit(status); /* and print its status */ 27 | 28 | if ((pid = fork()) < 0) 29 | err_sys("fork error"); 30 | else if (pid == 0) /* child */ 31 | status /= 0; /* divide by 0 generates SIGFPE */ 32 | 33 | if (wait(&status) != pid) /* wait for child */ 34 | err_sys("wait error"); 35 | pr_exit(status); /* and print its status */ 36 | 37 | exit(0); 38 | } 39 | -------------------------------------------------------------------------------- /Chapter04/exercise_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int 8 | main(const int argc, const char *argv[]) 9 | { 10 | int i; 11 | 12 | for (i = 1; i < argc; i++) { 13 | struct stat buf = {}; 14 | const char *ptr; 15 | 16 | printf("%s: ", argv[i]); 17 | if (stat(argv[i], &buf) < 0) { 18 | perror("lstat error"); 19 | continue; 20 | } 21 | 22 | if (S_ISREG(buf.st_mode)) 23 | ptr = "regular"; 24 | else if (S_ISDIR(buf.st_mode)) 25 | ptr = "directory"; 26 | else if (S_ISCHR(buf.st_mode)) 27 | ptr = "character special"; 28 | else if (S_ISBLK(buf.st_mode)) 29 | ptr = "block special"; 30 | else if (S_ISFIFO(buf.st_mode)) 31 | ptr = "fifo"; 32 | else if (S_ISLNK(buf.st_mode)) 33 | ptr = "symbolic link"; 34 | else if (S_ISSOCK(buf.st_mode)) 35 | ptr = "socket"; 36 | else 37 | ptr = "** unknown mode **"; 38 | 39 | printf("%s\n", ptr); 40 | } 41 | 42 | exit(0); 43 | } 44 | -------------------------------------------------------------------------------- /Chapter10/exercise_12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static void 7 | sig_handler(const int signo) 8 | { 9 | #define MESSAGE_TEXT "signal received\n" 10 | write(STDERR_FILENO, MESSAGE_TEXT, sizeof(MESSAGE_TEXT) - 1); 11 | #undef MESSAGE_TEXT 12 | } 13 | 14 | #define BUFFER_SIZE (1024 * 1024 * 1024) 15 | 16 | int 17 | main(void) 18 | { 19 | // Allocate a 1GB buffer 20 | char* const buffer = calloc(sizeof(char), BUFFER_SIZE); 21 | if (buffer == NULL) { 22 | perror("calloc"); 23 | return 1; 24 | } 25 | 26 | FILE* const file = fopen("/tmp/ex12.out", "w"); 27 | if (file == NULL) { 28 | perror("fopen"); 29 | free(buffer); 30 | return 1; 31 | } 32 | 33 | signal(SIGALRM, sig_handler); 34 | alarm(1); 35 | 36 | const size_t written = fwrite(buffer, BUFFER_SIZE, 1, file); 37 | if (written != 1) { 38 | fprintf(stderr, "Failed to write buffer\n"); 39 | } 40 | 41 | fclose(file); 42 | free(buffer); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /apue.3e/standards/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 | -------------------------------------------------------------------------------- /apue.3e/proc/test1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | int 4 | main(void) 5 | { 6 | pid_t pid; 7 | 8 | if ((pid = fork()) < 0) 9 | err_sys("fork error"); 10 | else if (pid != 0) { /* parent */ 11 | sleep(2); 12 | exit(2); /* terminate with exit status 2 */ 13 | } 14 | 15 | if ((pid = fork()) < 0) 16 | err_sys("fork error"); 17 | else if (pid != 0) { /* first child */ 18 | sleep(4); 19 | abort(); /* terminate with core dump */ 20 | } 21 | 22 | if ((pid = fork()) < 0) 23 | err_sys("fork error"); 24 | else if (pid != 0) { /* second child */ 25 | execl("/bin/dd", "dd", "if=/etc/passwd", "of=/dev/null", NULL); 26 | exit(7); /* shouldn't get here */ 27 | } 28 | 29 | if ((pid = fork()) < 0) 30 | err_sys("fork error"); 31 | else if (pid != 0) { /* third child */ 32 | sleep(8); 33 | exit(0); /* normal exit */ 34 | } 35 | 36 | sleep(6); /* fourth child */ 37 | kill(getpid(), SIGKILL); /* terminate w/signal, no core dump */ 38 | exit(6); /* shouldn't get here */ 39 | } 40 | -------------------------------------------------------------------------------- /apue.3e/advio/deadlock.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void 5 | lockabyte(const char *name, int fd, off_t offset) 6 | { 7 | if (writew_lock(fd, offset, SEEK_SET, 1) < 0) 8 | err_sys("%s: writew_lock error", name); 9 | printf("%s: got the lock, byte %lld\n", name, (long long)offset); 10 | } 11 | 12 | int 13 | main(void) 14 | { 15 | int fd; 16 | pid_t pid; 17 | 18 | /* 19 | * Create a file and write two bytes to it. 20 | */ 21 | if ((fd = creat("templock", FILE_MODE)) < 0) 22 | err_sys("creat error"); 23 | if (write(fd, "ab", 2) != 2) 24 | err_sys("write error"); 25 | 26 | TELL_WAIT(); 27 | if ((pid = fork()) < 0) { 28 | err_sys("fork error"); 29 | } else if (pid == 0) { /* child */ 30 | lockabyte("child", fd, 0); 31 | TELL_PARENT(getppid()); 32 | WAIT_PARENT(); 33 | lockabyte("child", fd, 1); 34 | } else { /* parent */ 35 | lockabyte("parent", fd, 1); 36 | TELL_CHILD(pid); 37 | WAIT_CHILD(); 38 | lockabyte("parent", fd, 0); 39 | } 40 | exit(0); 41 | } 42 | -------------------------------------------------------------------------------- /apue.3e/intro/shell2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void sig_int(int); /* our signal-catching function */ 5 | 6 | int 7 | main(void) 8 | { 9 | char buf[MAXLINE]; /* from apue.h */ 10 | pid_t pid; 11 | int status; 12 | 13 | if (signal(SIGINT, sig_int) == SIG_ERR) 14 | err_sys("signal error"); 15 | 16 | printf("%% "); /* print prompt (printf requires %% to print %) */ 17 | while (fgets(buf, MAXLINE, stdin) != NULL) { 18 | if (buf[strlen(buf) - 1] == '\n') 19 | buf[strlen(buf) - 1] = 0; /* replace newline with null */ 20 | 21 | if ((pid = fork()) < 0) { 22 | err_sys("fork error"); 23 | } else if (pid == 0) { /* child */ 24 | execlp(buf, buf, (char *)0); 25 | err_ret("couldn't execute: %s", buf); 26 | exit(127); 27 | } 28 | 29 | /* parent */ 30 | if ((pid = waitpid(pid, &status, 0)) < 0) 31 | err_sys("waitpid error"); 32 | printf("%% "); 33 | } 34 | exit(0); 35 | } 36 | 37 | void 38 | sig_int(int signo) 39 | { 40 | printf("interrupt\n%% "); 41 | } 42 | -------------------------------------------------------------------------------- /Chapter03/exercise_6.c: -------------------------------------------------------------------------------- 1 | /* exercise_6.c */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define BUFFER_SIZE 1024 10 | 11 | int 12 | main(const int argc, const char* argv[]) 13 | { 14 | int exit_status = 1; 15 | 16 | if (argc < 2) { 17 | fprintf(stderr, "usage: %s \n", argv[0]); 18 | return 1; 19 | } 20 | 21 | const int fd = open(argv[1], O_APPEND /* | O_RDWR */); 22 | if (fd < 0) { 23 | perror("open"); 24 | return 1; 25 | } 26 | char buffer[BUFFER_SIZE] = {}; 27 | 28 | if (lseek(fd, 0, SEEK_SET) < 0) { 29 | perror("lseek"); 30 | goto done; 31 | } 32 | 33 | if (read(fd, buffer, sizeof(buffer) - 1) < 0) { 34 | perror("read"); 35 | goto done; 36 | } 37 | printf("%s\n", buffer); 38 | 39 | if (write(fd, "Five", strlen("Five")) < 0) { 40 | perror("write"); 41 | goto done; 42 | } 43 | 44 | exit_status = 0; 45 | 46 | done: 47 | close(fd); 48 | 49 | return exit_status; 50 | } 51 | -------------------------------------------------------------------------------- /apue.3e/proc/fork2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | int 5 | main(void) 6 | { 7 | pid_t pid; 8 | 9 | if ((pid = fork()) < 0) { 10 | err_sys("fork error"); 11 | } else if (pid == 0) { /* first child */ 12 | if ((pid = fork()) < 0) 13 | err_sys("fork error"); 14 | else if (pid > 0) 15 | exit(0); /* parent from second fork == first child */ 16 | 17 | /* 18 | * We're the second child; our parent becomes init as soon 19 | * as our real parent calls exit() in the statement above. 20 | * Here's where we'd continue executing, knowing that when 21 | * we're done, init will reap our status. 22 | */ 23 | sleep(2); 24 | printf("second child, parent pid = %ld\n", (long)getppid()); 25 | exit(0); 26 | } 27 | 28 | if (waitpid(pid, NULL, 0) != pid) /* wait for first child */ 29 | err_sys("waitpid error"); 30 | 31 | /* 32 | * We're the parent (the original process); we continue executing, 33 | * knowing that we're not the parent of the second child. 34 | */ 35 | exit(0); 36 | } 37 | -------------------------------------------------------------------------------- /apue.3e/ipc1/slock.c: -------------------------------------------------------------------------------- 1 | #include "slock.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct slock * 8 | s_alloc() 9 | { 10 | struct slock *sp; 11 | static int cnt; 12 | 13 | if ((sp = malloc(sizeof(struct slock))) == NULL) 14 | return(NULL); 15 | do { 16 | snprintf(sp->name, sizeof(sp->name), "/%ld.%d", (long)getpid(), 17 | cnt++); 18 | sp->semp = sem_open(sp->name, O_CREAT|O_EXCL, S_IRWXU, 1); 19 | } while ((sp->semp == SEM_FAILED) && (errno == EEXIST)); 20 | if (sp->semp == SEM_FAILED) { 21 | free(sp); 22 | return(NULL); 23 | } 24 | sem_unlink(sp->name); 25 | return(sp); 26 | } 27 | 28 | void 29 | s_free(struct slock *sp) 30 | { 31 | sem_close(sp->semp); 32 | free(sp); 33 | } 34 | 35 | int 36 | s_lock(struct slock *sp) 37 | { 38 | return(sem_wait(sp->semp)); 39 | } 40 | 41 | int 42 | s_trylock(struct slock *sp) 43 | { 44 | return(sem_trywait(sp->semp)); 45 | } 46 | 47 | int 48 | s_unlock(struct slock *sp) 49 | { 50 | return(sem_post(sp->semp)); 51 | } 52 | -------------------------------------------------------------------------------- /apue.3e/relation/orphan3.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void 5 | sig_hup(int signo) 6 | { 7 | printf("SIGHUP received, pid = %ld\n", (long)getpid()); 8 | } 9 | 10 | static void 11 | pr_ids(char *name) 12 | { 13 | printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n", 14 | name, (long)getpid(), (long)getppid(), (long)getpgrp(), 15 | (long)tcgetpgrp(STDIN_FILENO)); 16 | fflush(stdout); 17 | } 18 | 19 | int 20 | main(void) 21 | { 22 | char c; 23 | pid_t pid; 24 | 25 | pr_ids("parent"); 26 | if ((pid = fork()) < 0) { 27 | err_sys("fork error"); 28 | } else if (pid > 0) { /* parent */ 29 | sleep(5); /* sleep to let child stop itself */ 30 | } else { /* child */ 31 | pr_ids("child"); 32 | signal(SIGHUP, sig_hup); /* establish signal handler */ 33 | kill(getpid(), SIGTSTP); /* stop ourself */ 34 | pr_ids("child"); /* prints only if we're continued */ 35 | if (read(STDIN_FILENO, &c, 1) != 1) 36 | printf("read error %d on controlling TTY\n", errno); 37 | } 38 | exit(0); 39 | } 40 | -------------------------------------------------------------------------------- /apue.3e/sockets/makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ifeq "$(PLATFORM)" "solaris" 6 | EXTRALIBS = -lsocket -lnsl 7 | endif 8 | 9 | PROGS = ruptime ruptimed ruptimed-fd ruptimed-dg 10 | MOREPROGS = findsvc ruptime-dg 11 | 12 | all: $(PROGS) $(MOREPROGS) clconn.o clconn2.o initsrv1.o initsrv2.o 13 | 14 | %: %.c $(LIBAPUE) 15 | 16 | ruptime: ruptime.o clconn2.o $(LIBAPUE) 17 | $(CC) $(CFLAGS) -o ruptime ruptime.o clconn2.o $(LDFLAGS) $(LDLIBS) 18 | 19 | ruptimed: ruptimed.o initsrv2.o $(LIBAPUE) 20 | $(CC) $(CFLAGS) -o ruptimed ruptimed.o initsrv2.o $(LDFLAGS) $(LDLIBS) 21 | 22 | ruptimed-fd: ruptimed-fd.o initsrv2.o $(LIBAPUE) 23 | $(CC) $(CFLAGS) -o ruptimed-fd ruptimed-fd.o initsrv2.o $(LDFLAGS) $(LDLIBS) 24 | 25 | ruptimed-dg: ruptimed-dg.o initsrv2.o $(LIBAPUE) 26 | $(CC) $(CFLAGS) -o ruptimed-dg ruptimed-dg.o initsrv2.o $(LDFLAGS) $(LDLIBS) 27 | 28 | clean: 29 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o 30 | 31 | include $(ROOT)/Make.libapue.inc 32 | -------------------------------------------------------------------------------- /Chapter08/exercise_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define LOG(fmt, ...) printf("[%d] %-4s: " fmt "\n", getpid(), __FUNCTION__, ##__VA_ARGS__) 6 | 7 | static int 8 | foo() 9 | { 10 | int x = 42; 11 | LOG("Entry, before vfork()"); 12 | pid_t pid = vfork(); 13 | LOG("after vfork(), x = %d", x); 14 | 15 | if (pid < 0) { 16 | perror("vfork"); 17 | exit(1); 18 | } else if (pid == 0) { 19 | LOG("return 1"); 20 | return 1; 21 | } 22 | LOG("return 0"); 23 | return 0; 24 | } 25 | 26 | static int 27 | baz() 28 | { 29 | int y = 69; 30 | LOG("Entry"); 31 | pid_t pid = 0; 32 | LOG("_exit 0"); 33 | _exit(0); 34 | LOG("return 0"); 35 | return 0; 36 | } 37 | 38 | static void 39 | bar() 40 | { 41 | LOG("Before foo()"); 42 | int ret = foo(); 43 | LOG("After foo()"); 44 | 45 | if(ret) { 46 | LOG("Before baz()"); 47 | baz(); 48 | LOG("After baz()"); 49 | } 50 | } 51 | 52 | int 53 | main(void) 54 | { 55 | LOG("Before bar()"); 56 | bar(); 57 | LOG("After bar()"); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /apue.3e/ipc1/tshm.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define ARRAY_SIZE 40000 5 | #define MALLOC_SIZE 100000 6 | #define SHM_SIZE 100000 7 | #define SHM_MODE 0600 /* user read/write */ 8 | 9 | char array[ARRAY_SIZE]; /* uninitialized data = bss */ 10 | 11 | int 12 | main(void) 13 | { 14 | int shmid; 15 | char *ptr, *shmptr; 16 | 17 | printf("array[] from %p to %p\n", (void *)&array[0], 18 | (void *)&array[ARRAY_SIZE]); 19 | printf("stack around %p\n", (void *)&shmid); 20 | 21 | if ((ptr = malloc(MALLOC_SIZE)) == NULL) 22 | err_sys("malloc error"); 23 | printf("malloced from %p to %p\n", (void *)ptr, 24 | (void *)ptr+MALLOC_SIZE); 25 | 26 | if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0) 27 | err_sys("shmget error"); 28 | if ((shmptr = shmat(shmid, 0, 0)) == (void *)-1) 29 | err_sys("shmat error"); 30 | printf("shared memory attached from %p to %p\n", (void *)shmptr, 31 | (void *)shmptr+SHM_SIZE); 32 | 33 | if (shmctl(shmid, IPC_RMID, 0) < 0) 34 | err_sys("shmctl error"); 35 | 36 | exit(0); 37 | } 38 | -------------------------------------------------------------------------------- /apue.3e/stdio/memstr.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #define BSZ 48 4 | 5 | int 6 | main() 7 | { 8 | FILE *fp; 9 | char buf[BSZ]; 10 | 11 | memset(buf, 'a', BSZ-2); 12 | buf[BSZ-2] = '\0'; 13 | buf[BSZ-1] = 'X'; 14 | if ((fp = fmemopen(buf, BSZ, "w+")) == NULL) 15 | err_sys("fmemopen failed"); 16 | printf("initial buffer contents: %s\n", buf); 17 | fprintf(fp, "hello, world"); 18 | printf("before flush: %s\n", buf); 19 | fflush(fp); 20 | printf("after fflush: %s\n", buf); 21 | printf("len of string in buf = %ld\n", (long)strlen(buf)); 22 | 23 | memset(buf, 'b', BSZ-2); 24 | buf[BSZ-2] = '\0'; 25 | buf[BSZ-1] = 'X'; 26 | fprintf(fp, "hello, world"); 27 | fseek(fp, 0, SEEK_SET); 28 | printf("after fseek: %s\n", buf); 29 | printf("len of string in buf = %ld\n", (long)strlen(buf)); 30 | 31 | memset(buf, 'c', BSZ-2); 32 | buf[BSZ-2] = '\0'; 33 | buf[BSZ-1] = 'X'; 34 | fprintf(fp, "hello, world"); 35 | fclose(fp); 36 | printf("after fclose: %s\n", buf); 37 | printf("len of string in buf = %ld\n", (long)strlen(buf)); 38 | 39 | return(0); 40 | } 41 | -------------------------------------------------------------------------------- /apue.3e/ipc2/opend/request.c: -------------------------------------------------------------------------------- 1 | #include "opend.h" 2 | #include 3 | 4 | void 5 | handle_request(char *buf, int nread, int clifd, uid_t uid) 6 | { 7 | int newfd; 8 | 9 | if (buf[nread-1] != 0) { 10 | snprintf(errmsg, MAXLINE-1, 11 | "request from uid %d not null terminated: %*.*s\n", 12 | uid, nread, nread, buf); 13 | send_err(clifd, -1, errmsg); 14 | return; 15 | } 16 | log_msg("request: %s, from uid %d", buf, uid); 17 | 18 | /* parse the arguments, set options */ 19 | if (buf_args(buf, cli_args) < 0) { 20 | send_err(clifd, -1, errmsg); 21 | log_msg(errmsg); 22 | return; 23 | } 24 | 25 | if ((newfd = open(pathname, oflag)) < 0) { 26 | snprintf(errmsg, MAXLINE-1, "can't open %s: %s\n", 27 | pathname, strerror(errno)); 28 | send_err(clifd, -1, errmsg); 29 | log_msg(errmsg); 30 | return; 31 | } 32 | 33 | /* send the descriptor */ 34 | if (send_fd(clifd, newfd) < 0) 35 | log_sys("send_fd error"); 36 | log_msg("sent fd %d over fd %d for %s", newfd, clifd, pathname); 37 | close(newfd); /* we're done with descriptor */ 38 | } 39 | -------------------------------------------------------------------------------- /apue.3e/advio/rot13a.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | #define BSZ 4096 6 | 7 | unsigned char buf[BSZ]; 8 | 9 | unsigned char 10 | translate(unsigned char c) 11 | { 12 | if (isalpha(c)) { 13 | if (c >= 'n') 14 | c -= 13; 15 | else if (c >= 'a') 16 | c += 13; 17 | else if (c >= 'N') 18 | c -= 13; 19 | else 20 | c += 13; 21 | } 22 | return(c); 23 | } 24 | 25 | int 26 | main(int argc, char* argv[]) 27 | { 28 | int ifd, ofd, i, n, nw; 29 | 30 | if (argc != 3) 31 | err_quit("usage: rot13 infile outfile"); 32 | if ((ifd = open(argv[1], O_RDONLY)) < 0) 33 | err_sys("can't open %s", argv[1]); 34 | if ((ofd = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, FILE_MODE)) < 0) 35 | err_sys("can't create %s", argv[2]); 36 | 37 | while ((n = read(ifd, buf, BSZ)) > 0) { 38 | for (i = 0; i < n; i++) 39 | buf[i] = translate(buf[i]); 40 | if ((nw = write(ofd, buf, n)) != n) { 41 | if (nw < 0) 42 | err_sys("write failed"); 43 | else 44 | err_quit("short write (%d/%d)", nw, n); 45 | } 46 | } 47 | 48 | fsync(ofd); 49 | exit(0); 50 | } 51 | -------------------------------------------------------------------------------- /apue.3e/exercises/goodexit.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | struct foo { 5 | int a, b, c, d; 6 | }; 7 | 8 | void 9 | printfoo(const char *s, const struct foo *fp) 10 | { 11 | fputs(s, stdout); 12 | printf(" structure at 0x%lx\n", (unsigned long)fp); 13 | printf(" foo.a = %d\n", fp->a); 14 | printf(" foo.b = %d\n", fp->b); 15 | printf(" foo.c = %d\n", fp->c); 16 | printf(" foo.d = %d\n", fp->d); 17 | } 18 | 19 | void * 20 | thr_fn1(void *arg) 21 | { 22 | struct foo *fp; 23 | 24 | if ((fp = malloc(sizeof(struct foo))) == NULL) 25 | err_sys("can't allocate memory"); 26 | fp->a = 1; 27 | fp->b = 2; 28 | fp->c = 3; 29 | fp->d = 4; 30 | printfoo("thread:\n", fp); 31 | return((void *)fp); 32 | } 33 | 34 | int 35 | main(void) 36 | { 37 | int err; 38 | pthread_t tid1; 39 | struct foo *fp; 40 | 41 | err = pthread_create(&tid1, NULL, thr_fn1, NULL); 42 | if (err != 0) 43 | err_exit(err, "can't create thread 1"); 44 | err = pthread_join(tid1, (void *)&fp); 45 | if (err != 0) 46 | err_exit(err, "can't join with thread 1"); 47 | printfoo("parent:\n", fp); 48 | exit(0); 49 | } 50 | -------------------------------------------------------------------------------- /Chapter16/exercise_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int 8 | main(void) 9 | { 10 | struct stat statbuf = {}; 11 | const int fd = socket(AF_INET, SOCK_STREAM, 0); 12 | if (fd < 0) { 13 | perror("socket"); 14 | return 1; 15 | } 16 | 17 | if (fstat(fd, &statbuf) < 0) { 18 | perror("fstat"); 19 | return 1; 20 | } 21 | 22 | printf("st_dev: %lu\n", statbuf.st_dev); 23 | printf("st_ino: %lu\n", statbuf.st_ino); 24 | printf("st_nlink: %lu\n", statbuf.st_nlink); 25 | printf("st_mode: %u\n", statbuf.st_mode); 26 | printf("st_uid: %u\n", statbuf.st_uid); 27 | printf("st_gid: %u\n", statbuf.st_gid); 28 | printf("st_rdev: %lu\n", statbuf.st_rdev); 29 | printf("st_size: %lu\n", statbuf.st_size); 30 | printf("st_blksize: %lu\n", statbuf.st_blksize); 31 | printf("st_blocks: %lu\n", statbuf.st_blocks); 32 | printf("st_atime: %lu\n", statbuf.st_atime); 33 | printf("st_mtime: %lu\n", statbuf.st_mtime); 34 | printf("st_ctime: %lu\n", statbuf.st_ctime); 35 | 36 | close(fd); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /apue.3e/threads/mutex1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct foo { 5 | int f_count; 6 | pthread_mutex_t f_lock; 7 | int f_id; 8 | /* ... more stuff here ... */ 9 | }; 10 | 11 | struct foo * 12 | foo_alloc(int id) /* allocate the object */ 13 | { 14 | struct foo *fp; 15 | 16 | if ((fp = malloc(sizeof(struct foo))) != NULL) { 17 | fp->f_count = 1; 18 | fp->f_id = id; 19 | if (pthread_mutex_init(&fp->f_lock, NULL) != 0) { 20 | free(fp); 21 | return(NULL); 22 | } 23 | /* ... continue initialization ... */ 24 | } 25 | return(fp); 26 | } 27 | 28 | void 29 | foo_hold(struct foo *fp) /* add a reference to the object */ 30 | { 31 | pthread_mutex_lock(&fp->f_lock); 32 | fp->f_count++; 33 | pthread_mutex_unlock(&fp->f_lock); 34 | } 35 | 36 | void 37 | foo_rele(struct foo *fp) /* release a reference to the object */ 38 | { 39 | pthread_mutex_lock(&fp->f_lock); 40 | if (--fp->f_count == 0) { /* last reference */ 41 | pthread_mutex_unlock(&fp->f_lock); 42 | pthread_mutex_destroy(&fp->f_lock); 43 | free(fp); 44 | } else { 45 | pthread_mutex_unlock(&fp->f_lock); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apue.3e/ipc2/open/open.c: -------------------------------------------------------------------------------- 1 | #include "open.h" 2 | #include /* struct iovec */ 3 | 4 | /* 5 | * Open the file by sending the "name" and "oflag" to the 6 | * connection server and reading a file descriptor back. 7 | */ 8 | int 9 | csopen(char *name, int oflag) 10 | { 11 | int len; 12 | char buf[12]; 13 | struct iovec iov[3]; 14 | static int csfd = -1; 15 | 16 | if (csfd < 0) { /* open connection to conn server */ 17 | if ((csfd = cli_conn(CS_OPEN)) < 0) { 18 | err_ret("cli_conn error"); 19 | return(-1); 20 | } 21 | } 22 | 23 | sprintf(buf, " %d", oflag); /* oflag to ascii */ 24 | iov[0].iov_base = CL_OPEN " "; /* string concatenation */ 25 | iov[0].iov_len = strlen(CL_OPEN) + 1; 26 | iov[1].iov_base = name; 27 | iov[1].iov_len = strlen(name); 28 | iov[2].iov_base = buf; 29 | iov[2].iov_len = strlen(buf) + 1; /* null always sent */ 30 | len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len; 31 | if (writev(csfd, &iov[0], 3) != len) { 32 | err_ret("writev error"); 33 | return(-1); 34 | } 35 | 36 | /* read back descriptor; returned errors handled by write() */ 37 | return(recv_fd(csfd, write)); 38 | } 39 | -------------------------------------------------------------------------------- /apue.3e/signals/critical.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void sig_quit(int); 4 | 5 | int 6 | main(void) 7 | { 8 | sigset_t newmask, oldmask, pendmask; 9 | 10 | if (signal(SIGQUIT, sig_quit) == SIG_ERR) 11 | err_sys("can't catch SIGQUIT"); 12 | 13 | /* 14 | * Block SIGQUIT and save current signal mask. 15 | */ 16 | sigemptyset(&newmask); 17 | sigaddset(&newmask, SIGQUIT); 18 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 19 | err_sys("SIG_BLOCK error"); 20 | 21 | sleep(5); /* SIGQUIT here will remain pending */ 22 | 23 | if (sigpending(&pendmask) < 0) 24 | err_sys("sigpending error"); 25 | if (sigismember(&pendmask, SIGQUIT)) 26 | printf("\nSIGQUIT pending\n"); 27 | 28 | /* 29 | * Restore signal mask which unblocks SIGQUIT. 30 | */ 31 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 32 | err_sys("SIG_SETMASK error"); 33 | printf("SIGQUIT unblocked\n"); 34 | 35 | sleep(5); /* SIGQUIT here will terminate with core file */ 36 | exit(0); 37 | } 38 | 39 | static void 40 | sig_quit(int signo) 41 | { 42 | printf("caught SIGQUIT\n"); 43 | if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) 44 | err_sys("can't reset SIGQUIT"); 45 | } 46 | -------------------------------------------------------------------------------- /apue.3e/proc/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | ACCT= 6 | ACCTFLAGS= 7 | ifeq "$(PLATFORM)" "linux" 8 | ACCT=pracct 9 | ACCTFLAGS = -DHAS_AXSIG -DHAS_ACORE 10 | endif 11 | ifeq "$(PLATFORM)" "macos" 12 | ACCT=pracct 13 | ACCTFLAGS = -DHAS_AXSIG -DHAS_ACORE 14 | endif 15 | ifeq "$(PLATFORM)" "solaris" 16 | ACCT=pracct 17 | ACCTFLAGS = -DHAS_AC_STAT 18 | endif 19 | 20 | PROGS = echoall exec1 exec2 fork1 fork2 nice pruids tellwait1 tellwait2 test1 times1 vfork1 wait1 21 | MOREPROGS = systest1 systest3 22 | 23 | all: $(PROGS) $(MOREPROGS) system.o $(ACCT) 24 | 25 | %: %.c $(LIBAPUE) 26 | $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 27 | 28 | systest1: system.o systest1.o $(LIBAPUE) 29 | $(CC) $(CFLAGS) -o systest1 systest1.o system.o $(LDFLAGS) $(LDLIBS) 30 | 31 | systest3: system.o systest3.o $(LIBAPUE) 32 | $(CC) $(CFLAGS) -o systest3 systest3.o system.o $(LDFLAGS) $(LDLIBS) 33 | 34 | pracct: pracct.c $(LIBAPUE) 35 | $(CC) $(CFLAGS) $(ACCTFLAGS) -o pracct pracct.c $(LDFLAGS) $(LDLIBS) 36 | 37 | clean: 38 | rm -f $(PROGS) $(MOREPROGS) $(TEMPFILES) *.o $(ACCT) 39 | 40 | include $(ROOT)/Make.libapue.inc 41 | -------------------------------------------------------------------------------- /apue.3e/threadctl/getenv2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | extern char **environ; 7 | 8 | pthread_mutex_t env_mutex; 9 | 10 | static pthread_once_t init_done = PTHREAD_ONCE_INIT; 11 | 12 | static void 13 | thread_init(void) 14 | { 15 | pthread_mutexattr_t attr; 16 | 17 | pthread_mutexattr_init(&attr); 18 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 19 | pthread_mutex_init(&env_mutex, &attr); 20 | pthread_mutexattr_destroy(&attr); 21 | } 22 | 23 | int 24 | getenv_r(const char *name, char *buf, int buflen) 25 | { 26 | int i, len, olen; 27 | 28 | pthread_once(&init_done, thread_init); 29 | len = strlen(name); 30 | pthread_mutex_lock(&env_mutex); 31 | for (i = 0; environ[i] != NULL; i++) { 32 | if ((strncmp(name, environ[i], len) == 0) && 33 | (environ[i][len] == '=')) { 34 | olen = strlen(&environ[i][len+1]); 35 | if (olen >= buflen) { 36 | pthread_mutex_unlock(&env_mutex); 37 | return(ENOSPC); 38 | } 39 | strcpy(buf, &environ[i][len+1]); 40 | pthread_mutex_unlock(&env_mutex); 41 | return(0); 42 | } 43 | } 44 | pthread_mutex_unlock(&env_mutex); 45 | return(ENOENT); 46 | } 47 | -------------------------------------------------------------------------------- /apue.3e/lib/bufargs.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #define MAXARGC 50 /* max number of arguments in buf */ 4 | #define WHITE " \t\n" /* white space for tokenizing arguments */ 5 | 6 | /* 7 | * buf[] contains white-space-separated arguments. We convert it to an 8 | * argv-style array of pointers, and call the user's function (optfunc) 9 | * to process the array. We return -1 if there's a problem parsing buf, 10 | * else we return whatever optfunc() returns. Note that user's buf[] 11 | * array is modified (nulls placed after each token). 12 | */ 13 | int 14 | buf_args(char *buf, int (*optfunc)(int, char **)) 15 | { 16 | char *ptr, *argv[MAXARGC]; 17 | int argc; 18 | 19 | if (strtok(buf, WHITE) == NULL) /* an argv[0] is required */ 20 | return(-1); 21 | argv[argc = 0] = buf; 22 | while ((ptr = strtok(NULL, WHITE)) != NULL) { 23 | if (++argc >= MAXARGC-1) /* -1 for room for NULL at end */ 24 | return(-1); 25 | argv[argc] = ptr; 26 | } 27 | argv[++argc] = NULL; 28 | 29 | /* 30 | * Since argv[] pointers point into the user's buf[], 31 | * user's function can just copy the pointers, even 32 | * though argv[] array will disappear on return. 33 | */ 34 | return((*optfunc)(argc, argv)); 35 | } 36 | -------------------------------------------------------------------------------- /apue.3e/environ/testjmp.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | static void f1(int, int, int, int); 5 | static void f2(void); 6 | 7 | static jmp_buf jmpbuffer; 8 | static int globval; 9 | 10 | int 11 | main(void) 12 | { 13 | int autoval; 14 | register int regival; 15 | volatile int volaval; 16 | static int statval; 17 | 18 | globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5; 19 | 20 | if (setjmp(jmpbuffer) != 0) { 21 | printf("after longjmp:\n"); 22 | printf("globval = %d, autoval = %d, regival = %d," 23 | " volaval = %d, statval = %d\n", 24 | globval, autoval, regival, volaval, statval); 25 | exit(0); 26 | } 27 | 28 | /* 29 | * Change variables after setjmp, but before longjmp. 30 | */ 31 | globval = 95; autoval = 96; regival = 97; volaval = 98; 32 | statval = 99; 33 | 34 | f1(autoval, regival, volaval, statval); /* never returns */ 35 | exit(0); 36 | } 37 | 38 | static void 39 | f1(int i, int j, int k, int l) 40 | { 41 | printf("in f1():\n"); 42 | printf("globval = %d, autoval = %d, regival = %d," 43 | " volaval = %d, statval = %d\n", globval, i, j, k, l); 44 | f2(); 45 | } 46 | 47 | static void 48 | f2(void) 49 | { 50 | longjmp(jmpbuffer, 1); 51 | } 52 | -------------------------------------------------------------------------------- /apue.3e/lib/sleep.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void 4 | sig_alrm(int signo) 5 | { 6 | /* nothing to do, just returning wakes up sigsuspend() */ 7 | } 8 | 9 | unsigned int 10 | sleep(unsigned int seconds) 11 | { 12 | struct sigaction newact, oldact; 13 | sigset_t newmask, oldmask, suspmask; 14 | unsigned int unslept; 15 | 16 | /* set our handler, save previous information */ 17 | newact.sa_handler = sig_alrm; 18 | sigemptyset(&newact.sa_mask); 19 | newact.sa_flags = 0; 20 | sigaction(SIGALRM, &newact, &oldact); 21 | 22 | /* block SIGALRM and save current signal mask */ 23 | sigemptyset(&newmask); 24 | sigaddset(&newmask, SIGALRM); 25 | sigprocmask(SIG_BLOCK, &newmask, &oldmask); 26 | 27 | alarm(seconds); 28 | suspmask = oldmask; 29 | 30 | /* make sure SIGALRM isn't blocked */ 31 | sigdelset(&suspmask, SIGALRM); 32 | 33 | /* wait for any signal to be caught */ 34 | sigsuspend(&suspmask); 35 | 36 | /* some signal has been caught, SIGALRM is now blocked */ 37 | 38 | unslept = alarm(0); 39 | 40 | /* reset previous action */ 41 | sigaction(SIGALRM, &oldact, NULL); 42 | 43 | /* reset signal mask, which unblocks SIGALRM */ 44 | sigprocmask(SIG_SETMASK, &oldmask, NULL); 45 | return(unslept); 46 | } 47 | -------------------------------------------------------------------------------- /apue.3e/db/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=.. 2 | PLATFORM=$(shell $(ROOT)/systype.sh) 3 | include $(ROOT)/Make.defines.$(PLATFORM) 4 | 5 | LIBMISC = libapue_db.a 6 | COMM_OBJ = db.o 7 | 8 | ifeq "$(PLATFORM)" "solaris" 9 | LDCMD=$(LD) -64 -G -Bdynamic -R/lib/64:/usr/ucblib/sparcv9 -o libapue_db.so.1 -L/lib/64 -L/usr/ucblib/sparcv9 -L$(ROOT)/lib -lapue db.o 10 | EXTRALD=-m64 -R. 11 | else 12 | LDCMD=$(CC) -shared -Wl,-dylib -o libapue_db.so.1 -L$(ROOT)/lib -lapue -lc db.o 13 | endif 14 | ifeq "$(PLATFORM)" "linux" 15 | EXTRALD=-Wl,-rpath=. 16 | endif 17 | ifeq "$(PLATFORM)" "freebsd" 18 | EXTRALD=-R. 19 | endif 20 | ifeq "$(PLATFORM)" "macos" 21 | EXTRALD=-R. 22 | endif 23 | 24 | all: libapue_db.so.1 t4 $(LIBMISC) 25 | 26 | libapue_db.a: $(COMM_OBJ) $(LIBAPUE) 27 | $(AR) rsv $(LIBMISC) $(COMM_OBJ) 28 | $(RANLIB) $(LIBMISC) 29 | 30 | libapue_db.so.1: db.c $(LIBAPUE) 31 | $(CC) -fPIC $(CFLAGS) -c db.c 32 | $(LDCMD) 33 | ln -s libapue_db.so.1 libapue_db.so 34 | 35 | t4: $(LIBAPUE) 36 | $(CC) $(CFLAGS) -c -I. t4.c 37 | $(CC) $(EXTRALD) -o t4 t4.o -L$(ROOT)/lib -L. -lapue_db -lapue 38 | 39 | clean: 40 | rm -f *.o a.out core temp.* $(LIBMISC) t4 libapue_db.so.* *.dat *.idx libapue_db.so 41 | 42 | include $(ROOT)/Make.libapue.inc 43 | -------------------------------------------------------------------------------- /apue.3e/signals/abort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void 7 | abort(void) /* POSIX-style abort() function */ 8 | { 9 | sigset_t mask; 10 | struct sigaction action; 11 | 12 | /* Caller can't ignore SIGABRT, if so reset to default */ 13 | sigaction(SIGABRT, NULL, &action); 14 | if (action.sa_handler == SIG_IGN) { 15 | action.sa_handler = SIG_DFL; 16 | sigaction(SIGABRT, &action, NULL); 17 | } 18 | if (action.sa_handler == SIG_DFL) 19 | fflush(NULL); /* flush all open stdio streams */ 20 | 21 | /* Caller can't block SIGABRT; make sure it's unblocked */ 22 | sigfillset(&mask); 23 | sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ 24 | sigprocmask(SIG_SETMASK, &mask, NULL); 25 | kill(getpid(), SIGABRT); /* send the signal */ 26 | 27 | /* If we're here, process caught SIGABRT and returned */ 28 | fflush(NULL); /* flush all open stdio streams */ 29 | action.sa_handler = SIG_DFL; 30 | sigaction(SIGABRT, &action, NULL); /* reset to default */ 31 | sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */ 32 | kill(getpid(), SIGABRT); /* and one more time */ 33 | exit(1); /* this should never be executed ... */ 34 | } 35 | -------------------------------------------------------------------------------- /apue.3e/threadctl/getenv3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAXSTRINGSZ 4096 7 | 8 | static pthread_key_t key; 9 | static pthread_once_t init_done = PTHREAD_ONCE_INIT; 10 | pthread_mutex_t env_mutex = PTHREAD_MUTEX_INITIALIZER; 11 | 12 | extern char **environ; 13 | 14 | static void 15 | thread_init(void) 16 | { 17 | pthread_key_create(&key, free); 18 | } 19 | 20 | char * 21 | getenv(const char *name) 22 | { 23 | int i, len; 24 | char *envbuf; 25 | 26 | pthread_once(&init_done, thread_init); 27 | pthread_mutex_lock(&env_mutex); 28 | envbuf = (char *)pthread_getspecific(key); 29 | if (envbuf == NULL) { 30 | envbuf = malloc(MAXSTRINGSZ); 31 | if (envbuf == NULL) { 32 | pthread_mutex_unlock(&env_mutex); 33 | return(NULL); 34 | } 35 | pthread_setspecific(key, envbuf); 36 | } 37 | len = strlen(name); 38 | for (i = 0; environ[i] != NULL; i++) { 39 | if ((strncmp(name, environ[i], len) == 0) && 40 | (environ[i][len] == '=')) { 41 | strncpy(envbuf, &environ[i][len+1], MAXSTRINGSZ-1); 42 | pthread_mutex_unlock(&env_mutex); 43 | return(envbuf); 44 | } 45 | } 46 | pthread_mutex_unlock(&env_mutex); 47 | return(NULL); 48 | } 49 | -------------------------------------------------------------------------------- /apue.3e/lib/servlisten.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define QLEN 10 7 | 8 | /* 9 | * Create a server endpoint of a connection. 10 | * Returns fd if all OK, <0 on error. 11 | */ 12 | int 13 | serv_listen(const char *name) 14 | { 15 | int fd, len, err, rval; 16 | struct sockaddr_un un; 17 | 18 | if (strlen(name) >= sizeof(un.sun_path)) { 19 | errno = ENAMETOOLONG; 20 | return(-1); 21 | } 22 | 23 | /* create a UNIX domain stream socket */ 24 | if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 25 | return(-2); 26 | 27 | unlink(name); /* in case it already exists */ 28 | 29 | /* fill in socket address structure */ 30 | memset(&un, 0, sizeof(un)); 31 | un.sun_family = AF_UNIX; 32 | strcpy(un.sun_path, name); 33 | len = offsetof(struct sockaddr_un, sun_path) + strlen(name); 34 | 35 | /* bind the name to the descriptor */ 36 | if (bind(fd, (struct sockaddr *)&un, len) < 0) { 37 | rval = -3; 38 | goto errout; 39 | } 40 | 41 | if (listen(fd, QLEN) < 0) { /* tell kernel we're a server */ 42 | rval = -4; 43 | goto errout; 44 | } 45 | return(fd); 46 | 47 | errout: 48 | err = errno; 49 | close(fd); 50 | errno = err; 51 | return(rval); 52 | } 53 | -------------------------------------------------------------------------------- /apue.3e/signals/suspend2.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | volatile sig_atomic_t quitflag; /* set nonzero by signal handler */ 4 | 5 | static void 6 | sig_int(int signo) /* one signal handler for SIGINT and SIGQUIT */ 7 | { 8 | if (signo == SIGINT) 9 | printf("\ninterrupt\n"); 10 | else if (signo == SIGQUIT) 11 | quitflag = 1; /* set flag for main loop */ 12 | } 13 | 14 | int 15 | main(void) 16 | { 17 | sigset_t newmask, oldmask, zeromask; 18 | 19 | if (signal(SIGINT, sig_int) == SIG_ERR) 20 | err_sys("signal(SIGINT) error"); 21 | if (signal(SIGQUIT, sig_int) == SIG_ERR) 22 | err_sys("signal(SIGQUIT) error"); 23 | 24 | sigemptyset(&zeromask); 25 | sigemptyset(&newmask); 26 | sigaddset(&newmask, SIGQUIT); 27 | 28 | /* 29 | * Block SIGQUIT and save current signal mask. 30 | */ 31 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 32 | err_sys("SIG_BLOCK error"); 33 | 34 | while (quitflag == 0) 35 | sigsuspend(&zeromask); 36 | 37 | /* 38 | * SIGQUIT has been caught and is now blocked; do whatever. 39 | */ 40 | quitflag = 0; 41 | 42 | /* 43 | * Reset signal mask which unblocks SIGQUIT. 44 | */ 45 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 46 | err_sys("SIG_SETMASK error"); 47 | 48 | exit(0); 49 | } 50 | -------------------------------------------------------------------------------- /apue.3e/exercises/longpath.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | 4 | #define DEPTH 1000 /* directory depth */ 5 | #define STARTDIR "/tmp" 6 | #define NAME "alonglonglonglonglonglonglonglonglonglongname" 7 | #define MAXSZ (10*8192) 8 | 9 | int 10 | main(void) 11 | { 12 | int i; 13 | size_t size; 14 | char *path; 15 | 16 | if (chdir(STARTDIR) < 0) 17 | err_sys("chdir error"); 18 | 19 | for (i = 0; i < DEPTH; i++) { 20 | if (mkdir(NAME, DIR_MODE) < 0) 21 | err_sys("mkdir failed, i = %d", i); 22 | if (chdir(NAME) < 0) 23 | err_sys("chdir failed, i = %d", i); 24 | } 25 | 26 | if (creat("afile", FILE_MODE) < 0) 27 | err_sys("creat error"); 28 | 29 | /* 30 | * The deep directory is created, with a file at the leaf. 31 | * Now let's try to obtain its pathname. 32 | */ 33 | path = path_alloc(&size); 34 | for ( ; ; ) { 35 | if (getcwd(path, size) != NULL) { 36 | break; 37 | } else { 38 | err_ret("getcwd failed, size = %ld", (long)size); 39 | size += 100; 40 | if (size > MAXSZ) 41 | err_quit("giving up"); 42 | if ((path = realloc(path, size)) == NULL) 43 | err_sys("realloc error"); 44 | } 45 | } 46 | printf("length = %ld\n%s\n", (long)strlen(path), path); 47 | 48 | exit(0); 49 | } 50 | -------------------------------------------------------------------------------- /apue.3e/signals/suspend1.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | static void sig_int(int); 4 | 5 | int 6 | main(void) 7 | { 8 | sigset_t newmask, oldmask, waitmask; 9 | 10 | pr_mask("program start: "); 11 | 12 | if (signal(SIGINT, sig_int) == SIG_ERR) 13 | err_sys("signal(SIGINT) error"); 14 | sigemptyset(&waitmask); 15 | sigaddset(&waitmask, SIGUSR1); 16 | sigemptyset(&newmask); 17 | sigaddset(&newmask, SIGINT); 18 | 19 | /* 20 | * Block SIGINT and save current signal mask. 21 | */ 22 | if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 23 | err_sys("SIG_BLOCK error"); 24 | 25 | /* 26 | * Critical region of code. 27 | */ 28 | pr_mask("in critical region: "); 29 | 30 | /* 31 | * Pause, allowing all signals except SIGUSR1. 32 | */ 33 | if (sigsuspend(&waitmask) != -1) 34 | err_sys("sigsuspend error"); 35 | 36 | pr_mask("after return from sigsuspend: "); 37 | 38 | /* 39 | * Reset signal mask which unblocks SIGINT. 40 | */ 41 | if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 42 | err_sys("SIG_SETMASK error"); 43 | 44 | /* 45 | * And continue processing ... 46 | */ 47 | pr_mask("program exit: "); 48 | 49 | exit(0); 50 | } 51 | 52 | static void 53 | sig_int(int signo) 54 | { 55 | pr_mask("\nin sig_int: "); 56 | } 57 | -------------------------------------------------------------------------------- /apue.3e/signals/sigtstp.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | #define BUFFSIZE 1024 4 | 5 | static void 6 | sig_tstp(int signo) /* signal handler for SIGTSTP */ 7 | { 8 | sigset_t mask; 9 | 10 | /* ... move cursor to lower left corner, reset tty mode ... */ 11 | 12 | /* 13 | * Unblock SIGTSTP, since it's blocked while we're handling it. 14 | */ 15 | sigemptyset(&mask); 16 | sigaddset(&mask, SIGTSTP); 17 | sigprocmask(SIG_UNBLOCK, &mask, NULL); 18 | 19 | signal(SIGTSTP, SIG_DFL); /* reset disposition to default */ 20 | 21 | kill(getpid(), SIGTSTP); /* and send the signal to ourself */ 22 | 23 | /* we won't return from the kill until we're continued */ 24 | 25 | signal(SIGTSTP, sig_tstp); /* reestablish signal handler */ 26 | 27 | /* ... reset tty mode, redraw screen ... */ 28 | } 29 | 30 | int 31 | main(void) 32 | { 33 | int n; 34 | char buf[BUFFSIZE]; 35 | 36 | /* 37 | * Only catch SIGTSTP if we're running with a job-control shell. 38 | */ 39 | if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) 40 | signal(SIGTSTP, sig_tstp); 41 | 42 | while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) 43 | if (write(STDOUT_FILENO, buf, n) != n) 44 | err_sys("write error"); 45 | 46 | if (n < 0) 47 | err_sys("read error"); 48 | 49 | exit(0); 50 | } 51 | -------------------------------------------------------------------------------- /apue.3e/sockets/ruptime.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUFLEN 128 7 | 8 | extern int connect_retry(int, int, int, const struct sockaddr *, 9 | socklen_t); 10 | 11 | void 12 | print_uptime(int sockfd) 13 | { 14 | int n; 15 | char buf[BUFLEN]; 16 | 17 | while ((n = recv(sockfd, buf, BUFLEN, 0)) > 0) 18 | write(STDOUT_FILENO, buf, n); 19 | if (n < 0) 20 | err_sys("recv error"); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | struct addrinfo *ailist, *aip; 27 | struct addrinfo hint; 28 | int sockfd, err; 29 | 30 | if (argc != 2) 31 | err_quit("usage: ruptime hostname"); 32 | memset(&hint, 0, sizeof(hint)); 33 | hint.ai_socktype = SOCK_STREAM; 34 | hint.ai_canonname = NULL; 35 | hint.ai_addr = NULL; 36 | hint.ai_next = NULL; 37 | if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0) 38 | err_quit("getaddrinfo error: %s", gai_strerror(err)); 39 | for (aip = ailist; aip != NULL; aip = aip->ai_next) { 40 | if ((sockfd = connect_retry(aip->ai_family, SOCK_STREAM, 0, 41 | aip->ai_addr, aip->ai_addrlen)) < 0) { 42 | err = errno; 43 | } else { 44 | print_uptime(sockfd); 45 | exit(0); 46 | } 47 | } 48 | err_exit(err, "can't connect to %s", argv[1]); 49 | } 50 | -------------------------------------------------------------------------------- /apue.3e/ipc1/devzero.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | #define NLOOPS 1000 6 | #define SIZE sizeof(long) /* size of shared memory area */ 7 | 8 | static int 9 | update(long *ptr) 10 | { 11 | return((*ptr)++); /* return value before increment */ 12 | } 13 | 14 | int 15 | main(void) 16 | { 17 | int fd, i, counter; 18 | pid_t pid; 19 | void *area; 20 | 21 | if ((fd = open("/dev/zero", O_RDWR)) < 0) 22 | err_sys("open error"); 23 | if ((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 24 | fd, 0)) == MAP_FAILED) 25 | err_sys("mmap error"); 26 | close(fd); /* can close /dev/zero now that it's mapped */ 27 | 28 | TELL_WAIT(); 29 | 30 | if ((pid = fork()) < 0) { 31 | err_sys("fork error"); 32 | } else if (pid > 0) { /* parent */ 33 | for (i = 0; i < NLOOPS; i += 2) { 34 | if ((counter = update((long *)area)) != i) 35 | err_quit("parent: expected %d, got %d", i, counter); 36 | 37 | TELL_CHILD(pid); 38 | WAIT_CHILD(); 39 | } 40 | } else { /* child */ 41 | for (i = 1; i < NLOOPS + 1; i += 2) { 42 | WAIT_PARENT(); 43 | 44 | if ((counter = update((long *)area)) != i) 45 | err_quit("child: expected %d, got %d", i, counter); 46 | 47 | TELL_PARENT(getppid()); 48 | } 49 | } 50 | 51 | exit(0); 52 | } 53 | -------------------------------------------------------------------------------- /apue.3e/signals/mask.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | #include 3 | #include 4 | 5 | static void sig_usr1(int); 6 | static void sig_alrm(int); 7 | static sigjmp_buf jmpbuf; 8 | static volatile sig_atomic_t canjump; 9 | 10 | int 11 | main(void) 12 | { 13 | if (signal(SIGUSR1, sig_usr1) == SIG_ERR) 14 | err_sys("signal(SIGUSR1) error"); 15 | if (signal(SIGALRM, sig_alrm) == SIG_ERR) 16 | err_sys("signal(SIGALRM) error"); 17 | 18 | pr_mask("starting main: "); /* {Prog prmask} */ 19 | 20 | if (sigsetjmp(jmpbuf, 1)) { 21 | 22 | pr_mask("ending main: "); 23 | 24 | exit(0); 25 | } 26 | canjump = 1; /* now sigsetjmp() is OK */ 27 | 28 | for ( ; ; ) 29 | pause(); 30 | } 31 | 32 | static void 33 | sig_usr1(int signo) 34 | { 35 | time_t starttime; 36 | 37 | if (canjump == 0) 38 | return; /* unexpected signal, ignore */ 39 | 40 | pr_mask("starting sig_usr1: "); 41 | 42 | alarm(3); /* SIGALRM in 3 seconds */ 43 | starttime = time(NULL); 44 | for ( ; ; ) /* busy wait for 5 seconds */ 45 | if (time(NULL) > starttime + 5) 46 | break; 47 | 48 | pr_mask("finishing sig_usr1: "); 49 | 50 | canjump = 0; 51 | siglongjmp(jmpbuf, 1); /* jump back to main, don't return */ 52 | } 53 | 54 | static void 55 | sig_alrm(int signo) 56 | { 57 | pr_mask("in sig_alrm: "); 58 | } 59 | -------------------------------------------------------------------------------- /Chapter16/exercise_4_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define BUFLEN 128 10 | 11 | static void 12 | client(const int sockfd) 13 | { 14 | char buffer[BUFLEN] = {};; 15 | 16 | if (recv(sockfd, buffer, sizeof(buffer) - 1, 0) < 0) { 17 | perror("read"); 18 | return; 19 | } 20 | 21 | printf("Num procs: %s", buffer); 22 | } 23 | 24 | int 25 | main(const int argc, const char* const argv[]) 26 | { 27 | if (argc < 3) { 28 | fprintf(stderr, "Usage: %s \n", argv[0]); 29 | return 1; 30 | } 31 | const char* const host = argv[1]; 32 | const char* const port_str = argv[2]; 33 | const int port = strtol(port_str, NULL, 10); 34 | 35 | const int sockfd = socket(AF_INET, SOCK_STREAM, 0); 36 | if (sockfd < 0) { 37 | perror("socket"); 38 | return 1; 39 | } 40 | 41 | const struct sockaddr_in servaddr = { 42 | .sin_family = AF_INET, 43 | .sin_addr.s_addr = inet_addr(host), 44 | .sin_port = htons(port), 45 | }; 46 | 47 | if (connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { 48 | perror("connect"); 49 | close(sockfd); 50 | return 1; 51 | } 52 | 53 | client(sockfd); 54 | close(sockfd); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /apue.3e/termios/getpass.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_PASS_LEN 8 /* max #chars for user to enter */ 6 | 7 | char * 8 | getpass(const char *prompt) 9 | { 10 | static char buf[MAX_PASS_LEN + 1]; /* null byte at end */ 11 | char *ptr; 12 | sigset_t sig, osig; 13 | struct termios ts, ots; 14 | FILE *fp; 15 | int c; 16 | 17 | if ((fp = fopen(ctermid(NULL), "r+")) == NULL) 18 | return(NULL); 19 | setbuf(fp, NULL); 20 | 21 | sigemptyset(&sig); 22 | sigaddset(&sig, SIGINT); /* block SIGINT */ 23 | sigaddset(&sig, SIGTSTP); /* block SIGTSTP */ 24 | sigprocmask(SIG_BLOCK, &sig, &osig); /* and save mask */ 25 | 26 | tcgetattr(fileno(fp), &ts); /* save tty state */ 27 | ots = ts; /* structure copy */ 28 | ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 29 | tcsetattr(fileno(fp), TCSAFLUSH, &ts); 30 | fputs(prompt, fp); 31 | 32 | ptr = buf; 33 | while ((c = getc(fp)) != EOF && c != '\n') 34 | if (ptr < &buf[MAX_PASS_LEN]) 35 | *ptr++ = c; 36 | *ptr = 0; /* null terminate */ 37 | putc('\n', fp); /* we echo a newline */ 38 | 39 | tcsetattr(fileno(fp), TCSAFLUSH, &ots); /* restore TTY state */ 40 | sigprocmask(SIG_SETMASK, &osig, NULL); /* restore mask */ 41 | fclose(fp); /* done with /dev/tty */ 42 | return(buf); 43 | } 44 | -------------------------------------------------------------------------------- /Chapter12/exercise_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int 7 | my_putenvr(char* string) 8 | { 9 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 10 | 11 | int retval = -1; 12 | int rc; 13 | sigset_t set = {}; 14 | sigset_t oldset = {}; 15 | 16 | rc = sigfillset(&set); 17 | if (rc < 0) { 18 | return rc; 19 | } 20 | 21 | /* Mask all signals, save existing mask */ 22 | rc = sigprocmask(SIG_SETMASK, &set, &oldset); 23 | if (rc < 0) { 24 | return rc; 25 | } 26 | 27 | if (pthread_mutex_lock(&mutex) != 0) { 28 | retval = -1; 29 | goto restore_signals; 30 | } 31 | 32 | retval = putenv(string); 33 | 34 | if (pthread_mutex_unlock(&mutex) != 0) { 35 | /* 36 | * We locked the lock successfully but failed to unlock it? 37 | * It might be better to terminate here 38 | */ 39 | if (retval == 0) { 40 | retval = -1; 41 | } 42 | } 43 | 44 | restore_signals: 45 | /* Restore previously-masked signals */ 46 | rc = sigprocmask(SIG_SETMASK, &oldset, NULL); 47 | if (retval == 0) { 48 | retval = rc; 49 | } 50 | 51 | return retval; 52 | } 53 | 54 | int 55 | main(void) 56 | { 57 | my_putenvr("x=y"); 58 | printf("x=%s\n", getenv("x")); 59 | 60 | my_putenvr("x=z"); 61 | printf("x=%s\n", getenv("x")); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /apue.3e/pty/driver.c: -------------------------------------------------------------------------------- 1 | #include "apue.h" 2 | 3 | void 4 | do_driver(char *driver) 5 | { 6 | pid_t child; 7 | int pipe[2]; 8 | 9 | /* 10 | * Create a full-duplex pipe to communicate with the driver. 11 | */ 12 | if (fd_pipe(pipe) < 0) 13 | err_sys("can't create stream pipe"); 14 | 15 | if ((child = fork()) < 0) { 16 | err_sys("fork error"); 17 | } else if (child == 0) { /* child */ 18 | close(pipe[1]); 19 | 20 | /* stdin for driver */ 21 | if (dup2(pipe[0], STDIN_FILENO) != STDIN_FILENO) 22 | err_sys("dup2 error to stdin"); 23 | 24 | /* stdout for driver */ 25 | if (dup2(pipe[0], STDOUT_FILENO) != STDOUT_FILENO) 26 | err_sys("dup2 error to stdout"); 27 | if (pipe[0] != STDIN_FILENO && pipe[0] != STDOUT_FILENO) 28 | close(pipe[0]); 29 | 30 | /* leave stderr for driver alone */ 31 | execlp(driver, driver, (char *)0); 32 | err_sys("execlp error for: %s", driver); 33 | } 34 | 35 | close(pipe[0]); /* parent */ 36 | if (dup2(pipe[1], STDIN_FILENO) != STDIN_FILENO) 37 | err_sys("dup2 error to stdin"); 38 | if (dup2(pipe[1], STDOUT_FILENO) != STDOUT_FILENO) 39 | err_sys("dup2 error to stdout"); 40 | if (pipe[1] != STDIN_FILENO && pipe[1] != STDOUT_FILENO) 41 | close(pipe[1]); 42 | 43 | /* 44 | * Parent returns, but with stdin and stdout connected 45 | * to the driver. 46 | */ 47 | } 48 | --------------------------------------------------------------------------------