From e20985d2d6d1d55f41c03f1b93d1b887c02fc933 Mon Sep 17 00:00:00 2001 From: Bruce Guenter Date: Thu, 6 May 2010 23:43:34 -0600 Subject: [PATCH] Initial commit Sources are from the daemontools-0.76.tar.gz, placed into the public domain by D. J. Bernstein on 2007-12-28 (http://cr.yp.to/distributors.html) --- CHANGES | 85 +++++++ Makefile | 510 +++++++++++++++++++++++++++++++++++++++ TODO | 3 + alloc.c | 33 +++ alloc.h | 10 + alloc_re.c | 19 ++ buffer.c | 12 + buffer.h | 61 +++++ buffer_0.c | 13 + buffer_1.c | 7 + buffer_2.c | 7 + buffer_get.c | 69 ++++++ buffer_put.c | 90 +++++++ buffer_read.c | 9 + buffer_write.c | 9 + byte.h | 15 ++ byte_chr.c | 22 ++ byte_copy.c | 16 ++ byte_cr.c | 18 ++ byte_diff.c | 18 ++ byte_rchr.c | 25 ++ chkshsgr.c | 12 + choose.sh | 18 ++ coe.c | 9 + coe.h | 8 + conf-cc | 3 + conf-ld | 3 + deepsleep.c | 19 ++ deepsleep.h | 6 + direntry.h1 | 12 + direntry.h2 | 12 + env.c | 17 ++ env.h | 10 + envdir.c | 86 +++++++ envuidgid.c | 35 +++ error.c | 132 +++++++++++ error.h | 30 +++ error_str.c | 267 +++++++++++++++++++++ fd.h | 9 + fd_copy.c | 14 ++ fd_move.c | 12 + fghack.c | 50 ++++ fifo.c | 12 + fifo.h | 8 + find-systype.sh | 143 +++++++++++ fmt.h | 27 +++ fmt_uint.c | 8 + fmt_uint0.c | 12 + fmt_ulong.c | 15 ++ gen_alloc.h | 9 + gen_allocdefs.h | 36 +++ hasflock.h1 | 3 + hasflock.h2 | 4 + hasmkffo.h1 | 3 + hasmkffo.h2 | 4 + hassgact.h1 | 3 + hassgact.h2 | 4 + hassgprm.h1 | 3 + hassgprm.h2 | 4 + hasshsgr.h1 | 3 + hasshsgr.h2 | 4 + haswaitp.h1 | 3 + haswaitp.h2 | 4 + iopause.c | 78 ++++++ iopause.h1 | 21 ++ iopause.h2 | 20 ++ lock.h | 10 + lock_ex.c | 13 + lock_exnb.c | 13 + match.c | 24 ++ match.h | 6 + matchtest.c | 23 ++ multilog.c | 617 ++++++++++++++++++++++++++++++++++++++++++++++++ ndelay.h | 9 + ndelay_off.c | 14 ++ ndelay_on.c | 14 ++ open.h | 12 + open_append.c | 8 + open_read.c | 8 + open_trunc.c | 8 + open_write.c | 8 + openreadclose.c | 18 ++ openreadclose.h | 10 + pathexec.h | 10 + pathexec_env.c | 69 ++++++ pathexec_run.c | 48 ++++ pgrphack.c | 13 + print-ar.sh | 14 ++ print-cc.sh | 5 + print-ld.sh | 6 + prot.c | 21 ++ prot.h | 9 + readclose.c | 23 ++ readclose.h | 11 + readproctitle.c | 30 +++ rts.tests | 302 ++++++++++++++++++++++++ scan.h | 30 +++ scan_ulong.c | 16 ++ seek.h | 17 ++ seek_set.c | 9 + select.h1 | 12 + select.h2 | 13 + setlock.c | 50 ++++ setuidgid.c | 29 +++ sgetopt.c | 53 +++++ sgetopt.h | 23 ++ sig.c | 15 ++ sig.h | 28 +++ sig_block.c | 40 ++++ sig_catch.c | 18 ++ sig_pause.c | 16 ++ softlimit.c | 127 ++++++++++ str.h | 16 ++ str_chr.c | 19 ++ str_diff.c | 17 ++ str_len.c | 16 ++ str_start.c | 15 ++ stralloc.h | 31 +++ stralloc_cat.c | 9 + stralloc_catb.c | 14 ++ stralloc_cats.c | 10 + stralloc_eady.c | 8 + stralloc_opyb.c | 13 + stralloc_opys.c | 10 + stralloc_pend.c | 7 + strerr.h | 80 +++++++ strerr_die.c | 33 +++ strerr_sys.c | 14 ++ subgetopt.c | 67 ++++++ subgetopt.h | 26 ++ supervise.c | 266 +++++++++++++++++++++ svc.c | 66 ++++++ svok.c | 26 ++ svscan.c | 203 ++++++++++++++++ svscanboot.sh | 11 + svstat.c | 144 +++++++++++ tai.h | 28 +++ tai64n.c | 47 ++++ tai64nlocal.c | 70 ++++++ tai_now.c | 9 + tai_pack.c | 18 ++ tai_sub.c | 8 + tai_unpack.c | 18 ++ taia.h | 36 +++ taia_add.c | 20 ++ taia_approx.c | 8 + taia_frac.c | 8 + taia_less.c | 14 ++ taia_now.c | 15 ++ taia_pack.c | 22 ++ taia_sub.c | 23 ++ taia_uint.c | 12 + timestamp.c | 20 ++ timestamp.h | 8 + trycpp.c | 9 + trydrent.c | 10 + tryflock.c | 10 + trymkffo.c | 9 + trypoll.c | 20 ++ trysgact.c | 12 + trysgprm.c | 12 + tryshsgr.c | 16 ++ trysysel.c | 11 + tryulong64.c | 13 + trywaitp.c | 9 + uint64.h1 | 10 + uint64.h2 | 10 + wait.h | 16 ++ wait_nohang.c | 14 ++ wait_pid.c | 41 ++++ warn-auto.sh | 2 + warn-shsgr | 3 + x86cpuid.c | 40 ++++ 173 files changed, 5890 insertions(+) create mode 100644 CHANGES create mode 100644 Makefile create mode 100644 TODO create mode 100644 alloc.c create mode 100644 alloc.h create mode 100644 alloc_re.c create mode 100644 buffer.c create mode 100644 buffer.h create mode 100644 buffer_0.c create mode 100644 buffer_1.c create mode 100644 buffer_2.c create mode 100644 buffer_get.c create mode 100644 buffer_put.c create mode 100644 buffer_read.c create mode 100644 buffer_write.c create mode 100644 byte.h create mode 100644 byte_chr.c create mode 100644 byte_copy.c create mode 100644 byte_cr.c create mode 100644 byte_diff.c create mode 100644 byte_rchr.c create mode 100644 chkshsgr.c create mode 100644 choose.sh create mode 100644 coe.c create mode 100644 coe.h create mode 100644 conf-cc create mode 100644 conf-ld create mode 100644 deepsleep.c create mode 100644 deepsleep.h create mode 100644 direntry.h1 create mode 100644 direntry.h2 create mode 100644 env.c create mode 100644 env.h create mode 100644 envdir.c create mode 100644 envuidgid.c create mode 100644 error.c create mode 100644 error.h create mode 100644 error_str.c create mode 100644 fd.h create mode 100644 fd_copy.c create mode 100644 fd_move.c create mode 100644 fghack.c create mode 100644 fifo.c create mode 100644 fifo.h create mode 100644 find-systype.sh create mode 100644 fmt.h create mode 100644 fmt_uint.c create mode 100644 fmt_uint0.c create mode 100644 fmt_ulong.c create mode 100644 gen_alloc.h create mode 100644 gen_allocdefs.h create mode 100644 hasflock.h1 create mode 100644 hasflock.h2 create mode 100644 hasmkffo.h1 create mode 100644 hasmkffo.h2 create mode 100644 hassgact.h1 create mode 100644 hassgact.h2 create mode 100644 hassgprm.h1 create mode 100644 hassgprm.h2 create mode 100644 hasshsgr.h1 create mode 100644 hasshsgr.h2 create mode 100644 haswaitp.h1 create mode 100644 haswaitp.h2 create mode 100644 iopause.c create mode 100644 iopause.h1 create mode 100644 iopause.h2 create mode 100644 lock.h create mode 100644 lock_ex.c create mode 100644 lock_exnb.c create mode 100644 match.c create mode 100644 match.h create mode 100644 matchtest.c create mode 100644 multilog.c create mode 100644 ndelay.h create mode 100644 ndelay_off.c create mode 100644 ndelay_on.c create mode 100644 open.h create mode 100644 open_append.c create mode 100644 open_read.c create mode 100644 open_trunc.c create mode 100644 open_write.c create mode 100644 openreadclose.c create mode 100644 openreadclose.h create mode 100644 pathexec.h create mode 100644 pathexec_env.c create mode 100644 pathexec_run.c create mode 100644 pgrphack.c create mode 100644 print-ar.sh create mode 100644 print-cc.sh create mode 100644 print-ld.sh create mode 100644 prot.c create mode 100644 prot.h create mode 100644 readclose.c create mode 100644 readclose.h create mode 100644 readproctitle.c create mode 100644 rts.tests create mode 100644 scan.h create mode 100644 scan_ulong.c create mode 100644 seek.h create mode 100644 seek_set.c create mode 100644 select.h1 create mode 100644 select.h2 create mode 100644 setlock.c create mode 100644 setuidgid.c create mode 100644 sgetopt.c create mode 100644 sgetopt.h create mode 100644 sig.c create mode 100644 sig.h create mode 100644 sig_block.c create mode 100644 sig_catch.c create mode 100644 sig_pause.c create mode 100644 softlimit.c create mode 100644 str.h create mode 100644 str_chr.c create mode 100644 str_diff.c create mode 100644 str_len.c create mode 100644 str_start.c create mode 100644 stralloc.h create mode 100644 stralloc_cat.c create mode 100644 stralloc_catb.c create mode 100644 stralloc_cats.c create mode 100644 stralloc_eady.c create mode 100644 stralloc_opyb.c create mode 100644 stralloc_opys.c create mode 100644 stralloc_pend.c create mode 100644 strerr.h create mode 100644 strerr_die.c create mode 100644 strerr_sys.c create mode 100644 subgetopt.c create mode 100644 subgetopt.h create mode 100644 supervise.c create mode 100644 svc.c create mode 100644 svok.c create mode 100644 svscan.c create mode 100644 svscanboot.sh create mode 100644 svstat.c create mode 100644 tai.h create mode 100644 tai64n.c create mode 100644 tai64nlocal.c create mode 100644 tai_now.c create mode 100644 tai_pack.c create mode 100644 tai_sub.c create mode 100644 tai_unpack.c create mode 100644 taia.h create mode 100644 taia_add.c create mode 100644 taia_approx.c create mode 100644 taia_frac.c create mode 100644 taia_less.c create mode 100644 taia_now.c create mode 100644 taia_pack.c create mode 100644 taia_sub.c create mode 100644 taia_uint.c create mode 100644 timestamp.c create mode 100644 timestamp.h create mode 100644 trycpp.c create mode 100644 trydrent.c create mode 100644 tryflock.c create mode 100644 trymkffo.c create mode 100644 trypoll.c create mode 100644 trysgact.c create mode 100644 trysgprm.c create mode 100644 tryshsgr.c create mode 100644 trysysel.c create mode 100644 tryulong64.c create mode 100644 trywaitp.c create mode 100644 uint64.h1 create mode 100644 uint64.h2 create mode 100644 wait.h create mode 100644 wait_nohang.c create mode 100644 wait_pid.c create mode 100644 warn-auto.sh create mode 100644 warn-shsgr create mode 100644 x86cpuid.c diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..28f310f --- /dev/null +++ b/CHANGES @@ -0,0 +1,85 @@ +19990824 + version: daemontools 0.60, alpha. +19990825 + portability problem: some systems need sys/time.h, not just + time.h, before sys/resource.h. impact: couldn't compile. + fix: change time.h to sys/time.h in softlimit.c. tnx Jos + Backus and Chris Johnson. + portability problem: echo -n echoes literal -n under traditional + System V. tnx Tim Goodwin. impact: rts mismatch. fix: + echo | tr -d. + doc: removed note on man pages in conf-home. tnx Mate Wierdl. + ui: do pidchange() and announce() before opening supervise/ok in + supervise.c. +19990826 + version: daemontools 0.61, alpha. +20000304 + internal: upgraded to latest installation system. + internal: switched from substdio to buffer. + internal: switched from execvp to pathexec. + internal: miscellaneous cleanups. + internal: sped up tai64n. + ui: svscan sleeps only 5 seconds. + ui: svscan chdirs to argv[1] if argv[1] is supplied. + ui: supervise does exec without waiting 1 second in child; but + it waits 1 second before continuing in parent. + ui: svstat reports time since last supervise pid change. + ui: added envdir. + ui: incorporated setlock from serialmail. +20000305 + internal: switched to new sig library. + internal: switched to iopause. + internal: more cleanups. + internal: sped up multilog. + ui: multilog sets current to mode 644 on restart. + version: daemontools 0.70, beta. +20000315 + internal: new iopause. +20000316 + internal: supervise does announce() only after changing state. + avoids disk writes when supervise is idle. +20010707 + internal: added const at various places. + internal: miscellaneous cleanups. + portability problem: with recent versions of glibc, and on AIX, + including sys/time.h doesn't define struct tm. impact: + couldn't compile. fix: also include time.h. tnx many + people. + portability problem: although sleep() isn't interrupted by + signals on my old BSD/OS development machine, it is + interrupted by signals on all new systems. impact: if a + supervised process dies quickly (but not too quickly), + supervise's 1-second sleep is interrupted, and the + process is restarted immediately. fix: new deepsleep(). + internal: switched signal handling in supervise and multilog + to blocked-by-default. + ui: multilog accepts ALRM to immediately rotate all cyclic logs + for which current is nonempty. tnx Peter Samuel and + William E. Baxter. +20010708 + portability problem: under System V, one process can hold many + exclusive locks on one file. impact: no impact on normal + use, but some of the setlock regression tests fail. fix: + change the tests to invoke an intermediate sh. tnx Mads + Eilertsen. + internal: fitfiles() in multilog. + ui: added readproctitle. + ui: added svscanboot. tnx Matthias Andree. + ui: svscan checks for log directory instead of sticky bit. tnx + many people. +20010709 + ui: added pgrphack. +20010710 + internal: upgraded to latest installation system. +20010711 + version: daemontools 0.75, beta. +20010712 + internal: ./package/compile creates ./compile/home. + internal: ./package/compile creates absolute ./compile/src + symlink instead of using .., so ./compile can itself be + a symlink. tnx Paul Jarc. + portability problem: Solaris sh has a built-in test that doesn't + support -e, even though the test program supports -e. + impact: package/{compile,run,upgrade} fail. tnx Mate + Wierdl. fix: use -d, -h, -r. + version: daemontools 0.76, beta. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d45aec9 --- /dev/null +++ b/Makefile @@ -0,0 +1,510 @@ +default: it + +clean: + rm -f alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ + buffer_get.o buffer_put.o buffer_read.o buffer_write.o byte.a \ + byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o chkshsgr \ + chkshsgr.o choose coe.o compile deepsleep.o direntry.h env.o envdir \ + envdir.o envuidgid envuidgid.o error.o error_str.o fd_copy.o \ + fd_move.o fghack fghack.o fifo.o fmt_uint.o fmt_uint0.o fmt_ulong.o \ + hasflock.h hasmkffo.h hassgact.h hassgprm.h hasshsgr.h haswaitp.h \ + iopause.h iopause.o it load lock_ex.o lock_exnb.o makelib match.o \ + matchtest matchtest.o multilog multilog.o ndelay_off.o ndelay_on.o \ + open_append.o open_read.o open_trunc.o open_write.o openreadclose.o \ + pathexec_env.o pathexec_run.o pgrphack pgrphack.o prot.o readclose.o \ + readproctitle readproctitle.o rts scan_ulong.o seek_set.o select.h \ + setlock setlock.o setuidgid setuidgid.o sgetopt.o sig.o sig_block.o \ + sig_catch.o sig_pause.o softlimit softlimit.o str_chr.o str_diff.o \ + str_len.o str_start.o stralloc_cat.o stralloc_catb.o stralloc_cats.o \ + stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o \ + strerr_die.o strerr_sys.o subgetopt.o supervise supervise.o svc svc.o \ + svok svok.o svscan svscan.o svscanboot svstat svstat.o sysdeps \ + systype tai64n tai64n.o tai64nlocal tai64nlocal.o tai_now.o \ + tai_pack.o tai_sub.o tai_unpack.o taia_add.o taia_approx.o \ + taia_frac.o taia_less.o taia_now.o taia_pack.o taia_sub.o taia_uint.o \ + time.a timestamp.o uint64.h unix.a wait_nohang.o wait_pid.o + +alloc.o: alloc.c alloc.h compile error.h + ./compile alloc.c + +alloc_re.o: alloc.h alloc_re.c byte.h compile + ./compile alloc_re.c + +buffer.o: buffer.c buffer.h compile + ./compile buffer.c + +buffer_0.o: buffer.h buffer_0.c compile + ./compile buffer_0.c + +buffer_1.o: buffer.h buffer_1.c compile + ./compile buffer_1.c + +buffer_2.o: buffer.h buffer_2.c compile + ./compile buffer_2.c + +buffer_get.o: buffer.h buffer_get.c byte.h compile error.h + ./compile buffer_get.c + +buffer_put.o: buffer.h buffer_put.c byte.h compile error.h str.h + ./compile buffer_put.c + +buffer_read.o: buffer.h buffer_read.c compile + ./compile buffer_read.c + +buffer_write.o: buffer.h buffer_write.c compile + ./compile buffer_write.c + +byte.a: byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o \ +fmt_uint.o fmt_uint0.o fmt_ulong.o makelib scan_ulong.o str_chr.o \ +str_diff.o str_len.o str_start.o + ./makelib byte.a byte_chr.o byte_copy.o byte_cr.o byte_diff.o \ + byte_rchr.o fmt_uint.o fmt_uint0.o fmt_ulong.o scan_ulong.o str_chr.o \ + str_diff.o str_len.o str_start.o + +byte_chr.o: byte.h byte_chr.c compile + ./compile byte_chr.c + +byte_copy.o: byte.h byte_copy.c compile + ./compile byte_copy.c + +byte_cr.o: byte.h byte_cr.c compile + ./compile byte_cr.c + +byte_diff.o: byte.h byte_diff.c compile + ./compile byte_diff.c + +byte_rchr.o: byte.h byte_rchr.c compile + ./compile byte_rchr.c + +chkshsgr: chkshsgr.o load + ./load chkshsgr + +chkshsgr.o: chkshsgr.c compile + ./compile chkshsgr.c + +choose: choose.sh home warn-auto.sh + rm -f choose + cat warn-auto.sh choose.sh \ + | sed s}HOME}"`head -1 home`"}g \ + > choose + chmod 555 choose + +coe.o: coe.c coe.h compile + ./compile coe.c + +compile: conf-cc print-cc.sh systype warn-auto.sh + rm -f compile + sh print-cc.sh > compile + chmod 555 compile + +deepsleep.o: compile deepsleep.c deepsleep.h iopause.h tai.h taia.h \ +uint64.h + ./compile deepsleep.c + +direntry.h: choose compile direntry.h1 direntry.h2 trydrent.c + ./choose c trydrent direntry.h1 direntry.h2 > direntry.h + +env.o: compile env.c env.h str.h + ./compile env.c + +envdir: byte.a envdir.o load unix.a + ./load envdir unix.a byte.a + +envdir.o: byte.h compile direntry.h envdir.c error.h gen_alloc.h \ +open.h openreadclose.h pathexec.h stralloc.h strerr.h + ./compile envdir.c + +envuidgid: byte.a envuidgid.o load unix.a + ./load envuidgid unix.a byte.a + +envuidgid.o: compile envuidgid.c fmt.h pathexec.h strerr.h + ./compile envuidgid.c + +error.o: compile error.c error.h + ./compile error.c + +error_str.o: compile error.h error_str.c + ./compile error_str.c + +fd_copy.o: compile fd.h fd_copy.c + ./compile fd_copy.c + +fd_move.o: compile fd.h fd_move.c + ./compile fd_move.c + +fghack: byte.a fghack.o load unix.a + ./load fghack unix.a byte.a + +fghack.o: buffer.h compile error.h fghack.c pathexec.h strerr.h \ +wait.h + ./compile fghack.c + +fifo.o: compile fifo.c fifo.h hasmkffo.h + ./compile fifo.c + +fmt_uint.o: compile fmt.h fmt_uint.c + ./compile fmt_uint.c + +fmt_uint0.o: compile fmt.h fmt_uint0.c + ./compile fmt_uint0.c + +fmt_ulong.o: compile fmt.h fmt_ulong.c + ./compile fmt_ulong.c + +hasflock.h: choose compile hasflock.h1 hasflock.h2 load tryflock.c + ./choose cl tryflock hasflock.h1 hasflock.h2 > hasflock.h + +hasmkffo.h: choose compile hasmkffo.h1 hasmkffo.h2 load trymkffo.c + ./choose cl trymkffo hasmkffo.h1 hasmkffo.h2 > hasmkffo.h + +hassgact.h: choose compile hassgact.h1 hassgact.h2 load trysgact.c + ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h + +hassgprm.h: choose compile hassgprm.h1 hassgprm.h2 load trysgprm.c + ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h + +hasshsgr.h: chkshsgr choose compile hasshsgr.h1 hasshsgr.h2 load \ +tryshsgr.c warn-shsgr + ./chkshsgr || ( cat warn-shsgr; exit 1 ) + ./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h + +haswaitp.h: choose compile haswaitp.h1 haswaitp.h2 load trywaitp.c + ./choose cl trywaitp haswaitp.h1 haswaitp.h2 > haswaitp.h + +iopause.h: choose compile iopause.h1 iopause.h2 load trypoll.c + ./choose clr trypoll iopause.h1 iopause.h2 > iopause.h + +iopause.o: compile iopause.c iopause.h select.h tai.h taia.h uint64.h + ./compile iopause.c + +it: rts sysdeps + +load: conf-ld print-ld.sh systype warn-auto.sh + rm -f load + sh print-ld.sh > load + chmod 555 load + +lock_ex.o: compile hasflock.h lock.h lock_ex.c + ./compile lock_ex.c + +lock_exnb.o: compile hasflock.h lock.h lock_exnb.c + ./compile lock_exnb.c + +makelib: print-ar.sh systype warn-auto.sh + rm -f makelib + sh print-ar.sh > makelib + chmod 555 makelib + +match.o: compile match.c match.h + ./compile match.c + +matchtest: byte.a load match.o matchtest.o unix.a + ./load matchtest match.o unix.a byte.a + +matchtest.o: buffer.h compile match.h matchtest.c str.h + ./compile matchtest.c + +multilog: byte.a deepsleep.o load match.o multilog.o time.a \ +timestamp.o unix.a + ./load multilog deepsleep.o timestamp.o match.o time.a unix.a byte.a + +multilog.o: alloc.h buffer.h byte.h coe.h compile deepsleep.h \ +direntry.h env.h error.h fd.h lock.h match.h multilog.c open.h scan.h \ +seek.h sig.h str.h strerr.h timestamp.h wait.h + ./compile multilog.c + +ndelay_off.o: compile ndelay.h ndelay_off.c + ./compile ndelay_off.c + +ndelay_on.o: compile ndelay.h ndelay_on.c + ./compile ndelay_on.c + +open_append.o: compile open.h open_append.c + ./compile open_append.c + +open_read.o: compile open.h open_read.c + ./compile open_read.c + +open_trunc.o: compile open.h open_trunc.c + ./compile open_trunc.c + +open_write.o: compile open.h open_write.c + ./compile open_write.c + +openreadclose.o: compile error.h gen_alloc.h open.h openreadclose.c \ +openreadclose.h readclose.h stralloc.h + ./compile openreadclose.c + +pathexec_env.o: alloc.h byte.h compile env.h gen_alloc.h pathexec.h \ +pathexec_env.c str.h stralloc.h + ./compile pathexec_env.c + +pathexec_run.o: compile env.h error.h gen_alloc.h pathexec.h \ +pathexec_run.c str.h stralloc.h + ./compile pathexec_run.c + +pgrphack: byte.a load pgrphack.o unix.a + ./load pgrphack unix.a byte.a + +pgrphack.o: compile pathexec.h pgrphack.c strerr.h + ./compile pgrphack.c + +prot.o: compile hasshsgr.h prot.c prot.h + ./compile prot.c + +readclose.o: compile error.h gen_alloc.h readclose.c readclose.h \ +stralloc.h + ./compile readclose.c + +readproctitle: byte.a load readproctitle.o unix.a + ./load readproctitle unix.a byte.a + +readproctitle.o: compile error.h readproctitle.c + ./compile readproctitle.c + +rts: envdir envuidgid fghack matchtest multilog pgrphack \ +readproctitle rts.tests setlock setuidgid softlimit supervise svc \ +svok svscan svscanboot svstat tai64n tai64nlocal + env - /bin/sh rts.tests 2>&1 | cat -v > rts + +scan_ulong.o: compile scan.h scan_ulong.c + ./compile scan_ulong.c + +seek_set.o: compile seek.h seek_set.c + ./compile seek_set.c + +select.h: choose compile select.h1 select.h2 trysysel.c + ./choose c trysysel select.h1 select.h2 > select.h + +setlock: byte.a load setlock.o unix.a + ./load setlock unix.a byte.a + +setlock.o: compile lock.h open.h pathexec.h setlock.c sgetopt.h \ +strerr.h subgetopt.h + ./compile setlock.c + +setuidgid: byte.a load setuidgid.o unix.a + ./load setuidgid unix.a byte.a + +setuidgid.o: compile pathexec.h prot.h setuidgid.c strerr.h + ./compile setuidgid.c + +sgetopt.o: buffer.h compile sgetopt.c sgetopt.h subgetopt.h + ./compile sgetopt.c + +sig.o: compile sig.c sig.h + ./compile sig.c + +sig_block.o: compile hassgprm.h sig.h sig_block.c + ./compile sig_block.c + +sig_catch.o: compile hassgact.h sig.h sig_catch.c + ./compile sig_catch.c + +sig_pause.o: compile hassgprm.h sig.h sig_pause.c + ./compile sig_pause.c + +softlimit: byte.a load softlimit.o unix.a + ./load softlimit unix.a byte.a + +softlimit.o: compile pathexec.h scan.h sgetopt.h softlimit.c str.h \ +strerr.h subgetopt.h + ./compile softlimit.c + +str_chr.o: compile str.h str_chr.c + ./compile str_chr.c + +str_diff.o: compile str.h str_diff.c + ./compile str_diff.c + +str_len.o: compile str.h str_len.c + ./compile str_len.c + +str_start.o: compile str.h str_start.c + ./compile str_start.c + +stralloc_cat.o: byte.h compile gen_alloc.h stralloc.h stralloc_cat.c + ./compile stralloc_cat.c + +stralloc_catb.o: byte.h compile gen_alloc.h stralloc.h \ +stralloc_catb.c + ./compile stralloc_catb.c + +stralloc_cats.o: byte.h compile gen_alloc.h str.h stralloc.h \ +stralloc_cats.c + ./compile stralloc_cats.c + +stralloc_eady.o: alloc.h compile gen_alloc.h gen_allocdefs.h \ +stralloc.h stralloc_eady.c + ./compile stralloc_eady.c + +stralloc_opyb.o: byte.h compile gen_alloc.h stralloc.h \ +stralloc_opyb.c + ./compile stralloc_opyb.c + +stralloc_opys.o: byte.h compile gen_alloc.h str.h stralloc.h \ +stralloc_opys.c + ./compile stralloc_opys.c + +stralloc_pend.o: alloc.h compile gen_alloc.h gen_allocdefs.h \ +stralloc.h stralloc_pend.c + ./compile stralloc_pend.c + +strerr_die.o: buffer.h compile strerr.h strerr_die.c + ./compile strerr_die.c + +strerr_sys.o: compile error.h strerr.h strerr_sys.c + ./compile strerr_sys.c + +subgetopt.o: compile subgetopt.c subgetopt.h + ./compile subgetopt.c + +supervise: byte.a deepsleep.o load supervise.o time.a unix.a + ./load supervise deepsleep.o time.a unix.a byte.a + +supervise.o: coe.h compile deepsleep.h env.h error.h fifo.h iopause.h \ +lock.h ndelay.h open.h sig.h strerr.h supervise.c tai.h taia.h \ +uint64.h wait.h + ./compile supervise.c + +svc: byte.a load svc.o unix.a + ./load svc unix.a byte.a + +svc.o: buffer.h byte.h compile error.h ndelay.h open.h sgetopt.h \ +sig.h strerr.h subgetopt.h svc.c + ./compile svc.c + +svok: byte.a load svok.o unix.a + ./load svok unix.a byte.a + +svok.o: compile error.h open.h strerr.h svok.c + ./compile svok.c + +svscan: byte.a load svscan.o unix.a + ./load svscan unix.a byte.a + +svscan.o: byte.h coe.h compile direntry.h env.h error.h fd.h \ +pathexec.h str.h strerr.h svscan.c wait.h + ./compile svscan.c + +svscanboot: home svscanboot.sh warn-auto.sh + rm -f svscanboot + cat warn-auto.sh svscanboot.sh \ + | sed s}HOME}"`head -1 home`"}g \ + > svscanboot + chmod 555 svscanboot + +svstat: byte.a load svstat.o time.a unix.a + ./load svstat time.a unix.a byte.a + +svstat.o: buffer.h compile error.h fmt.h open.h strerr.h svstat.c \ +tai.h uint64.h + ./compile svstat.c + +sysdeps: compile direntry.h hasflock.h hasmkffo.h hassgact.h \ +hassgprm.h hasshsgr.h haswaitp.h iopause.h load select.h systype \ +uint64.h + rm -f sysdeps + cat systype compile load >> sysdeps + grep sysdep direntry.h >> sysdeps + grep sysdep haswaitp.h >> sysdeps + grep sysdep hassgact.h >> sysdeps + grep sysdep hassgprm.h >> sysdeps + grep sysdep select.h >> sysdeps + grep sysdep uint64.h >> sysdeps + grep sysdep iopause.h >> sysdeps + grep sysdep hasmkffo.h >> sysdeps + grep sysdep hasflock.h >> sysdeps + grep sysdep hasshsgr.h >> sysdeps + +systype: find-systype.sh trycpp.c x86cpuid.c + sh find-systype.sh > systype + +tai64n: byte.a load tai64n.o time.a timestamp.o unix.a + ./load tai64n timestamp.o time.a unix.a byte.a + +tai64n.o: buffer.h compile tai64n.c timestamp.h + ./compile tai64n.c + +tai64nlocal: byte.a load tai64nlocal.o unix.a + ./load tai64nlocal unix.a byte.a + +tai64nlocal.o: buffer.h compile fmt.h tai64nlocal.c + ./compile tai64nlocal.c + +tai_now.o: compile tai.h tai_now.c uint64.h + ./compile tai_now.c + +tai_pack.o: compile tai.h tai_pack.c uint64.h + ./compile tai_pack.c + +tai_sub.o: compile tai.h tai_sub.c uint64.h + ./compile tai_sub.c + +tai_unpack.o: compile tai.h tai_unpack.c uint64.h + ./compile tai_unpack.c + +taia_add.o: compile tai.h taia.h taia_add.c uint64.h + ./compile taia_add.c + +taia_approx.o: compile tai.h taia.h taia_approx.c uint64.h + ./compile taia_approx.c + +taia_frac.o: compile tai.h taia.h taia_frac.c uint64.h + ./compile taia_frac.c + +taia_less.o: compile tai.h taia.h taia_less.c uint64.h + ./compile taia_less.c + +taia_now.o: compile tai.h taia.h taia_now.c uint64.h + ./compile taia_now.c + +taia_pack.o: compile tai.h taia.h taia_pack.c uint64.h + ./compile taia_pack.c + +taia_sub.o: compile tai.h taia.h taia_sub.c uint64.h + ./compile taia_sub.c + +taia_uint.o: compile tai.h taia.h taia_uint.c uint64.h + ./compile taia_uint.c + +time.a: iopause.o makelib tai_now.o tai_pack.o tai_sub.o tai_unpack.o \ +taia_add.o taia_approx.o taia_frac.o taia_less.o taia_now.o \ +taia_pack.o taia_sub.o taia_uint.o + ./makelib time.a iopause.o tai_now.o tai_pack.o tai_sub.o \ + tai_unpack.o taia_add.o taia_approx.o taia_frac.o taia_less.o \ + taia_now.o taia_pack.o taia_sub.o taia_uint.o + +timestamp.o: compile tai.h taia.h timestamp.c timestamp.h uint64.h + ./compile timestamp.c + +uint64.h: choose compile load tryulong64.c uint64.h1 uint64.h2 + ./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h + +unix.a: alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ +buffer_get.o buffer_put.o buffer_read.o buffer_write.o coe.o env.o \ +error.o error_str.o fd_copy.o fd_move.o fifo.o lock_ex.o lock_exnb.o \ +makelib ndelay_off.o ndelay_on.o open_append.o open_read.o \ +open_trunc.o open_write.o openreadclose.o pathexec_env.o \ +pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \ +sig_block.o sig_catch.o sig_pause.o stralloc_cat.o stralloc_catb.o \ +stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \ +stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o \ +wait_pid.o + ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o \ + buffer_2.o buffer_get.o buffer_put.o buffer_read.o buffer_write.o \ + coe.o env.o error.o error_str.o fd_copy.o fd_move.o fifo.o lock_ex.o \ + lock_exnb.o ndelay_off.o ndelay_on.o open_append.o open_read.o \ + open_trunc.o open_write.o openreadclose.o pathexec_env.o \ + pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \ + sig_block.o sig_catch.o sig_pause.o stralloc_cat.o stralloc_catb.o \ + stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \ + stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o \ + wait_pid.o + +wait_nohang.o: compile haswaitp.h wait_nohang.c + ./compile wait_nohang.c + +wait_pid.o: compile error.h haswaitp.h wait_pid.c + ./compile wait_pid.c + diff --git a/TODO b/TODO new file mode 100644 index 0000000..77a6425 --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +expand rts +document disk state diagram for a cyclic log in multilog +use libtai local-time routines in tai64nlocal diff --git a/alloc.c b/alloc.c new file mode 100644 index 0000000..c741aa4 --- /dev/null +++ b/alloc.c @@ -0,0 +1,33 @@ +/* Public domain. */ + +#include +#include "alloc.h" +#include "error.h" + +#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ +#define SPACE 2048 /* must be multiple of ALIGNMENT */ + +typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; +static aligned realspace[SPACE / ALIGNMENT]; +#define space ((char *) realspace) +static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +/*@null@*//*@out@*/char *alloc(n) +unsigned int n; +{ + char *x; + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); + if (!x) errno = error_nomem; + return x; +} + +void alloc_free(x) +char *x; +{ + if (x >= space) + if (x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); +} diff --git a/alloc.h b/alloc.h new file mode 100644 index 0000000..21122fc --- /dev/null +++ b/alloc.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef ALLOC_H +#define ALLOC_H + +extern /*@null@*//*@out@*/char *alloc(); +extern void alloc_free(); +extern int alloc_re(); + +#endif diff --git a/alloc_re.c b/alloc_re.c new file mode 100644 index 0000000..1074609 --- /dev/null +++ b/alloc_re.c @@ -0,0 +1,19 @@ +/* Public domain. */ + +#include "alloc.h" +#include "byte.h" + +int alloc_re(x,m,n) +char **x; +unsigned int m; +unsigned int n; +{ + char *y; + + y = alloc(n); + if (!y) return 0; + byte_copy(y,m,*x); + alloc_free(*x); + *x = y; + return 1; +} diff --git a/buffer.c b/buffer.c new file mode 100644 index 0000000..38e6d77 --- /dev/null +++ b/buffer.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include "buffer.h" + +void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len) +{ + s->x = buf; + s->fd = fd; + s->op = op; + s->p = 0; + s->n = len; +} diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..8f2e572 --- /dev/null +++ b/buffer.h @@ -0,0 +1,61 @@ +/* Public domain. */ + +#ifndef BUFFER_H +#define BUFFER_H + +typedef struct buffer { + char *x; + unsigned int p; + unsigned int n; + int fd; + int (*op)(); +} buffer; + +#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } +#define BUFFER_INSIZE 8192 +#define BUFFER_OUTSIZE 8192 + +extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int); + +extern int buffer_flush(buffer *); +extern int buffer_put(buffer *,const char *,unsigned int); +extern int buffer_putalign(buffer *,const char *,unsigned int); +extern int buffer_putflush(buffer *,const char *,unsigned int); +extern int buffer_puts(buffer *,const char *); +extern int buffer_putsalign(buffer *,const char *); +extern int buffer_putsflush(buffer *,const char *); + +#define buffer_PUTC(s,c) \ + ( ((s)->n != (s)->p) \ + ? ( (s)->x[(s)->p++] = (c), 0 ) \ + : buffer_put((s),&(c),1) \ + ) + +extern int buffer_get(buffer *,char *,unsigned int); +extern int buffer_bget(buffer *,char *,unsigned int); +extern int buffer_feed(buffer *); + +extern char *buffer_peek(buffer *); +extern void buffer_seek(buffer *,unsigned int); + +#define buffer_PEEK(s) ( (s)->x + (s)->n ) +#define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) + +#define buffer_GETC(s,c) \ + ( ((s)->p > 0) \ + ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \ + : buffer_get((s),(c),1) \ + ) + +extern int buffer_copy(buffer *,buffer *); + +extern int buffer_unixread(int,char *,unsigned int); +extern int buffer_unixwrite(int,const char *,unsigned int); + +extern buffer *buffer_0; +extern buffer *buffer_0small; +extern buffer *buffer_1; +extern buffer *buffer_1small; +extern buffer *buffer_2; + +#endif diff --git a/buffer_0.c b/buffer_0.c new file mode 100644 index 0000000..47d3263 --- /dev/null +++ b/buffer_0.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include "buffer.h" + +int buffer_0_read(fd,buf,len) int fd; char *buf; int len; +{ + if (buffer_flush(buffer_1) == -1) return -1; + return buffer_unixread(fd,buf,len); +} + +char buffer_0_space[BUFFER_INSIZE]; +static buffer it = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof buffer_0_space); +buffer *buffer_0 = ⁢ diff --git a/buffer_1.c b/buffer_1.c new file mode 100644 index 0000000..f4bac3d --- /dev/null +++ b/buffer_1.c @@ -0,0 +1,7 @@ +/* Public domain. */ + +#include "buffer.h" + +char buffer_1_space[BUFFER_OUTSIZE]; +static buffer it = BUFFER_INIT(buffer_unixwrite,1,buffer_1_space,sizeof buffer_1_space); +buffer *buffer_1 = ⁢ diff --git a/buffer_2.c b/buffer_2.c new file mode 100644 index 0000000..f255a92 --- /dev/null +++ b/buffer_2.c @@ -0,0 +1,7 @@ +/* Public domain. */ + +#include "buffer.h" + +char buffer_2_space[256]; +static buffer it = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof buffer_2_space); +buffer *buffer_2 = ⁢ diff --git a/buffer_get.c b/buffer_get.c new file mode 100644 index 0000000..3a6e1b6 --- /dev/null +++ b/buffer_get.c @@ -0,0 +1,69 @@ +/* Public domain. */ + +#include "buffer.h" +#include "byte.h" +#include "error.h" + +static int oneread(int (*op)(),int fd,char *buf,unsigned int len) +{ + int r; + + for (;;) { + r = op(fd,buf,len); + if (r == -1) if (errno == error_intr) continue; + return r; + } +} + +static int getthis(buffer *s,char *buf,unsigned int len) +{ + if (len > s->p) len = s->p; + s->p -= len; + byte_copy(buf,len,s->x + s->n); + s->n += len; + return len; +} + +int buffer_feed(buffer *s) +{ + int r; + + if (s->p) return s->p; + r = oneread(s->op,s->fd,s->x,s->n); + if (r <= 0) return r; + s->p = r; + s->n -= r; + if (s->n > 0) byte_copyr(s->x + s->n,r,s->x); + return r; +} + +int buffer_bget(buffer *s,char *buf,unsigned int len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); + r = buffer_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +int buffer_get(buffer *s,char *buf,unsigned int len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,len); + r = buffer_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +char *buffer_peek(buffer *s) +{ + return s->x + s->n; +} + +void buffer_seek(buffer *s,unsigned int len) +{ + s->n += len; + s->p -= len; +} diff --git a/buffer_put.c b/buffer_put.c new file mode 100644 index 0000000..23164b3 --- /dev/null +++ b/buffer_put.c @@ -0,0 +1,90 @@ +/* Public domain. */ + +#include "buffer.h" +#include "str.h" +#include "byte.h" +#include "error.h" + +static int allwrite(int (*op)(),int fd,const char *buf,unsigned int len) +{ + int w; + + while (len) { + w = op(fd,buf,len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +int buffer_flush(buffer *s) +{ + int p; + + p = s->p; + if (!p) return 0; + s->p = 0; + return allwrite(s->op,s->fd,s->x,p); +} + +int buffer_putalign(buffer *s,const char *buf,unsigned int len) +{ + unsigned int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; + if (buffer_flush(s) == -1) return -1; + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_put(buffer *s,const char *buf,unsigned int len) +{ + unsigned int n; + + n = s->n; + if (len > n - s->p) { + if (buffer_flush(s) == -1) return -1; + /* now s->p == 0 */ + if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; + while (len > s->n) { + if (n > len) n = len; + if (allwrite(s->op,s->fd,buf,n) == -1) return -1; + buf += n; + len -= n; + } + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_putflush(buffer *s,const char *buf,unsigned int len) +{ + if (buffer_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +} + +int buffer_putsalign(buffer *s,const char *buf) +{ + return buffer_putalign(s,buf,str_len(buf)); +} + +int buffer_puts(buffer *s,const char *buf) +{ + return buffer_put(s,buf,str_len(buf)); +} + +int buffer_putsflush(buffer *s,const char *buf) +{ + return buffer_putflush(s,buf,str_len(buf)); +} diff --git a/buffer_read.c b/buffer_read.c new file mode 100644 index 0000000..09db05f --- /dev/null +++ b/buffer_read.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include "buffer.h" + +int buffer_unixread(int fd,char *buf,unsigned int len) +{ + return read(fd,buf,len); +} diff --git a/buffer_write.c b/buffer_write.c new file mode 100644 index 0000000..4ba13ef --- /dev/null +++ b/buffer_write.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include "buffer.h" + +int buffer_unixwrite(int fd,const char *buf,unsigned int len) +{ + return write(fd,buf,len); +} diff --git a/byte.h b/byte.h new file mode 100644 index 0000000..09aab61 --- /dev/null +++ b/byte.h @@ -0,0 +1,15 @@ +/* Public domain. */ + +#ifndef BYTE_H +#define BYTE_H + +extern unsigned int byte_chr(); +extern unsigned int byte_rchr(); +extern void byte_copy(); +extern void byte_copyr(); +extern int byte_diff(); +extern void byte_zero(); + +#define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +#endif diff --git a/byte_chr.c b/byte_chr.c new file mode 100644 index 0000000..fd56056 --- /dev/null +++ b/byte_chr.c @@ -0,0 +1,22 @@ +/* Public domain. */ + +#include "byte.h" + +unsigned int byte_chr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + + ch = c; + t = s; + for (;;) { + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + } + return t - s; +} diff --git a/byte_copy.c b/byte_copy.c new file mode 100644 index 0000000..74c9e4a --- /dev/null +++ b/byte_copy.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include "byte.h" + +void byte_copy(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + for (;;) { + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + } +} diff --git a/byte_cr.c b/byte_cr.c new file mode 100644 index 0000000..52dc251 --- /dev/null +++ b/byte_cr.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "byte.h" + +void byte_copyr(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + to += n; + from += n; + for (;;) { + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + } +} diff --git a/byte_diff.c b/byte_diff.c new file mode 100644 index 0000000..0c4d17b --- /dev/null +++ b/byte_diff.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "byte.h" + +int byte_diff(s,n,t) +register char *s; +register unsigned int n; +register char *t; +{ + for (;;) { + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + } + return ((int)(unsigned int)(unsigned char) *s) + - ((int)(unsigned int)(unsigned char) *t); +} diff --git a/byte_rchr.c b/byte_rchr.c new file mode 100644 index 0000000..7ea9948 --- /dev/null +++ b/byte_rchr.c @@ -0,0 +1,25 @@ +/* Public domain. */ + +#include "byte.h" + +unsigned int byte_rchr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + register char *u; + + ch = c; + t = s; + u = 0; + for (;;) { + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + } + if (!u) u = t; + return u - s; +} diff --git a/chkshsgr.c b/chkshsgr.c new file mode 100644 index 0000000..38c352d --- /dev/null +++ b/chkshsgr.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include + +int main() +{ + short x[4]; + + x[0] = x[1] = 0; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + _exit(0); +} diff --git a/choose.sh b/choose.sh new file mode 100644 index 0000000..feff2da --- /dev/null +++ b/choose.sh @@ -0,0 +1,18 @@ + +result="$4" + +case "$1" in + *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *r*) ./$2 >/dev/null 2>&1 || result="$3" ;; +esac + +rm -f $2.o $2 + +exec cat "$result" diff --git a/coe.c b/coe.c new file mode 100644 index 0000000..50b2397 --- /dev/null +++ b/coe.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include "coe.h" + +int coe(int fd) +{ + return fcntl(fd,F_SETFD,1); +} diff --git a/coe.h b/coe.h new file mode 100644 index 0000000..b17db54 --- /dev/null +++ b/coe.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef COE_H +#define COE_H + +extern int coe(int); + +#endif diff --git a/conf-cc b/conf-cc new file mode 100644 index 0000000..b315ecb --- /dev/null +++ b/conf-cc @@ -0,0 +1,3 @@ +gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings + +This will be used to compile .c files. diff --git a/conf-ld b/conf-ld new file mode 100644 index 0000000..59a0de7 --- /dev/null +++ b/conf-ld @@ -0,0 +1,3 @@ +gcc -s + +This will be used to link .o files into an executable. diff --git a/deepsleep.c b/deepsleep.c new file mode 100644 index 0000000..50932ea --- /dev/null +++ b/deepsleep.c @@ -0,0 +1,19 @@ +#include "iopause.h" +#include "deepsleep.h" + +extern void deepsleep(unsigned int s) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + + taia_now(&now); + taia_uint(&deadline,s); + taia_add(&deadline,&now,&deadline); + + for (;;) { + taia_now(&now); + if (taia_less(&deadline,&now)) return; + iopause(&x,0,&deadline,&now); + } +} diff --git a/deepsleep.h b/deepsleep.h new file mode 100644 index 0000000..3ba17f3 --- /dev/null +++ b/deepsleep.h @@ -0,0 +1,6 @@ +#ifndef DEEPSLEEP_H +#define DEEPSLEEP_H + +extern void deepsleep(unsigned int); + +#endif diff --git a/direntry.h1 b/direntry.h1 new file mode 100644 index 0000000..6cb088d --- /dev/null +++ b/direntry.h1 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef DIRENTRY_H +#define DIRENTRY_H + +/* sysdep: -dirent */ + +#include +#include +#define direntry struct direct + +#endif diff --git a/direntry.h2 b/direntry.h2 new file mode 100644 index 0000000..bfd4d19 --- /dev/null +++ b/direntry.h2 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef DIRENTRY_H +#define DIRENTRY_H + +/* sysdep: +dirent */ + +#include +#include +#define direntry struct dirent + +#endif diff --git a/env.c b/env.c new file mode 100644 index 0000000..1b3ef62 --- /dev/null +++ b/env.c @@ -0,0 +1,17 @@ +/* Public domain. */ + +#include "str.h" +#include "env.h" + +extern /*@null@*/char *env_get(const char *s) +{ + int i; + unsigned int len; + + if (!s) return 0; + len = str_len(s); + for (i = 0;environ[i];++i) + if (str_start(environ[i],s) && (environ[i][len] == '=')) + return environ[i] + len + 1; + return 0; +} diff --git a/env.h b/env.h new file mode 100644 index 0000000..834d331 --- /dev/null +++ b/env.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef ENV_H +#define ENV_H + +extern char **environ; + +extern /*@null@*/char *env_get(const char *); + +#endif diff --git a/envdir.c b/envdir.c new file mode 100644 index 0000000..beb1b1f --- /dev/null +++ b/envdir.c @@ -0,0 +1,86 @@ +#include +#include "byte.h" +#include "open.h" +#include "error.h" +#include "direntry.h" +#include "stralloc.h" +#include "openreadclose.h" +#include "strerr.h" +#include "pathexec.h" + +#define FATAL "envdir: fatal: " + +void die_usage(void) +{ + strerr_die1x(111,"envdir: usage: envdir dir child"); +} +void nomem(void) +{ + strerr_die2x(111,FATAL,"out of memory"); +} + +static stralloc sa; + +int main(int argc,const char *const *argv) +{ + int fdorigdir; + const char *fn; + DIR *dir; + direntry *d; + int i; + + if (!*argv) die_usage(); + + if (!*++argv) die_usage(); + fn = *argv; + + if (!*++argv) die_usage(); + + fdorigdir = open_read("."); + if (fdorigdir == -1) + strerr_die2sys(111,FATAL,"unable to switch to current directory: "); + if (chdir(fn) == -1) + strerr_die4sys(111,FATAL,"unable to switch to directory ",fn,": "); + + dir = opendir("."); + if (!dir) + strerr_die4sys(111,FATAL,"unable to read directory ",fn,": "); + for (;;) { + errno = 0; + d = readdir(dir); + if (!d) { + if (errno) + strerr_die4sys(111,FATAL,"unable to read directory ",fn,": "); + break; + } + if (d->d_name[0] != '.') { + if (openreadclose(d->d_name,&sa,256) == -1) + strerr_die6sys(111,FATAL,"unable to read ",fn,"/",d->d_name,": "); + if (sa.len) { + sa.len = byte_chr(sa.s,sa.len,'\n'); + while (sa.len) { + if (sa.s[sa.len - 1] != ' ') + if (sa.s[sa.len - 1] != '\t') + break; + --sa.len; + } + for (i = 0;i < sa.len;++i) + if (!sa.s[i]) + sa.s[i] = '\n'; + if (!stralloc_0(&sa)) nomem(); + if (!pathexec_env(d->d_name,sa.s)) nomem(); + } + else { + if (!pathexec_env(d->d_name,0)) nomem(); + } + } + } + closedir(dir); + + if (fchdir(fdorigdir) == -1) + strerr_die2sys(111,FATAL,"unable to switch to starting directory: "); + close(fdorigdir); + + pathexec(argv); + strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); +} diff --git a/envuidgid.c b/envuidgid.c new file mode 100644 index 0000000..294960a --- /dev/null +++ b/envuidgid.c @@ -0,0 +1,35 @@ +#include +#include +#include "fmt.h" +#include "strerr.h" +#include "pathexec.h" + +#define FATAL "envuidgid: fatal: " + +void nomem(void) +{ + strerr_die2x(111,FATAL,"out of memory"); +} + +char strnum[FMT_ULONG]; +const char *account; +struct passwd *pw; + +int main(int argc,const char *const *argv) +{ + account = *++argv; + if (!account || !*++argv) + strerr_die1x(100,"envuidgid: usage: envuidgid account child"); + + pw = getpwnam(account); + if (!pw) + strerr_die3x(111,FATAL,"unknown account ",account); + + strnum[fmt_ulong(strnum,pw->pw_gid)] = 0; + if (!pathexec_env("GID",strnum)) nomem(); + strnum[fmt_ulong(strnum,pw->pw_uid)] = 0; + if (!pathexec_env("UID",strnum)) nomem(); + + pathexec(argv); + strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); +} diff --git a/error.c b/error.c new file mode 100644 index 0000000..ea5f9c2 --- /dev/null +++ b/error.c @@ -0,0 +1,132 @@ +/* Public domain. */ + +#include +#include "error.h" + +/* warning: as coverage improves here, should update error_{str,temp} */ + +int error_intr = +#ifdef EINTR +EINTR; +#else +-1; +#endif + +int error_nomem = +#ifdef ENOMEM +ENOMEM; +#else +-2; +#endif + +int error_noent = +#ifdef ENOENT +ENOENT; +#else +-3; +#endif + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +int error_io = +#ifdef EIO +EIO; +#else +-5; +#endif + +int error_exist = +#ifdef EEXIST +EEXIST; +#else +-6; +#endif + +int error_timeout = +#ifdef ETIMEDOUT +ETIMEDOUT; +#else +-7; +#endif + +int error_inprogress = +#ifdef EINPROGRESS +EINPROGRESS; +#else +-8; +#endif + +int error_wouldblock = +#ifdef EWOULDBLOCK +EWOULDBLOCK; +#else +-9; +#endif + +int error_again = +#ifdef EAGAIN +EAGAIN; +#else +-10; +#endif + +int error_pipe = +#ifdef EPIPE +EPIPE; +#else +-11; +#endif + +int error_perm = +#ifdef EPERM +EPERM; +#else +-12; +#endif + +int error_acces = +#ifdef EACCES +EACCES; +#else +-13; +#endif + +int error_nodevice = +#ifdef ENXIO +ENXIO; +#else +-14; +#endif + +int error_proto = +#ifdef EPROTO +EPROTO; +#else +-15; +#endif + +int error_isdir = +#ifdef EISDIR +EISDIR; +#else +-16; +#endif + +int error_connrefused = +#ifdef ECONNREFUSED +ECONNREFUSED; +#else +-17; +#endif + +int error_notdir = +#ifdef ENOTDIR +ENOTDIR; +#else +-18; +#endif diff --git a/error.h b/error.h new file mode 100644 index 0000000..086fb55 --- /dev/null +++ b/error.h @@ -0,0 +1,30 @@ +/* Public domain. */ + +#ifndef ERROR_H +#define ERROR_H + +extern int errno; + +extern int error_intr; +extern int error_nomem; +extern int error_noent; +extern int error_txtbsy; +extern int error_io; +extern int error_exist; +extern int error_timeout; +extern int error_inprogress; +extern int error_wouldblock; +extern int error_again; +extern int error_pipe; +extern int error_perm; +extern int error_acces; +extern int error_nodevice; +extern int error_proto; +extern int error_isdir; +extern int error_connrefused; +extern int error_notdir; + +extern const char *error_str(int); +extern int error_temp(int); + +#endif diff --git a/error_str.c b/error_str.c new file mode 100644 index 0000000..e002efe --- /dev/null +++ b/error_str.c @@ -0,0 +1,267 @@ +/* Public domain. */ + +#include +#include "error.h" + +#define X(e,s) if (i == e) return s; + +const char *error_str(int i) +{ + X(0,"no error") + X(error_intr,"interrupted system call") + X(error_nomem,"out of memory") + X(error_noent,"file does not exist") + X(error_txtbsy,"text busy") + X(error_io,"input/output error") + X(error_exist,"file already exists") + X(error_timeout,"timed out") + X(error_inprogress,"operation in progress") + X(error_again,"temporary failure") + X(error_wouldblock,"input/output would block") + X(error_pipe,"broken pipe") + X(error_perm,"permission denied") + X(error_acces,"access denied") + X(error_nodevice,"device not configured") + X(error_proto,"protocol error") + X(error_isdir,"is a directory") + X(error_connrefused,"connection refused") + X(error_notdir,"not a directory") +#ifdef ESRCH + X(ESRCH,"no such process") +#endif +#ifdef E2BIG + X(E2BIG,"argument list too long") +#endif +#ifdef ENOEXEC + X(ENOEXEC,"exec format error") +#endif +#ifdef EBADF + X(EBADF,"file descriptor not open") +#endif +#ifdef ECHILD + X(ECHILD,"no child processes") +#endif +#ifdef EDEADLK + X(EDEADLK,"operation would cause deadlock") +#endif +#ifdef EFAULT + X(EFAULT,"bad address") +#endif +#ifdef ENOTBLK + X(ENOTBLK,"not a block device") +#endif +#ifdef EBUSY + X(EBUSY,"device busy") +#endif +#ifdef EXDEV + X(EXDEV,"cross-device link") +#endif +#ifdef ENODEV + X(ENODEV,"device does not support operation") +#endif +#ifdef EINVAL + X(EINVAL,"invalid argument") +#endif +#ifdef ENFILE + X(ENFILE,"system cannot open more files") +#endif +#ifdef EMFILE + X(EMFILE,"process cannot open more files") +#endif +#ifdef ENOTTY + X(ENOTTY,"not a tty") +#endif +#ifdef EFBIG + X(EFBIG,"file too big") +#endif +#ifdef ENOSPC + X(ENOSPC,"out of disk space") +#endif +#ifdef ESPIPE + X(ESPIPE,"unseekable descriptor") +#endif +#ifdef EROFS + X(EROFS,"read-only file system") +#endif +#ifdef EMLINK + X(EMLINK,"too many links") +#endif +#ifdef EDOM + X(EDOM,"input out of range") +#endif +#ifdef ERANGE + X(ERANGE,"output out of range") +#endif +#ifdef EALREADY + X(EALREADY,"operation already in progress") +#endif +#ifdef ENOTSOCK + X(ENOTSOCK,"not a socket") +#endif +#ifdef EDESTADDRREQ + X(EDESTADDRREQ,"destination address required") +#endif +#ifdef EMSGSIZE + X(EMSGSIZE,"message too long") +#endif +#ifdef EPROTOTYPE + X(EPROTOTYPE,"incorrect protocol type") +#endif +#ifdef ENOPROTOOPT + X(ENOPROTOOPT,"protocol not available") +#endif +#ifdef EPROTONOSUPPORT + X(EPROTONOSUPPORT,"protocol not supported") +#endif +#ifdef ESOCKTNOSUPPORT + X(ESOCKTNOSUPPORT,"socket type not supported") +#endif +#ifdef EOPNOTSUPP + X(EOPNOTSUPP,"operation not supported") +#endif +#ifdef EPFNOSUPPORT + X(EPFNOSUPPORT,"protocol family not supported") +#endif +#ifdef EAFNOSUPPORT + X(EAFNOSUPPORT,"address family not supported") +#endif +#ifdef EADDRINUSE + X(EADDRINUSE,"address already used") +#endif +#ifdef EADDRNOTAVAIL + X(EADDRNOTAVAIL,"address not available") +#endif +#ifdef ENETDOWN + X(ENETDOWN,"network down") +#endif +#ifdef ENETUNREACH + X(ENETUNREACH,"network unreachable") +#endif +#ifdef ENETRESET + X(ENETRESET,"network reset") +#endif +#ifdef ECONNABORTED + X(ECONNABORTED,"connection aborted") +#endif +#ifdef ECONNRESET + X(ECONNRESET,"connection reset") +#endif +#ifdef ENOBUFS + X(ENOBUFS,"out of buffer space") +#endif +#ifdef EISCONN + X(EISCONN,"already connected") +#endif +#ifdef ENOTCONN + X(ENOTCONN,"not connected") +#endif +#ifdef ESHUTDOWN + X(ESHUTDOWN,"socket shut down") +#endif +#ifdef ETOOMANYREFS + X(ETOOMANYREFS,"too many references") +#endif +#ifdef ELOOP + X(ELOOP,"symbolic link loop") +#endif +#ifdef ENAMETOOLONG + X(ENAMETOOLONG,"file name too long") +#endif +#ifdef EHOSTDOWN + X(EHOSTDOWN,"host down") +#endif +#ifdef EHOSTUNREACH + X(EHOSTUNREACH,"host unreachable") +#endif +#ifdef ENOTEMPTY + X(ENOTEMPTY,"directory not empty") +#endif +#ifdef EPROCLIM + X(EPROCLIM,"too many processes") +#endif +#ifdef EUSERS + X(EUSERS,"too many users") +#endif +#ifdef EDQUOT + X(EDQUOT,"disk quota exceeded") +#endif +#ifdef ESTALE + X(ESTALE,"stale NFS file handle") +#endif +#ifdef EREMOTE + X(EREMOTE,"too many levels of remote in path") +#endif +#ifdef EBADRPC + X(EBADRPC,"RPC structure is bad") +#endif +#ifdef ERPCMISMATCH + X(ERPCMISMATCH,"RPC version mismatch") +#endif +#ifdef EPROGUNAVAIL + X(EPROGUNAVAIL,"RPC program unavailable") +#endif +#ifdef EPROGMISMATCH + X(EPROGMISMATCH,"program version mismatch") +#endif +#ifdef EPROCUNAVAIL + X(EPROCUNAVAIL,"bad procedure for program") +#endif +#ifdef ENOLCK + X(ENOLCK,"no locks available") +#endif +#ifdef ENOSYS + X(ENOSYS,"system call not available") +#endif +#ifdef EFTYPE + X(EFTYPE,"bad file type") +#endif +#ifdef EAUTH + X(EAUTH,"authentication error") +#endif +#ifdef ENEEDAUTH + X(ENEEDAUTH,"not authenticated") +#endif +#ifdef ENOSTR + X(ENOSTR,"not a stream device") +#endif +#ifdef ETIME + X(ETIME,"timer expired") +#endif +#ifdef ENOSR + X(ENOSR,"out of stream resources") +#endif +#ifdef ENOMSG + X(ENOMSG,"no message of desired type") +#endif +#ifdef EBADMSG + X(EBADMSG,"bad message type") +#endif +#ifdef EIDRM + X(EIDRM,"identifier removed") +#endif +#ifdef ENONET + X(ENONET,"machine not on network") +#endif +#ifdef ERREMOTE + X(ERREMOTE,"object not local") +#endif +#ifdef ENOLINK + X(ENOLINK,"link severed") +#endif +#ifdef EADV + X(EADV,"advertise error") +#endif +#ifdef ESRMNT + X(ESRMNT,"srmount error") +#endif +#ifdef ECOMM + X(ECOMM,"communication error") +#endif +#ifdef EMULTIHOP + X(EMULTIHOP,"multihop attempted") +#endif +#ifdef EREMCHG + X(EREMCHG,"remote address changed") +#endif + return "unknown error"; +} diff --git a/fd.h b/fd.h new file mode 100644 index 0000000..1c7a035 --- /dev/null +++ b/fd.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef FD_H +#define FD_H + +extern int fd_copy(int,int); +extern int fd_move(int,int); + +#endif diff --git a/fd_copy.c b/fd_copy.c new file mode 100644 index 0000000..80e9d15 --- /dev/null +++ b/fd_copy.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include +#include +#include "fd.h" + +int fd_copy(int to,int from) +{ + if (to == from) return 0; + if (fcntl(from,F_GETFL,0) == -1) return -1; + close(to); + if (fcntl(from,F_DUPFD,to) == -1) return -1; + return 0; +} diff --git a/fd_move.c b/fd_move.c new file mode 100644 index 0000000..49f723f --- /dev/null +++ b/fd_move.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include +#include "fd.h" + +int fd_move(int to,int from) +{ + if (to == from) return 0; + if (fd_copy(to,from) == -1) return -1; + close(from); + return 0; +} diff --git a/fghack.c b/fghack.c new file mode 100644 index 0000000..34ca1db --- /dev/null +++ b/fghack.c @@ -0,0 +1,50 @@ +#include +#include "wait.h" +#include "error.h" +#include "strerr.h" +#include "buffer.h" +#include "pathexec.h" + +#define FATAL "fghack: fatal: " + +int pid; + +int main(int argc,const char * const *argv,const char * const *envp) +{ + char ch; + int wstat; + int pi[2]; + int i; + + if (!argv[1]) + strerr_die1x(100,"fghack: usage: fghack child"); + + if (pipe(pi) == -1) + strerr_die2sys(111,FATAL,"unable to create pipe: "); + + switch(pid = fork()) { + case -1: + strerr_die2sys(111,FATAL,"unable to fork: "); + case 0: + close(pi[0]); + for (i = 0;i < 30;++i) + dup(pi[1]); + pathexec_run(argv[1],argv + 1,envp); + strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); + } + + close(pi[1]); + + for (;;) { + i = buffer_unixread(pi[0],&ch,1); + if ((i == -1) && (errno == error_intr)) continue; + if (i == 1) continue; + break; + } + + if (wait_pid(&wstat,pid) == -1) + strerr_die2sys(111,FATAL,"wait failed: "); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); + _exit(wait_exitcode(wstat)); +} diff --git a/fifo.c b/fifo.c new file mode 100644 index 0000000..c14f683 --- /dev/null +++ b/fifo.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include +#include +#include "hasmkffo.h" +#include "fifo.h" + +#ifdef HASMKFIFO +int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); } +#else +int fifo_make(const char *fn,int mode) { return mknod(fn,S_IFIFO | mode,0); } +#endif diff --git a/fifo.h b/fifo.h new file mode 100644 index 0000000..ba75678 --- /dev/null +++ b/fifo.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef FIFO_H +#define FIFO_H + +extern int fifo_make(const char *,int); + +#endif diff --git a/find-systype.sh b/find-systype.sh new file mode 100644 index 0000000..9f6e565 --- /dev/null +++ b/find-systype.sh @@ -0,0 +1,143 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null + +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os|freebsd|netbsd|openbsd) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + gcc -c trycpp.c + gcc -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +if gcc -c x86cpuid.c +then + if gcc -o x86cpuid x86cpuid.o + then + x86cpuid="`./x86cpuid | tr /: ..`" + case "$x86cpuid" in + ?*) + chip="$x86cpuid" + ;; + esac + fi +fi +rm -f x86cpuid x86cpuid.o + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' diff --git a/fmt.h b/fmt.h new file mode 100644 index 0000000..8847fa6 --- /dev/null +++ b/fmt.h @@ -0,0 +1,27 @@ +/* Public domain. */ + +#ifndef FMT_H +#define FMT_H + +#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ +#define FMT_LEN ((char *) 0) /* convenient abbreviation */ + +extern unsigned int fmt_uint(char *,unsigned int); +extern unsigned int fmt_uint0(char *,unsigned int,unsigned int); +extern unsigned int fmt_xint(char *,unsigned int); +extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int); +extern unsigned int fmt_ushort(char *,unsigned short); +extern unsigned int fmt_xshort(char *,unsigned short); +extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short); +extern unsigned int fmt_ulong(char *,unsigned long); +extern unsigned int fmt_xlong(char *,unsigned long); +extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long); + +extern unsigned int fmt_plusminus(char *,int); +extern unsigned int fmt_minus(char *,int); +extern unsigned int fmt_0x(char *,int); + +extern unsigned int fmt_str(char *,const char *); +extern unsigned int fmt_strn(char *,const char *,unsigned int); + +#endif diff --git a/fmt_uint.c b/fmt_uint.c new file mode 100644 index 0000000..b8ec0b7 --- /dev/null +++ b/fmt_uint.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "fmt.h" + +unsigned int fmt_uint(register char *s,register unsigned int u) +{ + return fmt_ulong(s,u); +} diff --git a/fmt_uint0.c b/fmt_uint0.c new file mode 100644 index 0000000..728a5aa --- /dev/null +++ b/fmt_uint0.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include "fmt.h" + +unsigned int fmt_uint0(char *s,unsigned int u,unsigned int n) +{ + unsigned int len; + len = fmt_uint(FMT_LEN,u); + while (len < n) { if (s) *s++ = '0'; ++len; } + if (s) fmt_uint(s,u); + return len; +} diff --git a/fmt_ulong.c b/fmt_ulong.c new file mode 100644 index 0000000..168572f --- /dev/null +++ b/fmt_ulong.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include "fmt.h" + +unsigned int fmt_ulong(register char *s,register unsigned long u) +{ + register unsigned int len; register unsigned long q; + len = 1; q = u; + while (q > 9) { ++len; q /= 10; } + if (s) { + s += len; + do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ + } + return len; +} diff --git a/gen_alloc.h b/gen_alloc.h new file mode 100644 index 0000000..bd55e5b --- /dev/null +++ b/gen_alloc.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +#define GEN_ALLOC_typedef(ta,type,field,len,a) \ + typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; + +#endif diff --git a/gen_allocdefs.h b/gen_allocdefs.h new file mode 100644 index 0000000..3afd92b --- /dev/null +++ b/gen_allocdefs.h @@ -0,0 +1,36 @@ +/* Public domain. */ + +#ifndef GEN_ALLOC_DEFS_H +#define GEN_ALLOC_DEFS_H + +#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ +int ta_ready(register ta *x,register unsigned int n) \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ +int ta_rplus(register ta *x,register unsigned int n) \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; n += x->len; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ +int ta_append(register ta *x,register const type *i) \ +{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } + +#endif diff --git a/hasflock.h1 b/hasflock.h1 new file mode 100644 index 0000000..ac7dfc3 --- /dev/null +++ b/hasflock.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -flock */ diff --git a/hasflock.h2 b/hasflock.h2 new file mode 100644 index 0000000..1878f64 --- /dev/null +++ b/hasflock.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +flock */ +#define HASFLOCK 1 diff --git a/hasmkffo.h1 b/hasmkffo.h1 new file mode 100644 index 0000000..a562451 --- /dev/null +++ b/hasmkffo.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -mkfifo */ diff --git a/hasmkffo.h2 b/hasmkffo.h2 new file mode 100644 index 0000000..8ac8943 --- /dev/null +++ b/hasmkffo.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +mkfifo */ +#define HASMKFIFO 1 diff --git a/hassgact.h1 b/hassgact.h1 new file mode 100644 index 0000000..7639d24 --- /dev/null +++ b/hassgact.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -sigaction */ diff --git a/hassgact.h2 b/hassgact.h2 new file mode 100644 index 0000000..60ff776 --- /dev/null +++ b/hassgact.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +sigaction */ +#define HASSIGACTION 1 diff --git a/hassgprm.h1 b/hassgprm.h1 new file mode 100644 index 0000000..ef3eee9 --- /dev/null +++ b/hassgprm.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -sigprocmask */ diff --git a/hassgprm.h2 b/hassgprm.h2 new file mode 100644 index 0000000..be9d0d7 --- /dev/null +++ b/hassgprm.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +sigprocmask */ +#define HASSIGPROCMASK 1 diff --git a/hasshsgr.h1 b/hasshsgr.h1 new file mode 100644 index 0000000..3806277 --- /dev/null +++ b/hasshsgr.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -shortsetgroups */ diff --git a/hasshsgr.h2 b/hasshsgr.h2 new file mode 100644 index 0000000..5624ed0 --- /dev/null +++ b/hasshsgr.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +shortsetgroups */ +#define HASSHORTSETGROUPS 1 diff --git a/haswaitp.h1 b/haswaitp.h1 new file mode 100644 index 0000000..0d6f82c --- /dev/null +++ b/haswaitp.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -waitpid */ diff --git a/haswaitp.h2 b/haswaitp.h2 new file mode 100644 index 0000000..015413f --- /dev/null +++ b/haswaitp.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +waitpid */ +#define HASWAITPID 1 diff --git a/iopause.c b/iopause.c new file mode 100644 index 0000000..ea5a426 --- /dev/null +++ b/iopause.c @@ -0,0 +1,78 @@ +/* Public domain. */ + +#include "taia.h" +#include "select.h" +#include "iopause.h" + +void iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp) +{ + struct taia t; + int millisecs; + double d; + int i; + + if (taia_less(deadline,stamp)) + millisecs = 0; + else { + t = *stamp; + taia_sub(&t,deadline,&t); + d = taia_approx(&t); + if (d > 1000.0) d = 1000.0; + millisecs = d * 1000.0 + 20.0; + } + + for (i = 0;i < len;++i) + x[i].revents = 0; + +#ifdef IOPAUSE_POLL + + poll(x,len,millisecs); + /* XXX: some kernels apparently need x[0] even if len is 0 */ + /* XXX: how to handle EAGAIN? are kernels really this dumb? */ + /* XXX: how to handle EINVAL? when exactly can this happen? */ + +#else +{ + + struct timeval tv; + fd_set rfds; + fd_set wfds; + int nfds; + int fd; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + nfds = 1; + for (i = 0;i < len;++i) { + fd = x[i].fd; + if (fd < 0) continue; + if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ + + if (fd >= nfds) nfds = fd + 1; + if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds); + if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds); + } + + tv.tv_sec = millisecs / 1000; + tv.tv_usec = 1000 * (millisecs % 1000); + + if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) <= 0) + return; + /* XXX: for EBADF, could seek out and destroy the bad descriptor */ + + for (i = 0;i < len;++i) { + fd = x[i].fd; + if (fd < 0) continue; + if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ + + if (x[i].events & IOPAUSE_READ) + if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ; + if (x[i].events & IOPAUSE_WRITE) + if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE; + } + +} +#endif + +} diff --git a/iopause.h1 b/iopause.h1 new file mode 100644 index 0000000..5c53de7 --- /dev/null +++ b/iopause.h1 @@ -0,0 +1,21 @@ +/* Public domain. */ + +#ifndef IOPAUSE_H +#define IOPAUSE_H + +/* sysdep: -poll */ + +typedef struct { + int fd; + short events; + short revents; +} iopause_fd; + +#define IOPAUSE_READ 1 +#define IOPAUSE_WRITE 4 + +#include "taia.h" + +extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *); + +#endif diff --git a/iopause.h2 b/iopause.h2 new file mode 100644 index 0000000..8e58452 --- /dev/null +++ b/iopause.h2 @@ -0,0 +1,20 @@ +/* Public domain. */ + +#ifndef IOPAUSE_H +#define IOPAUSE_H + +/* sysdep: +poll */ +#define IOPAUSE_POLL + +#include +#include + +typedef struct pollfd iopause_fd; +#define IOPAUSE_READ POLLIN +#define IOPAUSE_WRITE POLLOUT + +#include "taia.h" + +extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *); + +#endif diff --git a/lock.h b/lock.h new file mode 100644 index 0000000..4a96cdc --- /dev/null +++ b/lock.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef LOCK_H +#define LOCK_H + +extern int lock_ex(int); +extern int lock_un(int); +extern int lock_exnb(int); + +#endif diff --git a/lock_ex.c b/lock_ex.c new file mode 100644 index 0000000..b75a764 --- /dev/null +++ b/lock_ex.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include +#include +#include +#include "hasflock.h" +#include "lock.h" + +#ifdef HASFLOCK +int lock_ex(int fd) { return flock(fd,LOCK_EX); } +#else +int lock_ex(int fd) { return lockf(fd,1,0); } +#endif diff --git a/lock_exnb.c b/lock_exnb.c new file mode 100644 index 0000000..9ec2b9c --- /dev/null +++ b/lock_exnb.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include +#include +#include +#include "hasflock.h" +#include "lock.h" + +#ifdef HASFLOCK +int lock_exnb(int fd) { return flock(fd,LOCK_EX | LOCK_NB); } +#else +int lock_exnb(int fd) { return lockf(fd,2,0); } +#endif diff --git a/match.c b/match.c new file mode 100644 index 0000000..e4c1864 --- /dev/null +++ b/match.c @@ -0,0 +1,24 @@ +#include "match.h" + +int match(const char *pattern,const char *buf,unsigned int len) +{ + char ch; + + for (;;) { + ch = *pattern++; + if (!ch) return !len; + if (ch == '*') { + ch = *pattern; + if (!ch) return 1; + for (;;) { + if (!len) return 0; + if (*buf == ch) break; + ++buf; --len; + } + continue; + } + if (!len) return 0; + if (*buf != ch) return 0; + ++buf; --len; + } +} diff --git a/match.h b/match.h new file mode 100644 index 0000000..2e64e3f --- /dev/null +++ b/match.h @@ -0,0 +1,6 @@ +#ifndef MATCH_H +#define MATCH_H + +extern int match(const char *,const char *,unsigned int); + +#endif diff --git a/matchtest.c b/matchtest.c new file mode 100644 index 0000000..980dd1c --- /dev/null +++ b/matchtest.c @@ -0,0 +1,23 @@ +#include "match.h" +#include "buffer.h" +#include "str.h" + +int main(int argc,char **argv) +{ + const char *pattern = ""; + const char *buf = ""; + + if (argv[1]) { + pattern = argv[1]; + if (argv[2]) + buf = argv[2]; + } + + buffer_puts(buffer_1,match(pattern,buf,str_len(buf)) ? "+" : "-"); + buffer_puts(buffer_1,pattern); + buffer_puts(buffer_1," ("); + buffer_puts(buffer_1,buf); + buffer_puts(buffer_1,")\n"); + buffer_flush(buffer_1); + _exit(0); +} diff --git a/multilog.c b/multilog.c new file mode 100644 index 0000000..be27a6a --- /dev/null +++ b/multilog.c @@ -0,0 +1,617 @@ +#include +#include +#include +#include "direntry.h" +#include "alloc.h" +#include "buffer.h" +#include "strerr.h" +#include "error.h" +#include "open.h" +#include "lock.h" +#include "scan.h" +#include "str.h" +#include "byte.h" +#include "seek.h" +#include "timestamp.h" +#include "wait.h" +#include "coe.h" +#include "env.h" +#include "fd.h" +#include "sig.h" +#include "match.h" +#include "deepsleep.h" + +#define FATAL "multilog: fatal: " +#define WARNING "multilog: warning: " + +void pause3(const char *s1,const char *s2,const char *s3) +{ + strerr_warn4(WARNING,s1,s2,s3,&strerr_sys); + deepsleep(5); +} + +void pause5(const char *s1,const char *s2,const char *s3,const char *s4,const char *s5) +{ + strerr_warn6(WARNING,s1,s2,s3,s4,s5,&strerr_sys); + deepsleep(5); +} + +int fdstartdir; + +int *f; + +void f_init(char **script) +{ + int i; + int fd; + + for (i = 0;script[i];++i) + ; + + f = (int *) alloc(i * sizeof(*f)); + if (!f) strerr_die2x(111,FATAL,"out of memory"); + + for (i = 0;script[i];++i) { + fd = -1; + if (script[i][0] == '=') { + if (fchdir(fdstartdir) == -1) + strerr_die2sys(111,FATAL,"unable to switch to starting directory: "); + fd = open_append(script[i] + 1); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to create ",script[i] + 1,": "); + close(fd); + fd = open_write(script[i] + 1); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to write ",script[i] + 1,": "); + coe(fd); + } + f[i] = fd; + } +} + +struct cyclog { + char buf[512]; + buffer ss; + int fdcurrent; + unsigned long bytes; + unsigned long num; + unsigned long size; + char *processor; + char *dir; + int fddir; + int fdlock; + int flagselected; +} *c; +int cnum; + +char fn[40]; + +int filesfit(struct cyclog *d) +{ + DIR *dir; + direntry *x; + int count; + int i; + + dir = opendir("."); + if (!dir) return -1; + + fn[0] = '@'; + fn[1] = 'z'; + fn[2] = 0; + + count = 0; + for (;;) { + errno = 0; + x = readdir(dir); + if (!x) break; + if (x->d_name[0] == '@') + if (str_len(x->d_name) >= 25) { + ++count; + if (str_diff(x->d_name,fn) < 0) { + for (i = 0;i < 25;++i) + fn[i] = x->d_name[i]; + fn[25] = 0; + } + } + } + if (errno) { closedir(dir); return -1; } + closedir(dir); + + if (count < d->num) return 1; + + dir = opendir("."); + if (!dir) return -1; + + for (;;) { + errno = 0; + x = readdir(dir); + if (!x) break; + if (x->d_name[0] == '@') + if (str_len(x->d_name) >= 25) + if (str_start(x->d_name,fn)) { + unlink(x->d_name); + break; + } + } + if (errno) { closedir(dir); return -1; } + closedir(dir); + return 0; +} + +void finish(struct cyclog *d,const char *file,const char *code) +{ + struct stat st; + + for (;;) { + if (stat(file,&st) == 0) break; + if (errno == error_noent) return; + pause5("unable to stat ",d->dir,"/",file,", pausing: "); + } + + if (st.st_nlink == 1) + for (;;) { + timestamp(fn); + fn[25] = '.'; + fn[26] = code[0]; + fn[27] = 0; + + if (link(file,fn) == 0) break; + pause5("unable to link to ",d->dir,"/",fn,", pausing: "); + } + + while (unlink(file) == -1) + pause5("unable to remove ",d->dir,"/",file,", pausing: "); + + for (;;) + switch(filesfit(d)) { + case 1: return; + case -1: pause3("unable to read ",d->dir,", pausing: "); + } +} + +void startprocessor(struct cyclog *d) +{ + const char *args[4]; + int fd; + + sig_uncatch(sig_term); + sig_uncatch(sig_alarm); + sig_unblock(sig_term); + sig_unblock(sig_alarm); + + fd = open_read("previous"); + if (fd == -1) return; + if (fd_move(0,fd) == -1) return; + fd = open_trunc("processed"); + if (fd == -1) return; + if (fd_move(1,fd) == -1) return; + fd = open_read("state"); + if (fd == -1) return; + if (fd_move(4,fd) == -1) return; + fd = open_trunc("newstate"); + if (fd == -1) return; + if (fd_move(5,fd) == -1) return; + + args[0] = "sh"; + args[1] = "-c"; + args[2] = d->processor; + args[3] = 0; + execve("/bin/sh",args,environ); +} + +void fullcurrent(struct cyclog *d) +{ + int fd; + int pid; + int wstat; + + while (fchdir(d->fddir) == -1) + pause3("unable to switch to ",d->dir,", pausing: "); + + while (fsync(d->fdcurrent) == -1) + pause3("unable to write ",d->dir,"/current to disk, pausing: "); + close(d->fdcurrent); + + while (rename("current","previous") == -1) + pause3("unable to rename current to previous in directory ",d->dir,", pausing: "); + while ((d->fdcurrent = open_append("current")) == -1) + pause3("unable to create ",d->dir,"/current, pausing: "); + coe(d->fdcurrent); + d->bytes = 0; + while (fchmod(d->fdcurrent,0644) == -1) + pause3("unable to set mode of ",d->dir,"/current, pausing: "); + + while (chmod("previous",0744) == -1) + pause3("unable to set mode of ",d->dir,"/previous, pausing: "); + + if (!d->processor) + finish(d,"previous","s"); + else { + for (;;) { + while ((pid = fork()) == -1) + pause3("unable to fork for processor in ",d->dir,", pausing: "); + if (!pid) { + startprocessor(d); + strerr_die4sys(111,FATAL,"unable to run ",d->processor,": "); + } + if (wait_pid(&wstat,pid) == -1) + pause3("wait failed for processor in ",d->dir,", pausing: "); + else if (wait_crashed(wstat)) + pause3("processor crashed in ",d->dir,", pausing: "); + else if (!wait_exitcode(wstat)) + break; + strerr_warn4(WARNING,"processor failed in ",d->dir,", pausing",0); + deepsleep(5); + } + + while ((fd = open_append("processed")) == -1) + pause3("unable to create ",d->dir,"/processed, pausing: "); + while (fsync(fd) == -1) + pause3("unable to write ",d->dir,"/processed to disk, pausing: "); + while (fchmod(fd,0744) == -1) + pause3("unable to set mode of ",d->dir,"/processed, pausing: "); + close(fd); + + while ((fd = open_append("newstate")) == -1) + pause3("unable to create ",d->dir,"/newstate, pausing: "); + while (fsync(fd) == -1) + pause3("unable to write ",d->dir,"/newstate to disk, pausing: "); + close(fd); + + while (unlink("previous") == -1) + pause3("unable to remove ",d->dir,"/previous, pausing: "); + while (rename("newstate","state") == -1) + pause3("unable to rename newstate to state in directory ",d->dir,", pausing: "); + finish(d,"processed","s"); + } +} + +int c_write(int pos,char *buf,int len) +{ + struct cyclog *d; + int w; + + d = c + pos; + + if (d->bytes >= d->size) + fullcurrent(d); + + if (len >= d->size - d->bytes) + len = d->size - d->bytes; + + if (d->bytes + len >= d->size - 2000) { + w = byte_rchr(buf,len,'\n'); + if (w < len) + len = w + 1; + } + + for (;;) { + w = write(d->fdcurrent,buf,len); + if (w > 0) break; + pause3("unable to write to ",d->dir,"/current, pausing: "); + } + + d->bytes += w; + if (d->bytes >= d->size - 2000) + if (buf[w - 1] == '\n') + fullcurrent(d); + + return w; +} + +void restart(struct cyclog *d) +{ + struct stat st; + int fd; + int flagprocessed; + + if (fchdir(fdstartdir) == -1) + strerr_die2sys(111,FATAL,"unable to switch to starting directory: "); + + mkdir(d->dir,0700); + d->fddir = open_read(d->dir); + if ((d->fddir == -1) || (fchdir(d->fddir) == -1)) + strerr_die4sys(111,FATAL,"unable to open directory ",d->dir,": "); + coe(d->fddir); + + d->fdlock = open_append("lock"); + if ((d->fdlock == -1) || (lock_exnb(d->fdlock) == -1)) + strerr_die4sys(111,FATAL,"unable to lock directory ",d->dir,": "); + coe(d->fdlock); + + if (stat("current",&st) == -1) { + if (errno != error_noent) + strerr_die4sys(111,FATAL,"unable to stat ",d->dir,"/current: "); + } + else + if (st.st_mode & 0100) { + fd = open_append("current"); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to append to ",d->dir,"/current: "); + if (fchmod(fd,0644) == -1) + strerr_die4sys(111,FATAL,"unable to set mode of ",d->dir,"/current: "); + coe(fd); + d->fdcurrent = fd; + d->bytes = st.st_size; + return; + } + + unlink("state"); + unlink("newstate"); + + flagprocessed = 0; + if (stat("processed",&st) == -1) { + if (errno != error_noent) + strerr_die4sys(111,FATAL,"unable to stat ",d->dir,"/processed: "); + } + else if (st.st_mode & 0100) + flagprocessed = 1; + + if (flagprocessed) { + unlink("previous"); + finish(d,"processed","s"); + } + else { + unlink("processed"); + finish(d,"previous","u"); + } + + finish(d,"current","u"); + + fd = open_trunc("state"); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to write to ",d->dir,"/state: "); + close(fd); + fd = open_append("current"); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to write to ",d->dir,"/current: "); + if (fchmod(fd,0644) == -1) + strerr_die4sys(111,FATAL,"unable to set mode of ",d->dir,"/current: "); + coe(fd); + d->fdcurrent = fd; + d->bytes = 0; +} + +void c_init(char **script) +{ + int i; + struct cyclog *d; + char *processor; + unsigned long num; + unsigned long size; + + cnum = 0; + for (i = 0;script[i];++i) + if ((script[i][0] == '.') || (script[i][0] == '/')) + ++cnum; + + c = (struct cyclog *) alloc(cnum * sizeof(*c)); + if (!c) strerr_die2x(111,FATAL,"out of memory"); + + d = c; + processor = 0; + num = 10; + size = 99999; + + for (i = 0;script[i];++i) + if (script[i][0] == 's') { + scan_ulong(script[i] + 1,&size); + if (size < 4096) size = 4096; + if (size > 16777215) size = 16777215; + } + else if (script[i][0] == 'n') { + scan_ulong(script[i] + 1,&num); + if (num < 2) num = 2; + } + else if (script[i][0] == '!') { + processor = script[i] + 1; + } + else if ((script[i][0] == '.') || (script[i][0] == '/')) { + d->num = num; + d->size = size; + d->processor = processor; + d->dir = script[i]; + buffer_init(&d->ss,c_write,d - c,d->buf,sizeof d->buf); + restart(d); + ++d; + } +} + +void c_quit(void) +{ + int j; + + for (j = 0;j < cnum;++j) { + buffer_flush(&c[j].ss); + while (fsync(c[j].fdcurrent) == -1) + pause3("unable to write ",c[j].dir,"/current to disk, pausing: "); + while (fchmod(c[j].fdcurrent,0744) == -1) + pause3("unable to set mode of ",c[j].dir,"/current, pausing: "); + } +} + +int flagexitasap = 0; +int flagforcerotate = 0; +int flagnewline = 1; + +void exitasap(void) +{ + flagexitasap = 1; +} + +void forcerotate(void) +{ + flagforcerotate = 1; +} + +int flushread(int fd,char *buf,int len) +{ + int j; + + for (j = 0;j < cnum;++j) + buffer_flush(&c[j].ss); + if (flagforcerotate) { + for (j = 0;j < cnum;++j) + if (c[j].bytes > 0) + fullcurrent(&c[j]); + flagforcerotate = 0; + } + + if (!len) return 0; + if (flagexitasap) { + if (flagnewline) return 0; + len = 1; + } + + sig_unblock(sig_term); + sig_unblock(sig_alarm); + + len = read(fd,buf,len); + + sig_block(sig_term); + sig_block(sig_alarm); + + if (len <= 0) return len; + flagnewline = (buf[len - 1] == '\n'); + return len; +} + +char inbuf[1024]; +buffer ssin = BUFFER_INIT(flushread,0,inbuf,sizeof inbuf); + +char line[1001]; +int linelen; /* 0 <= linelen <= 1000 */ + +void doit(char **script) +{ + int flageof; + char ch; + int j; + int i; + char *action; + int flagselected; + int flagtimestamp; + + flagtimestamp = 0; + if (script[0]) + if (script[0][0] == 't') + flagtimestamp = 1; + + for (i = 0;i <= 1000;++i) line[i] = '\n'; + linelen = 0; + + flageof = 0; + for (;;) { + for (i = 0;i < linelen;++i) line[i] = '\n'; + linelen = 0; + + while (linelen < 1000) { + if (buffer_GETC(&ssin,&ch) <= 0) { + if (!linelen) return; + flageof = 1; + break; + } + if (!linelen) + if (flagtimestamp) { + timestamp(line); + line[25] = ' '; + linelen = 26; + } + if (ch == '\n') + break; + line[linelen++] = ch; + } + + flagselected = 1; + j = 0; + for (i = 0;action = script[i];++i) + switch(*action) { + case '+': + if (!flagselected) + if (match(action + 1,line,linelen)) + flagselected = 1; + break; + case '-': + if (flagselected) + if (match(action + 1,line,linelen)) + flagselected = 0; + break; + case 'e': + if (flagselected) { + if (linelen > 200) { + buffer_put(buffer_2,line,200); + buffer_puts(buffer_2,"...\n"); + } + else { + buffer_put(buffer_2,line,linelen); + buffer_puts(buffer_2,"\n"); + } + buffer_flush(buffer_2); + } + break; + case '=': + if (flagselected) + for (;;) { + while (seek_begin(f[i]) == -1) + pause3("unable to move to beginning of ",action + 1,", pausing: "); + if (write(f[i],line,1001) == 1001) + break; + pause3("unable to write ",action + 1,", pausing: "); + } + break; + case '.': + case '/': + c[j].flagselected = flagselected; + ++j; + break; + } + + for (j = 0;j < cnum;++j) + if (c[j].flagselected) + buffer_put(&c[j].ss,line,linelen); + + if (linelen == 1000) + for (;;) { + if (buffer_GETC(&ssin,&ch) <= 0) { + flageof = 1; + break; + } + if (ch == '\n') + break; + for (j = 0;j < cnum;++j) + if (c[j].flagselected) + buffer_PUTC(&c[j].ss,ch); + } + + for (j = 0;j < cnum;++j) + if (c[j].flagselected) { + ch = '\n'; + buffer_PUTC(&c[j].ss,ch); + } + + if (flageof) return; + } +} + +int main(int argc,char **argv) +{ + umask(022); + + fdstartdir = open_read("."); + if (fdstartdir == -1) + strerr_die2sys(111,FATAL,"unable to switch to current directory: "); + coe(fdstartdir); + + sig_block(sig_term); + sig_block(sig_alarm); + sig_catch(sig_term,exitasap); + sig_catch(sig_alarm,forcerotate); + + ++argv; + f_init(argv); + c_init(argv); + doit(argv); + c_quit(); + _exit(0); +} diff --git a/ndelay.h b/ndelay.h new file mode 100644 index 0000000..dbe91b2 --- /dev/null +++ b/ndelay.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef NDELAY_H +#define NDELAY_H + +extern int ndelay_on(int); +extern int ndelay_off(int); + +#endif diff --git a/ndelay_off.c b/ndelay_off.c new file mode 100644 index 0000000..92d3244 --- /dev/null +++ b/ndelay_off.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include +#include +#include "ndelay.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_off(int fd) +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); +} diff --git a/ndelay_on.c b/ndelay_on.c new file mode 100644 index 0000000..b96a6b2 --- /dev/null +++ b/ndelay_on.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include +#include +#include "ndelay.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_on(int fd) +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); +} diff --git a/open.h b/open.h new file mode 100644 index 0000000..9939663 --- /dev/null +++ b/open.h @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef OPEN_H +#define OPEN_H + +extern int open_read(const char *); +extern int open_excl(const char *); +extern int open_append(const char *); +extern int open_trunc(const char *); +extern int open_write(const char *); + +#endif diff --git a/open_append.c b/open_append.c new file mode 100644 index 0000000..d1b241b --- /dev/null +++ b/open_append.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include +#include +#include "open.h" + +int open_append(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } diff --git a/open_read.c b/open_read.c new file mode 100644 index 0000000..99b3cd1 --- /dev/null +++ b/open_read.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include +#include +#include "open.h" + +int open_read(const char *fn) +{ return open(fn,O_RDONLY | O_NDELAY); } diff --git a/open_trunc.c b/open_trunc.c new file mode 100644 index 0000000..6e0c4c2 --- /dev/null +++ b/open_trunc.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include +#include +#include "open.h" + +int open_trunc(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } diff --git a/open_write.c b/open_write.c new file mode 100644 index 0000000..34cfa9b --- /dev/null +++ b/open_write.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include +#include +#include "open.h" + +int open_write(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY); } diff --git a/openreadclose.c b/openreadclose.c new file mode 100644 index 0000000..635933b --- /dev/null +++ b/openreadclose.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "error.h" +#include "open.h" +#include "readclose.h" +#include "openreadclose.h" + +int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize) +{ + int fd; + fd = open_read(fn); + if (fd == -1) { + if (errno == error_noent) return 0; + return -1; + } + if (readclose(fd,sa,bufsize) == -1) return -1; + return 1; +} diff --git a/openreadclose.h b/openreadclose.h new file mode 100644 index 0000000..728899c --- /dev/null +++ b/openreadclose.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef OPENREADCLOSE_H +#define OPENREADCLOSE_H + +#include "stralloc.h" + +extern int openreadclose(const char *,stralloc *,unsigned int); + +#endif diff --git a/pathexec.h b/pathexec.h new file mode 100644 index 0000000..61da922 --- /dev/null +++ b/pathexec.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef PATHEXEC_H +#define PATHEXEC_H + +extern void pathexec_run(const char *,const char * const *,const char * const *); +extern int pathexec_env(const char *,const char *); +extern void pathexec(const char * const *); + +#endif diff --git a/pathexec_env.c b/pathexec_env.c new file mode 100644 index 0000000..2cb101c --- /dev/null +++ b/pathexec_env.c @@ -0,0 +1,69 @@ +/* Public domain. */ + +#include "stralloc.h" +#include "alloc.h" +#include "str.h" +#include "byte.h" +#include "env.h" +#include "pathexec.h" + +static stralloc plus; +static stralloc tmp; + +int pathexec_env(const char *s,const char *t) +{ + if (!s) return 1; + if (!stralloc_copys(&tmp,s)) return 0; + if (t) { + if (!stralloc_cats(&tmp,"=")) return 0; + if (!stralloc_cats(&tmp,t)) return 0; + } + if (!stralloc_0(&tmp)) return 0; + return stralloc_cat(&plus,&tmp); +} + +void pathexec(const char *const *argv) +{ + const char **e; + unsigned int elen; + unsigned int i; + unsigned int j; + unsigned int split; + unsigned int t; + + if (!stralloc_cats(&plus,"")) return; + + elen = 0; + for (i = 0;environ[i];++i) + ++elen; + for (i = 0;i < plus.len;++i) + if (!plus.s[i]) + ++elen; + + e = (const char **) alloc((elen + 1) * sizeof(char *)); + if (!e) return; + + elen = 0; + for (i = 0;environ[i];++i) + e[elen++] = environ[i]; + + j = 0; + for (i = 0;i < plus.len;++i) + if (!plus.s[i]) { + split = str_chr(plus.s + j,'='); + for (t = 0;t < elen;++t) + if (byte_equal(plus.s + j,split,e[t])) + if (e[t][split] == '=') { + --elen; + e[t] = e[elen]; + break; + } + if (plus.s[j + split]) + e[elen++] = plus.s + j; + j = i + 1; + } + e[elen] = 0; + + pathexec_run(*argv,argv,e); + alloc_free(e); +} diff --git a/pathexec_run.c b/pathexec_run.c new file mode 100644 index 0000000..1770ac7 --- /dev/null +++ b/pathexec_run.c @@ -0,0 +1,48 @@ +/* Public domain. */ + +#include "error.h" +#include "stralloc.h" +#include "str.h" +#include "env.h" +#include "pathexec.h" + +static stralloc tmp; + +void pathexec_run(const char *file,const char * const *argv,const char * const *envp) +{ + const char *path; + unsigned int split; + int savederrno; + + if (file[str_chr(file,'/')]) { + execve(file,argv,envp); + return; + } + + path = env_get("PATH"); + if (!path) path = "/bin:/usr/bin"; + + savederrno = 0; + for (;;) { + split = str_chr(path,':'); + if (!stralloc_copyb(&tmp,path,split)) return; + if (!split) + if (!stralloc_cats(&tmp,".")) return; + if (!stralloc_cats(&tmp,"/")) return; + if (!stralloc_cats(&tmp,file)) return; + if (!stralloc_0(&tmp)) return; + + execve(tmp.s,argv,envp); + if (errno != error_noent) { + savederrno = errno; + if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; + } + + if (!path[split]) { + if (savederrno) errno = savederrno; + return; + } + path += split; + path += 1; + } +} diff --git a/pgrphack.c b/pgrphack.c new file mode 100644 index 0000000..9aa10dc --- /dev/null +++ b/pgrphack.c @@ -0,0 +1,13 @@ +#include +#include "strerr.h" +#include "pathexec.h" + +#define FATAL "pgrphack: fatal: " + +int main(int argc,const char * const *argv,const char * const *envp) +{ + if (!argv[1]) strerr_die1x(100,"pgrphack: usage: pgrphack child"); + setsid(); /* shouldn't fail; if it does, too bad */ + pathexec_run(argv[1],argv + 1,envp); + strerr_die4sys(111,"pgrphack: fatal: ","unable to run ",argv[1],": "); +} diff --git a/print-ar.sh b/print-ar.sh new file mode 100644 index 0000000..99bc116 --- /dev/null +++ b/print-ar.sh @@ -0,0 +1,14 @@ +cat warn-auto.sh +echo 'main="$1"; shift' +echo 'rm -f "$main"' +echo 'ar cr "$main" ${1+"$@"}' +case "`cat systype`" in + sunos-5.*) ;; + unix_sv*) ;; + irix64-*) ;; + irix-*) ;; + dgux-*) ;; + hp-ux-*) ;; + sco*) ;; + *) echo 'ranlib "$main"' ;; +esac diff --git a/print-cc.sh b/print-cc.sh new file mode 100644 index 0000000..bc28452 --- /dev/null +++ b/print-cc.sh @@ -0,0 +1,5 @@ +cc="`head -1 conf-cc`" +systype="`cat systype`" + +cat warn-auto.sh +echo exec "$cc" '-c ${1+"$@"}' diff --git a/print-ld.sh b/print-ld.sh new file mode 100644 index 0000000..b7fbbf5 --- /dev/null +++ b/print-ld.sh @@ -0,0 +1,6 @@ +ld="`head -1 conf-ld`" +systype="`cat systype`" + +cat warn-auto.sh +echo 'main="$1"; shift' +echo exec "$ld" '-o "$main" "$main".o ${1+"$@"}' diff --git a/prot.c b/prot.c new file mode 100644 index 0000000..79a88c5 --- /dev/null +++ b/prot.c @@ -0,0 +1,21 @@ +/* Public domain. */ + +#include "hasshsgr.h" +#include "prot.h" + +int prot_gid(int gid) +{ +#ifdef HASSHORTSETGROUPS + short x[2]; + x[0] = gid; x[1] = 73; /* catch errors */ + if (setgroups(1,x) == -1) return -1; +#else + if (setgroups(1,&gid) == -1) return -1; +#endif + return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ +} + +int prot_uid(int uid) +{ + return setuid(uid); +} diff --git a/prot.h b/prot.h new file mode 100644 index 0000000..2e5cb81 --- /dev/null +++ b/prot.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef PROT_H +#define PROT_H + +extern int prot_gid(int); +extern int prot_uid(int); + +#endif diff --git a/readclose.c b/readclose.c new file mode 100644 index 0000000..9d83007 --- /dev/null +++ b/readclose.c @@ -0,0 +1,23 @@ +/* Public domain. */ + +#include +#include "error.h" +#include "readclose.h" + +int readclose_append(int fd,stralloc *sa,unsigned int bufsize) +{ + int r; + for (;;) { + if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } + r = read(fd,sa->s + sa->len,bufsize); + if (r == -1) if (errno == error_intr) continue; + if (r <= 0) { close(fd); return r; } + sa->len += r; + } +} + +int readclose(int fd,stralloc *sa,unsigned int bufsize) +{ + if (!stralloc_copys(sa,"")) { close(fd); return -1; } + return readclose_append(fd,sa,bufsize); +} diff --git a/readclose.h b/readclose.h new file mode 100644 index 0000000..bde9889 --- /dev/null +++ b/readclose.h @@ -0,0 +1,11 @@ +/* Public domain. */ + +#ifndef READCLOSE_H +#define READCLOSE_H + +#include "stralloc.h" + +extern int readclose_append(int,stralloc *,unsigned int); +extern int readclose(int,stralloc *,unsigned int); + +#endif diff --git a/readproctitle.c b/readproctitle.c new file mode 100644 index 0000000..82fbffd --- /dev/null +++ b/readproctitle.c @@ -0,0 +1,30 @@ +#include +#include "error.h" + +int main(int argc,char **argv) +{ + char *buf; + unsigned int len; + int i; + char ch; + + if (argc < 2) _exit(100); + buf = argv[argc - 1]; + len = 0; + while (buf[len]) buf[len++] = '.'; + if (len < 5) _exit(100); + + for (;;) + switch(read(0,&ch,1)) { + case 1: + if (ch) { + for (i = 4;i < len;++i) buf[i - 1] = buf[i]; + buf[len - 1] = ch; + } + break; + case 0: + _exit(0); + case -1: + if (errno != error_intr) _exit(111); + } +} diff --git a/rts.tests b/rts.tests new file mode 100644 index 0000000..0e37b2c --- /dev/null +++ b/rts.tests @@ -0,0 +1,302 @@ +# not tested: + +# multilog handles TERM +# multilog handles ALRM +# multilog handles out-of-memory +# multilog handles log directories +# multilog matches only first 1000 characters of long lines +# multilog t produces the right time +# multilog closes descriptors properly +# tai64n produces the right time +# tai64nlocal converts times correctly + +# supervise closes descriptors properly +# svc -d +# svc -p +# svc -c +# svc -a +# svc -i +# svc -t +# svc -k +# svscan +# svscanboot + +# envuidgid sets GID +# setuidgid + +# pgrphack works properly + +# readproctitle works properly + +# softlimit -m +# softlimit -d +# softlimit -s +# softlimit -l +# softlimit -a +# softlimit -p0 preventing fork; need to run this as non-root +# softlimit -o; shared libraries make tests difficult here +# softlimit -c +# softlimit -f +# softlimit -r +# softlimit -t + + +PATH=`pwd`:/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin +export PATH + +umask 022 + +rm -rf rts-tmp +mkdir rts-tmp +cd rts-tmp +mkdir test.sv + + +echo '--- svstat handles new and nonexistent directories' +( echo '#!/bin/sh'; echo echo hi ) > test.sv/run +chmod 755 test.sv/run +touch test.sv/down +svstat test.sv nonexistent; echo $? + +echo '--- svc handles new and nonexistent directories' +svc test.sv nonexistent; echo $? + +echo '--- svok handles new and nonexistent directories' +svok test.sv; echo $? +svok nonexistent; echo $? + +echo '--- supervise handles nonexistent directories' +supervise nonexistent; echo $? + +echo '--- supervise starts, svok works, svstat works, svc -x works' +supervise test.sv & +until svok test.sv +do + sleep 1 +done +svstat test.sv | sed 's/[0-9]* seconds/x seconds/'; echo $? +svc -x test.sv; echo $? +wait +svstat test.sv; echo $? + +echo '--- svc -ox works' +supervise test.sv & +until svok test.sv +do + sleep 1 +done +svc -ox test.sv +wait + +echo '--- svstat works for up services' +( echo '#!/bin/sh'; echo sleep 1; echo svstat . ) > test.sv/run +chmod 755 test.sv/run +supervise test.sv \ +| sed -e 's/[0-9]* seconds/x seconds/' -e 's/pid [0-9]*/pid x/' & +until svok test.sv +do + sleep 1 +done +svc -ox test.sv +wait + +echo '--- svc -u works' +( echo '#!/bin/sh'; echo echo first; echo mv run2 run ) > test.sv/run +chmod 755 test.sv/run +( echo '#!/bin/sh'; echo echo second; echo svc -x . ) > test.sv/run2 +chmod 755 test.sv/run2 +supervise test.sv & +until svok test.sv +do + sleep 1 +done +svc -u test.sv +wait + + +echo '--- tai64n has the right format' +( echo ONE; echo TWO ) | tai64n | sed 's/[0-9a-f]/x/g' + +echo '--- tai64nlocal handles non-@ lines correctly' +( echo one; echo two ) | tai64nlocal; echo $? + + +echo '--- softlimit insists on an argument' +softlimit; echo $? + +echo '--- softlimit complains if it cannot run program' +softlimit ./nonexistent; echo $? + +echo '--- softlimit -p0 still allows exec' +softlimit -p0 echo ./nonexistent; echo $? + + +echo '--- fghack insists on an argument' +fghack; echo $? + +echo '--- fghack complains if it cannot run program' +fghack ./nonexistent; echo $? + +echo '--- fghack runs a program' +fghack sh -c 'echo hi &'; echo $? + + +echo '--- pgrphack insists on an argument' +pgrphack; echo $? + +echo '--- pgrphack complains if it cannot run program' +pgrphack ./nonexistent; echo $? + +echo '--- pgrphack runs a program' +pgrphack echo ok; echo $? + + +echo '--- readproctitle insists on an argument' +readproctitle < /dev/null; echo $? + +echo '--- readproctitle insists on last argument being at least five bytes' +readproctitle .......... four < /dev/null; echo $? + + +echo '--- multilog prints nothing with no actions' +( echo one; echo two ) | multilog; echo $? + +echo '--- multilog e prints to stderr' +( echo one; echo two ) | multilog e 2>&1; echo $? + +echo '--- multilog inserts newline after partial final line' +( echo one; echo two | tr -d '\012' ) | multilog e 2>&1; echo $? + +echo '--- multilog handles multiple actions' +( echo one; echo two ) | multilog e e 2>&1; echo $? + +echo '--- multilog handles wildcard -' +( echo one; echo two ) | multilog '-*' e 2>&1; echo $? + +echo '--- multilog handles literal +' +( echo one; echo two ) | multilog '-*' '+one' e 2>&1; echo $? + +echo '--- multilog handles long lines for stderr' +echo 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 \ +| multilog e 2>&1; echo $? +echo 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \ +| multilog e 2>&1; echo $? +echo 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 \ +| multilog e 2>&1; echo $? + +echo '--- multilog handles status files' +rm -f test.status +( echo one; echo two ) | multilog =test.status; echo $? +uniq -c < test.status | sed 's/[ ]*[ ]/_/g' + +echo '--- multilog t has the right format' +( echo ONE; echo TWO ) | multilog t e 2>&1 | sed 's/[0-9a-f]/x/g' + + +echo '--- match handles literal string' +matchtest one one +matchtest one '' +matchtest one on +matchtest one onf +matchtest one 'one*' +matchtest one onetwo + +echo '--- match handles empty string' +matchtest '' '' +matchtest '' x + +echo '--- match handles full-line wildcard' +matchtest '*' '' +matchtest '*' x +matchtest '*' '*' +matchtest '*' one + +echo '--- match handles ending wildcard' +matchtest 'one*' one +matchtest 'one*' 'one*' +matchtest 'one*' onetwo +matchtest 'one*' '' +matchtest 'one*' x +matchtest 'one*' on +matchtest 'one*' onf + +echo '--- match handles wildcard termination' +matchtest '* one' ' one' +matchtest '* one' 'x one' +matchtest '* one' '* one' +matchtest '* one' 'xy one' +matchtest '* one' 'one' +matchtest '* one' ' two' +matchtest '* one' ' one' +matchtest '* one' 'xy one ' + +echo '--- match handles multiple wildcards' +matchtest '* * one' ' one' +matchtest '* * one' 'x one' +matchtest '* * one' ' y one' +matchtest '* * one' 'x y one' +matchtest '* * one' 'one' +matchtest '* * one' ' one' +matchtest '* * one' ' one' + + +echo '--- envuidgid insists on two arguments' +envuidgid; echo $? +envuidgid root; echo $? + +echo '--- envuidgid sets UID=0 for root' +envuidgid root printenv UID; echo $? + +echo '--- envuidgid complains if it cannot run program' +envuidgid root ./nonexistent; echo $? + + +echo '--- envdir requires arguments' +envdir whatever; echo $? + +echo '--- envdir complains if it cannot read directory' +ln -s env1 env1 +envdir env1 echo yes; echo $? + +echo '--- envdir complains if it cannot read file' +rm env1 +mkdir env1 +ln -s Message env1/Message +envdir env1 echo yes; echo $? + +echo '--- envdir adds variables' +rm env1/Message +echo This is a test. This is only a test. > env1/Message +envdir env1 sh -c 'echo $Message'; echo $? + +echo '--- envdir removes variables' +mkdir env2 +touch env2/Message +envdir env1 envdir env2 sh -c 'echo $Message'; echo $? + + +echo '--- setlock requires arguments' +setlock whatever; echo $? + +echo '--- setlock complains if it cannot create lock file' +setlock nonexistent/lock echo wrong; echo $? + +echo '--- setlock -x exits quietly if it cannot create lock file' +setlock -x nonexistent/lock echo wrong; echo $? + +echo '--- setlock creates lock file' +setlock lock echo ok; echo $? + +echo '--- setlock does not truncate lock file' +echo ok > lock +setlock lock cat lock; echo $? +rm -f lock + +echo '--- setlock -n complains if file is already locked' +setlock lock sh -c 'setlock -n lock echo one && echo two'; echo $? + +echo '--- setlock -nx exits quietly if file is already locked' +setlock lock sh -c 'setlock -nx lock echo one && echo two'; echo $? + + +exit 0 diff --git a/scan.h b/scan.h new file mode 100644 index 0000000..3db49d3 --- /dev/null +++ b/scan.h @@ -0,0 +1,30 @@ +/* Public domain. */ + +#ifndef SCAN_H +#define SCAN_H + +extern unsigned int scan_uint(const char *,unsigned int *); +extern unsigned int scan_xint(const char *,unsigned int *); +extern unsigned int scan_nbbint(const char *,unsigned int,unsigned int,unsigned int,unsigned int *); +extern unsigned int scan_ushort(const char *,unsigned short *); +extern unsigned int scan_xshort(const char *,unsigned short *); +extern unsigned int scan_nbbshort(const char *,unsigned int,unsigned int,unsigned int,unsigned short *); +extern unsigned int scan_ulong(const char *,unsigned long *); +extern unsigned int scan_xlong(const char *,unsigned long *); +extern unsigned int scan_nbblong(const char *,unsigned int,unsigned int,unsigned int,unsigned long *); + +extern unsigned int scan_plusminus(const char *,int *); +extern unsigned int scan_0x(const char *,unsigned int *); + +extern unsigned int scan_whitenskip(const char *,unsigned int); +extern unsigned int scan_nonwhitenskip(const char *,unsigned int); +extern unsigned int scan_charsetnskip(const char *,const char *,unsigned int); +extern unsigned int scan_noncharsetnskip(const char *,const char *,unsigned int); + +extern unsigned int scan_strncmp(const char *,const char *,unsigned int); +extern unsigned int scan_memcmp(const char *,const char *,unsigned int); + +extern unsigned int scan_long(const char *,long *); +extern unsigned int scan_8long(const char *,unsigned long *); + +#endif diff --git a/scan_ulong.c b/scan_ulong.c new file mode 100644 index 0000000..af19701 --- /dev/null +++ b/scan_ulong.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include "scan.h" + +unsigned int scan_ulong(register const char *s,register unsigned long *u) +{ + register unsigned int pos = 0; + register unsigned long result = 0; + register unsigned long c; + while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { + result = result * 10 + c; + ++pos; + } + *u = result; + return pos; +} diff --git a/seek.h b/seek.h new file mode 100644 index 0000000..8011701 --- /dev/null +++ b/seek.h @@ -0,0 +1,17 @@ +/* Public domain. */ + +#ifndef SEEK_H +#define SEEK_H + +typedef unsigned long seek_pos; + +extern seek_pos seek_cur(int); + +extern int seek_set(int,seek_pos); +extern int seek_end(int); + +extern int seek_trunc(int,seek_pos); + +#define seek_begin(fd) (seek_set((fd),(seek_pos) 0)) + +#endif diff --git a/seek_set.c b/seek_set.c new file mode 100644 index 0000000..19b8265 --- /dev/null +++ b/seek_set.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include "seek.h" + +#define SET 0 /* sigh */ + +int seek_set(int fd,seek_pos pos) +{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; } diff --git a/select.h1 b/select.h1 new file mode 100644 index 0000000..68e971f --- /dev/null +++ b/select.h1 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef SELECT_H +#define SELECT_H + +/* sysdep: -sysselect */ + +#include +#include +extern int select(); + +#endif diff --git a/select.h2 b/select.h2 new file mode 100644 index 0000000..4bd4fcf --- /dev/null +++ b/select.h2 @@ -0,0 +1,13 @@ +/* Public domain. */ + +#ifndef SELECT_H +#define SELECT_H + +/* sysdep: +sysselect */ + +#include +#include +#include +extern int select(); + +#endif diff --git a/setlock.c b/setlock.c new file mode 100644 index 0000000..eec2192 --- /dev/null +++ b/setlock.c @@ -0,0 +1,50 @@ +#include +#include "lock.h" +#include "open.h" +#include "strerr.h" +#include "pathexec.h" +#include "sgetopt.h" + +#define FATAL "setlock: fatal: " + +void usage() { + strerr_die1x(100,"setlock: usage: setlock [ -nNxX ] file program [ arg ... ]"); +} + +int flagndelay = 0; +int flagx = 0; + +int main(int argc,const char *const *argv,const char *const *envp) +{ + int opt; + int fd; + const char *file; + + while ((opt = getopt(argc,argv,"nNxX")) != opteof) + switch(opt) { + case 'n': flagndelay = 1; break; + case 'N': flagndelay = 0; break; + case 'x': flagx = 1; break; + case 'X': flagx = 0; break; + default: usage(); + } + + argv += optind; + if (!*argv) usage(); + file = *argv++; + if (!*argv) usage(); + + fd = open_append(file); + if (fd == -1) { + if (flagx) _exit(0); + strerr_die4sys(111,FATAL,"unable to open ",file,": "); + } + + if ((flagndelay ? lock_exnb : lock_ex)(fd) == -1) { + if (flagx) _exit(0); + strerr_die4sys(111,FATAL,"unable to lock ",file,": "); + } + + pathexec_run(*argv,argv,envp); + strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); +} diff --git a/setuidgid.c b/setuidgid.c new file mode 100644 index 0000000..8c683de --- /dev/null +++ b/setuidgid.c @@ -0,0 +1,29 @@ +#include +#include +#include "prot.h" +#include "strerr.h" +#include "pathexec.h" + +#define FATAL "setuidgid: fatal: " + +const char *account; +struct passwd *pw; + +int main(int argc,const char *const *argv,const char *const *envp) +{ + account = *++argv; + if (!account || !*++argv) + strerr_die1x(100,"setuidgid: usage: setuidgid account child"); + + pw = getpwnam(account); + if (!pw) + strerr_die3x(111,FATAL,"unknown account ",account); + + if (prot_gid(pw->pw_gid) == -1) + strerr_die2sys(111,FATAL,"unable to setgid: "); + if (prot_uid(pw->pw_uid) == -1) + strerr_die2sys(111,FATAL,"unable to setuid: "); + + pathexec_run(*argv,argv,envp); + strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); +} diff --git a/sgetopt.c b/sgetopt.c new file mode 100644 index 0000000..8bb608f --- /dev/null +++ b/sgetopt.c @@ -0,0 +1,53 @@ +/* Public domain. */ + +/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer +D. J. Bernstein, djb@pobox.com. +Depends on subgetopt.h, buffer.h. +No system requirements. +19991219: Switched to buffer.h. +19970208: Cleanups. +931201: Baseline. +No known patent problems. + +Documentation in sgetopt.3. +*/ + +#include "buffer.h" +#define SGETOPTNOSHORT +#include "sgetopt.h" +#define SUBGETOPTNOSHORT +#include "subgetopt.h" + +#define getopt sgetoptmine +#define optind subgetoptind +#define opterr sgetopterr +#define optproblem subgetoptproblem +#define optprogname sgetoptprogname + +int opterr = 1; +const char *optprogname = 0; + +int getopt(int argc,const char *const *argv,const char *opts) +{ + int c; + const char *s; + + if (!optprogname) { + optprogname = *argv; + if (!optprogname) optprogname = ""; + for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; + } + c = subgetopt(argc,argv,opts); + if (opterr) + if (c == '?') { + char chp[2]; chp[0] = optproblem; chp[1] = '\n'; + buffer_puts(buffer_2,optprogname); + if (argv[optind] && (optind < argc)) + buffer_puts(buffer_2,": illegal option -- "); + else + buffer_puts(buffer_2,": option requires an argument -- "); + buffer_put(buffer_2,chp,2); + buffer_flush(buffer_2); + } + return c; +} diff --git a/sgetopt.h b/sgetopt.h new file mode 100644 index 0000000..bf8bce6 --- /dev/null +++ b/sgetopt.h @@ -0,0 +1,23 @@ +/* Public domain. */ + +#ifndef SGETOPT_H +#define SGETOPT_H + +#ifndef SGETOPTNOSHORT +#define getopt sgetoptmine +#define optarg subgetoptarg +#define optind subgetoptind +#define optpos subgetoptpos +#define opterr sgetopterr +#define optproblem subgetoptproblem +#define optprogname sgetoptprogname +#define opteof subgetoptdone +#endif + +#include "subgetopt.h" + +extern int sgetoptmine(int,const char *const *,const char *); +extern int sgetopterr; +extern const char *sgetoptprogname; + +#endif diff --git a/sig.c b/sig.c new file mode 100644 index 0000000..423d18e --- /dev/null +++ b/sig.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include +#include "sig.h" + +int sig_alarm = SIGALRM; +int sig_child = SIGCHLD; +int sig_cont = SIGCONT; +int sig_hangup = SIGHUP; +int sig_int = SIGINT; +int sig_pipe = SIGPIPE; +int sig_term = SIGTERM; + +void (*sig_defaulthandler)() = SIG_DFL; +void (*sig_ignorehandler)() = SIG_IGN; diff --git a/sig.h b/sig.h new file mode 100644 index 0000000..2a3c780 --- /dev/null +++ b/sig.h @@ -0,0 +1,28 @@ +/* Public domain. */ + +#ifndef SIG_H +#define SIG_H + +extern int sig_alarm; +extern int sig_child; +extern int sig_cont; +extern int sig_hangup; +extern int sig_int; +extern int sig_pipe; +extern int sig_term; + +extern void (*sig_defaulthandler)(); +extern void (*sig_ignorehandler)(); + +extern void sig_catch(int,void (*)()); +#define sig_ignore(s) (sig_catch((s),sig_ignorehandler)) +#define sig_uncatch(s) (sig_catch((s),sig_defaulthandler)) + +extern void sig_block(int); +extern void sig_unblock(int); +extern void sig_blocknone(void); +extern void sig_pause(void); + +extern void sig_dfl(int); + +#endif diff --git a/sig_block.c b/sig_block.c new file mode 100644 index 0000000..a46c860 --- /dev/null +++ b/sig_block.c @@ -0,0 +1,40 @@ +/* Public domain. */ + +#include +#include "sig.h" +#include "hassgprm.h" + +void sig_block(int sig) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); +#else + sigblock(1 << (sig - 1)); +#endif +} + +void sig_unblock(int sig) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); +#else + sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); +#endif +} + +void sig_blocknone(void) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +#else + sigsetmask(0); +#endif +} diff --git a/sig_catch.c b/sig_catch.c new file mode 100644 index 0000000..7b5bd89 --- /dev/null +++ b/sig_catch.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include +#include "sig.h" +#include "hassgact.h" + +void sig_catch(int sig,void (*f)()) +{ +#ifdef HASSIGACTION + struct sigaction sa; + sa.sa_handler = f; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(sig,&sa,(struct sigaction *) 0); +#else + signal(sig,f); /* won't work under System V, even nowadays---dorks */ +#endif +} diff --git a/sig_pause.c b/sig_pause.c new file mode 100644 index 0000000..3d1a793 --- /dev/null +++ b/sig_pause.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include +#include "sig.h" +#include "hassgprm.h" + +void sig_pause(void) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigsuspend(&ss); +#else + sigpause(0); +#endif +} diff --git a/softlimit.c b/softlimit.c new file mode 100644 index 0000000..8be40b8 --- /dev/null +++ b/softlimit.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include "pathexec.h" +#include "sgetopt.h" +#include "strerr.h" +#include "scan.h" +#include "str.h" + +#define FATAL "softlimit: fatal: " + +void die_usage(void) +{ + strerr_die1x(100,"softlimit: usage: softlimit [-a allbytes] [-c corebytes] [-d databytes] [-f filebytes] [-l lockbytes] [-m membytes] [-o openfiles] [-p processes] [-r residentbytes] [-s stackbytes] [-t cpusecs] child"); +} + +void doit(int resource,const char *arg) +{ + unsigned long u; + struct rlimit r; + + if (getrlimit(resource,&r) == -1) + strerr_die2sys(111,FATAL,"getrlimit failed: "); + + if (str_equal(arg,"=")) + r.rlim_cur = r.rlim_max; + else { + if (arg[scan_ulong(arg,&u)]) die_usage(); + r.rlim_cur = u; + if (r.rlim_cur > r.rlim_max) + r.rlim_cur = r.rlim_max; + } + + if (setrlimit(resource,&r) == -1) + strerr_die2sys(111,FATAL,"setrlimit failed: "); +} + +int main(int argc,const char *const *argv,const char *const *envp) +{ + int opt; + + while ((opt = getopt(argc,argv,"a:c:d:f:l:m:o:p:r:s:t:")) != opteof) + switch(opt) { + case '?': + die_usage(); + case 'a': +#ifdef RLIMIT_AS + doit(RLIMIT_AS,optarg); +#endif +#ifdef RLIMIT_VMEM + doit(RLIMIT_VMEM,optarg); +#endif + break; + case 'c': +#ifdef RLIMIT_CORE + doit(RLIMIT_CORE,optarg); +#endif + break; + case 'd': +#ifdef RLIMIT_DATA + doit(RLIMIT_DATA,optarg); +#endif + break; + case 'f': +#ifdef RLIMIT_FSIZE + doit(RLIMIT_FSIZE,optarg); +#endif + break; + case 'l': +#ifdef RLIMIT_MEMLOCK + doit(RLIMIT_MEMLOCK,optarg); +#endif + break; + case 'm': +#ifdef RLIMIT_DATA + doit(RLIMIT_DATA,optarg); +#endif +#ifdef RLIMIT_STACK + doit(RLIMIT_STACK,optarg); +#endif +#ifdef RLIMIT_MEMLOCK + doit(RLIMIT_MEMLOCK,optarg); +#endif +#ifdef RLIMIT_VMEM + doit(RLIMIT_VMEM,optarg); +#endif +#ifdef RLIMIT_AS + doit(RLIMIT_AS,optarg); +#endif + break; + case 'o': +#ifdef RLIMIT_NOFILE + doit(RLIMIT_NOFILE,optarg); +#endif +#ifdef RLIMIT_OFILE + doit(RLIMIT_OFILE,optarg); +#endif + break; + case 'p': +#ifdef RLIMIT_NPROC + doit(RLIMIT_NPROC,optarg); +#endif + break; + case 'r': +#ifdef RLIMIT_RSS + doit(RLIMIT_RSS,optarg); +#endif + break; + case 's': +#ifdef RLIMIT_STACK + doit(RLIMIT_STACK,optarg); +#endif + break; + case 't': +#ifdef RLIMIT_CPU + doit(RLIMIT_CPU,optarg); +#endif + break; + } + + argv += optind; + if (!*argv) die_usage(); + + pathexec_run(*argv,argv,envp); + strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); +} diff --git a/str.h b/str.h new file mode 100644 index 0000000..f65b8f6 --- /dev/null +++ b/str.h @@ -0,0 +1,16 @@ +/* Public domain. */ + +#ifndef STR_H +#define STR_H + +extern unsigned int str_copy(char *,const char *); +extern int str_diff(const char *,const char *); +extern int str_diffn(const char *,const char *,unsigned int); +extern unsigned int str_len(const char *); +extern unsigned int str_chr(const char *,int); +extern unsigned int str_rchr(const char *,int); +extern int str_start(const char *,const char *); + +#define str_equal(s,t) (!str_diff((s),(t))) + +#endif diff --git a/str_chr.c b/str_chr.c new file mode 100644 index 0000000..9b467eb --- /dev/null +++ b/str_chr.c @@ -0,0 +1,19 @@ +/* Public domain. */ + +#include "str.h" + +unsigned int str_chr(register const char *s,int c) +{ + register char ch; + register const char *t; + + ch = c; + t = s; + for (;;) { + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + } + return t - s; +} diff --git a/str_diff.c b/str_diff.c new file mode 100644 index 0000000..47dff22 --- /dev/null +++ b/str_diff.c @@ -0,0 +1,17 @@ +/* Public domain. */ + +#include "str.h" + +int str_diff(register const char *s,register const char *t) +{ + register char x; + + for (;;) { + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + } + return ((int)(unsigned int)(unsigned char) x) + - ((int)(unsigned int)(unsigned char) *t); +} diff --git a/str_len.c b/str_len.c new file mode 100644 index 0000000..dedd005 --- /dev/null +++ b/str_len.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include "str.h" + +unsigned int str_len(const char *s) +{ + register const char *t; + + t = s; + for (;;) { + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + } +} diff --git a/str_start.c b/str_start.c new file mode 100644 index 0000000..017efc7 --- /dev/null +++ b/str_start.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include "str.h" + +int str_start(register const char *s,register const char *t) +{ + register char x; + + for (;;) { + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + } +} diff --git a/stralloc.h b/stralloc.h new file mode 100644 index 0000000..51d61bd --- /dev/null +++ b/stralloc.h @@ -0,0 +1,31 @@ +/* Public domain. */ + +#ifndef STRALLOC_H +#define STRALLOC_H + +#include "gen_alloc.h" + +GEN_ALLOC_typedef(stralloc,char,s,len,a) + +extern int stralloc_ready(stralloc *,unsigned int); +extern int stralloc_readyplus(stralloc *,unsigned int); +extern int stralloc_copy(stralloc *,const stralloc *); +extern int stralloc_cat(stralloc *,const stralloc *); +extern int stralloc_copys(stralloc *,const char *); +extern int stralloc_cats(stralloc *,const char *); +extern int stralloc_copyb(stralloc *,const char *,unsigned int); +extern int stralloc_catb(stralloc *,const char *,unsigned int); +extern int stralloc_append(stralloc *,const char *); /* beware: this takes a pointer to 1 char */ +extern int stralloc_starts(stralloc *,const char *); + +#define stralloc_0(sa) stralloc_append(sa,"") + +extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int); +extern int stralloc_catlong0(stralloc *,long,unsigned int); + +#define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) +#define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n))) +#define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n))) +#define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0)) + +#endif diff --git a/stralloc_cat.c b/stralloc_cat.c new file mode 100644 index 0000000..2c6ad58 --- /dev/null +++ b/stralloc_cat.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include "byte.h" +#include "stralloc.h" + +int stralloc_cat(stralloc *sato,const stralloc *safrom) +{ + return stralloc_catb(sato,safrom->s,safrom->len); +} diff --git a/stralloc_catb.c b/stralloc_catb.c new file mode 100644 index 0000000..8ee0af4 --- /dev/null +++ b/stralloc_catb.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include "stralloc.h" +#include "byte.h" + +int stralloc_catb(stralloc *sa,const char *s,unsigned int n) +{ + if (!sa->s) return stralloc_copyb(sa,s,n); + if (!stralloc_readyplus(sa,n + 1)) return 0; + byte_copy(sa->s + sa->len,n,s); + sa->len += n; + sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ + return 1; +} diff --git a/stralloc_cats.c b/stralloc_cats.c new file mode 100644 index 0000000..ea1e290 --- /dev/null +++ b/stralloc_cats.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_cats(stralloc *sa,const char *s) +{ + return stralloc_catb(sa,s,str_len(s)); +} diff --git a/stralloc_eady.c b/stralloc_eady.c new file mode 100644 index 0000000..81dbb85 --- /dev/null +++ b/stralloc_eady.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) +GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) diff --git a/stralloc_opyb.c b/stralloc_opyb.c new file mode 100644 index 0000000..bbcff48 --- /dev/null +++ b/stralloc_opyb.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include "stralloc.h" +#include "byte.h" + +int stralloc_copyb(stralloc *sa,const char *s,unsigned int n) +{ + if (!stralloc_ready(sa,n + 1)) return 0; + byte_copy(sa->s,n,s); + sa->len = n; + sa->s[n] = 'Z'; /* ``offensive programming'' */ + return 1; +} diff --git a/stralloc_opys.c b/stralloc_opys.c new file mode 100644 index 0000000..075b6f8 --- /dev/null +++ b/stralloc_opys.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_copys(stralloc *sa,const char *s) +{ + return stralloc_copyb(sa,s,str_len(s)); +} diff --git a/stralloc_pend.c b/stralloc_pend.c new file mode 100644 index 0000000..70cb55c --- /dev/null +++ b/stralloc_pend.c @@ -0,0 +1,7 @@ +/* Public domain. */ + +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) diff --git a/strerr.h b/strerr.h new file mode 100644 index 0000000..21d812d --- /dev/null +++ b/strerr.h @@ -0,0 +1,80 @@ +/* Public domain. */ + +#ifndef STRERR_H +#define STRERR_H + +struct strerr { + struct strerr *who; + const char *x; + const char *y; + const char *z; +} ; + +extern struct strerr strerr_sys; +extern void strerr_sysinit(void); + +extern const char *strerr(const struct strerr *); +extern void strerr_warn(const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); +extern void strerr_die(int,const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); + +#define STRERR(r,se,a) \ +{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } + +#define STRERR_SYS(r,se,a) \ +{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } +#define STRERR_SYS3(r,se,a,b,c) \ +{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } + +#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se)) +#define strerr_warn5(x1,x2,x3,x4,x5,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se)) +#define strerr_warn4(x1,x2,x3,x4,se) \ +strerr_warn((x1),(x2),(x3),(x4),0,0,(se)) +#define strerr_warn3(x1,x2,x3,se) \ +strerr_warn((x1),(x2),(x3),0,0,0,(se)) +#define strerr_warn2(x1,x2,se) \ +strerr_warn((x1),(x2),0,0,0,0,(se)) +#define strerr_warn1(x1,se) \ +strerr_warn((x1),0,0,0,0,0,(se)) + +#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se)) +#define strerr_die5(e,x1,x2,x3,x4,x5,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se)) +#define strerr_die4(e,x1,x2,x3,x4,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se)) +#define strerr_die3(e,x1,x2,x3,se) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,(se)) +#define strerr_die2(e,x1,x2,se) \ +strerr_die((e),(x1),(x2),0,0,0,0,(se)) +#define strerr_die1(e,x1,se) \ +strerr_die((e),(x1),0,0,0,0,0,(se)) + +#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) +#define strerr_die5sys(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys) +#define strerr_die4sys(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys) +#define strerr_die3sys(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys) +#define strerr_die2sys(e,x1,x2) \ +strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys) +#define strerr_die1sys(e,x1) \ +strerr_die((e),(x1),0,0,0,0,0,&strerr_sys) + +#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0) +#define strerr_die5x(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0) +#define strerr_die4x(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,0) +#define strerr_die3x(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,0) +#define strerr_die2x(e,x1,x2) \ +strerr_die((e),(x1),(x2),0,0,0,0,0) +#define strerr_die1x(e,x1) \ +strerr_die((e),(x1),0,0,0,0,0,0) + +#endif diff --git a/strerr_die.c b/strerr_die.c new file mode 100644 index 0000000..f226b80 --- /dev/null +++ b/strerr_die.c @@ -0,0 +1,33 @@ +/* Public domain. */ + +#include +#include "buffer.h" +#include "strerr.h" + +void strerr_warn(const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) +{ + strerr_sysinit(); + + if (x1) buffer_puts(buffer_2,x1); + if (x2) buffer_puts(buffer_2,x2); + if (x3) buffer_puts(buffer_2,x3); + if (x4) buffer_puts(buffer_2,x4); + if (x5) buffer_puts(buffer_2,x5); + if (x6) buffer_puts(buffer_2,x6); + + while(se) { + if (se->x) buffer_puts(buffer_2,se->x); + if (se->y) buffer_puts(buffer_2,se->y); + if (se->z) buffer_puts(buffer_2,se->z); + se = se->who; + } + + buffer_puts(buffer_2,"\n"); + buffer_flush(buffer_2); +} + +void strerr_die(int e,const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) +{ + strerr_warn(x1,x2,x3,x4,x5,x6,se); + _exit(e); +} diff --git a/strerr_sys.c b/strerr_sys.c new file mode 100644 index 0000000..84b302f --- /dev/null +++ b/strerr_sys.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include "error.h" +#include "strerr.h" + +struct strerr strerr_sys; + +void strerr_sysinit(void) +{ + strerr_sys.who = 0; + strerr_sys.x = error_str(errno); + strerr_sys.y = ""; + strerr_sys.z = ""; +} diff --git a/subgetopt.c b/subgetopt.c new file mode 100644 index 0000000..266e72a --- /dev/null +++ b/subgetopt.c @@ -0,0 +1,67 @@ +/* Public domain. */ + +#define SUBGETOPTNOSHORT +#include "subgetopt.h" + +#define sgopt subgetopt +#define optind subgetoptind +#define optpos subgetoptpos +#define optarg subgetoptarg +#define optproblem subgetoptproblem +#define optdone subgetoptdone + +int optind = 1; +int optpos = 0; +const char *optarg = 0; +int optproblem = 0; +int optdone = SUBGETOPTDONE; + +int sgopt(int argc,const char *const *argv,const char *opts) +{ + int c; + const char *s; + + optarg = 0; + if (!argv || (optind >= argc) || !argv[optind]) return optdone; + if (optpos && !argv[optind][optpos]) { + ++optind; + optpos = 0; + if ((optind >= argc) || !argv[optind]) return optdone; + } + if (!optpos) { + if (argv[optind][0] != '-') return optdone; + ++optpos; + c = argv[optind][1]; + if ((c == '-') || (c == 0)) { + if (c) ++optind; + optpos = 0; + return optdone; + } + /* otherwise c is reassigned below */ + } + c = argv[optind][optpos]; + ++optpos; + s = opts; + while (*s) { + if (c == *s) { + if (s[1] == ':') { + optarg = argv[optind] + optpos; + ++optind; + optpos = 0; + if (!*optarg) { + optarg = argv[optind]; + if ((optind >= argc) || !optarg) { /* argument past end */ + optproblem = c; + return '?'; + } + ++optind; + } + } + return c; + } + ++s; + if (*s == ':') ++s; + } + optproblem = c; + return '?'; +} diff --git a/subgetopt.h b/subgetopt.h new file mode 100644 index 0000000..41ad26a --- /dev/null +++ b/subgetopt.h @@ -0,0 +1,26 @@ +/* Public domain. */ + +#ifndef SUBGETOPT_H +#define SUBGETOPT_H + +#ifndef SUBGETOPTNOSHORT +#define sgopt subgetopt +#define sgoptarg subgetoptarg +#define sgoptind subgetoptind +#define sgoptpos subgetoptpos +#define sgoptproblem subgetoptproblem +#define sgoptprogname subgetoptprogname +#define sgoptdone subgetoptdone +#endif + +#define SUBGETOPTDONE -1 + +extern int subgetopt(int,const char *const *,const char *); +extern const char *subgetoptarg; +extern int subgetoptind; +extern int subgetoptpos; +extern int subgetoptproblem; +extern const char *subgetoptprogname; +extern int subgetoptdone; + +#endif diff --git a/supervise.c b/supervise.c new file mode 100644 index 0000000..2482ad2 --- /dev/null +++ b/supervise.c @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include "sig.h" +#include "strerr.h" +#include "error.h" +#include "fifo.h" +#include "open.h" +#include "lock.h" +#include "wait.h" +#include "coe.h" +#include "ndelay.h" +#include "env.h" +#include "iopause.h" +#include "taia.h" +#include "deepsleep.h" + +#define FATAL "supervise: fatal: " +#define WARNING "supervise: warning: " + +char *dir; +int selfpipe[2]; +int fdlock; +int fdcontrolwrite; +int fdcontrol; +int fdok; + +int flagexit = 0; +int flagwant = 1; +int flagwantup = 1; +int pid = 0; /* 0 means down */ +int flagpaused; /* defined if(pid) */ + +char status[18]; + +void pidchange(void) +{ + struct taia now; + unsigned long u; + + taia_now(&now); + taia_pack(status,&now); + + u = (unsigned long) pid; + status[12] = u; u >>= 8; + status[13] = u; u >>= 8; + status[14] = u; u >>= 8; + status[15] = u; +} + +void announce(void) +{ + int fd; + int r; + + status[16] = (pid ? flagpaused : 0); + status[17] = (flagwant ? (flagwantup ? 'u' : 'd') : 0); + + fd = open_trunc("supervise/status.new"); + if (fd == -1) { + strerr_warn4(WARNING,"unable to open ",dir,"/supervise/status.new: ",&strerr_sys); + return; + } + + r = write(fd,status,sizeof status); + if (r == -1) { + strerr_warn4(WARNING,"unable to write ",dir,"/supervise/status.new: ",&strerr_sys); + close(fd); + return; + } + close(fd); + if (r < sizeof status) { + strerr_warn4(WARNING,"unable to write ",dir,"/supervise/status.new: partial write",0); + return; + } + + if (rename("supervise/status.new","supervise/status") == -1) + strerr_warn4(WARNING,"unable to rename ",dir,"/supervise/status.new to status: ",&strerr_sys); +} + +void trigger(void) +{ + write(selfpipe[1],"",1); +} + +const char *run[2] = { "./run", 0 }; + +void trystart(void) +{ + int f; + + switch(f = fork()) { + case -1: + strerr_warn4(WARNING,"unable to fork for ",dir,", sleeping 60 seconds: ",&strerr_sys); + deepsleep(60); + trigger(); + return; + case 0: + sig_uncatch(sig_child); + sig_unblock(sig_child); + execve(*run,run,environ); + strerr_die4sys(111,FATAL,"unable to start ",dir,"/run: "); + } + flagpaused = 0; + pid = f; + pidchange(); + announce(); + deepsleep(1); +} + +void doit(void) +{ + iopause_fd x[2]; + struct taia deadline; + struct taia stamp; + int wstat; + int r; + char ch; + + announce(); + + for (;;) { + if (flagexit && !pid) return; + + sig_unblock(sig_child); + + x[0].fd = selfpipe[0]; + x[0].events = IOPAUSE_READ; + x[1].fd = fdcontrol; + x[1].events = IOPAUSE_READ; + taia_now(&stamp); + taia_uint(&deadline,3600); + taia_add(&deadline,&stamp,&deadline); + iopause(x,2,&deadline,&stamp); + + sig_block(sig_child); + + while (read(selfpipe[0],&ch,1) == 1) + ; + + for (;;) { + r = wait_nohang(&wstat); + if (!r) break; + if ((r == -1) && (errno != error_intr)) break; + if (r == pid) { + pid = 0; + pidchange(); + announce(); + if (flagexit) return; + if (flagwant && flagwantup) trystart(); + break; + } + } + + if (read(fdcontrol,&ch,1) == 1) + switch(ch) { + case 'd': + flagwant = 1; + flagwantup = 0; + if (pid) { kill(pid,SIGTERM); kill(pid,SIGCONT); flagpaused = 0; } + announce(); + break; + case 'u': + flagwant = 1; + flagwantup = 1; + announce(); + if (!pid) trystart(); + break; + case 'o': + flagwant = 0; + announce(); + if (!pid) trystart(); + break; + case 'a': + if (pid) kill(pid,SIGALRM); + break; + case 'h': + if (pid) kill(pid,SIGHUP); + break; + case 'k': + if (pid) kill(pid,SIGKILL); + break; + case 't': + if (pid) kill(pid,SIGTERM); + break; + case 'i': + if (pid) kill(pid,SIGINT); + break; + case 'p': + flagpaused = 1; + announce(); + if (pid) kill(pid,SIGSTOP); + break; + case 'c': + flagpaused = 0; + announce(); + if (pid) kill(pid,SIGCONT); + break; + case 'x': + flagexit = 1; + announce(); + break; + } + } +} + +int main(int argc,char **argv) +{ + struct stat st; + + dir = argv[1]; + if (!dir || argv[2]) + strerr_die1x(100,"supervise: usage: supervise dir"); + + if (pipe(selfpipe) == -1) + strerr_die4sys(111,FATAL,"unable to create pipe for ",dir,": "); + coe(selfpipe[0]); + coe(selfpipe[1]); + ndelay_on(selfpipe[0]); + ndelay_on(selfpipe[1]); + + sig_block(sig_child); + sig_catch(sig_child,trigger); + + if (chdir(dir) == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",dir,": "); + + if (stat("down",&st) != -1) + flagwantup = 0; + else + if (errno != error_noent) + strerr_die4sys(111,FATAL,"unable to stat ",dir,"/down: "); + + mkdir("supervise",0700); + fdlock = open_append("supervise/lock"); + if ((fdlock == -1) || (lock_exnb(fdlock) == -1)) + strerr_die4sys(111,FATAL,"unable to acquire ",dir,"/supervise/lock: "); + coe(fdlock); + + fifo_make("supervise/control",0600); + fdcontrol = open_read("supervise/control"); + if (fdcontrol == -1) + strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/control: "); + coe(fdcontrol); + ndelay_on(fdcontrol); /* shouldn't be necessary */ + fdcontrolwrite = open_write("supervise/control"); + if (fdcontrolwrite == -1) + strerr_die4sys(111,FATAL,"unable to write ",dir,"/supervise/control: "); + coe(fdcontrolwrite); + + pidchange(); + announce(); + + fifo_make("supervise/ok",0600); + fdok = open_read("supervise/ok"); + if (fdok == -1) + strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/ok: "); + coe(fdok); + + if (!flagwant || flagwantup) trystart(); + + doit(); + announce(); + _exit(0); +} diff --git a/svc.c b/svc.c new file mode 100644 index 0000000..4a8c8c1 --- /dev/null +++ b/svc.c @@ -0,0 +1,66 @@ +#include +#include "ndelay.h" +#include "strerr.h" +#include "error.h" +#include "open.h" +#include "sgetopt.h" +#include "buffer.h" +#include "byte.h" +#include "sig.h" + +#define FATAL "svc: fatal: " +#define WARNING "svc: warning: " + +int datalen = 0; +char data[20]; + +buffer b; +char bspace[1]; + +int fdorigdir; + +int main(int argc,const char *const *argv) +{ + int opt; + int fd; + const char *dir; + + sig_ignore(sig_pipe); + + while ((opt = getopt(argc,argv,"udopchaitkx")) != opteof) + if (opt == '?') + strerr_die1x(100,"svc options: u up, d down, o once, x exit, p pause, c continue, h hup, a alarm, i interrupt, t term, k kill"); + else + if (datalen < sizeof data) + if (byte_chr(data,datalen,opt) == datalen) + data[datalen++] = opt; + argv += optind; + + fdorigdir = open_read("."); + if (fdorigdir == -1) + strerr_die2sys(111,FATAL,"unable to open current directory: "); + + while (dir = *argv++) { + if (chdir(dir) == -1) + strerr_warn4(WARNING,"unable to chdir to ",dir,": ",&strerr_sys); + else { + fd = open_write("supervise/control"); + if (fd == -1) + if (errno == error_nodevice) + strerr_warn4(WARNING,"unable to control ",dir,": supervise not running",0); + else + strerr_warn4(WARNING,"unable to control ",dir,": ",&strerr_sys); + else { + ndelay_off(fd); + buffer_init(&b,buffer_unixwrite,fd,bspace,sizeof bspace); + if (buffer_putflush(&b,data,datalen) == -1) + strerr_warn4(WARNING,"error writing commands to ",dir,": ",&strerr_sys); + close(fd); + } + } + if (fchdir(fdorigdir) == -1) + strerr_die2sys(111,FATAL,"unable to set directory: "); + } + + _exit(0); +} diff --git a/svok.c b/svok.c new file mode 100644 index 0000000..d29abcc --- /dev/null +++ b/svok.c @@ -0,0 +1,26 @@ +#include +#include "strerr.h" +#include "error.h" +#include "open.h" + +#define FATAL "svok: fatal: " + +int main(int argc,char **argv) +{ + int fd; + + if (!argv[1]) + strerr_die1x(100,"svok: usage: svok dir"); + + if (chdir(argv[1]) == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",argv[1],": "); + + fd = open_write("supervise/ok"); + if (fd == -1) { + if (errno == error_noent) _exit(100); + if (errno == error_nodevice) _exit(100); + strerr_die4sys(111,FATAL,"unable to open ",argv[1],"/supervise/ok: "); + } + + _exit(0); +} diff --git a/svscan.c b/svscan.c new file mode 100644 index 0000000..15a8c89 --- /dev/null +++ b/svscan.c @@ -0,0 +1,203 @@ +#include +#include +#include +#include "direntry.h" +#include "strerr.h" +#include "error.h" +#include "wait.h" +#include "coe.h" +#include "fd.h" +#include "env.h" +#include "str.h" +#include "byte.h" +#include "pathexec.h" + +#define SERVICES 1000 + +#define WARNING "svscan: warning: " +#define FATAL "svscan: fatal: " + +struct { + unsigned long dev; + unsigned long ino; + int flagactive; + int flaglog; + int pid; /* 0 if not running */ + int pidlog; /* 0 if not running */ + int pi[2]; /* defined if flaglog */ +} x[SERVICES]; +int numx = 0; + +char fnlog[260]; + +void start(char *fn) +{ + unsigned int fnlen; + struct stat st; + int child; + int i; + const char *args[3]; + + if (fn[0] == '.') return; + + if (stat(fn,&st) == -1) { + strerr_warn4(WARNING,"unable to stat ",fn,": ",&strerr_sys); + return; + } + + if ((st.st_mode & S_IFMT) != S_IFDIR) return; + + for (i = 0;i < numx;++i) + if (x[i].ino == st.st_ino) + if (x[i].dev == st.st_dev) + break; + + if (i == numx) { + if (numx >= SERVICES) { + strerr_warn4(WARNING,"unable to start ",fn,": running too many services",0); + return; + } + x[i].ino = st.st_ino; + x[i].dev = st.st_dev; + x[i].pid = 0; + x[i].pidlog = 0; + x[i].flaglog = 0; + + fnlen = str_len(fn); + if (fnlen <= 255) { + byte_copy(fnlog,fnlen,fn); + byte_copy(fnlog + fnlen,5,"/log"); + if (stat(fnlog,&st) == 0) + x[i].flaglog = 1; + else + if (errno != error_noent) { + strerr_warn4(WARNING,"unable to stat ",fn,"/log: ",&strerr_sys); + return; + } + } + + if (x[i].flaglog) { + if (pipe(x[i].pi) == -1) { + strerr_warn4(WARNING,"unable to create pipe for ",fn,": ",&strerr_sys); + return; + } + coe(x[i].pi[0]); + coe(x[i].pi[1]); + } + ++numx; + } + + x[i].flagactive = 1; + + if (!x[i].pid) + switch(child = fork()) { + case -1: + strerr_warn4(WARNING,"unable to fork for ",fn,": ",&strerr_sys); + return; + case 0: + if (x[i].flaglog) + if (fd_move(1,x[i].pi[1]) == -1) + strerr_die4sys(111,WARNING,"unable to set up descriptors for ",fn,": "); + args[0] = "supervise"; + args[1] = fn; + args[2] = 0; + pathexec_run(*args,args,environ); + strerr_die4sys(111,WARNING,"unable to start supervise ",fn,": "); + default: + x[i].pid = child; + } + + if (x[i].flaglog && !x[i].pidlog) + switch(child = fork()) { + case -1: + strerr_warn4(WARNING,"unable to fork for ",fn,"/log: ",&strerr_sys); + return; + case 0: + if (fd_move(0,x[i].pi[0]) == -1) + strerr_die4sys(111,WARNING,"unable to set up descriptors for ",fn,"/log: "); + if (chdir(fn) == -1) + strerr_die4sys(111,WARNING,"unable to switch to ",fn,": "); + args[0] = "supervise"; + args[1] = "log"; + args[2] = 0; + pathexec_run(*args,args,environ); + strerr_die4sys(111,WARNING,"unable to start supervise ",fn,"/log: "); + default: + x[i].pidlog = child; + } +} + +void direrror(void) +{ + strerr_warn2(WARNING,"unable to read directory: ",&strerr_sys); +} + +void doit(void) +{ + DIR *dir; + direntry *d; + int i; + int r; + int wstat; + + for (;;) { + r = wait_nohang(&wstat); + if (!r) break; + if (r == -1) { + if (errno == error_intr) continue; /* impossible */ + break; + } + + for (i = 0;i < numx;++i) { + if (x[i].pid == r) { x[i].pid = 0; break; } + if (x[i].pidlog == r) { x[i].pidlog = 0; break; } + } + } + + for (i = 0;i < numx;++i) + x[i].flagactive = 0; + + dir = opendir("."); + if (!dir) { + direrror(); + return; + } + for (;;) { + errno = 0; + d = readdir(dir); + if (!d) break; + start(d->d_name); + } + if (errno) { + direrror(); + closedir(dir); + return; + } + closedir(dir); + + i = 0; + while (i < numx) { + if (!x[i].flagactive && !x[i].pid && !x[i].pidlog) { + if (x[i].flaglog) { + close(x[i].pi[0]); + close(x[i].pi[1]); + x[i].flaglog = 0; + } + x[i] = x[--numx]; + continue; + } + ++i; + } +} + +int main(int argc,char **argv) +{ + if (argv[0] && argv[1]) + if (chdir(argv[1]) == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",argv[1],": "); + + for (;;) { + doit(); + sleep(5); + } +} diff --git a/svscanboot.sh b/svscanboot.sh new file mode 100644 index 0000000..74079ea --- /dev/null +++ b/svscanboot.sh @@ -0,0 +1,11 @@ + +PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin + +exec /dev/null +exec 2>/dev/null + +/command/svc -dx /service/* /service/*/log + +env - PATH=$PATH svscan /service 2>&1 | \ +env - PATH=$PATH readproctitle service errors: ................................................................................................................................................................................................................................................................................................................................................................................................................ diff --git a/svstat.c b/svstat.c new file mode 100644 index 0000000..fcc4732 --- /dev/null +++ b/svstat.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include "strerr.h" +#include "error.h" +#include "open.h" +#include "fmt.h" +#include "tai.h" +#include "buffer.h" + +#define FATAL "svstat: fatal: " +#define WARNING "svstat: warning: " + +char bspace[1024]; +buffer b = BUFFER_INIT(buffer_unixwrite,1,bspace,sizeof bspace); + +char status[18]; +char strnum[FMT_ULONG]; + +unsigned long pid; +unsigned char normallyup; +unsigned char want; +unsigned char paused; + +void doit(char *dir) +{ + struct stat st; + int r; + int fd; + const char *x; + struct tai when; + struct tai now; + + buffer_puts(&b,dir); + buffer_puts(&b,": "); + + if (chdir(dir) == -1) { + x = error_str(errno); + buffer_puts(&b,"unable to chdir: "); + buffer_puts(&b,x); + return; + } + + normallyup = 0; + if (stat("down",&st) == -1) { + if (errno != error_noent) { + x = error_str(errno); + buffer_puts(&b,"unable to stat down: "); + buffer_puts(&b,x); + return; + } + normallyup = 1; + } + + fd = open_write("supervise/ok"); + if (fd == -1) { + if (errno == error_nodevice) { + buffer_puts(&b,"supervise not running"); + return; + } + x = error_str(errno); + buffer_puts(&b,"unable to open supervise/ok: "); + buffer_puts(&b,x); + return; + } + close(fd); + + fd = open_read("supervise/status"); + if (fd == -1) { + x = error_str(errno); + buffer_puts(&b,"unable to open supervise/status: "); + buffer_puts(&b,x); + return; + } + r = buffer_unixread(fd,status,sizeof status); + close(fd); + if (r < sizeof status) { + if (r == -1) + x = error_str(errno); + else + x = "bad format"; + buffer_puts(&b,"unable to read supervise/status: "); + buffer_puts(&b,x); + return; + } + + pid = (unsigned char) status[15]; + pid <<= 8; pid += (unsigned char) status[14]; + pid <<= 8; pid += (unsigned char) status[13]; + pid <<= 8; pid += (unsigned char) status[12]; + + paused = status[16]; + want = status[17]; + + tai_unpack(status,&when); + tai_now(&now); + if (tai_less(&now,&when)) when = now; + tai_sub(&when,&now,&when); + + if (pid) { + buffer_puts(&b,"up (pid "); + buffer_put(&b,strnum,fmt_ulong(strnum,pid)); + buffer_puts(&b,") "); + } + else + buffer_puts(&b,"down "); + + buffer_put(&b,strnum,fmt_ulong(strnum,tai_approx(&when))); + buffer_puts(&b," seconds"); + + if (pid && !normallyup) + buffer_puts(&b,", normally down"); + if (!pid && normallyup) + buffer_puts(&b,", normally up"); + if (pid && paused) + buffer_puts(&b,", paused"); + if (!pid && (want == 'u')) + buffer_puts(&b,", want up"); + if (pid && (want == 'd')) + buffer_puts(&b,", want down"); +} + +int main(int argc,char **argv) +{ + int fdorigdir; + char *dir; + + ++argv; + + fdorigdir = open_read("."); + if (fdorigdir == -1) + strerr_die2sys(111,FATAL,"unable to open current directory: "); + + while (dir = *argv++) { + doit(dir); + buffer_puts(&b,"\n"); + if (fchdir(fdorigdir) == -1) + strerr_die2sys(111,FATAL,"unable to set directory: "); + } + + buffer_flush(&b); + + _exit(0); +} diff --git a/tai.h b/tai.h new file mode 100644 index 0000000..1839f76 --- /dev/null +++ b/tai.h @@ -0,0 +1,28 @@ +/* Public domain. */ + +#ifndef TAI_H +#define TAI_H + +#include "uint64.h" + +struct tai { + uint64 x; +} ; + +#define tai_unix(t,u) ((void) ((t)->x = 4611686018427387914ULL + (uint64) (u))) + +extern void tai_now(struct tai *); + +#define tai_approx(t) ((double) ((t)->x)) + +extern void tai_add(struct tai *,const struct tai *,const struct tai *); +extern void tai_sub(struct tai *,const struct tai *,const struct tai *); +#define tai_less(t,u) ((t)->x < (u)->x) + +#define TAI_PACK 8 +extern void tai_pack(char *,const struct tai *); +extern void tai_unpack(const char *,struct tai *); + +extern void tai_uint(struct tai *,unsigned int); + +#endif diff --git a/tai64n.c b/tai64n.c new file mode 100644 index 0000000..17bdb82 --- /dev/null +++ b/tai64n.c @@ -0,0 +1,47 @@ +#include +#include "timestamp.h" +#include "buffer.h" + +int mywrite(int fd,char *buf,int len) +{ + int w; + w = buffer_unixwrite(fd,buf,len); + if (w == -1) _exit(111); + return w; +} + +char outbuf[2048]; +buffer out = BUFFER_INIT(mywrite,1,outbuf,sizeof outbuf); + +int myread(int fd,char *buf,int len) +{ + int r; + buffer_flush(&out); + r = buffer_unixread(fd,buf,len); + if (r == -1) _exit(111); + return r; +} + +char inbuf[1024]; +buffer in = BUFFER_INIT(myread,0,inbuf,sizeof inbuf); + +char stamp[TIMESTAMP + 1]; + +int main() +{ + char ch; + + for (;;) { + if (buffer_GETC(&in,&ch) != 1) _exit(0); + + timestamp(stamp); + stamp[TIMESTAMP] = ' '; + buffer_put(&out,stamp,TIMESTAMP + 1); + + for (;;) { + buffer_PUTC(&out,ch); + if (ch == '\n') break; + if (buffer_GETC(&in,&ch) != 1) _exit(0); + } + } +} diff --git a/tai64nlocal.c b/tai64nlocal.c new file mode 100644 index 0000000..ce16ad8 --- /dev/null +++ b/tai64nlocal.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include "buffer.h" +#include "fmt.h" + +char num[FMT_ULONG]; + +void get(char *ch) +{ + int r; + + r = buffer_GETC(buffer_0,ch); + if (r == 1) return; + if (r == 0) _exit(0); + _exit(111); +} + +void out(const char *buf,int len) +{ + if (buffer_put(buffer_1,buf,len) == -1) + _exit(111); +} + +time_t secs; +unsigned long nanosecs; +unsigned long u; +struct tm *t; + +int main() +{ + char ch; + + for (;;) { + get(&ch); + if (ch == '@') { + secs = 0; + nanosecs = 0; + for (;;) { + get(&ch); + u = ch - '0'; + if (u >= 10) { + u = ch - 'a'; + if (u >= 6) break; + u += 10; + } + secs <<= 4; + secs += nanosecs >> 28; + nanosecs &= 0xfffffff; + nanosecs <<= 4; + nanosecs += u; + } + secs -= 4611686018427387914ULL; + t = localtime(&secs); + out(num,fmt_ulong(num,1900 + t->tm_year)); + out("-",1); out(num,fmt_uint0(num,1 + t->tm_mon,2)); + out("-",1); out(num,fmt_uint0(num,t->tm_mday,2)); + out(" ",1); out(num,fmt_uint0(num,t->tm_hour,2)); + out(":",1); out(num,fmt_uint0(num,t->tm_min,2)); + out(":",1); out(num,fmt_uint0(num,t->tm_sec,2)); + out(".",1); out(num,fmt_uint0(num,nanosecs,9)); + } + for (;;) { + out(&ch,1); + if (ch == '\n') break; + get(&ch); + } + } +} diff --git a/tai_now.c b/tai_now.c new file mode 100644 index 0000000..217ba75 --- /dev/null +++ b/tai_now.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include "tai.h" + +void tai_now(struct tai *t) +{ + tai_unix(t,time((time_t *) 0)); +} diff --git a/tai_pack.c b/tai_pack.c new file mode 100644 index 0000000..641fa5b --- /dev/null +++ b/tai_pack.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "tai.h" + +void tai_pack(char *s,const struct tai *t) +{ + uint64 x; + + x = t->x; + s[7] = x & 255; x >>= 8; + s[6] = x & 255; x >>= 8; + s[5] = x & 255; x >>= 8; + s[4] = x & 255; x >>= 8; + s[3] = x & 255; x >>= 8; + s[2] = x & 255; x >>= 8; + s[1] = x & 255; x >>= 8; + s[0] = x; +} diff --git a/tai_sub.c b/tai_sub.c new file mode 100644 index 0000000..e891600 --- /dev/null +++ b/tai_sub.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "tai.h" + +void tai_sub(struct tai *t,const struct tai *u,const struct tai *v) +{ + t->x = u->x - v->x; +} diff --git a/tai_unpack.c b/tai_unpack.c new file mode 100644 index 0000000..4541ff5 --- /dev/null +++ b/tai_unpack.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "tai.h" + +void tai_unpack(const char *s,struct tai *t) +{ + uint64 x; + + x = (unsigned char) s[0]; + x <<= 8; x += (unsigned char) s[1]; + x <<= 8; x += (unsigned char) s[2]; + x <<= 8; x += (unsigned char) s[3]; + x <<= 8; x += (unsigned char) s[4]; + x <<= 8; x += (unsigned char) s[5]; + x <<= 8; x += (unsigned char) s[6]; + x <<= 8; x += (unsigned char) s[7]; + t->x = x; +} diff --git a/taia.h b/taia.h new file mode 100644 index 0000000..3882d1d --- /dev/null +++ b/taia.h @@ -0,0 +1,36 @@ +/* Public domain. */ + +#ifndef TAIA_H +#define TAIA_H + +#include "tai.h" + +struct taia { + struct tai sec; + unsigned long nano; /* 0...999999999 */ + unsigned long atto; /* 0...999999999 */ +} ; + +extern void taia_tai(const struct taia *,struct tai *); + +extern void taia_now(struct taia *); + +extern double taia_approx(const struct taia *); +extern double taia_frac(const struct taia *); + +extern void taia_add(struct taia *,const struct taia *,const struct taia *); +extern void taia_addsec(struct taia *,const struct taia *,int); +extern void taia_sub(struct taia *,const struct taia *,const struct taia *); +extern void taia_half(struct taia *,const struct taia *); +extern int taia_less(const struct taia *,const struct taia *); + +#define TAIA_PACK 16 +extern void taia_pack(char *,const struct taia *); +extern void taia_unpack(const char *,struct taia *); + +#define TAIA_FMTFRAC 19 +extern unsigned int taia_fmtfrac(char *,const struct taia *); + +extern void taia_uint(struct taia *,unsigned int); + +#endif diff --git a/taia_add.c b/taia_add.c new file mode 100644 index 0000000..0ac8e6b --- /dev/null +++ b/taia_add.c @@ -0,0 +1,20 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +void taia_add(struct taia *t,const struct taia *u,const struct taia *v) +{ + t->sec.x = u->sec.x + v->sec.x; + t->nano = u->nano + v->nano; + t->atto = u->atto + v->atto; + if (t->atto > 999999999UL) { + t->atto -= 1000000000UL; + ++t->nano; + } + if (t->nano > 999999999UL) { + t->nano -= 1000000000UL; + ++t->sec.x; + } +} diff --git a/taia_approx.c b/taia_approx.c new file mode 100644 index 0000000..c6f5f27 --- /dev/null +++ b/taia_approx.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "taia.h" + +double taia_approx(const struct taia *t) +{ + return tai_approx(&t->sec) + taia_frac(t); +} diff --git a/taia_frac.c b/taia_frac.c new file mode 100644 index 0000000..f709f3e --- /dev/null +++ b/taia_frac.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "taia.h" + +double taia_frac(const struct taia *t) +{ + return (t->atto * 0.000000001 + t->nano) * 0.000000001; +} diff --git a/taia_less.c b/taia_less.c new file mode 100644 index 0000000..18a9378 --- /dev/null +++ b/taia_less.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +int taia_less(const struct taia *t,const struct taia *u) +{ + if (t->sec.x < u->sec.x) return 1; + if (t->sec.x > u->sec.x) return 0; + if (t->nano < u->nano) return 1; + if (t->nano > u->nano) return 0; + return t->atto < u->atto; +} diff --git a/taia_now.c b/taia_now.c new file mode 100644 index 0000000..3a951a9 --- /dev/null +++ b/taia_now.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include +#include +#include +#include "taia.h" + +void taia_now(struct taia *t) +{ + struct timeval now; + gettimeofday(&now,(struct timezone *) 0); + tai_unix(&t->sec,now.tv_sec); + t->nano = 1000 * now.tv_usec + 500; + t->atto = 0; +} diff --git a/taia_pack.c b/taia_pack.c new file mode 100644 index 0000000..9047da1 --- /dev/null +++ b/taia_pack.c @@ -0,0 +1,22 @@ +/* Public domain. */ + +#include "taia.h" + +void taia_pack(char *s,const struct taia *t) +{ + unsigned long x; + + tai_pack(s,&t->sec); + s += 8; + + x = t->atto; + s[7] = x & 255; x >>= 8; + s[6] = x & 255; x >>= 8; + s[5] = x & 255; x >>= 8; + s[4] = x; + x = t->nano; + s[3] = x & 255; x >>= 8; + s[2] = x & 255; x >>= 8; + s[1] = x & 255; x >>= 8; + s[0] = x; +} diff --git a/taia_sub.c b/taia_sub.c new file mode 100644 index 0000000..d902e50 --- /dev/null +++ b/taia_sub.c @@ -0,0 +1,23 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +void taia_sub(struct taia *t,const struct taia *u,const struct taia *v) +{ + unsigned long unano = u->nano; + unsigned long uatto = u->atto; + + t->sec.x = u->sec.x - v->sec.x; + t->nano = unano - v->nano; + t->atto = uatto - v->atto; + if (t->atto > uatto) { + t->atto += 1000000000UL; + --t->nano; + } + if (t->nano > unano) { + t->nano += 1000000000UL; + --t->sec.x; + } +} diff --git a/taia_uint.c b/taia_uint.c new file mode 100644 index 0000000..8b7f2d4 --- /dev/null +++ b/taia_uint.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +void taia_uint(struct taia *t,unsigned int s) +{ + t->sec.x = s; + t->nano = 0; + t->atto = 0; +} diff --git a/timestamp.c b/timestamp.c new file mode 100644 index 0000000..37a75d1 --- /dev/null +++ b/timestamp.c @@ -0,0 +1,20 @@ +#include "taia.h" +#include "timestamp.h" + +static char hex[16] = "0123456789abcdef"; + +void timestamp(char s[TIMESTAMP]) +{ + struct taia now; + char nowpack[TAIA_PACK]; + int i; + + taia_now(&now); + taia_pack(nowpack,&now); + + s[0] = '@'; + for (i = 0;i < 12;++i) { + s[i * 2 + 1] = hex[(nowpack[i] >> 4) & 15]; + s[i * 2 + 2] = hex[nowpack[i] & 15]; + } +} diff --git a/timestamp.h b/timestamp.h new file mode 100644 index 0000000..c923633 --- /dev/null +++ b/timestamp.h @@ -0,0 +1,8 @@ +#ifndef TIMESTAMP_H +#define TIMESTAMP_H + +#define TIMESTAMP 25 + +extern void timestamp(char *); + +#endif diff --git a/trycpp.c b/trycpp.c new file mode 100644 index 0000000..e4503d4 --- /dev/null +++ b/trycpp.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +int main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} diff --git a/trydrent.c b/trydrent.c new file mode 100644 index 0000000..3333ac0 --- /dev/null +++ b/trydrent.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include +#include + +void foo() +{ + DIR *dir; + struct dirent *d; +} diff --git a/tryflock.c b/tryflock.c new file mode 100644 index 0000000..a82ffc2 --- /dev/null +++ b/tryflock.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include +#include +#include + +main() +{ + flock(0,LOCK_EX | LOCK_UN | LOCK_NB); +} diff --git a/trymkffo.c b/trymkffo.c new file mode 100644 index 0000000..9356342 --- /dev/null +++ b/trymkffo.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include + +void main() +{ + mkfifo("temp-trymkffo",0); +} diff --git a/trypoll.c b/trypoll.c new file mode 100644 index 0000000..6506617 --- /dev/null +++ b/trypoll.c @@ -0,0 +1,20 @@ +/* Public domain. */ + +#include +#include +#include + +int main() +{ + struct pollfd x; + + x.fd = open("trypoll.c",O_RDONLY); + if (x.fd == -1) _exit(111); + x.events = POLLIN; + if (poll(&x,1,10) == -1) _exit(1); + if (x.revents != POLLIN) _exit(1); + + /* XXX: try to detect and avoid poll() imitation libraries */ + + _exit(0); +} diff --git a/trysgact.c b/trysgact.c new file mode 100644 index 0000000..e264ef2 --- /dev/null +++ b/trysgact.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include + +main() +{ + struct sigaction sa; + sa.sa_handler = 0; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(0,&sa,(struct sigaction *) 0); +} diff --git a/trysgprm.c b/trysgprm.c new file mode 100644 index 0000000..a46c82c --- /dev/null +++ b/trysgprm.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include + +main() +{ + sigset_t ss; + + sigemptyset(&ss); + sigaddset(&ss,SIGCHLD); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +} diff --git a/tryshsgr.c b/tryshsgr.c new file mode 100644 index 0000000..c5ed6d6 --- /dev/null +++ b/tryshsgr.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +int main() +{ + short x[4]; + + x[0] = x[1] = 1; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 1) _exit(1); + x[1] = 2; + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 2) _exit(1); + _exit(0); +} diff --git a/trysysel.c b/trysysel.c new file mode 100644 index 0000000..5be862d --- /dev/null +++ b/trysysel.c @@ -0,0 +1,11 @@ +/* Public domain. */ + +#include +#include +#include +#include /* SVR4 silliness */ + +void foo() +{ + ; +} diff --git a/tryulong64.c b/tryulong64.c new file mode 100644 index 0000000..003548a --- /dev/null +++ b/tryulong64.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +int main() +{ + unsigned long u; + u = 1; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + if (!u) _exit(1); + _exit(0); +} diff --git a/trywaitp.c b/trywaitp.c new file mode 100644 index 0000000..319b81f --- /dev/null +++ b/trywaitp.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include +#include + +main() +{ + waitpid(0,0,0); +} diff --git a/uint64.h1 b/uint64.h1 new file mode 100644 index 0000000..486a380 --- /dev/null +++ b/uint64.h1 @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef UINT64_H +#define UINT64_H + +/* sysdep: -ulong64 */ + +typedef unsigned long long uint64; + +#endif diff --git a/uint64.h2 b/uint64.h2 new file mode 100644 index 0000000..8869e43 --- /dev/null +++ b/uint64.h2 @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef UINT64_H +#define UINT64_H + +/* sysdep: +ulong64 */ + +typedef unsigned long uint64; + +#endif diff --git a/wait.h b/wait.h new file mode 100644 index 0000000..d294e9d --- /dev/null +++ b/wait.h @@ -0,0 +1,16 @@ +/* Public domain. */ + +#ifndef WAIT_H +#define WAIT_H + +extern int wait_pid(); +extern int wait_nohang(); +extern int wait_stop(); +extern int wait_stopnohang(); + +#define wait_crashed(w) ((w) & 127) +#define wait_exitcode(w) ((w) >> 8) +#define wait_stopsig(w) ((w) >> 8) +#define wait_stopped(w) (((w) & 127) == 127) + +#endif diff --git a/wait_nohang.c b/wait_nohang.c new file mode 100644 index 0000000..5c9c53d --- /dev/null +++ b/wait_nohang.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include +#include +#include "haswaitp.h" + +int wait_nohang(wstat) int *wstat; +{ +#ifdef HASWAITPID + return waitpid(-1,wstat,WNOHANG); +#else + return wait3(wstat,WNOHANG,(struct rusage *) 0); +#endif +} diff --git a/wait_pid.c b/wait_pid.c new file mode 100644 index 0000000..c2869b8 --- /dev/null +++ b/wait_pid.c @@ -0,0 +1,41 @@ +/* Public domain. */ + +#include +#include +#include "error.h" +#include "haswaitp.h" + +#ifdef HASWAITPID + +int wait_pid(wstat,pid) int *wstat; int pid; +{ + int r; + + do + r = waitpid(pid,wstat,0); + while ((r == -1) && (errno == error_intr)); + return r; +} + +#else + +/* XXX untested */ +/* XXX breaks down with more than two children */ +static int oldpid = 0; +static int oldwstat; /* defined if(oldpid) */ + +int wait_pid(wstat,pid) int *wstat; int pid; +{ + int r; + + if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } + + do { + r = wait(wstat); + if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } + } + while ((r == -1) && (errno == error_intr)); + return r; +} + +#endif diff --git a/warn-auto.sh b/warn-auto.sh new file mode 100644 index 0000000..36d2313 --- /dev/null +++ b/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! diff --git a/warn-shsgr b/warn-shsgr new file mode 100644 index 0000000..37c351e --- /dev/null +++ b/warn-shsgr @@ -0,0 +1,3 @@ +Oops. Your getgroups() returned 0, and setgroups() failed; this means +that I can't reliably do my shsgr test. Please either ``make'' as root +or ``make'' while you're in one or more supplementary groups. diff --git a/x86cpuid.c b/x86cpuid.c new file mode 100644 index 0000000..f81c593 --- /dev/null +++ b/x86cpuid.c @@ -0,0 +1,40 @@ +/* Public domain. */ + +#include + +void nope() +{ + exit(1); +} + +int main() +{ + unsigned long x[4]; + unsigned long y[4]; + int i; + int j; + char c; + + signal(SIGILL,nope); + + x[0] = 0; + x[1] = 0; + x[2] = 0; + x[3] = 0; + + asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) ); + if (!x[0]) return 0; + asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) ); + + for (i = 1;i < 4;++i) + for (j = 0;j < 4;++j) { + c = x[i] >> (8 * j); + if (c < 32) c = 32; + if (c > 126) c = 126; + putchar(c); + } + + printf("-%08x-%08x\n",y[0],y[3]); + + return 0; +}