├── BLURB ├── CHANGES ├── FILES ├── INSTALL ├── Makefile ├── README ├── SYSDEPS ├── TODO ├── VERSION ├── alloc.c ├── alloc.h ├── alloc_re.c ├── background.1 ├── background.c ├── background.do ├── byte.h ├── byte_chr.c ├── byte_copy.c ├── byte_cr.c ├── byte_diff.c ├── byte_rchr.c ├── byte_zero.c ├── conf-cc.sh ├── conf-group.h ├── conf-home.h ├── conf-secure.h ├── default.0.do ├── default.a.do ├── default.do ├── default.o.do ├── env.c ├── env.h ├── envread.c ├── error.c ├── error.h ├── error_str.c ├── error_temp.c ├── excloff.1 ├── excloff.c ├── excloff.do ├── exclon.1 ├── exclon.c ├── exclon.do ├── exit.h ├── fdcopy.c ├── fdcopy.h ├── find-systype.sh ├── fmt.h ├── fmt_str.c ├── fmt_strn.c ├── fmt_uint.c ├── fmt_uint0.c ├── fmt_ulong.c ├── fmt_ushort.c ├── fork.h.do ├── fork.h1 ├── fork.h2 ├── gen_alloc.h ├── gen_allocdefs.h ├── getopt.3 ├── getopt.c ├── getopt.h ├── hasptc.h.do ├── hasptmx.h.do ├── hassgact.h.do ├── hassgprm.h.do ├── haswaitp.h.do ├── home.c ├── it.do ├── liballoc.use ├── libenv.use ├── liberror.use ├── libfs.use ├── libgetopt.use ├── libopen.use ├── libsig.use ├── libstr.use ├── libstralloc.use ├── libstrerr.use ├── libsubstdio.use ├── libwait.use ├── make-cmds.sh ├── nobuf.1 ├── nobuf.do ├── nobuf.sh ├── open.h ├── open_append.c ├── open_excl.c ├── open_read.c ├── open_trunc.c ├── open_write.c ├── printgids.c ├── ptybandage.1 ├── ptybandage.do ├── ptybandage.sh ├── ptyget-setup.c ├── ptyget.8 ├── ptyget.c ├── ptyget.do ├── ptyio.8 ├── ptyio.c ├── ptyio.do ├── ptyrun.1 ├── ptyrun.do ├── ptyrun.sh ├── ptyspawn.8 ├── ptyspawn.c ├── ptyspawn.do ├── readwrite.h ├── select.h.do ├── select.h1 ├── select.h2 ├── setup.do ├── sgetopt.3 ├── sgetopt.c ├── sgetopt.h ├── sig.h ├── sig_block.c ├── sig_catch.c ├── sig_cont.c ├── sig_dfl.c ├── sig_pipe.c ├── str.h ├── str_chr.c ├── str_cpy.c ├── str_diff.c ├── str_diffn.c ├── str_len.c ├── str_rchr.c ├── stralloc.h ├── stralloc_cat.c ├── stralloc_catb.c ├── stralloc_cats.c ├── stralloc_copy.c ├── stralloc_eady.c ├── stralloc_opyb.c ├── stralloc_opys.c ├── stralloc_pend.c ├── strerr.c ├── strerr.h ├── strerr_die.c ├── strerr_sys.c ├── subfd.h ├── subfderr.c ├── subfdin.c ├── subfdout.c ├── subgetopt.3 ├── subgetopt.c ├── subgetopt.h ├── substdi.c ├── substdio.c ├── substdio.h ├── substdio_copy.c ├── substdo.c ├── trycpp.c ├── tryptc.c ├── tryptmx.c ├── trysgact.c ├── trysgprm.c ├── trysysel.c ├── tryvfork.c ├── trywaitp.c ├── ttyctrl.c ├── ttyctrl.h ├── ttydetach.1 ├── ttydetach.c ├── ttydetach.do ├── ttymodes.c ├── ttymodes.h ├── wait.h ├── wait_nohang.c ├── wait_pid.c ├── wait_snh.c ├── wait_stop.c └── warn-auto.sh /BLURB: -------------------------------------------------------------------------------- 1 | ptyget is a universal pseudo-terminal interface. It is designed to be 2 | used by any program that needs a pty. 3 | 4 | ptyget can also serve as a wrapper to improve the behavior of existing 5 | programs. For example, ``ptybandage telnet'' is like ``telnet'' but can 6 | be put into a pipeline. ``nobuf grep'' is like ``grep'' but won't 7 | block-buffer if it's redirected. 8 | 9 | Previous pty-allocating programs---rlogind, telnetd, sshd, xterm, 10 | screen, emacs, expect, etc.---have caused dozens of security problems. 11 | There are two fundamental reasons for this. First, these programs are 12 | installed setuid root so that they can allocate ptys; this turns every 13 | little bug in hundreds of thousands of lines of code into a potential 14 | security hole. Second, these programs are not careful enough to protect 15 | the pty from access by other users. 16 | 17 | ptyget solves both of these problems. All the privileged code is in one 18 | tiny program. This program guarantees that one user can't touch another 19 | user's pty. 20 | 21 | ptyget is a complete rewrite of pty 4.0, my previous pty-allocating 22 | package. pty 4.0's session management features have been split off into 23 | a separate package, sess. 24 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 19960910 ptyget 0.50, alpha. 2 | -------------------------------------------------------------------------------- /FILES: -------------------------------------------------------------------------------- 1 | BLURB 2 | README 3 | INSTALL 4 | TODO 5 | CHANGES 6 | FILES 7 | SYSDEPS 8 | VERSION 9 | Makefile 10 | ptyrun.1 11 | ptyrun.do 12 | ptyrun.sh 13 | ptybandage.1 14 | ptybandage.do 15 | ptybandage.sh 16 | nobuf.1 17 | nobuf.do 18 | nobuf.sh 19 | ptyget.8 20 | ptyget.do 21 | ptyget.c 22 | hasptmx.h.do 23 | tryptmx.c 24 | hasptc.h.do 25 | tryptc.c 26 | ptyspawn.8 27 | ptyspawn.do 28 | ptyspawn.c 29 | ptyio.8 30 | ptyio.do 31 | ptyio.c 32 | ttydetach.1 33 | ttydetach.do 34 | ttydetach.c 35 | background.1 36 | background.do 37 | background.c 38 | exclon.1 39 | exclon.do 40 | exclon.c 41 | excloff.1 42 | excloff.do 43 | excloff.c 44 | ttymodes.h 45 | ttymodes.c 46 | ttyctrl.h 47 | ttyctrl.c 48 | home.c 49 | printgids.c 50 | ptyget-setup.c 51 | it.do 52 | setup.do 53 | default.do 54 | default.a.do 55 | default.o.do 56 | default.0.do 57 | conf-home.h 58 | conf-secure.h 59 | conf-group.h 60 | conf-cc.sh 61 | find-systype.sh 62 | make-cmds.sh 63 | trycpp.c 64 | warn-auto.sh 65 | liberror.use 66 | error.h 67 | error.c 68 | error_str.c 69 | error_temp.c 70 | libgetopt.use 71 | getopt.3 72 | getopt.h 73 | getopt.c 74 | sgetopt.3 75 | sgetopt.h 76 | sgetopt.c 77 | subgetopt.3 78 | subgetopt.h 79 | subgetopt.c 80 | libsubstdio.use 81 | substdio.h 82 | substdio.c 83 | substdi.c 84 | substdo.c 85 | substdio_copy.c 86 | subfd.h 87 | subfderr.c 88 | subfdout.c 89 | subfdin.c 90 | readwrite.h 91 | exit.h 92 | fork.h.do 93 | fork.h1 94 | fork.h2 95 | tryvfork.c 96 | libstr.use 97 | byte.h 98 | byte_chr.c 99 | byte_copy.c 100 | byte_cr.c 101 | byte_diff.c 102 | byte_rchr.c 103 | byte_zero.c 104 | str.h 105 | str_chr.c 106 | str_cpy.c 107 | str_diff.c 108 | str_diffn.c 109 | str_len.c 110 | str_rchr.c 111 | libsig.use 112 | sig.h 113 | sig_block.c 114 | sig_catch.c 115 | sig_cont.c 116 | sig_dfl.c 117 | sig_pipe.c 118 | hassgact.h.do 119 | hassgprm.h.do 120 | trysgact.c 121 | trysgprm.c 122 | libenv.use 123 | env.h 124 | env.c 125 | envread.c 126 | libwait.use 127 | wait.h 128 | wait_pid.c 129 | wait_nohang.c 130 | wait_stop.c 131 | wait_snh.c 132 | trywaitp.c 133 | haswaitp.h.do 134 | liballoc.use 135 | alloc.h 136 | alloc.c 137 | alloc_re.c 138 | fdcopy.h 139 | fdcopy.c 140 | select.h.do 141 | select.h1 142 | select.h2 143 | trysysel.c 144 | libstrerr.use 145 | strerr.h 146 | strerr.c 147 | strerr_sys.c 148 | strerr_die.c 149 | libfs.use 150 | fmt.h 151 | fmt_str.c 152 | fmt_strn.c 153 | fmt_uint.c 154 | fmt_uint0.c 155 | fmt_ulong.c 156 | fmt_ushort.c 157 | libstralloc.use 158 | gen_alloc.h 159 | gen_allocdefs.h 160 | stralloc.h 161 | stralloc_eady.c 162 | stralloc_pend.c 163 | stralloc_copy.c 164 | stralloc_opyb.c 165 | stralloc_opys.c 166 | stralloc_cat.c 167 | stralloc_catb.c 168 | stralloc_cats.c 169 | libopen.use 170 | open.h 171 | open_append.c 172 | open_excl.c 173 | open_read.c 174 | open_trunc.c 175 | open_write.c 176 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Things you have to decide before starting: 2 | 3 | * The ptyget home directory, normally /usr/local. Binaries will be 4 | stored in /usr/local/bin; man pages will be installed in /usr/local/man. 5 | (To change this directory, edit conf-home.h now.) 6 | 7 | * Whether you want secure pty allocation. The default is yes; the ptyget 8 | program will be setuid root and will guarantee that one user can't touch 9 | another user's ptys. There are three situations where you will have to 10 | change the default: 11 | 12 | (1) You do not have privileges on this machine, so you cannot install 13 | ptyget setuid root. 14 | 15 | (2) You are using an operating system where ptyget cannot guarantee 16 | security. ptyget.c will refuse to compile in this case. 17 | 18 | (3) You have other, non-setuid programs that need to allocate ptys. 19 | (In this case, your security is already toast.) If ptyget is 20 | installed setuid root, it will interfere with these programs, 21 | since it never changes slaves to mode 666. 22 | 23 | (If you are in one of these situations, edit conf-secure.h now.) 24 | 25 | 26 | How to install: 27 | 28 | 1. Create the ptyget home directory, if it doesn't already exist: 29 | # mkdir /usr/local; chmod 755 /usr/local 30 | 2. Compile the programs and format the man pages: 31 | # make 32 | 3. Install the programs and man pages: 33 | # make setup 34 | 35 | How to test: 36 | 37 | 4. XXX 38 | 39 | 40 | That's it! To report success: 41 | % cat `cat SYSDEPS` | mail djb-qst@koobera.math.uic.edu 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: it 2 | 3 | alloc.o: \ 4 | compile alloc.c alloc.h alloc.c error.h alloc.c 5 | ./compile alloc.c 6 | 7 | alloc_re.o: \ 8 | compile alloc_re.c alloc.h alloc_re.c byte.h alloc_re.c 9 | ./compile alloc_re.c 10 | 11 | auto-gids.h: \ 12 | printgids 13 | ./printgids > temp-gids.h 14 | mv temp-gids.h auto-gids.h 15 | 16 | background: \ 17 | load background.o libstrerr.a libsubstdio.a liballoc.a liberror.a \ 18 | libstr.a 19 | ./load background libstrerr.a libsubstdio.a liballoc.a \ 20 | liberror.a libstr.a 21 | 22 | background.0: \ 23 | background.1 24 | nroff -man background.1 > background.0 25 | 26 | background.o: \ 27 | compile background.c strerr.h background.c error.h background.c 28 | ./compile background.c 29 | 30 | byte_chr.o: \ 31 | compile byte_chr.c byte.h byte_chr.c 32 | ./compile byte_chr.c 33 | 34 | byte_copy.o: \ 35 | compile byte_copy.c byte.h byte_copy.c 36 | ./compile byte_copy.c 37 | 38 | byte_cr.o: \ 39 | compile byte_cr.c byte.h byte_cr.c 40 | ./compile byte_cr.c 41 | 42 | byte_diff.o: \ 43 | compile byte_diff.c byte.h byte_diff.c 44 | ./compile byte_diff.c 45 | 46 | byte_rchr.o: \ 47 | compile byte_rchr.c byte.h byte_rchr.c 48 | ./compile byte_rchr.c 49 | 50 | byte_zero.o: \ 51 | compile byte_zero.c byte.h byte_zero.c 52 | ./compile byte_zero.c 53 | 54 | compile: \ 55 | make-commands systype 56 | ./make-commands "`cat ./systype`" compile > compile 57 | chmod 755 compile 58 | 59 | env.o: \ 60 | compile env.c str.h env.c alloc.h env.c env.h env.c 61 | ./compile env.c 62 | 63 | envread.o: \ 64 | compile envread.c env.h envread.c str.h envread.c 65 | ./compile envread.c 66 | 67 | error.o: \ 68 | compile error.c error.c error.h error.c 69 | ./compile error.c 70 | 71 | error_str.o: \ 72 | compile error_str.c error_str.c error.h error_str.c 73 | ./compile error_str.c 74 | 75 | error_temp.o: \ 76 | compile error_temp.c error_temp.c error.h error_temp.c 77 | ./compile error_temp.c 78 | 79 | excloff: \ 80 | load excloff.o 81 | ./load excloff 82 | 83 | excloff.0: \ 84 | excloff.1 85 | nroff -man excloff.1 > excloff.0 86 | 87 | excloff.o: \ 88 | compile excloff.c excloff.c excloff.c 89 | ./compile excloff.c 90 | 91 | exclon: \ 92 | load exclon.o 93 | ./load exclon 94 | 95 | exclon.0: \ 96 | exclon.1 97 | nroff -man exclon.1 > exclon.0 98 | 99 | exclon.o: \ 100 | compile exclon.c exclon.c exclon.c 101 | ./compile exclon.c 102 | 103 | fdcopy.o: \ 104 | compile fdcopy.c fdcopy.c fdcopy.h fdcopy.c 105 | ./compile fdcopy.c 106 | 107 | find-systype: \ 108 | find-systype.sh conf-cc.sh warn-auto.sh 109 | cat warn-auto.sh conf-cc.sh find-systype.sh > find-systype 110 | chmod 755 find-systype 111 | 112 | fmt_str.o: \ 113 | compile fmt_str.c fmt.h fmt_str.c 114 | ./compile fmt_str.c 115 | 116 | fmt_strn.o: \ 117 | compile fmt_strn.c fmt.h fmt_strn.c 118 | ./compile fmt_strn.c 119 | 120 | fmt_uint.o: \ 121 | compile fmt_uint.c fmt.h fmt_uint.c 122 | ./compile fmt_uint.c 123 | 124 | fmt_uint0.o: \ 125 | compile fmt_uint0.c fmt.h fmt_uint0.c 126 | ./compile fmt_uint0.c 127 | 128 | fmt_ulong.o: \ 129 | compile fmt_ulong.c fmt.h fmt_ulong.c 130 | ./compile fmt_ulong.c 131 | 132 | fmt_ushort.o: \ 133 | compile fmt_ushort.c fmt.h fmt_ushort.c 134 | ./compile fmt_ushort.c 135 | 136 | fork.h: \ 137 | compile load tryvfork.c fork.h1 fork.h2 138 | ( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null \ 139 | 2>&1 \ 140 | && cat fork.h2 || cat fork.h1 ) > fork.h 141 | rm -f tryvfork.o tryvfork 142 | 143 | getopt.o: \ 144 | compile getopt.c getopt.c getopt.h getopt.h subgetopt.h getopt.h \ 145 | getopt.c subgetopt.h subgetopt.h getopt.c 146 | ./compile getopt.c 147 | 148 | hasptc.h: \ 149 | tryptc.c compile load 150 | ( ( ./compile tryptc.c && ./load tryptc && ./tryptc ) \ 151 | >/dev/null 2>&1 \ 152 | && echo \#define HASPTC 1 || exit 0 ) > hasptc.h 153 | rm -f tryptc.o tryptc 154 | 155 | hasptmx.h: \ 156 | tryptmx.c compile load 157 | ( ( ./compile tryptmx.c && ./load tryptmx && ./tryptmx ) \ 158 | >/dev/null 2>&1 \ 159 | && echo \#define HASPTMX 1 || exit 0 ) > hasptmx.h 160 | rm -f tryptmx.o tryptmx 161 | 162 | hassgact.h: \ 163 | trysgact.c compile load 164 | ( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \ 165 | 2>&1 \ 166 | && echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h 167 | rm -f trysgact.o trysgact 168 | 169 | hassgprm.h: \ 170 | trysgprm.c compile load 171 | ( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \ 172 | 2>&1 \ 173 | && echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h 174 | rm -f trysgprm.o trysgprm 175 | 176 | haswaitp.h: \ 177 | trywaitp.c compile load 178 | ( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \ 179 | 2>&1 \ 180 | && echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h 181 | rm -f trywaitp.o trywaitp 182 | 183 | home: \ 184 | load home.o libsubstdio.a liberror.a libstr.a 185 | ./load home libsubstdio.a liberror.a libstr.a 186 | 187 | home.o: \ 188 | compile home.c substdio.h home.c readwrite.h home.c exit.h home.c \ 189 | conf-home.h home.c 190 | ./compile home.c 191 | 192 | it: \ 193 | ptyrun ptyrun.0 ptybandage ptybandage.0 nobuf nobuf.0 ptyget ptyget.0 \ 194 | ptyspawn ptyspawn.0 ptyio ptyio.0 ttydetach ttydetach.0 background \ 195 | background.0 exclon exclon.0 excloff excloff.0 196 | 197 | liballoc.a: \ 198 | makelib alloc.o alloc_re.o 199 | ./makelib liballoc.a alloc.o alloc_re.o 200 | 201 | libenv.a: \ 202 | makelib env.o envread.o 203 | ./makelib libenv.a env.o envread.o 204 | 205 | liberror.a: \ 206 | makelib error.o error_str.o error_temp.o 207 | ./makelib liberror.a error.o error_str.o error_temp.o 208 | 209 | libfs.a: \ 210 | makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \ 211 | fmt_ushort.o 212 | ./makelib libfs.a fmt_str.o fmt_strn.o fmt_uint.o \ 213 | fmt_uint0.o fmt_ulong.o fmt_ushort.o 214 | 215 | libgetopt.a: \ 216 | makelib subgetopt.o sgetopt.o getopt.o 217 | ./makelib libgetopt.a subgetopt.o sgetopt.o getopt.o 218 | 219 | libopen.a: \ 220 | makelib open_append.o open_excl.o open_read.o open_trunc.o \ 221 | open_write.o 222 | ./makelib libopen.a open_append.o open_excl.o open_read.o \ 223 | open_trunc.o open_write.o 224 | 225 | libsig.a: \ 226 | makelib sig_block.o sig_catch.o sig_dfl.o sig_pipe.o sig_cont.o 227 | ./makelib libsig.a sig_block.o sig_catch.o sig_dfl.o \ 228 | sig_pipe.o sig_cont.o 229 | 230 | libstr.a: \ 231 | makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \ 232 | str_rchr.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o byte_cr.o \ 233 | byte_zero.o 234 | ./makelib libstr.a str_len.o str_diff.o str_diffn.o \ 235 | str_cpy.o str_chr.o str_rchr.o byte_chr.o byte_rchr.o \ 236 | byte_diff.o byte_copy.o byte_cr.o byte_zero.o 237 | 238 | libstralloc.a: \ 239 | makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \ 240 | stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \ 241 | stralloc_catb.o 242 | ./makelib libstralloc.a stralloc_eady.o stralloc_pend.o \ 243 | stralloc_copy.o stralloc_opys.o stralloc_opyb.o \ 244 | stralloc_cat.o stralloc_cats.o stralloc_catb.o 245 | 246 | libstrerr.a: \ 247 | makelib strerr.o strerr_sys.o strerr_die.o 248 | ./makelib libstrerr.a strerr.o strerr_sys.o strerr_die.o 249 | 250 | libsubstdio.a: \ 251 | makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \ 252 | subfdin.o substdio_copy.o 253 | ./makelib libsubstdio.a substdio.o substdi.o substdo.o \ 254 | subfderr.o subfdout.o subfdin.o substdio_copy.o 255 | 256 | libwait.a: \ 257 | makelib wait_pid.o wait_nohang.o wait_stop.o wait_snh.o 258 | ./makelib libwait.a wait_pid.o wait_nohang.o wait_stop.o \ 259 | wait_snh.o 260 | 261 | load: \ 262 | make-commands systype 263 | ./make-commands "`cat ./systype`" load > load 264 | chmod 755 load 265 | 266 | make-commands: \ 267 | make-cmds.sh conf-cc.sh warn-auto.sh 268 | cat warn-auto.sh conf-cc.sh make-cmds.sh > make-commands 269 | chmod 755 make-commands 270 | 271 | makelib: \ 272 | make-commands systype 273 | ./make-commands "`cat ./systype`" makelib > makelib 274 | chmod 755 makelib 275 | 276 | nobuf: \ 277 | warn-auto.sh nobuf.sh home 278 | cat warn-auto.sh nobuf.sh | sed s}HOME}`./home`}g > nobuf 279 | chmod 755 nobuf 280 | 281 | nobuf.0: \ 282 | nobuf.1 283 | nroff -man nobuf.1 > nobuf.0 284 | 285 | open_append.o: \ 286 | compile open_append.c open_append.c open_append.c open.h \ 287 | open_append.c 288 | ./compile open_append.c 289 | 290 | open_excl.o: \ 291 | compile open_excl.c open_excl.c open_excl.c open.h open_excl.c 292 | ./compile open_excl.c 293 | 294 | open_read.o: \ 295 | compile open_read.c open_read.c open_read.c open.h open_read.c 296 | ./compile open_read.c 297 | 298 | open_trunc.o: \ 299 | compile open_trunc.c open_trunc.c open_trunc.c open.h open_trunc.c 300 | ./compile open_trunc.c 301 | 302 | open_write.o: \ 303 | compile open_write.c open_write.c open_write.c open.h open_write.c 304 | ./compile open_write.c 305 | 306 | printgids: \ 307 | load printgids.o libsubstdio.a liberror.a libstr.a libfs.a 308 | ./load printgids libsubstdio.a liberror.a libstr.a libfs.a 309 | 310 | printgids.o: \ 311 | compile printgids.c printgids.c printgids.c subfd.h printgids.c \ 312 | substdio.h printgids.c fmt.h printgids.c exit.h printgids.c \ 313 | conf-group.h printgids.c 314 | ./compile printgids.c 315 | 316 | ptybandage: \ 317 | warn-auto.sh ptybandage.sh home 318 | cat warn-auto.sh ptybandage.sh | sed s}HOME}`./home`}g > \ 319 | ptybandage 320 | chmod 755 ptybandage 321 | 322 | ptybandage.0: \ 323 | ptybandage.1 324 | nroff -man ptybandage.1 > ptybandage.0 325 | 326 | ptyget: \ 327 | load ptyget.o fdcopy.o libenv.a liballoc.a libstrerr.a libsubstdio.a \ 328 | liberror.a libfs.a libstr.a 329 | ./load ptyget fdcopy.o libenv.a liballoc.a libstrerr.a \ 330 | libsubstdio.a liberror.a libfs.a libstr.a 331 | 332 | ptyget-setup: \ 333 | load ptyget-setup.o libopen.a libstralloc.a liballoc.a libsubstdio.a \ 334 | liberror.a libstr.a 335 | ./load ptyget-setup libopen.a libstralloc.a liballoc.a \ 336 | libsubstdio.a liberror.a libstr.a 337 | 338 | ptyget-setup.o: \ 339 | compile ptyget-setup.c ptyget-setup.c subfd.h ptyget-setup.c \ 340 | readwrite.h ptyget-setup.c substdio.h ptyget-setup.c stralloc.h \ 341 | gen_alloc.h stralloc.h ptyget-setup.c open.h ptyget-setup.c exit.h \ 342 | ptyget-setup.c error.h ptyget-setup.c conf-home.h ptyget-setup.c \ 343 | conf-secure.h ptyget-setup.c auto-gids.h ptyget-setup.c 344 | ./compile ptyget-setup.c 345 | 346 | ptyget.0: \ 347 | ptyget.8 348 | nroff -man ptyget.8 > ptyget.0 349 | 350 | ptyget.o: \ 351 | compile ptyget.c ptyget.c ptyget.c ptyget.c ptyget.c ptyget.c env.h \ 352 | ptyget.c fmt.h ptyget.c str.h ptyget.c strerr.h ptyget.c ptyget.c \ 353 | hasptmx.h ptyget.c hasptc.h ptyget.c conf-secure.h ptyget.c ptyget.c \ 354 | ptyget.c 355 | ./compile ptyget.c 356 | 357 | ptyio: \ 358 | load ptyio.o ttyctrl.o ttymodes.o fdcopy.o libwait.a libsig.a \ 359 | libenv.a libgetopt.a libsubstdio.a liberror.a libstr.a 360 | ./load ptyio ttyctrl.o ttymodes.o fdcopy.o libwait.a \ 361 | libsig.a libenv.a libgetopt.a libsubstdio.a liberror.a \ 362 | libstr.a 363 | 364 | ptyio.0: \ 365 | ptyio.8 366 | nroff -man ptyio.8 > ptyio.0 367 | 368 | ptyio.o: \ 369 | compile ptyio.c wait.h ptyio.c fork.h ptyio.c select.h select.h \ 370 | select.h select.h ptyio.c sig.h ptyio.c ptyio.c error.h ptyio.c \ 371 | readwrite.h ptyio.c exit.h ptyio.c ttyctrl.h ptyio.c ttymodes.h \ 372 | ttymodes.h ttymodes.h ptyio.c sgetopt.h subgetopt.h sgetopt.h ptyio.c \ 373 | substdio.h ptyio.c subfd.h ptyio.c 374 | ./compile ptyio.c 375 | 376 | ptyrun: \ 377 | warn-auto.sh ptyrun.sh home 378 | cat warn-auto.sh ptyrun.sh | sed s}HOME}`./home`}g > ptyrun 379 | chmod 755 ptyrun 380 | 381 | ptyrun.0: \ 382 | ptyrun.1 383 | nroff -man ptyrun.1 > ptyrun.0 384 | 385 | ptyspawn: \ 386 | load ptyspawn.o libwait.a libsig.a libenv.a libstrerr.a libgetopt.a \ 387 | libsubstdio.a liberror.a libstr.a 388 | ./load ptyspawn libwait.a libsig.a libenv.a libstrerr.a \ 389 | libgetopt.a libsubstdio.a liberror.a libstr.a 390 | 391 | ptyspawn.0: \ 392 | ptyspawn.8 393 | nroff -man ptyspawn.8 > ptyspawn.0 394 | 395 | ptyspawn.o: \ 396 | compile ptyspawn.c ptyspawn.c ptyspawn.c ptyspawn.c ptyspawn.c \ 397 | fdcopy.h ptyspawn.c sgetopt.h subgetopt.h sgetopt.h ptyspawn.c exit.h \ 398 | ptyspawn.c fork.h ptyspawn.c wait.h ptyspawn.c env.h ptyspawn.c \ 399 | error.h ptyspawn.c readwrite.h ptyspawn.c strerr.h ptyspawn.c sig.h \ 400 | ptyspawn.c ptyspawn.c ptyspawn.c 401 | ./compile ptyspawn.c 402 | 403 | select.h: \ 404 | compile trysysel.c select.h1 select.h2 405 | ( ./compile trysysel.c >/dev/null 2>&1 \ 406 | && cat select.h2 || cat select.h1 ) > select.h 407 | rm -f trysysel.o trysysel 408 | 409 | setup: \ 410 | it home ptyget-setup 411 | ./ptyget-setup 412 | 413 | sgetopt.o: \ 414 | compile sgetopt.c substdio.h sgetopt.c subfd.h sgetopt.c sgetopt.h \ 415 | sgetopt.h subgetopt.h sgetopt.h sgetopt.c subgetopt.h subgetopt.h \ 416 | sgetopt.c 417 | ./compile sgetopt.c 418 | 419 | shar: \ 420 | FILES BLURB README INSTALL TODO CHANGES FILES SYSDEPS VERSION \ 421 | Makefile ptyrun.1 ptyrun.sh ptybandage.1 ptybandage.sh nobuf.1 \ 422 | nobuf.sh ptyget.8 ptyget.c tryptmx.c tryptc.c ptyspawn.8 ptyspawn.c \ 423 | ptyio.8 ptyio.c ttydetach.1 ttydetach.c background.1 background.c \ 424 | exclon.1 exclon.c excloff.1 excloff.c ttymodes.h ttymodes.c ttyctrl.h \ 425 | ttyctrl.c home.c printgids.c ptyget-setup.c conf-home.h conf-secure.h \ 426 | conf-group.h conf-cc.sh find-systype.sh make-cmds.sh trycpp.c \ 427 | warn-auto.sh error.h error.c error_str.c error_temp.c getopt.3 \ 428 | getopt.h getopt.c sgetopt.3 sgetopt.h sgetopt.c subgetopt.3 \ 429 | subgetopt.h subgetopt.c substdio.h substdio.c substdi.c substdo.c \ 430 | substdio_copy.c subfd.h subfderr.c subfdout.c subfdin.c readwrite.h \ 431 | exit.h fork.h1 fork.h2 tryvfork.c byte.h byte_chr.c byte_copy.c \ 432 | byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h str_chr.c \ 433 | str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c sig.h \ 434 | sig_block.c sig_catch.c sig_cont.c sig_dfl.c sig_pipe.c trysgact.c \ 435 | trysgprm.c env.h env.c envread.c wait.h wait_pid.c wait_nohang.c \ 436 | wait_stop.c wait_snh.c trywaitp.c alloc.h alloc.c alloc_re.c fdcopy.h \ 437 | fdcopy.c select.h1 select.h2 trysysel.c strerr.h strerr.c \ 438 | strerr_sys.c strerr_die.c fmt.h fmt_str.c fmt_strn.c fmt_uint.c \ 439 | fmt_uint0.c fmt_ulong.c fmt_ushort.c gen_alloc.h gen_allocdefs.h \ 440 | stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c \ 441 | stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c \ 442 | stralloc_cats.c open.h open_append.c open_excl.c open_read.c \ 443 | open_trunc.c open_write.c 444 | shar -m `cat FILES` > shar 445 | chmod 400 shar 446 | 447 | sig_block.o: \ 448 | compile sig_block.c sig_block.c sig.h sig_block.c hassgprm.h \ 449 | sig_block.c 450 | ./compile sig_block.c 451 | 452 | sig_catch.o: \ 453 | compile sig_catch.c sig_catch.c sig.h sig_catch.c hassgact.h \ 454 | sig_catch.c 455 | ./compile sig_catch.c 456 | 457 | sig_cont.o: \ 458 | compile sig_cont.c sig_cont.c sig.h sig_cont.c 459 | ./compile sig_cont.c 460 | 461 | sig_dfl.o: \ 462 | compile sig_dfl.c sig_dfl.c sig.h sig_dfl.c hassgact.h sig_dfl.c \ 463 | hassgprm.h sig_dfl.c 464 | ./compile sig_dfl.c 465 | 466 | sig_pipe.o: \ 467 | compile sig_pipe.c sig_pipe.c sig.h sig_pipe.c 468 | ./compile sig_pipe.c 469 | 470 | str_chr.o: \ 471 | compile str_chr.c str.h str_chr.c 472 | ./compile str_chr.c 473 | 474 | str_cpy.o: \ 475 | compile str_cpy.c str.h str_cpy.c 476 | ./compile str_cpy.c 477 | 478 | str_diff.o: \ 479 | compile str_diff.c str.h str_diff.c 480 | ./compile str_diff.c 481 | 482 | str_diffn.o: \ 483 | compile str_diffn.c str.h str_diffn.c 484 | ./compile str_diffn.c 485 | 486 | str_len.o: \ 487 | compile str_len.c str.h str_len.c 488 | ./compile str_len.c 489 | 490 | str_rchr.o: \ 491 | compile str_rchr.c str.h str_rchr.c 492 | ./compile str_rchr.c 493 | 494 | stralloc_cat.o: \ 495 | compile stralloc_cat.c byte.h stralloc_cat.c stralloc.h gen_alloc.h \ 496 | stralloc.h stralloc_cat.c 497 | ./compile stralloc_cat.c 498 | 499 | stralloc_catb.o: \ 500 | compile stralloc_catb.c stralloc.h gen_alloc.h stralloc.h \ 501 | stralloc_catb.c byte.h stralloc_catb.c 502 | ./compile stralloc_catb.c 503 | 504 | stralloc_cats.o: \ 505 | compile stralloc_cats.c byte.h stralloc_cats.c str.h stralloc_cats.c \ 506 | stralloc.h gen_alloc.h stralloc.h stralloc_cats.c 507 | ./compile stralloc_cats.c 508 | 509 | stralloc_copy.o: \ 510 | compile stralloc_copy.c byte.h stralloc_copy.c stralloc.h gen_alloc.h \ 511 | stralloc.h stralloc_copy.c 512 | ./compile stralloc_copy.c 513 | 514 | stralloc_eady.o: \ 515 | compile stralloc_eady.c alloc.h stralloc_eady.c stralloc.h \ 516 | gen_alloc.h stralloc.h stralloc_eady.c gen_allocdefs.h \ 517 | stralloc_eady.c 518 | ./compile stralloc_eady.c 519 | 520 | stralloc_opyb.o: \ 521 | compile stralloc_opyb.c stralloc.h gen_alloc.h stralloc.h \ 522 | stralloc_opyb.c byte.h stralloc_opyb.c 523 | ./compile stralloc_opyb.c 524 | 525 | stralloc_opys.o: \ 526 | compile stralloc_opys.c byte.h stralloc_opys.c str.h stralloc_opys.c \ 527 | stralloc.h gen_alloc.h stralloc.h stralloc_opys.c 528 | ./compile stralloc_opys.c 529 | 530 | stralloc_pend.o: \ 531 | compile stralloc_pend.c alloc.h stralloc_pend.c stralloc.h \ 532 | gen_alloc.h stralloc.h stralloc_pend.c gen_allocdefs.h \ 533 | stralloc_pend.c 534 | ./compile stralloc_pend.c 535 | 536 | strerr.o: \ 537 | compile strerr.c stralloc.h gen_alloc.h stralloc.h strerr.c strerr.h \ 538 | strerr.c 539 | ./compile strerr.c 540 | 541 | strerr_die.o: \ 542 | compile strerr_die.c substdio.h strerr_die.c subfd.h strerr_die.c \ 543 | exit.h strerr_die.c strerr.h strerr_die.c 544 | ./compile strerr_die.c 545 | 546 | strerr_sys.o: \ 547 | compile strerr_sys.c error.h strerr_sys.c strerr.h strerr_sys.c 548 | ./compile strerr_sys.c 549 | 550 | subfderr.o: \ 551 | compile subfderr.c readwrite.h subfderr.c substdio.h subfderr.c \ 552 | subfd.h subfderr.c 553 | ./compile subfderr.c 554 | 555 | subfdin.o: \ 556 | compile subfdin.c readwrite.h subfdin.c substdio.h subfdin.c subfd.h \ 557 | subfdin.c 558 | ./compile subfdin.c 559 | 560 | subfdout.o: \ 561 | compile subfdout.c readwrite.h subfdout.c substdio.h subfdout.c \ 562 | subfd.h subfdout.c 563 | ./compile subfdout.c 564 | 565 | subgetopt.o: \ 566 | compile subgetopt.c subgetopt.h subgetopt.h subgetopt.c 567 | ./compile subgetopt.c 568 | 569 | substdi.o: \ 570 | compile substdi.c substdio.h substdi.c byte.h substdi.c error.h \ 571 | substdi.c 572 | ./compile substdi.c 573 | 574 | substdio.o: \ 575 | compile substdio.c substdio.h substdio.c 576 | ./compile substdio.c 577 | 578 | substdio_copy.o: \ 579 | compile substdio_copy.c substdio.h substdio_copy.c 580 | ./compile substdio_copy.c 581 | 582 | substdo.o: \ 583 | compile substdo.c substdio.h substdo.c str.h substdo.c byte.h \ 584 | substdo.c error.h substdo.c 585 | ./compile substdo.c 586 | 587 | systype: \ 588 | find-systype trycpp.c 589 | ./find-systype > systype 590 | 591 | ttyctrl.o: \ 592 | compile ttyctrl.c ttyctrl.c ttyctrl.c ttyctrl.c ttyctrl.h ttyctrl.c 593 | ./compile ttyctrl.c 594 | 595 | ttydetach: \ 596 | load ttydetach.o ttyctrl.o libstrerr.a libsubstdio.a libenv.a \ 597 | liballoc.a liberror.a libstr.a 598 | ./load ttydetach ttyctrl.o libstrerr.a libsubstdio.a \ 599 | libenv.a liballoc.a liberror.a libstr.a 600 | 601 | ttydetach.0: \ 602 | ttydetach.1 603 | nroff -man ttydetach.1 > ttydetach.0 604 | 605 | ttydetach.o: \ 606 | compile ttydetach.c env.h ttydetach.c strerr.h ttydetach.c 607 | ./compile ttydetach.c 608 | 609 | ttymodes.o: \ 610 | compile ttymodes.c ttymodes.c ttymodes.c error.h ttymodes.c \ 611 | ttymodes.c ttymodes.h ttymodes.h ttymodes.h ttymodes.c 612 | ./compile ttymodes.c 613 | 614 | wait_nohang.o: \ 615 | compile wait_nohang.c wait_nohang.c wait_nohang.c haswaitp.h \ 616 | wait_nohang.c 617 | ./compile wait_nohang.c 618 | 619 | wait_pid.o: \ 620 | compile wait_pid.c wait_pid.c wait_pid.c error.h wait_pid.c 621 | ./compile wait_pid.c 622 | 623 | wait_snh.o: \ 624 | compile wait_snh.c wait_snh.c wait_snh.c haswaitp.h wait_snh.c 625 | ./compile wait_snh.c 626 | 627 | wait_stop.o: \ 628 | compile wait_stop.c wait_stop.c wait_stop.c haswaitp.h wait_stop.c \ 629 | error.h wait_stop.c 630 | ./compile wait_stop.c 631 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ptyget 0.50, alpha. 2 | 19960910 3 | Copyright 1996 4 | D. J. Bernstein, djb@pobox.com 5 | 6 | ptyget is a universal pseudo-terminal interface. It is designed to be 7 | used by any program that needs a pty. It can also serve as a wrapper to 8 | improve the behavior of existing programs. See BLURB for a more detailed 9 | advertisement. 10 | 11 | You may distribute unmodified copies of the ptyget package. 12 | 13 | INSTALL says how to set up and test ptyget. 14 | 15 | The rest of this file is a list of systypes where various versions of 16 | ptyget have been reported to work. 0.50 was the first alpha version. 17 | 18 | 0.50: bsd.os-2.0.1-:i386-:-:pentium-:- 19 | -------------------------------------------------------------------------------- /SYSDEPS: -------------------------------------------------------------------------------- 1 | VERSION 2 | hasptc.h 3 | hasptmx.h 4 | hassgact.h 5 | hassgprm.h 6 | haswaitp.h 7 | select.h 8 | fork.h 9 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | more ports 2 | add -p options to ptyspawn 3 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | ptyget 0.50 2 | -------------------------------------------------------------------------------- /alloc.c: -------------------------------------------------------------------------------- 1 | #include "alloc.h" 2 | #include "error.h" 3 | extern char *malloc(); 4 | extern void free(); 5 | 6 | #define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ 7 | #define SPACE 4096 /* must be multiple of ALIGNMENT */ 8 | 9 | typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; 10 | static aligned realspace[SPACE / ALIGNMENT]; 11 | #define space ((char *) realspace) 12 | static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ 13 | 14 | char *alloc(n) 15 | unsigned int n; 16 | { 17 | char *x; 18 | 19 | n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ 20 | 21 | if (n <= avail) { avail -= n; return space + avail; } 22 | 23 | x = malloc(n); 24 | if (!x) errno = error_nomem; 25 | return x; 26 | } 27 | 28 | void alloc_free(x) 29 | char *x; 30 | { 31 | if (x >= space) 32 | if (x < space + SPACE) 33 | return; /* XXX: assuming that pointers are flat */ 34 | free(x); 35 | } 36 | -------------------------------------------------------------------------------- /alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef ALLOC_H 2 | #define ALLOC_H 3 | 4 | extern char *alloc(); 5 | extern void alloc_free(); 6 | extern int alloc_re(); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /alloc_re.c: -------------------------------------------------------------------------------- 1 | #include "alloc.h" 2 | #include "byte.h" 3 | 4 | int alloc_re(x,m,n) 5 | char **x; 6 | unsigned int m; 7 | unsigned int n; 8 | { 9 | char *y; 10 | 11 | y = alloc(n); 12 | if (!y) return 0; 13 | byte_copy(y,m,*x); 14 | alloc_free(*x); 15 | *x = y; 16 | return 1; 17 | } 18 | -------------------------------------------------------------------------------- /background.1: -------------------------------------------------------------------------------- 1 | .TH background 1 2 | .SH NAME 3 | background \- run program without waiting for it 4 | .SH SYNOPSIS 5 | .B background 6 | .I subprogram 7 | [ 8 | .I args ... 9 | ] 10 | .SH DESCRIPTION 11 | .B background 12 | runs 13 | .I subprogram 14 | as a child process (not a process group leader) 15 | and then exits without waiting for 16 | .I subprogram 17 | to finish. 18 | .SH "SEE ALSO" 19 | ttydetach(1) 20 | -------------------------------------------------------------------------------- /background.c: -------------------------------------------------------------------------------- 1 | #include "strerr.h" 2 | #include "error.h" 3 | 4 | void main(argc,argv) 5 | int argc; 6 | char **argv; 7 | { 8 | int pi[2]; /* synchronization, to eliminate zombies */ 9 | char ch; 10 | 11 | if (pipe(pi) == -1) 12 | strerr_die2sys(111,"background: fatal: ","unable to create internal pipe: "); 13 | switch(fork()) { 14 | case -1: 15 | strerr_die2sys(111,"background: fatal: ","unable to fork: "); 16 | case 0: 17 | close(pi[1]); 18 | while (read(pi[0],&ch,1) == -1) 19 | if (errno != error_intr) 20 | break; /* oh, well */ 21 | close(pi[0]); 22 | execvp(argv[1],argv + 1); 23 | strerr_die4sys(111,"ttydetach: fatal: ","unable to run ",argv[1],": "); 24 | } 25 | _exit(0); 26 | } 27 | -------------------------------------------------------------------------------- /background.do: -------------------------------------------------------------------------------- 1 | objs="libstrerr.a libsubstdio.a liballoc.a liberror.a libstr.a" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /byte.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTE_H 2 | #define BYTE_H 3 | 4 | extern unsigned int byte_chr(); 5 | extern unsigned int byte_rchr(); 6 | extern void byte_copy(); 7 | extern void byte_copyr(); 8 | extern int byte_diff(); 9 | extern void byte_zero(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /byte_chr.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | 3 | unsigned int byte_chr(s,n,c) 4 | char *s; 5 | register unsigned int n; 6 | int c; 7 | { 8 | register char ch; 9 | register char *t; 10 | 11 | ch = c; 12 | t = s; 13 | for (;;) 14 | { 15 | if (!n) break; if (*t == ch) break; ++t; --n; 16 | if (!n) break; if (*t == ch) break; ++t; --n; 17 | if (!n) break; if (*t == ch) break; ++t; --n; 18 | if (!n) break; if (*t == ch) break; ++t; --n; 19 | } 20 | return t - s; 21 | } 22 | -------------------------------------------------------------------------------- /byte_copy.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | 3 | void byte_copy(to,n,from) 4 | register char *to; 5 | register unsigned int n; 6 | register char *from; 7 | { 8 | for (;;) 9 | { 10 | if (!n) return; *to++ = *from++; --n; 11 | if (!n) return; *to++ = *from++; --n; 12 | if (!n) return; *to++ = *from++; --n; 13 | if (!n) return; *to++ = *from++; --n; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /byte_cr.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | 3 | void byte_copyr(to,n,from) 4 | register char *to; 5 | register unsigned int n; 6 | register char *from; 7 | { 8 | to += n; 9 | from += n; 10 | for (;;) 11 | { 12 | if (!n) return; *--to = *--from; --n; 13 | if (!n) return; *--to = *--from; --n; 14 | if (!n) return; *--to = *--from; --n; 15 | if (!n) return; *--to = *--from; --n; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /byte_diff.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | 3 | int byte_diff(s,n,t) 4 | register char *s; 5 | register unsigned int n; 6 | register char *t; 7 | { 8 | for (;;) 9 | { 10 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; 11 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; 12 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; 13 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; 14 | } 15 | return ((int)(unsigned int)(unsigned char) *s) 16 | - ((int)(unsigned int)(unsigned char) *t); 17 | } 18 | -------------------------------------------------------------------------------- /byte_rchr.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | 3 | unsigned int byte_rchr(s,n,c) 4 | char *s; 5 | register unsigned int n; 6 | int c; 7 | { 8 | register char ch; 9 | register char *t; 10 | register char *u; 11 | 12 | ch = c; 13 | t = s; 14 | u = 0; 15 | for (;;) 16 | { 17 | if (!n) break; if (*t == ch) u = t; ++t; --n; 18 | if (!n) break; if (*t == ch) u = t; ++t; --n; 19 | if (!n) break; if (*t == ch) u = t; ++t; --n; 20 | if (!n) break; if (*t == ch) u = t; ++t; --n; 21 | } 22 | if (!u) u = t; 23 | return u - s; 24 | } 25 | -------------------------------------------------------------------------------- /byte_zero.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | 3 | void byte_zero(s,n) 4 | char *s; 5 | register unsigned int n; 6 | { 7 | for (;;) 8 | { 9 | if (!n) break; *s++ = 0; --n; 10 | if (!n) break; *s++ = 0; --n; 11 | if (!n) break; *s++ = 0; --n; 12 | if (!n) break; *s++ = 0; --n; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /conf-cc.sh: -------------------------------------------------------------------------------- 1 | CC='cc -O2' 2 | LD='cc -s' 3 | -------------------------------------------------------------------------------- /conf-group.h: -------------------------------------------------------------------------------- 1 | #ifndef CONF_GROUP_H 2 | #define CONF_GROUP_H 3 | 4 | #define GROUP_TTY "tty" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /conf-home.h: -------------------------------------------------------------------------------- 1 | #ifndef CONF_HOME_H 2 | #define CONF_HOME_H 3 | 4 | #define CONF_HOME "/usr/local" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /conf-secure.h: -------------------------------------------------------------------------------- 1 | #ifndef CONF_SECURE_H 2 | #define CONF_SECURE_H 3 | 4 | #define PTYGET_SECURE 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /default.0.do: -------------------------------------------------------------------------------- 1 | case $2 in 2 | ptybandage|ptyrun|nobuf|ttydetach|exclon|excloff|background) 3 | dependon $2.1 4 | nroff -man $2.1 5 | formake nroff -man $2.1 '>' $1 6 | ;; 7 | ptyget|ptyspawn|ptyio) 8 | dependon $2.8 9 | nroff -man $2.8 10 | formake nroff -man $2.8 '>' $1 11 | ;; 12 | *) 13 | nosuchtarget 14 | ;; 15 | esac 16 | -------------------------------------------------------------------------------- /default.a.do: -------------------------------------------------------------------------------- 1 | if test -r "$2.use" 2 | then 3 | dependon "$2.use" 4 | dependon makelib `cat "$2.use"` 5 | directtarget 6 | formake ./makelib $1 `cat "$2.use"` 7 | ./makelib $1 `cat "$2.use"` 8 | else 9 | nosuchtarget 10 | fi 11 | -------------------------------------------------------------------------------- /default.do: -------------------------------------------------------------------------------- 1 | case "$1" in 2 | shar) 3 | dependon FILES `cat FILES` 4 | formake 'shar -m `cat FILES` > shar' 5 | formake 'chmod 400 shar' 6 | shar -m `cat FILES` 7 | chmod 400 $3 8 | ;; 9 | makelib|loaddns|load|compile) 10 | dependon make-commands systype 11 | formake './make-commands "`cat ./systype`"' $1 '>' $1 12 | formake 'chmod 755' $1 13 | ./make-commands "`cat ./systype`" $1 14 | chmod 755 $3 15 | ;; 16 | make-commands) 17 | dependon make-cmds.sh conf-cc.sh warn-auto.sh 18 | formake 'cat warn-auto.sh conf-cc.sh make-cmds.sh > make-commands' 19 | formake 'chmod 755 make-commands' 20 | cat warn-auto.sh conf-cc.sh make-cmds.sh 21 | chmod 755 $3 22 | ;; 23 | find-systype) 24 | dependon find-systype.sh conf-cc.sh warn-auto.sh 25 | formake 'cat warn-auto.sh conf-cc.sh find-systype.sh > find-systype' 26 | formake 'chmod 755 find-systype' 27 | cat warn-auto.sh conf-cc.sh find-systype.sh 28 | chmod 755 $3 29 | ;; 30 | systype) 31 | dependon find-systype trycpp.c 32 | formake './find-systype > systype' 33 | ./find-systype 34 | ;; 35 | *) 36 | nosuchtarget 37 | ;; 38 | esac 39 | -------------------------------------------------------------------------------- /default.o.do: -------------------------------------------------------------------------------- 1 | directtarget 2 | dependon compile 3 | dependcc $2.c 4 | formake ./compile $2.c 5 | ./compile $2.c 6 | -------------------------------------------------------------------------------- /env.c: -------------------------------------------------------------------------------- 1 | /* env.c, envread.c, env.h: environ library 2 | Daniel J. Bernstein, djb@silverton.berkeley.edu. 3 | Depends on str.h, alloc.h. 4 | Requires environ. 5 | 19960113: rewrite. warning: interface is different. 6 | No known patent problems. 7 | */ 8 | 9 | #include "str.h" 10 | #include "alloc.h" 11 | #include "env.h" 12 | 13 | int env_isinit = 0; /* if env_isinit: */ 14 | static int ea; /* environ is a pointer to ea+1 char*'s. */ 15 | static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ 16 | 17 | static void env_goodbye(i) int i; 18 | { 19 | alloc_free(environ[i]); 20 | environ[i] = environ[--en]; 21 | environ[en] = 0; 22 | } 23 | 24 | static char *null = 0; 25 | 26 | void env_clear() 27 | { 28 | if (env_isinit) while (en) env_goodbye(0); 29 | else environ = &null; 30 | } 31 | 32 | static void env_unsetlen(s,len) char *s; int len; 33 | { 34 | int i; 35 | for (i = en - 1;i >= 0;--i) 36 | if (!str_diffn(s,environ[i],len)) 37 | if (environ[i][len] == '=') 38 | env_goodbye(i); 39 | } 40 | 41 | int env_unset(s) char *s; 42 | { 43 | if (!env_isinit) if (!env_init()) return 0; 44 | env_unsetlen(s,str_len(s)); 45 | return 1; 46 | } 47 | 48 | static int env_add(s) char *s; 49 | { 50 | char *t; 51 | t = env_findeq(s); 52 | if (t) env_unsetlen(s,t - s); 53 | if (en == ea) 54 | { 55 | ea += 30; 56 | if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) 57 | { ea = en; return 0; } 58 | } 59 | environ[en++] = s; 60 | environ[en] = 0; 61 | return 1; 62 | } 63 | 64 | int env_put(s) char *s; 65 | { 66 | char *u; 67 | if (!env_isinit) if (!env_init()) return 0; 68 | u = alloc(str_len(s) + 1); 69 | if (!u) return 0; 70 | str_copy(u,s); 71 | if (!env_add(u)) { alloc_free(u); return 0; } 72 | return 1; 73 | } 74 | 75 | int env_put2(s,t) char *s; char *t; 76 | { 77 | char *u; 78 | int slen; 79 | if (!env_isinit) if (!env_init()) return 0; 80 | slen = str_len(s); 81 | u = alloc(slen + str_len(t) + 2); 82 | if (!u) return 0; 83 | str_copy(u,s); 84 | u[slen] = '='; 85 | str_copy(u + slen + 1,t); 86 | if (!env_add(u)) { alloc_free(u); return 0; } 87 | return 1; 88 | } 89 | 90 | int env_init() 91 | { 92 | char **newenviron; 93 | int i; 94 | for (en = 0;environ[en];++en) ; 95 | ea = en + 10; 96 | newenviron = (char **) alloc((ea + 1) * sizeof(char *)); 97 | if (!newenviron) return 0; 98 | for (en = 0;environ[en];++en) 99 | { 100 | newenviron[en] = alloc(str_len(environ[en]) + 1); 101 | if (!newenviron[en]) 102 | { 103 | for (i = 0;i < en;++i) alloc_free(newenviron[i]); 104 | alloc_free(newenviron); 105 | return 0; 106 | } 107 | str_copy(newenviron[en],environ[en]); 108 | } 109 | newenviron[en] = 0; 110 | environ = newenviron; 111 | env_isinit = 1; 112 | return 1; 113 | } 114 | -------------------------------------------------------------------------------- /env.h: -------------------------------------------------------------------------------- 1 | #ifndef ENV_H 2 | #define ENV_H 3 | 4 | extern int env_isinit; 5 | 6 | extern int env_init(); 7 | extern int env_put(); 8 | extern int env_put2(); 9 | extern int env_unset(); 10 | extern char *env_get(); 11 | extern char *env_pick(); 12 | extern void env_clear(); 13 | extern char *env_findeq(); 14 | 15 | extern char **environ; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /envread.c: -------------------------------------------------------------------------------- 1 | /* see env.c */ 2 | 3 | #include "env.h" 4 | #include "str.h" 5 | 6 | extern char *env_get(s) 7 | char *s; 8 | { 9 | int i; 10 | int slen; 11 | char *envi; 12 | 13 | slen = str_len(s); 14 | for (i = 0;envi = environ[i];++i) 15 | if ((!str_diffn(s,envi,slen)) && (envi[slen] == '=')) 16 | return envi + slen + 1; 17 | return 0; 18 | } 19 | 20 | extern char *env_pick() 21 | { 22 | return environ[0]; 23 | } 24 | 25 | extern char *env_findeq(s) 26 | char *s; 27 | { 28 | for (;*s;++s) 29 | if (*s == '=') 30 | return s; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "error.h" 3 | 4 | /* warning: as coverage improves here, should update error_{str,temp} */ 5 | 6 | int error_intr = 7 | #ifdef EINTR 8 | EINTR; 9 | #else 10 | -1; 11 | #endif 12 | 13 | int error_nomem = 14 | #ifdef ENOMEM 15 | ENOMEM; 16 | #else 17 | -2; 18 | #endif 19 | 20 | int error_noent = 21 | #ifdef ENOENT 22 | ENOENT; 23 | #else 24 | -3; 25 | #endif 26 | 27 | int error_txtbsy = 28 | #ifdef ETXTBSY 29 | ETXTBSY; 30 | #else 31 | -4; 32 | #endif 33 | 34 | int error_io = 35 | #ifdef EIO 36 | EIO; 37 | #else 38 | -5; 39 | #endif 40 | 41 | int error_exist = 42 | #ifdef EEXIST 43 | EEXIST; 44 | #else 45 | -6; 46 | #endif 47 | 48 | int error_timeout = 49 | #ifdef ETIMEDOUT 50 | ETIMEDOUT; 51 | #else 52 | -7; 53 | #endif 54 | 55 | int error_inprogress = 56 | #ifdef EINPROGRESS 57 | EINPROGRESS; 58 | #else 59 | -8; 60 | #endif 61 | 62 | int error_wouldblock = 63 | #ifdef EWOULDBLOCK 64 | EWOULDBLOCK; 65 | #else 66 | -9; 67 | #endif 68 | 69 | int error_again = 70 | #ifdef EAGAIN 71 | EAGAIN; 72 | #else 73 | -10; 74 | #endif 75 | 76 | int error_pipe = 77 | #ifdef EPIPE 78 | EPIPE; 79 | #else 80 | -11; 81 | #endif 82 | -------------------------------------------------------------------------------- /error.h: -------------------------------------------------------------------------------- 1 | #ifndef ERROR_H 2 | #define ERROR_H 3 | 4 | extern int errno; 5 | 6 | extern int error_intr; 7 | extern int error_nomem; 8 | extern int error_noent; 9 | extern int error_txtbsy; 10 | extern int error_io; 11 | extern int error_exist; 12 | extern int error_timeout; 13 | extern int error_inprogress; 14 | extern int error_wouldblock; 15 | extern int error_again; 16 | extern int error_pipe; 17 | 18 | extern char *error_str(); 19 | extern int error_temp(); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /error_str.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "error.h" 3 | 4 | #define X(e,s) if (i == e) return s; 5 | 6 | char *error_str(i) 7 | int i; 8 | { 9 | X(0,"no error") 10 | X(error_intr,"interrupted system call") 11 | X(error_nomem,"out of memory") 12 | X(error_noent,"file does not exist") 13 | X(error_txtbsy,"text busy") 14 | X(error_io,"input/output error") 15 | X(error_exist,"file already exists") 16 | X(error_timeout,"timed out") 17 | X(error_inprogress,"operation in progress") 18 | X(error_again,"temporary failure") 19 | X(error_wouldblock,"input/output would block") 20 | X(error_pipe,"broken pipe") 21 | #ifdef EPERM 22 | X(EPERM,"permission denied") 23 | #endif 24 | #ifdef EACCES 25 | X(EACCES,"access denied") 26 | #endif 27 | #ifdef ESRCH 28 | X(ESRCH,"no such process") 29 | #endif 30 | #ifdef ENXIO 31 | X(ENXIO,"device not configured") 32 | #endif 33 | #ifdef E2BIG 34 | X(E2BIG,"argument list too long") 35 | #endif 36 | #ifdef ENOEXEC 37 | X(ENOEXEC,"exec format error") 38 | #endif 39 | #ifdef EBADF 40 | X(EBADF,"file descriptor not open") 41 | #endif 42 | #ifdef ECHILD 43 | X(ECHILD,"no child processes") 44 | #endif 45 | #ifdef EDEADLK 46 | X(EDEADLK,"operation would cause deadlock") 47 | #endif 48 | #ifdef EFAULT 49 | X(EFAULT,"bad address") 50 | #endif 51 | #ifdef ENOTBLK 52 | X(ENOTBLK,"not a block device") 53 | #endif 54 | #ifdef EBUSY 55 | X(EBUSY,"device busy") 56 | #endif 57 | #ifdef EXDEV 58 | X(EXDEV,"cross-device link") 59 | #endif 60 | #ifdef ENODEV 61 | X(ENODEV,"device does not support operation") 62 | #endif 63 | #ifdef ENOTDIR 64 | X(ENOTDIR,"not a directory") 65 | #endif 66 | #ifdef EISDIR 67 | X(EISDIR,"is a directory") 68 | #endif 69 | #ifdef EINVAL 70 | X(EINVAL,"invalid argument") 71 | #endif 72 | #ifdef ENFILE 73 | X(ENFILE,"system cannot open more files") 74 | #endif 75 | #ifdef EMFILE 76 | X(EMFILE,"process cannot open more files") 77 | #endif 78 | #ifdef ENOTTY 79 | X(ENOTTY,"not a tty") 80 | #endif 81 | #ifdef EFBIG 82 | X(EFBIG,"file too big") 83 | #endif 84 | #ifdef ENOSPC 85 | X(ENOSPC,"out of disk space") 86 | #endif 87 | #ifdef ESPIPE 88 | X(ESPIPE,"unseekable descriptor") 89 | #endif 90 | #ifdef EROFS 91 | X(EROFS,"read-only file system") 92 | #endif 93 | #ifdef EMLINK 94 | X(EMLINK,"too many links") 95 | #endif 96 | #ifdef EDOM 97 | X(EDOM,"input out of range") 98 | #endif 99 | #ifdef ERANGE 100 | X(ERANGE,"output out of range") 101 | #endif 102 | #ifdef EALREADY 103 | X(EALREADY,"operation already in progress") 104 | #endif 105 | #ifdef ENOTSOCK 106 | X(ENOTSOCK,"not a socket") 107 | #endif 108 | #ifdef EDESTADDRREQ 109 | X(EDESTADDRREQ,"destination address required") 110 | #endif 111 | #ifdef EMSGSIZE 112 | X(EMSGSIZE,"message too long") 113 | #endif 114 | #ifdef EPROTOTYPE 115 | X(EPROTOTYPE,"incorrect protocol type") 116 | #endif 117 | #ifdef ENOPROTOOPT 118 | X(ENOPROTOOPT,"protocol not available") 119 | #endif 120 | #ifdef EPROTONOSUPPORT 121 | X(EPROTONOSUPPORT,"protocol not supported") 122 | #endif 123 | #ifdef ESOCKTNOSUPPORT 124 | X(ESOCKTNOSUPPORT,"socket type not supported") 125 | #endif 126 | #ifdef EOPNOTSUPP 127 | X(EOPNOTSUPP,"operation not supported") 128 | #endif 129 | #ifdef EPFNOSUPPORT 130 | X(EPFNOSUPPORT,"protocol family not supported") 131 | #endif 132 | #ifdef EAFNOSUPPORT 133 | X(EAFNOSUPPORT,"address family not supported") 134 | #endif 135 | #ifdef EADDRINUSE 136 | X(EADDRINUSE,"address already used") 137 | #endif 138 | #ifdef EADDRNOTAVAIL 139 | X(EADDRNOTAVAIL,"address not available") 140 | #endif 141 | #ifdef ENETDOWN 142 | X(ENETDOWN,"network down") 143 | #endif 144 | #ifdef ENETUNREACH 145 | X(ENETUNREACH,"network unreachable") 146 | #endif 147 | #ifdef ENETRESET 148 | X(ENETRESET,"network reset") 149 | #endif 150 | #ifdef ECONNABORTED 151 | X(ECONNABORTED,"connection aborted") 152 | #endif 153 | #ifdef ECONNRESET 154 | X(ECONNRESET,"connection reset") 155 | #endif 156 | #ifdef ENOBUFS 157 | X(ENOBUFS,"out of buffer space") 158 | #endif 159 | #ifdef EISCONN 160 | X(EISCONN,"already connected") 161 | #endif 162 | #ifdef ENOTCONN 163 | X(ENOTCONN,"not connected") 164 | #endif 165 | #ifdef ESHUTDOWN 166 | X(ESHUTDOWN,"socket shut down") 167 | #endif 168 | #ifdef ETOOMANYREFS 169 | X(ETOOMANYREFS,"too many references") 170 | #endif 171 | #ifdef ECONNREFUSED 172 | X(ECONNREFUSED,"connection refused") 173 | #endif 174 | #ifdef ELOOP 175 | X(ELOOP,"symbolic link loop") 176 | #endif 177 | #ifdef ENAMETOOLONG 178 | X(ENAMETOOLONG,"file name too long") 179 | #endif 180 | #ifdef EHOSTDOWN 181 | X(EHOSTDOWN,"host down") 182 | #endif 183 | #ifdef EHOSTUNREACH 184 | X(EHOSTUNREACH,"host unreachable") 185 | #endif 186 | #ifdef ENOTEMPTY 187 | X(ENOTEMPTY,"directory not empty") 188 | #endif 189 | #ifdef EPROCLIM 190 | X(EPROCLIM,"too many processes") 191 | #endif 192 | #ifdef EUSERS 193 | X(EUSERS,"too many users") 194 | #endif 195 | #ifdef EDQUOT 196 | X(EDQUOT,"disk quota exceeded") 197 | #endif 198 | #ifdef ESTALE 199 | X(ESTALE,"stale NFS file handle") 200 | #endif 201 | #ifdef EREMOTE 202 | X(EREMOTE,"too many levels of remote in path") 203 | #endif 204 | #ifdef EBADRPC 205 | X(EBADRPC,"RPC structure is bad") 206 | #endif 207 | #ifdef ERPCMISMATCH 208 | X(ERPCMISMATCH,"RPC version mismatch") 209 | #endif 210 | #ifdef EPROGUNAVAIL 211 | X(EPROGUNAVAIL,"RPC program unavailable") 212 | #endif 213 | #ifdef EPROGMISMATCH 214 | X(EPROGMISMATCH,"program version mismatch") 215 | #endif 216 | #ifdef EPROCUNAVAIL 217 | X(EPROCUNAVAIL,"bad procedure for program") 218 | #endif 219 | #ifdef ENOLCK 220 | X(ENOLCK,"no locks available") 221 | #endif 222 | #ifdef ENOSYS 223 | X(ENOSYS,"system call not available") 224 | #endif 225 | #ifdef EFTYPE 226 | X(EFTYPE,"bad file type") 227 | #endif 228 | #ifdef EAUTH 229 | X(EAUTH,"authentication error") 230 | #endif 231 | #ifdef ENEEDAUTH 232 | X(ENEEDAUTH,"not authenticated") 233 | #endif 234 | #ifdef ENOSTR 235 | X(ENOSTR,"not a stream device") 236 | #endif 237 | #ifdef ETIME 238 | X(ETIME,"timer expired") 239 | #endif 240 | #ifdef ENOSR 241 | X(ENOSR,"out of stream resources") 242 | #endif 243 | #ifdef ENOMSG 244 | X(ENOMSG,"no message of desired type") 245 | #endif 246 | #ifdef EBADMSG 247 | X(EBADMSG,"bad message type") 248 | #endif 249 | #ifdef EIDRM 250 | X(EIDRM,"identifier removed") 251 | #endif 252 | #ifdef ENONET 253 | X(ENONET,"machine not on network") 254 | #endif 255 | #ifdef ERREMOTE 256 | X(ERREMOTE,"object not local") 257 | #endif 258 | #ifdef ENOLINK 259 | X(ENOLINK,"link severed") 260 | #endif 261 | #ifdef EADV 262 | X(EADV,"advertise error") 263 | #endif 264 | #ifdef ESRMNT 265 | X(ESRMNT,"srmount error") 266 | #endif 267 | #ifdef ECOMM 268 | X(ECOMM,"communication error") 269 | #endif 270 | #ifdef EPROTO 271 | X(EPROTO,"protocol error") 272 | #endif 273 | #ifdef EMULTIHOP 274 | X(EMULTIHOP,"multihop attempted") 275 | #endif 276 | #ifdef EREMCHG 277 | X(EREMCHG,"remote address changed") 278 | #endif 279 | return "unknown error"; 280 | } 281 | -------------------------------------------------------------------------------- /error_temp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "error.h" 3 | 4 | #define X(n) if (e == n) return 1; 5 | 6 | int error_temp(e) 7 | int e; 8 | { 9 | X(error_intr) 10 | X(error_nomem) 11 | X(error_txtbsy) 12 | X(error_io) 13 | X(error_timeout) 14 | X(error_wouldblock) 15 | X(error_again) 16 | #ifdef EDEADLK 17 | X(EDEADLK) 18 | #endif 19 | #ifdef EBUSY 20 | X(EBUSY) 21 | #endif 22 | #ifdef ENFILE 23 | X(ENFILE) 24 | #endif 25 | #ifdef EMFILE 26 | X(EMFILE) 27 | #endif 28 | #ifdef EFBIG 29 | X(EFBIG) 30 | #endif 31 | #ifdef ENOSPC 32 | X(ENOSPC) 33 | #endif 34 | #ifdef ENETDOWN 35 | X(ENETDOWN) 36 | #endif 37 | #ifdef ENETUNREACH 38 | X(ENETUNREACH) 39 | #endif 40 | #ifdef ENETRESET 41 | X(ENETRESET) 42 | #endif 43 | #ifdef ECONNABORTED 44 | X(ECONNABORTED) 45 | #endif 46 | #ifdef ECONNRESET 47 | X(ECONNRESET) 48 | #endif 49 | #ifdef ENOBUFS 50 | X(ENOBUFS) 51 | #endif 52 | #ifdef ETOOMANYREFS 53 | X(ETOOMANYREFS) 54 | #endif 55 | #ifdef ECONNREFUSED 56 | X(ECONNREFUSED) 57 | #endif 58 | #ifdef EHOSTDOWN 59 | X(EHOSTDOWN) 60 | #endif 61 | #ifdef EHOSTUNREACH 62 | X(EHOSTUNREACH) 63 | #endif 64 | #ifdef EPROCLIM 65 | X(EPROCLIM) 66 | #endif 67 | #ifdef EUSERS 68 | X(EUSERS) 69 | #endif 70 | #ifdef EDQUOT 71 | X(EDQUOT) 72 | #endif 73 | #ifdef ESTALE 74 | X(ESTALE) 75 | #endif 76 | #ifdef ENOLCK 77 | X(ENOLCK) 78 | #endif 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /excloff.1: -------------------------------------------------------------------------------- 1 | .TH excloff 1 2 | .SH NAME 3 | excloff \- stop reserving tty for exclusive use 4 | .SH SYNOPSIS 5 | .B excloff 6 | .SH DESCRIPTION 7 | .B excloff 8 | attempts to undo the effect of 9 | .BR exclon . 10 | .SH "SEE ALSO" 11 | exclon(1) 12 | -------------------------------------------------------------------------------- /excloff.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() 5 | { 6 | ioctl(1,TIOCNXCL,(char *) 0); 7 | } 8 | -------------------------------------------------------------------------------- /excloff.do: -------------------------------------------------------------------------------- 1 | objs="" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /exclon.1: -------------------------------------------------------------------------------- 1 | .TH exclon 1 2 | .SH NAME 3 | exclon \- reserve tty for exclusive use 4 | .SH SYNOPSIS 5 | .B exclon 6 | .SH DESCRIPTION 7 | .B exclon 8 | attempts to reserve your terminal for exclusive use. 9 | This means that any attempt to open your terminal, 10 | including through /dev/tty, 11 | will fail. 12 | 13 | Exception: 14 | root can still open your terminal. 15 | On most systems this means that 16 | .B talk 17 | is not affected by 18 | .B exclon 19 | even though 20 | .B write 21 | is. 22 | .SH "SEE ALSO" 23 | excloff(1), 24 | talk(1), 25 | write(1) 26 | -------------------------------------------------------------------------------- /exclon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() 5 | { 6 | ioctl(1,TIOCEXCL,(char *) 0); 7 | } 8 | -------------------------------------------------------------------------------- /exclon.do: -------------------------------------------------------------------------------- 1 | objs="" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /exit.h: -------------------------------------------------------------------------------- 1 | #ifndef EXIT_H 2 | #define EXIT_H 3 | 4 | extern void _exit(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /fdcopy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fdcopy.h" 3 | 4 | int fdcopy(to,from) 5 | int to; 6 | int from; 7 | { 8 | if (to == from) return 0; 9 | if (fcntl(from,F_GETFL,0) == -1) return -1; 10 | close(to); 11 | if (fcntl(from,F_DUPFD,to) == -1) return -1; 12 | return 0; 13 | } 14 | 15 | int fdmove(to,from) 16 | int to; 17 | int from; 18 | { 19 | if (to == from) return 0; 20 | if (fdcopy(to,from) == -1) return -1; 21 | close(from); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /fdcopy.h: -------------------------------------------------------------------------------- 1 | #ifndef FDCOPY_H 2 | #define FDCOPY_H 3 | 4 | extern int fdcopy(); 5 | extern int fdmove(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /find-systype.sh: -------------------------------------------------------------------------------- 1 | # oper-:arch-:syst-:chip-:kern- 2 | # oper = operating system type; e.g., sunos-4.1.4 3 | # arch = machine language; e.g., sparc 4 | # syst = which binaries can run; e.g., sun4 5 | # chip = chip model; e.g., micro-2-80 6 | # kern = kernel version; e.g., sun4m 7 | # dependence: arch --- chip 8 | # \ \ 9 | # oper --- syst --- kern 10 | # so, for example, syst is interpreted in light of oper, but chip is not. 11 | # anyway, no slashes, no extra colons, no uppercase letters. 12 | # the point of the extra -'s is to ease parsing: can add hierarchies later. 13 | # e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, 14 | # and i386-486 (486s do have more instructions, you know) as well as i386. 15 | # the idea here is to include ALL useful available information. 16 | 17 | exec 2>/dev/null 18 | sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" 19 | if [ x"$sys" != x ] 20 | then 21 | unamer="`uname -r | tr /: ..`" 22 | unamem="`uname -m | tr /: ..`" 23 | unamev="`uname -v | tr /: ..`" 24 | 25 | case "$sys" in 26 | bsd.os) 27 | # in bsd 4.4, uname -v does not have useful info. 28 | # in bsd 4.4, uname -m is arch, not chip. 29 | oper="$sys-$unamer" 30 | arch="$unamem" 31 | syst="" 32 | chip="`sysctl -n hw.model`" 33 | kern="" 34 | ;; 35 | freebsd) 36 | # see above about bsd 4.4 37 | oper="$sys-$unamer" 38 | arch="$unamem" 39 | syst="" 40 | chip="`sysctl -n hw.model`" # hopefully 41 | kern="" 42 | ;; 43 | netbsd) 44 | # see above about bsd 4.4 45 | oper="$sys-$unamer" 46 | arch="$unamem" 47 | syst="" 48 | chip="`sysctl -n hw.model`" # hopefully 49 | kern="" 50 | ;; 51 | linux) 52 | # as in bsd 4.4, uname -v does not have useful info. 53 | oper="$sys-$unamer" 54 | arch="i386" # always correct for now 55 | syst="" 56 | chip="$unamem" 57 | kern="" 58 | ;; 59 | aix) 60 | # naturally IBM has to get uname -r and uname -v backwards. dorks. 61 | oper="$sys-$unamev-$unamer" 62 | arch="`arch | tr /: ..`" 63 | syst="" 64 | chip="$unamem" 65 | kern="" 66 | ;; 67 | sunos) 68 | oper="$sys-$unamer-$unamev" 69 | arch="`(uname -p || mach) | tr /: ..`" 70 | syst="`arch | tr /: ..`" 71 | chip="$unamem" # this is wrong; is there any way to get the real info? 72 | kern="`arch -k | tr /: ..`" 73 | ;; 74 | unix_sv) 75 | oper="$sys-$unamer-$unamev" 76 | arch="`uname -m`" 77 | syst="" 78 | chip="$unamem" 79 | kern="" 80 | ;; 81 | *) 82 | oper="$sys-$unamer-$unamev" 83 | arch="`arch | tr /: ..`" 84 | syst="" 85 | chip="$unamem" 86 | kern="" 87 | ;; 88 | esac 89 | else 90 | $CC -c trycpp.c 91 | $LD -o trycpp trycpp.o 92 | case `./trycpp` in 93 | nextstep) 94 | oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" 95 | arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" 96 | syst="" 97 | chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" 98 | kern="" 99 | ;; 100 | *) 101 | oper="unknown" 102 | arch="" 103 | syst="" 104 | chip="" 105 | kern="" 106 | ;; 107 | esac 108 | fi 109 | 110 | case "$chip" in 111 | Intel.586) 112 | # no, you nitwits, there is no such chip. (NeXTStep) 113 | chip=pentium 114 | ;; 115 | i586) 116 | # no, you nitwits, there is no such chip. (Linux) 117 | chip=pentium 118 | ;; 119 | esac 120 | 121 | echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' 122 | -------------------------------------------------------------------------------- /fmt.h: -------------------------------------------------------------------------------- 1 | #ifndef FMT_H 2 | #define FMT_H 3 | 4 | #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ 5 | #define FMT_LEN ((char *) 0) /* convenient abbreviation */ 6 | 7 | extern unsigned int fmt_uint(); 8 | extern unsigned int fmt_uint0(); 9 | extern unsigned int fmt_xint(); 10 | extern unsigned int fmt_nbbint(); 11 | extern unsigned int fmt_ushort(); 12 | extern unsigned int fmt_xshort(); 13 | extern unsigned int fmt_nbbshort(); 14 | extern unsigned int fmt_ulong(); 15 | extern unsigned int fmt_xlong(); 16 | extern unsigned int fmt_nbblong(); 17 | 18 | extern unsigned int fmt_plusminus(); 19 | extern unsigned int fmt_minus(); 20 | extern unsigned int fmt_0x(); 21 | 22 | extern unsigned int fmt_str(); 23 | extern unsigned int fmt_strn(); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /fmt_str.c: -------------------------------------------------------------------------------- 1 | #include "fmt.h" 2 | 3 | unsigned int fmt_str(s,t) 4 | register char *s; register char *t; 5 | { 6 | register unsigned int len; 7 | char ch; 8 | len = 0; 9 | if (s) { while (ch = t[len]) s[len++] = ch; } 10 | else while (t[len]) len++; 11 | return len; 12 | } 13 | -------------------------------------------------------------------------------- /fmt_strn.c: -------------------------------------------------------------------------------- 1 | #include "fmt.h" 2 | 3 | unsigned int fmt_strn(s,t,n) 4 | register char *s; register char *t; register unsigned int n; 5 | { 6 | register unsigned int len; 7 | char ch; 8 | len = 0; 9 | if (s) { while (n-- && (ch = t[len])) s[len++] = ch; } 10 | else while (n-- && t[len]) len++; 11 | return len; 12 | } 13 | -------------------------------------------------------------------------------- /fmt_uint.c: -------------------------------------------------------------------------------- 1 | #include "fmt.h" 2 | 3 | unsigned int fmt_uint(s,u) register char *s; register unsigned int u; 4 | { 5 | register unsigned long l; l = u; return fmt_ulong(s,l); 6 | } 7 | -------------------------------------------------------------------------------- /fmt_uint0.c: -------------------------------------------------------------------------------- 1 | #include "fmt.h" 2 | 3 | unsigned int fmt_uint0(s,u,n) char *s; unsigned int u; unsigned int n; 4 | { 5 | unsigned int len; 6 | len = fmt_uint(FMT_LEN,u); 7 | while (len < n) { if (s) *s++ = '0'; ++len; } 8 | if (s) fmt_uint(s,u); 9 | return len; 10 | } 11 | -------------------------------------------------------------------------------- /fmt_ulong.c: -------------------------------------------------------------------------------- 1 | #include "fmt.h" 2 | 3 | unsigned int fmt_ulong(s,u) register char *s; register unsigned long u; 4 | { 5 | register unsigned int len; register unsigned long q; 6 | len = 1; q = u; 7 | while (q > 9) { ++len; q /= 10; } 8 | if (s) 9 | { 10 | s += len; 11 | do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ 12 | } 13 | return len; 14 | } 15 | -------------------------------------------------------------------------------- /fmt_ushort.c: -------------------------------------------------------------------------------- 1 | #include "fmt.h" 2 | 3 | unsigned int fmt_ushort(s,u) register char *s; register unsigned short u; 4 | { 5 | register unsigned long l; l = u; return fmt_ulong(s,l); 6 | } 7 | -------------------------------------------------------------------------------- /fork.h.do: -------------------------------------------------------------------------------- 1 | dependon compile load tryvfork.c fork.h1 fork.h2 2 | ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null 2>&1 \ 3 | && cat fork.h2 || cat fork.h1 4 | rm -f tryvfork.o tryvfork 5 | formake '( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null 2>&1 \' 6 | formake '&& cat fork.h2 || cat fork.h1 ) > fork.h' 7 | formake 'rm -f tryvfork.o tryvfork' 8 | -------------------------------------------------------------------------------- /fork.h1: -------------------------------------------------------------------------------- 1 | #ifndef FORK_H 2 | #define FORK_H 3 | 4 | extern int fork(); 5 | #define vfork fork 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /fork.h2: -------------------------------------------------------------------------------- 1 | #ifndef FORK_H 2 | #define FORK_H 3 | 4 | extern int fork(); 5 | extern int vfork(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /gen_alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef GEN_ALLOC_H 2 | #define GEN_ALLOC_H 3 | 4 | #define GEN_ALLOC_typedef(ta,type,field,len,a) \ 5 | typedef struct ta { type *field; int len; int a; } ta; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /gen_allocdefs.h: -------------------------------------------------------------------------------- 1 | #ifndef GEN_ALLOC_DEFS_H 2 | #define GEN_ALLOC_DEFS_H 3 | 4 | #define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ 5 | int ta_ready(x,n) register ta *x; register int n; { register int i; \ 6 | if (x->field) { i = x->a; \ 7 | if (n > i) { x->a = base + n + (n >> 3); \ 8 | if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ 9 | x->a = i; return 0; } \ 10 | return 1; } \ 11 | x->len = 0; return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } 12 | 13 | #define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ 14 | int ta_rplus(x,n) register ta *x; register int n; { register int i; \ 15 | if (x->field) { i = x->a; n += x->len; \ 16 | if (n > i) { x->a = base + n + (n >> 3); \ 17 | if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ 18 | x->a = i; return 0; } \ 19 | return 1; } \ 20 | x->len = 0; return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } 21 | 22 | #define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ 23 | int ta_append(x,i) register ta *x; register type *i; { \ 24 | if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /getopt.3: -------------------------------------------------------------------------------- 1 | .TH getopt 3 2 | .SH NAME 3 | getopt \- get option character from command line 4 | .SH SYNTAX 5 | .B #include 6 | 7 | char *\fBoptarg\fP; 8 | .br 9 | int \fBoptind\fP; 10 | .br 11 | int \fBoptpos\fP; 12 | .br 13 | int \fBopteof\fP; 14 | .br 15 | int \fBoptproblem\fP; 16 | .br 17 | char *\fBoptprogname\fP; 18 | .br 19 | int \fBopterr\fP; 20 | 21 | int \fBgetopt(\fP\fIargc,argv,opts\fR\fB)\fP; 22 | 23 | int \fIargc\fR; 24 | .br 25 | char **\fIargv\fR; 26 | .br 27 | char *\fIopts\fR; 28 | .SH DESCRIPTION 29 | This is a clone version of 30 | the standard 31 | .B getopt 32 | library, 33 | built on top of 34 | .BR subgetopt(3) . 35 | 36 | See 37 | .B subgetopt(3) 38 | for a detailed description of 39 | .B getopt 40 | processing. 41 | The main difference between 42 | .B getopt 43 | and 44 | .B subgetopt 45 | is that 46 | .B getopt 47 | prints error messages 48 | in case of problems. 49 | To turn off these error messages, set 50 | .B opterr 51 | (default nonzero) 52 | to zero. 53 | 54 | This clone version of 55 | .B getopt 56 | also provides an 57 | .B optprogname 58 | variable. 59 | There are two uses for this variable: 60 | 61 | (1) 62 | By default 63 | .B optprogname 64 | is null. 65 | When 66 | .B getopt 67 | sees this, 68 | it 69 | attempts to initialize 70 | .B optprogname 71 | from 72 | .IR argv\fB[0] , 73 | stripping the directory name. 74 | The calling program can use 75 | .B optprogname 76 | after calling 77 | .B getopt 78 | at least once. 79 | This is appropriate if the name of the program should be 80 | determined from its command line. 81 | 82 | (2) 83 | .B getopt 84 | prints 85 | .B optprogname 86 | at the beginning 87 | of any error messages. 88 | So the calling program can, 89 | before calling 90 | .BR getopt , 91 | initialize 92 | .B optprogname 93 | as desired. 94 | This is appropriate if the name of the program should not be 95 | determined from its command line. 96 | .SH "COMPATIBILITY" 97 | Old versions of 98 | .B getopt 99 | do not include 100 | .BR opterr . 101 | .BR optpos , 102 | .BR opteof , 103 | .BR optproblem , 104 | and 105 | .B optprogname 106 | are specific to this clone version of 107 | .BR getopt . 108 | 109 | Many features of this clone version of 110 | .B getopt 111 | are poorly defined, if available at all, 112 | in most versions of 113 | .BR getopt . 114 | For example, the standard 115 | .B getopt 116 | interface does not define 117 | .B optind 118 | until the end of the option list. 119 | And 120 | .B optarg 121 | is not defined 122 | unless 123 | .B getopt 124 | has just returned 125 | an option which takes an argument. 126 | In this clone version, 127 | .B optind 128 | and 129 | .B optpos 130 | always indicate the next character to be read, 131 | and 132 | .B optarg 133 | is null whenever 134 | the current option does not take an argument. 135 | See 136 | .B subgetopt(3) 137 | for precise definitions of the parsing procedure. 138 | 139 | When it reaches the end of the option list, 140 | this version of 141 | .B getopt 142 | always returns 143 | .BR opteof , 144 | which is the same as 145 | .BR subgetoptdone , 146 | which is initialized to 147 | .BR SUBGETOPTDONE , 148 | which is defined as \-1. 149 | The standard behavior is to return 150 | EOF 151 | from 152 | .B stdio(3). 153 | This is incompatible 154 | on any weird machine where 155 | EOF is different from \-1. 156 | The calling program could set 157 | .B opteof 158 | to EOF to imitate the standard behavior. 159 | 160 | Like most versions of 161 | .BR getopt , 162 | this clone version allows, but does not demand, that 163 | option arguments be 164 | separated from the option by whitespace, i.e., be 165 | in the next command-line argument. 166 | 167 | Some versions of 168 | .B getopt 169 | provide an 170 | .B optopt 171 | variable. 172 | .B optopt 173 | is incompatible across systems: 174 | for example, 175 | GNU 176 | .B getopt 177 | uses it the same way that this clone version uses 178 | .BR optproblem , 179 | while 180 | BSD 181 | .B getopt 182 | uses it to 183 | indicate the last option character returned by 184 | .BR getopt . 185 | This clone version does not provide 186 | .BR optopt . 187 | The use of 188 | .B optopt 189 | is strongly discouraged. 190 | 191 | Some versions of 192 | .B getopt 193 | do not recognize a double hyphen as the end of arguments. 194 | This version allows a double hyphen, or in fact any argument beginning 195 | with two hyphens. 196 | 197 | A lone hyphen is always recognized as the end of arguments. 198 | Some versions of 199 | .B getopt 200 | allow lone hyphens as options. 201 | This practice is wrong and is strongly discouraged. 202 | .SH "SYNTAX NOTE" 203 | .B getopt 204 | is actually a macro abbreviation for 205 | .BR getoptmine . 206 | The external 207 | .B opterr 208 | and 209 | .B optprogname 210 | variables 211 | are macros for 212 | .B getopterr 213 | and 214 | .BR getoptprogname . 215 | All the other 216 | .B opt 217 | variables are macros 218 | for 219 | .BR subgetopt . 220 | These macros are defined in 221 | .BR , 222 | unless 223 | .B GETOPTNOSHORT 224 | is defined. 225 | Further macros are defined in 226 | .BR , 227 | which is included by 228 | .BR , 229 | unless 230 | .B SUBGETOPTNOSHORT 231 | is defined. 232 | .SH VERSION 233 | getopt version 1.9, 931129. 234 | .SH AUTHOR 235 | Placed into the public domain by Daniel J. Bernstein. 236 | -------------------------------------------------------------------------------- /getopt.c: -------------------------------------------------------------------------------- 1 | /* getopt.c, getopt.h: (yet another) improved getopt clone, outer layer 2 | Daniel J. Bernstein, djb@silverton.berkeley.edu. 3 | Depends on subgetopt.h. 4 | Requires stdio. 5 | 931129: Rewrote in terms of subgetopt. 6 | No known patent problems. 7 | 8 | Documentation in getopt.3. 9 | */ 10 | 11 | #include 12 | #define GETOPTNOSHORT 13 | #include "getopt.h" 14 | #define SUBGETOPTNOSHORT 15 | #include "subgetopt.h" 16 | 17 | #define getopt getoptmine 18 | #define optind subgetoptind 19 | #define opterr getopterr 20 | #define optproblem subgetoptproblem 21 | #define optprogname getoptprogname 22 | 23 | int opterr = 1; 24 | char *optprogname = 0; 25 | 26 | int getopt(argc,argv,opts) 27 | int argc; 28 | char **argv; 29 | char *opts; 30 | { 31 | int c; 32 | char *s; 33 | 34 | if (!optprogname) 35 | { 36 | optprogname = *argv; 37 | if (!optprogname) /* oh boy */ 38 | optprogname = ""; /*XXX*/ 39 | for (s = optprogname;*s;++s) 40 | if (*s == '/') 41 | optprogname = s + 1; 42 | } 43 | c = subgetopt(argc,argv,opts); 44 | if (opterr) 45 | if (c == '?') 46 | if (argv[optind] && (optind < argc)) 47 | fprintf(stderr,"%s: illegal option -- %c\n",optprogname,optproblem); 48 | else 49 | fprintf(stderr,"%s: option requires an argument -- %c\n" 50 | ,optprogname,optproblem); 51 | return c; 52 | } 53 | -------------------------------------------------------------------------------- /getopt.h: -------------------------------------------------------------------------------- 1 | #ifndef GETOPT_H 2 | #define GETOPT_H 3 | 4 | #ifndef GETOPTNOSHORT 5 | #define getopt getoptmine 6 | #define optarg subgetoptarg 7 | #define optind subgetoptind 8 | #define optpos subgetoptpos 9 | #define opterr getopterr 10 | #define optproblem subgetoptproblem 11 | #define optprogname getoptprogname 12 | #define opteof subgetoptdone 13 | #endif 14 | 15 | #include "subgetopt.h" 16 | 17 | extern int getoptmine(); 18 | extern int getopterr; 19 | extern char *getoptprogname; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /hasptc.h.do: -------------------------------------------------------------------------------- 1 | dependon tryptc.c compile load 2 | ( ./compile tryptc.c && ./load tryptc && ./tryptc ) >/dev/null 2>&1 \ 3 | && echo \#define HASPTC 1 4 | rm -f tryptc.o tryptc 5 | formake '( ( ./compile tryptc.c && ./load tryptc && ./tryptc ) >/dev/null 2>&1 \' 6 | formake '&& echo \#define HASPTC 1 || exit 0 ) > hasptc.h' 7 | formake 'rm -f tryptc.o tryptc' 8 | -------------------------------------------------------------------------------- /hasptmx.h.do: -------------------------------------------------------------------------------- 1 | dependon tryptmx.c compile load 2 | ( ./compile tryptmx.c && ./load tryptmx && ./tryptmx ) >/dev/null 2>&1 \ 3 | && echo \#define HASPTMX 1 4 | rm -f tryptmx.o tryptmx 5 | formake '( ( ./compile tryptmx.c && ./load tryptmx && ./tryptmx ) >/dev/null 2>&1 \' 6 | formake '&& echo \#define HASPTMX 1 || exit 0 ) > hasptmx.h' 7 | formake 'rm -f tryptmx.o tryptmx' 8 | -------------------------------------------------------------------------------- /hassgact.h.do: -------------------------------------------------------------------------------- 1 | dependon trysgact.c compile load 2 | ( ./compile trysgact.c && ./load trysgact ) >/dev/null 2>&1 \ 3 | && echo \#define HASSIGACTION 1 4 | rm -f trysgact.o trysgact 5 | formake '( ( ./compile trysgact.c && ./load trysgact ) >/dev/null 2>&1 \' 6 | formake '&& echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h' 7 | formake 'rm -f trysgact.o trysgact' 8 | -------------------------------------------------------------------------------- /hassgprm.h.do: -------------------------------------------------------------------------------- 1 | dependon trysgprm.c compile load 2 | ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null 2>&1 \ 3 | && echo \#define HASSIGPROCMASK 1 4 | rm -f trysgprm.o trysgprm 5 | formake '( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null 2>&1 \' 6 | formake '&& echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h' 7 | formake 'rm -f trysgprm.o trysgprm' 8 | -------------------------------------------------------------------------------- /haswaitp.h.do: -------------------------------------------------------------------------------- 1 | dependon trywaitp.c compile load 2 | ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null 2>&1 \ 3 | && echo \#define HASWAITPID 1 4 | rm -f trywaitp.o trywaitp 5 | formake '( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null 2>&1 \' 6 | formake '&& echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h' 7 | formake 'rm -f trywaitp.o trywaitp' 8 | -------------------------------------------------------------------------------- /home.c: -------------------------------------------------------------------------------- 1 | #include "substdio.h" 2 | #include "readwrite.h" 3 | #include "exit.h" 4 | #include "conf-home.h" 5 | 6 | char buf[16]; 7 | substdio out = SUBSTDIO_FDBUF(write,1,buf,sizeof(buf)); 8 | 9 | void main() 10 | { 11 | substdio_puts(&out,CONF_HOME); 12 | substdio_putsflush(&out,"\n"); 13 | _exit(0); 14 | } 15 | -------------------------------------------------------------------------------- /it.do: -------------------------------------------------------------------------------- 1 | exec dependon \ 2 | ptyrun ptyrun.0 ptybandage ptybandage.0 nobuf nobuf.0 \ 3 | ptyget ptyget.0 ptyspawn ptyspawn.0 ptyio ptyio.0 \ 4 | ttydetach ttydetach.0 background background.0 \ 5 | exclon exclon.0 excloff excloff.0 6 | -------------------------------------------------------------------------------- /liballoc.use: -------------------------------------------------------------------------------- 1 | alloc.o 2 | alloc_re.o 3 | -------------------------------------------------------------------------------- /libenv.use: -------------------------------------------------------------------------------- 1 | env.o 2 | envread.o 3 | -------------------------------------------------------------------------------- /liberror.use: -------------------------------------------------------------------------------- 1 | error.o 2 | error_str.o 3 | error_temp.o 4 | -------------------------------------------------------------------------------- /libfs.use: -------------------------------------------------------------------------------- 1 | fmt_str.o 2 | fmt_strn.o 3 | fmt_uint.o 4 | fmt_uint0.o 5 | fmt_ulong.o 6 | fmt_ushort.o 7 | -------------------------------------------------------------------------------- /libgetopt.use: -------------------------------------------------------------------------------- 1 | subgetopt.o 2 | sgetopt.o 3 | getopt.o 4 | -------------------------------------------------------------------------------- /libopen.use: -------------------------------------------------------------------------------- 1 | open_append.o 2 | open_excl.o 3 | open_read.o 4 | open_trunc.o 5 | open_write.o 6 | -------------------------------------------------------------------------------- /libsig.use: -------------------------------------------------------------------------------- 1 | sig_block.o 2 | sig_catch.o 3 | sig_dfl.o 4 | sig_pipe.o 5 | sig_cont.o 6 | -------------------------------------------------------------------------------- /libstr.use: -------------------------------------------------------------------------------- 1 | str_len.o 2 | str_diff.o 3 | str_diffn.o 4 | str_cpy.o 5 | str_chr.o 6 | str_rchr.o 7 | byte_chr.o 8 | byte_rchr.o 9 | byte_diff.o 10 | byte_copy.o 11 | byte_cr.o 12 | byte_zero.o 13 | -------------------------------------------------------------------------------- /libstralloc.use: -------------------------------------------------------------------------------- 1 | stralloc_eady.o 2 | stralloc_pend.o 3 | stralloc_copy.o 4 | stralloc_opys.o 5 | stralloc_opyb.o 6 | stralloc_cat.o 7 | stralloc_cats.o 8 | stralloc_catb.o 9 | -------------------------------------------------------------------------------- /libstrerr.use: -------------------------------------------------------------------------------- 1 | strerr.o 2 | strerr_sys.o 3 | strerr_die.o 4 | -------------------------------------------------------------------------------- /libsubstdio.use: -------------------------------------------------------------------------------- 1 | substdio.o 2 | substdi.o 3 | substdo.o 4 | subfderr.o 5 | subfdout.o 6 | subfdin.o 7 | substdio_copy.o 8 | -------------------------------------------------------------------------------- /libwait.use: -------------------------------------------------------------------------------- 1 | wait_pid.o 2 | wait_nohang.o 3 | wait_stop.o 4 | wait_snh.o 5 | -------------------------------------------------------------------------------- /make-cmds.sh: -------------------------------------------------------------------------------- 1 | AR='ar cr' 2 | RANLIB=ranlib 3 | LIBS='' 4 | DNSLIBS='' 5 | 6 | case "$1" in 7 | sunos-5.*) 8 | # we can survive without /usr/ucbinclude and /usr/ucblib 9 | LIBS='-lsocket -lnsl' 10 | DNSLIBS=-lresolv 11 | RANLIB=: 12 | ;; 13 | unix_sv*) 14 | LIBS='-lsocket -lnsl' 15 | DNSLIBS=-lresolv 16 | RANLIB=: 17 | ;; 18 | sunos-4.*) 19 | DNSLIBS=-lresolv 20 | ;; 21 | irix-*) 22 | RANLIB=: 23 | ;; 24 | hp-ux-*) 25 | RANLIB=: 26 | ;; 27 | sco*) 28 | LIBS='-lsocket -lnsl' 29 | RANLIB=: 30 | ;; 31 | aix-*) 32 | LIBS=-lbsd # appears to not screw up readdir(); ibm did something right! 33 | ;; 34 | nextstep-*) 35 | ;; 36 | esac 37 | 38 | echo '#!/bin/sh' 39 | case "$2" in 40 | compile) 41 | echo exec "$CC" -c '${1+"$@"}' 42 | ;; 43 | load) 44 | echo 'main="$1"; shift' 45 | echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' "$LIBS" 46 | ;; 47 | loaddns) 48 | echo 'main="$1"; shift' 49 | echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' "$DNSLIBS" "$LIBS" 50 | ;; 51 | makelib) 52 | echo 'main="$1"; shift' 53 | echo 'rm -f "$main"' 54 | echo "$AR" '"$main" ${1+"$@"}' 55 | echo "$RANLIB" '"$main"' 56 | ;; 57 | esac 58 | -------------------------------------------------------------------------------- /nobuf.1: -------------------------------------------------------------------------------- 1 | .TH nobuf 1 2 | .SH NAME 3 | nobuf \- run a program without stdio block buffering 4 | .SH SYNOPSIS 5 | .B nobuf 6 | .I subprogram 7 | [ 8 | .I args ... 9 | ] 10 | .SH DESCRIPTION 11 | .B nobuf 12 | .I subprogram 13 | is similar to 14 | .IR subprogram , 15 | with one exception. 16 | If 17 | .I subprogram 18 | uses stdio, it will use block buffering rather than line buffering 19 | when its output is redirected; 20 | .B nobuf 21 | .I subprogram 22 | will always use line buffering. 23 | 24 | Internally, 25 | .B nobuf 26 | obtains a new pty and runs 27 | .I subprogram 28 | under it, 29 | transparently forwarding input and output. 30 | .B nobuf 31 | initializes the pty to remote mode, 32 | where tty processing is disabled, 33 | input is flow-controlled, 34 | and 35 | end-of-file is passed through to 36 | .IR subprogram . 37 | 38 | .B nobuf 39 | is a synonym for 40 | .B ptyget 41 | .B ptyio \-r 42 | .B ptyspawn \-23x\fR. 43 | Any 44 | .B ptyspawn 45 | options may be used with 46 | .BR nobuf . 47 | .SH "SEE ALSO" 48 | ptyrun(1), 49 | ptyget(8), 50 | ptyio(8), 51 | ptyspawn(8) 52 | -------------------------------------------------------------------------------- /nobuf.do: -------------------------------------------------------------------------------- 1 | dependon warn-auto.sh $1.sh home 2 | cat warn-auto.sh $1.sh | sed s}HOME}`./home`}g 3 | chmod 755 $3 4 | formake cat warn-auto.sh $1.sh '| sed s}HOME}`./home`}g >' $1 5 | formake chmod 755 $1 6 | -------------------------------------------------------------------------------- /nobuf.sh: -------------------------------------------------------------------------------- 1 | exec HOME/bin/ptyget HOME/bin/ptyio -r HOME/bin/ptyspawn -23x ${1+"$@"} 2 | -------------------------------------------------------------------------------- /open.h: -------------------------------------------------------------------------------- 1 | #ifndef OPEN_H 2 | #define OPEN_H 3 | 4 | extern int open_read(); 5 | extern int open_excl(); 6 | extern int open_append(); 7 | extern int open_trunc(); 8 | extern int open_write(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /open_append.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "open.h" 4 | 5 | int open_append(fn) char *fn; 6 | { return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } 7 | -------------------------------------------------------------------------------- /open_excl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "open.h" 4 | 5 | int open_excl(fn) char *fn; 6 | { return open(fn,O_WRONLY | O_EXCL | O_CREAT,0644); } 7 | -------------------------------------------------------------------------------- /open_read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "open.h" 4 | 5 | int open_read(fn) char *fn; 6 | { return open(fn,O_RDONLY | O_NDELAY); } 7 | -------------------------------------------------------------------------------- /open_trunc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "open.h" 4 | 5 | int open_trunc(fn) char *fn; 6 | { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0600); } 7 | -------------------------------------------------------------------------------- /open_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "open.h" 4 | 5 | int open_write(fn) char *fn; 6 | { return open(fn,O_WRONLY | O_NDELAY); } 7 | -------------------------------------------------------------------------------- /printgids.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "subfd.h" 4 | #include "substdio.h" 5 | #include "fmt.h" 6 | #include "exit.h" 7 | #include "conf-group.h" 8 | 9 | void fatal(type,name) char *type; char *name; 10 | { 11 | substdio_puts(subfderr,"fatal: can't find "); 12 | substdio_puts(subfderr,type); 13 | substdio_puts(subfderr," "); 14 | substdio_puts(subfderr,name); 15 | substdio_putsflush(subfderr,"\n"); 16 | _exit(1); 17 | } 18 | 19 | void define(s,d) char *s; int d; 20 | { 21 | char strd[FMT_ULONG]; 22 | strd[fmt_ulong(strd,(unsigned long) d)] = 0; 23 | substdio_puts(subfdout,"#define "); 24 | substdio_puts(subfdout,s); 25 | substdio_puts(subfdout," "); 26 | substdio_puts(subfdout,strd); 27 | substdio_puts(subfdout,"\n"); 28 | } 29 | 30 | void group(s,g) char *s; char *g; 31 | { 32 | struct group *gr; 33 | gr = getgrnam(g); 34 | if (!gr) fatal("group",g); 35 | define(s,(int) gr->gr_gid); 36 | } 37 | 38 | void main() 39 | { 40 | substdio_puts(subfdout,"#ifndef AUTO_GIDS_H\n#define AUTO_GIDS_H\n"); 41 | group("GID_TTY",GROUP_TTY); 42 | substdio_putsflush(subfdout,"#endif\n"); 43 | _exit(0); 44 | } 45 | -------------------------------------------------------------------------------- /ptybandage.1: -------------------------------------------------------------------------------- 1 | .TH ptybandage 1 2 | .SH NAME 3 | ptybandage \- wrap a transparent pty around a program 4 | .SH SYNOPSIS 5 | .B ptybandage 6 | .I subprogram 7 | [ 8 | .I args ... 9 | ] 10 | .SH DESCRIPTION 11 | .B ptybandage 12 | obtains a new pty and runs 13 | .I subprogram 14 | under it. 15 | This has the following effects: 16 | .TP 17 | .B * 18 | Descriptors 0, 1, and 2 19 | of 20 | .I subprogram 21 | are redirected to the pty. 22 | .BR ptybandage 's 23 | input 24 | is transparently 25 | forwarded to the pty's input; 26 | the pty's output is transparently forwarded to 27 | .BR ptybandage 's 28 | output. 29 | .TP 30 | .B * 31 | The pty's mode is set to the mode of 32 | .BR ptybandage 's 33 | controlling tty. 34 | Meanwhile, 35 | .BR ptybandage 's 36 | controlling tty is set to raw mode. 37 | .TP 38 | .B * 39 | When 40 | .I subprogram 41 | exits, 42 | .B ptybandage 43 | exits with the same exit code, 44 | after restoring the mode of its controlling tty. 45 | .TP 46 | .B * 47 | If 48 | .I subprogram 49 | stops, 50 | .B ptybandage 51 | stops with the same signal, 52 | temporarily restoring the mode of its controlling tty. 53 | When 54 | .B ptybandage 55 | continues, 56 | .IR subprogram 's 57 | process group will receive a SIGCONT. 58 | .TP 59 | .B * 60 | .B ptybandage 61 | forwards window-size changes to the pty. 62 | .TP 63 | .B * 64 | The controlling tty of 65 | .I subprogram 66 | is replaced with the pty. 67 | .TP 68 | .B * 69 | As an added bonus, 70 | .B ptybandage 71 | gives 72 | .I subprogram 73 | descriptor 3 pointing to /dev/tty, 74 | and an environment variable TTY 75 | giving the name of the pty. 76 | Beware: 77 | .B ptybandage 78 | also closes descriptors 4, 5, and 9. 79 | .PP 80 | .B ptybandage 81 | is useful for handling programs that refuse to run inside a pipe. 82 | As far as 83 | .I subprogram 84 | can see, it is talking to a tty. 85 | .B ptybandage 86 | doesn't mind being put inside a pipe. 87 | 88 | .B ptybandage 89 | also fools 90 | .BR isatty . 91 | If 92 | .I subprogram 93 | uses stdio, its output will be line-buffered. 94 | 95 | .B ptybandage 96 | is a synonym for 97 | .B ptyget 98 | .B ptyio \-t 99 | .BR ptyspawn . 100 | Any 101 | .B ptyspawn 102 | options may be used with 103 | .BR ptybandage . 104 | .SH "SEE ALSO" 105 | ptyrun(1), 106 | isatty(3), 107 | ptyget(8), 108 | ptyio(8), 109 | ptyspawn(8) 110 | -------------------------------------------------------------------------------- /ptybandage.do: -------------------------------------------------------------------------------- 1 | dependon warn-auto.sh $1.sh home 2 | cat warn-auto.sh $1.sh | sed s}HOME}`./home`}g 3 | chmod 755 $3 4 | formake cat warn-auto.sh $1.sh '| sed s}HOME}`./home`}g >' $1 5 | formake chmod 755 $1 6 | -------------------------------------------------------------------------------- /ptybandage.sh: -------------------------------------------------------------------------------- 1 | exec HOME/bin/ptyget HOME/bin/ptyio -t HOME/bin/ptyspawn ${1+"$@"} 2 | -------------------------------------------------------------------------------- /ptyget-setup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "subfd.h" 3 | #include "readwrite.h" 4 | #include "substdio.h" 5 | #include "stralloc.h" 6 | #include "open.h" 7 | #include "exit.h" 8 | #include "error.h" 9 | #include "conf-home.h" 10 | #include "conf-secure.h" 11 | #include "auto-gids.h" 12 | 13 | void die(s,fn,t,err) char *s; char *fn; char *t; char *err; 14 | { 15 | substdio_puts(subfderr,"ptyget-setup: "); 16 | substdio_puts(subfderr,s); 17 | substdio_puts(subfderr,fn); 18 | substdio_puts(subfderr,t); 19 | substdio_puts(subfderr,err); 20 | substdio_puts(subfderr,"\n"); 21 | substdio_flush(subfderr); 22 | _exit(1); 23 | } 24 | void die_nomem() { die("fatal: out of memory","","",""); } 25 | void die_write(s) char *s; { die("fatal: unable to write ",s,": ",error_str(errno)); } 26 | void die_read(s) char *s; { die("fatal: unable to read ", s,": ",error_str(errno)); } 27 | void die_chmod(s) char *s; { die("fatal: unable to chmod ", s,": ",error_str(errno)); } 28 | void die_chown(s) char *s; { die("fatal: unable to chown ", s,": ",error_str(errno)); } 29 | void die_mkdir(s) char *s; { die("fatal: unable to mkdir ", s,": ",error_str(errno)); } 30 | 31 | stralloc homefn = {0}; 32 | 33 | void makehomefn(fn) 34 | char *fn; 35 | { 36 | if (!stralloc_copys(&homefn,CONF_HOME)) die_nomem(); 37 | if (!stralloc_cats(&homefn,"/")) die_nomem(); 38 | if (!stralloc_cats(&homefn,fn)) die_nomem(); 39 | if (!stralloc_0(&homefn)) die_nomem(); 40 | } 41 | 42 | void protect(fn,mode) 43 | char *fn; 44 | int mode; 45 | { 46 | #ifdef PTYGET_SECURE 47 | if (chown(fn,0,GID_TTY) == -1) die_chown(fn); 48 | #endif 49 | if (chmod(fn,mode) == -1) die_chmod(fn); 50 | } 51 | 52 | char inbuf[SUBSTDIO_INSIZE]; 53 | char outbuf[SUBSTDIO_OUTSIZE]; 54 | 55 | void copy(fnfrom,fn,mode) 56 | char *fnfrom; 57 | char *fn; 58 | int mode; 59 | { 60 | int fd; 61 | int fdfrom; 62 | substdio ssin; 63 | substdio ssout; 64 | 65 | makehomefn(fn); 66 | fdfrom = open_read(fnfrom); 67 | if (fdfrom == -1) die_read(fnfrom); 68 | fd = open_trunc(homefn.s); 69 | if (fd == -1) die_write(fn); 70 | 71 | substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); 72 | substdio_fdbuf(&ssin,read,fdfrom,inbuf,sizeof(inbuf)); 73 | 74 | switch(substdio_copy(&ssout,&ssin)) 75 | { 76 | case -2: die_read(fnfrom); 77 | case -3: die_write(fn); 78 | } 79 | 80 | if (substdio_flush(&ssout) == -1) die_write(fn); 81 | 82 | close(fdfrom); 83 | close(fd); 84 | protect(homefn.s,mode); 85 | } 86 | 87 | void creatdir(fn,mode) 88 | char *fn; 89 | int mode; 90 | { 91 | makehomefn(fn); 92 | if (mkdir(homefn.s,mode) == -1) 93 | if (errno != error_exist) 94 | die_mkdir(homefn.s); 95 | protect(homefn.s,mode); 96 | } 97 | 98 | void main() 99 | { 100 | creatdir("bin",0755); 101 | #ifdef PTYGET_SECURE 102 | copy("ptyget","bin/ptyget",06755); 103 | #else 104 | copy("ptyget","bin/ptyget",00755); 105 | #endif 106 | copy("ptyrun","bin/ptyrun",0755); 107 | copy("ptybandage","bin/ptybandage",0755); 108 | copy("nobuf","bin/nobuf",0755); 109 | copy("background","bin/background",0755); 110 | copy("ttydetach","bin/ttydetach",0755); 111 | copy("ptyspawn","bin/ptyspawn",0755); 112 | copy("ptyio","bin/ptyio",0755); 113 | copy("exclon","bin/exclon",0755); 114 | copy("excloff","bin/excloff",0755); 115 | 116 | creatdir("man",0755); 117 | creatdir("man/cat1",0755); 118 | creatdir("man/cat8",0755); 119 | 120 | copy("ptyget.0","man/cat8/ptyget.0",0644); 121 | copy("ptybandage.0","man/cat1/ptybandage.0",0644); 122 | copy("ptyrun.0","man/cat1/ptyrun.0",0644); 123 | copy("nobuf.0","man/cat1/nobuf.0",0644); 124 | copy("background.0","man/cat1/background.0",0644); 125 | copy("ttydetach.0","man/cat1/ttydetach.0",0644); 126 | copy("ptyspawn.0","man/cat8/ptyspawn.0",0644); 127 | copy("ptyio.0","man/cat8/ptyio.0",0644); 128 | copy("exclon.0","man/cat1/exclon.0",0644); 129 | copy("excloff.0","man/cat1/excloff.0",0644); 130 | 131 | _exit(0); 132 | } 133 | -------------------------------------------------------------------------------- /ptyget.8: -------------------------------------------------------------------------------- 1 | .TH ptyget 8 2 | .SH NAME 3 | ptyget \- allocate a pty 4 | .SH SYNOPSIS 5 | .B ptyget 6 | .I subprogram 7 | [ 8 | .I args ... 9 | ] 10 | .SH DESCRIPTION 11 | .B ptyget 12 | allocates a new pty, 13 | makes the master side available as fd 4 (non-blocking), 14 | makes the slave side available as fd 5, 15 | and runs 16 | .IR subprogram . 17 | It passes 18 | .I subprogram 19 | a TTY environment variable 20 | giving the name of the pty slave. 21 | 22 | On current systems, 23 | .B ptyget 24 | is setuid root and setgid tty. 25 | It changes the ownership of the pty slave to the user, 26 | so that the user can open it, 27 | and makes it mode 600, 28 | so that nobody else can open it. 29 | It also puts the pty slave under group tty. 30 | It will refuse to run if these protections fail. 31 | 32 | .B ptyget 33 | does not make any provisions to clean up when the 34 | user finishes using the pty. 35 | .SH "SYSTEM-SPECIFIC NOTES" 36 | On pty/tty-based systems (e.g., BSD 4.4), 37 | the slave is 38 | .B /dev/tty\fIxy 39 | where 40 | .I xy 41 | are two characters. 42 | .B ptyget 43 | searches through masters starting from a random point 44 | (with a random increment to avoid secondary clustering). 45 | .B ptyget 46 | relies for security on the kernel's 47 | .B revoke() 48 | function. 49 | 50 | On ptmx/pts-based systems (e.g., Solaris), 51 | the slave is 52 | .B /dev/pts/\fIN 53 | where 54 | .I N 55 | is a nonnegative integer. 56 | .B ptyget 57 | does not invoke 58 | .BR /usr/lib/pt_chmod . 59 | .B ptyget 60 | relies for security on the kernel's built-in slave locking. 61 | .SH "SEE ALSO" 62 | ptyget(8) 63 | -------------------------------------------------------------------------------- /ptyget.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "env.h" 7 | #include "fmt.h" 8 | #include "str.h" 9 | #include "strerr.h" 10 | #include 11 | 12 | #include "hasptmx.h" 13 | #include "hasptc.h" 14 | #include "conf-secure.h" 15 | 16 | 17 | #ifdef HASPTMX 18 | #ifndef PTYGET_OK 19 | #define PTYGET_OK 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | char fnslave[10 + FMT_ULONG]; /* 10 for /dev/pts/ */ 27 | 28 | char *pty45() 29 | { 30 | struct strioctl si; 31 | struct stat st; 32 | int fd; 33 | char *s; 34 | 35 | fd = open("/dev/ptmx",O_RDWR | O_NDELAY); 36 | if (fd == -1) return 0; 37 | if (fdmove(4,fd) == -1) return 0; 38 | 39 | if (fstat(4,&st) == -1) return 0; 40 | s = fnslave; 41 | s += fmt_str(s,"/dev/pts/"); 42 | s += fmt_ulong(s,(unsigned long) minor(st.st_rdev)); 43 | *s = 0; 44 | 45 | #ifdef PTYGET_SECURE 46 | if (chown(fnslave,getuid(),getegid()) == -1) 47 | return 0; 48 | if (chmod(fnslave,0600) == -1) 49 | return 0; 50 | #endif 51 | 52 | si.ic_cmd = UNLKPT; 53 | si.ic_timout = 0; 54 | si.ic_len = 0; 55 | si.ic_dp = 0; 56 | if (ioctl(4,I_STR,&si) == -1) return 0; 57 | 58 | fd = open(fnslave,O_RDWR | O_NOCTTY); 59 | if (fd == -1) return 0; 60 | if (fdmove(5,fd) == -1) return 0; 61 | 62 | if (ioctl(5,I_PUSH,"ptem") == -1) return 0; 63 | if (ioctl(5,I_PUSH,"ldterm") == -1) return 0; 64 | if (tcflush(5,TCIOFLUSH) == -1) return 0; 65 | 66 | return fnslave; 67 | } 68 | 69 | #endif 70 | #endif 71 | 72 | 73 | #ifdef HASPTC 74 | #ifndef PTYGET_OK 75 | #define PTYGET_OK 76 | 77 | #ifdef PTYGET_SECURE 78 | 79 | ERROR! ptc-based systems have no pty security. 80 | 81 | #endif 82 | 83 | #include 84 | 85 | char fnslave[10 + FMT_ULONG]; /* 10 for /dev/pts/ */ 86 | 87 | char *pty45() 88 | { 89 | struct stat st; 90 | int fd; 91 | 92 | fd = open("/dev/ptc",O_RDWR | O_NDELAY); 93 | if (fd == -1) return 0; 94 | if (fdmove(4,fd) == -1) return 0; 95 | 96 | if (fstat(4,&st) == -1) return 0; 97 | s = fnslave; 98 | s += fmt_str(s,"/dev/pts/"); 99 | s += fmt_ulong(s,(unsigned long) minor(st.st_rdev)); 100 | *s = 0; 101 | 102 | fd = open(fnslave,O_RDWR | O_NOCTTY); 103 | if (fd == -1) return 0; 104 | if (fdmove(5,fd) == -1) return 0; 105 | 106 | return fnslave; 107 | } 108 | 109 | #endif 110 | #endif 111 | 112 | 113 | #ifndef PTYGET_OK 114 | 115 | char fnmaster[] = "/dev/pty??"; 116 | char fnslave[] = "/dev/tty??"; 117 | 118 | /* Do not change the sizes of pty1 and pty2! */ 119 | char pty1[16] = "pqrstuvwxyzPQRST"; 120 | char pty2[16] = "0123456789abcdef"; 121 | 122 | char *pty45() 123 | { 124 | int fd; 125 | struct stat st; 126 | int pos; 127 | int increment; 128 | int loop; 129 | 130 | pos = 255 & getpid(); 131 | increment = 1 + (254 & time((long *) 0)); 132 | 133 | for (loop = 0;loop < 256;++loop) { 134 | pos = 255 & (pos + increment); 135 | 136 | fnslave[8] = fnmaster[8] = pty1[15 & pos]; 137 | fnslave[9] = fnmaster[9] = pty2[15 & (pos >> 4)]; 138 | 139 | if (fnmaster[8] == '-') continue; 140 | if (stat(fnmaster,&st) == -1) { pty1[15 & pos] = '-'; continue; } 141 | 142 | fd = open(fnmaster,O_RDWR | O_NDELAY); 143 | if (fd != -1) { 144 | if (fdmove(4,fd) == -1) return 0; 145 | 146 | #ifdef PTYGET_SECURE 147 | if (chown(fnslave,getuid(),getegid()) == -1) 148 | return 0; 149 | if (chmod(fnslave,0600) == -1) 150 | return 0; 151 | revoke(fnslave); 152 | #endif 153 | 154 | fd = open(fnslave,O_RDWR | O_NOCTTY); 155 | if (fd != -1) { 156 | if (fdmove(5,fd) == -1) return 0; 157 | return fnslave; 158 | } 159 | close(4); 160 | } 161 | } 162 | return 0; 163 | } 164 | 165 | #endif 166 | 167 | 168 | void main(argc,argv) 169 | int argc; 170 | char **argv; 171 | { 172 | char *tty; 173 | 174 | tty = pty45(); 175 | 176 | if (setgid(getgid()) == -1) _exit(1); 177 | if (setuid(getuid()) == -1) _exit(1); 178 | 179 | if (!tty) 180 | strerr_die2sys(111,"ptyget: fatal: ","unable to allocate pty: "); 181 | 182 | #ifndef PTYGET_SECURE 183 | strerr_warn1("ptyget: warning: unable to allocate secure pty",0); 184 | #endif 185 | 186 | if (!env_put2("TTY",tty)) 187 | strerr_die2x(111,"ptyget: fatal: ","out of memory"); 188 | 189 | if (!argv[1]) 190 | strerr_die1x(1,"ptyget: usage: ptyget subprogram [ args ... ]"); 191 | 192 | execvp(argv[1],argv + 1); 193 | strerr_die4sys(111,"ptyget: fatal: ","unable to run ",argv[1],": "); 194 | } 195 | -------------------------------------------------------------------------------- /ptyget.do: -------------------------------------------------------------------------------- 1 | objs="fdcopy.o libenv.a liballoc.a libstrerr.a libsubstdio.a liberror.a libfs.a libstr.a" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /ptyio.8: -------------------------------------------------------------------------------- 1 | .TH ptyio 8 2 | .SH NAME 3 | ptyio \- feed input to a pty and print its output 4 | .SH SYNOPSIS 5 | .B ptyio 6 | [ 7 | .B \-tTr 8 | ] 9 | .I subprogram 10 | [ 11 | .I args ... 12 | ] 13 | .SH DESCRIPTION 14 | .B ptyio 15 | copies its input to the master side of a pty. 16 | Meanwhile, it prints all output that shows up from the master. 17 | 18 | .B ptyio 19 | runs 20 | .I subprogram 21 | as a child process (not a process group leader). 22 | It supplies a ``job control'' pipe to 23 | .I subprogram 24 | as descriptor 9. 25 | After the pipe closes, 26 | .B ptyio 27 | will wait for 28 | .I subprogram 29 | to exit; then 30 | .B ptyio 31 | will exit with the same exit code. 32 | 33 | If 34 | .B ptyio 35 | reaches EOF or sees an error on its input, 36 | it stops reading input, but it continues printing output. 37 | If 38 | .B ptyio 39 | sees an error on its output, 40 | it sends SIGPIPE to 41 | .I subprogram 42 | and stops writing output. 43 | 44 | .B ptyio 45 | must be invoked with descriptor 4 pointing to the pty master and 46 | descriptor 5 pointing to the pty slave. 47 | It passes these descriptors to 48 | .IR subprogram . 49 | It must also be invoked with 50 | environment variable TTY 51 | giving the name of the pty slave. 52 | It passes this variable to 53 | .IR subprogram . 54 | .SH "OPTIONS" 55 | .TP 56 | .B \-t 57 | Attached to a tty. 58 | .B ptyio 59 | must be attached to a tty in one of the following places: 60 | descriptor 3; /dev/tty; descriptor 2; descriptor 0; descriptor 1. 61 | Before running 62 | .IR subprogram , 63 | .B ptyio 64 | sets the attached tty to raw mode, 65 | and copies the original mode to the pty. 66 | Before exiting, 67 | .B ptyio 68 | restores the original mode of the attached tty. 69 | 70 | Whenever 71 | .I subprogram 72 | writes a byte to the job control pipe, 73 | .B ptyio 74 | stops itself, 75 | using the stop signal given by that byte. 76 | It restores the mode of the attached tty before stopping. 77 | After 78 | .B ptyio 79 | continues, 80 | it sets the attached tty to raw mode again, 81 | and then sends SIGCONT to 82 | .IR subprogram . 83 | 84 | .B ptyio 85 | passes window-size changes through to the pty. 86 | 87 | Many programs handle tty modes incorrectly when they are run 88 | in the background; 89 | for example, try 90 | 91 | .EX 92 | (sleep 2;vi) &; vi 93 | .EE 94 | 95 | .B ptyio 96 | handles this situation correctly. 97 | .TP 98 | .B \-T 99 | (Default.) Not attached to a tty. 100 | Before running 101 | .IR subprogram , 102 | .B ptyio 103 | sets the pty mode to sane mode. 104 | Whenever 105 | .I subprogram 106 | writes a byte to the job control pipe, 107 | .B ptyio 108 | sends 109 | SIGCONT 110 | to 111 | .IR subprogram . 112 | .TP 113 | .B \-r 114 | Remote mode. 115 | Before running 116 | .IR subprogram , 117 | .B ptyio 118 | sets the pty mode to raw mode, 119 | and enables TIOCREMOTE on the master. 120 | After reaching end of file on standard input, 121 | .B ptyio 122 | writes 0-byte packets to the pty master, 123 | which (with correct TIOCREMOTE implementations) 124 | produces end-of-file for any program reading the pty slave. 125 | .SH "RAW MODE" 126 | Raw mode eliminates input echoing, input line buffering, input line editing, 127 | input signals (control-C producing SIGINT, control-Z producing 128 | SIGTSTP, etc.), output conversion of LF to CR LF, and 129 | XON/XOFF flow control. 130 | It is, unfortunately, not completely clean: 131 | if too much tty input arrives at once, the kernel will discard characters. 132 | .SH "SANE MODE" 133 | Sane mode supports input echoing, input line buffering, 134 | input signals, 135 | input conversion of CR to LF, 136 | 8-bit input, 137 | output conversion of LF to CR LF, 138 | and XON/XOFF flow control. 139 | It supports the following keys: 140 | delete for ERASE, 141 | control-backslash for QUIT, 142 | control-C for INTR, 143 | control-D for EOF, 144 | control-O for DISCARD, 145 | control-R for REPRINT, 146 | control-T for STATUS, 147 | control-U for KILL, 148 | control-V for LNEXT, 149 | control-W for WERASE, 150 | control-Y for DSUSP, 151 | and 152 | control-Z for SUSP. 153 | .SH "SEE ALSO" 154 | ptyrun(1), 155 | ptybandage(1), 156 | ptyget(8), 157 | ptyspawn(8) 158 | -------------------------------------------------------------------------------- /ptyio.c: -------------------------------------------------------------------------------- 1 | #include "wait.h" 2 | #include "fork.h" 3 | #include "select.h" 4 | #include "sig.h" 5 | #include 6 | #include "error.h" 7 | #include "readwrite.h" 8 | #include "exit.h" 9 | #include "ttyctrl.h" 10 | #include "ttymodes.h" 11 | #include "sgetopt.h" 12 | #include "substdio.h" 13 | #include "subfd.h" 14 | 15 | char bufin[1024]; 16 | int bufinpos; 17 | int bufinsize; 18 | char bufout[1024]; 19 | int bufoutsize; 20 | int bufoutpos; 21 | 22 | struct ttymodes tminit; 23 | 24 | int fdtty; 25 | struct ttymodes tmraw; 26 | int flagcont = 0; 27 | struct ttymodes tmcont; 28 | void sigcont() 29 | { 30 | if (ttymodes_get(&tmcont,fdtty) != -1) flagcont = 1; 31 | } 32 | 33 | int pi9[2]; 34 | int flagptyrok = 1; 35 | int flagptywok = 1; 36 | int flagremote = 0; 37 | int flagreading = 1; 38 | int flagwriting = 1; 39 | int flageof9 = 0; 40 | int flagtty = 0; 41 | 42 | void sigwinch() 43 | { 44 | if (flagtty) { 45 | ttymodes_getw(&tminit,fdtty); 46 | ttymodes_setw(&tminit,5); 47 | } 48 | } 49 | 50 | void main(argc,argv) 51 | int argc; 52 | char **argv; 53 | { 54 | int r; 55 | int w; 56 | fd_set rfds; 57 | fd_set wfds; 58 | int wstat; 59 | int opt; 60 | int child; 61 | 62 | while ((opt = getopt(argc,argv,"rtT")) != opteof) 63 | switch(opt) { 64 | case 'r': flagremote = 1; break; 65 | case 'T': flagtty = 0; break; 66 | case 't': flagtty = 1; break; 67 | case '?': 68 | default: 69 | _exit(1); 70 | } 71 | argc -= optind; 72 | argv += optind; 73 | if (!*argv) { 74 | substdio_putsflush(subfderr,"ptyio: usage: ptyio subprogram [ args ... ]\n"); 75 | _exit(1); 76 | } 77 | 78 | sig_pipeignore(); 79 | sig_block(SIGWINCH); 80 | 81 | if (pipe(pi9) == -1) { 82 | substdio_putsflush(subfderr,"ptyio: fatal: unable to create internal pipe\n"); 83 | _exit(111); 84 | } 85 | 86 | if (!flagtty) 87 | ttymodes_sane(&tminit); 88 | else { 89 | fdtty = ttyctrl(); 90 | if (fdtty == -1) { 91 | substdio_putsflush(subfderr,"ptyio: fatal: unable to find attached tty\n"); 92 | _exit(111); 93 | } 94 | 95 | sig_catch(SIGTTOU,SIG_DFL); 96 | sig_unblock(SIGTTOU); 97 | sig_contcatch(sigcont); 98 | sig_contunblock(); 99 | 100 | if (ttymodes_get(&tminit,fdtty) == -1) { 101 | substdio_putsflush(subfderr,"ptyio: fatal: unable to get modes of attached tty\n"); 102 | _exit(111); 103 | } 104 | tmraw = tminit; 105 | ttymodes_makeraw(&tmraw); 106 | ttymodes_set(&tmraw,fdtty); 107 | 108 | sig_contblock(); 109 | while (flagcont) { 110 | flagcont = 0; 111 | tminit = tmcont; 112 | tmraw = tminit; 113 | ttymodes_makeraw(&tmraw); 114 | sig_contunblock(); 115 | ttymodes_set(&tmraw,fdtty); 116 | sig_contblock(); 117 | } 118 | 119 | sig_contdefault(); 120 | sig_contunblock(); 121 | } 122 | 123 | if (flagremote) { 124 | int on; 125 | on = 1; 126 | if (ioctl(4,TIOCREMOTE,&on) == -1) { 127 | substdio_putsflush(subfderr,"ptyio: fatal: unable to set remote mode\n"); 128 | _exit(111); 129 | } 130 | ttymodes_makeraw(&tminit); 131 | } 132 | 133 | sig_block(SIGTTOU); 134 | ttymodes_set(&tminit,5); 135 | 136 | switch(child = vfork()) { 137 | case -1: 138 | if (flagtty) 139 | ttymodes_set(&tminit,fdtty); 140 | substdio_putsflush(subfderr,"ptyio: fatal: unable to fork\n"); 141 | _exit(111); 142 | case 0: 143 | close(pi9[0]); 144 | if (flagtty) 145 | close(fdtty); 146 | if (fdmove(9,pi9[1]) == -1) { 147 | substdio_putsflush(subfderr,"ptyio: fatal: unable to copy child fd\n"); 148 | _exit(111); 149 | } 150 | sig_unblock(SIGTTOU); 151 | sig_unblock(SIGWINCH); 152 | execvp(*argv,argv); 153 | substdio_putsflush(subfderr,"ptyio: fatal: unable to run subprogram\n"); 154 | _exit(111); 155 | } 156 | 157 | close(pi9[1]); 158 | if (fdmove(2,pi9[0]) == -1) { 159 | substdio_putsflush(subfderr,"ptyio: fatal: unable to copy parent fd\n"); 160 | _exit(111); 161 | } 162 | 163 | sig_catch(SIGWINCH,sigwinch); 164 | 165 | bufinpos = bufinsize = 0; 166 | bufoutpos = bufoutsize = 0; 167 | 168 | while ((flagptyrok && flagwriting) || !flageof9) { 169 | FD_ZERO(&rfds); 170 | FD_ZERO(&wfds); 171 | 172 | if (flagreading && flagptywok) 173 | if (bufinpos == bufinsize) 174 | FD_SET(0,&rfds); 175 | if (flagptywok) 176 | if ((bufinpos < bufinsize) || (flagremote && !flagreading)) 177 | FD_SET(4,&wfds); 178 | if (flagptyrok && flagwriting) 179 | if (bufoutpos == bufoutsize) 180 | FD_SET(4,&rfds); 181 | if (flagwriting) 182 | if (bufoutpos < bufoutsize) 183 | FD_SET(1,&wfds); 184 | if (!flageof9) 185 | FD_SET(2,&rfds); 186 | 187 | sig_unblock(SIGWINCH); 188 | if (select(6,&rfds,&wfds,(fd_set *) 0,(struct timeval *) 0) == -1) 189 | continue; 190 | sig_block(SIGWINCH); 191 | 192 | if (FD_ISSET(0,&rfds)) if (flagreading && flagptywok) { 193 | r = read(0,bufin,sizeof(bufin)); 194 | if (r <= 0) 195 | flagreading = 0; 196 | else { 197 | bufinpos = 0; 198 | bufinsize = r; 199 | } 200 | } 201 | 202 | if (FD_ISSET(4,&wfds)) if (flagptywok) { 203 | if (bufinpos < bufinsize) { 204 | w = write(4,bufin + bufinpos,bufinsize - bufinpos); 205 | if (w <= 0) 206 | flagptywok = 0; 207 | else 208 | bufinpos += w; 209 | } 210 | else if (flagremote && !flagreading) { 211 | w = write(4,bufin,0); 212 | if (w < 0) 213 | flagptywok = 0; 214 | } 215 | } 216 | 217 | if (FD_ISSET(4,&rfds)) if (flagptyrok && flagwriting) { 218 | r = read(4,bufout,sizeof(bufout)); 219 | if (r <= 0) 220 | flagptyrok = 0; 221 | else { 222 | bufoutpos = 0; 223 | bufoutsize = r; 224 | } 225 | } 226 | 227 | if (FD_ISSET(1,&wfds)) if (flagwriting) { 228 | w = write(1,bufout + bufoutpos,bufoutsize - bufoutpos); 229 | if (w <= 0) { 230 | flagwriting = 0; 231 | kill(child,SIGPIPE); 232 | } 233 | else 234 | bufoutpos += w; 235 | } 236 | 237 | if (FD_ISSET(2,&rfds)) if (!flageof9) { 238 | unsigned char ch; 239 | 240 | r = read(2,&ch,1); 241 | if (r <= 0) { 242 | flageof9 = 1; 243 | close(5); 244 | } 245 | else { 246 | if (flagtty) { 247 | ttymodes_set(&tminit,fdtty); 248 | sig_dfl((unsigned int) ch); 249 | sig_unblock(SIGTTOU); 250 | ttymodes_sett(&tmraw,fdtty); 251 | sig_block(SIGTTOU); 252 | ttymodes_getw(&tminit,fdtty); 253 | ttymodes_setw(&tminit,5); 254 | } 255 | kill(child,SIGCONT); 256 | } 257 | } 258 | } 259 | 260 | close(4); 261 | r = wait_pid(&wstat,child); 262 | if (flagtty) 263 | ttymodes_set(&tminit,fdtty); 264 | if (r == -1) { 265 | substdio_putsflush(subfderr,"ptyio: fatal: child disappeared!\n"); 266 | _exit(111); 267 | } 268 | if (wait_crashed(wstat)) { 269 | substdio_putsflush(subfderr,"ptyio: fatal: child crashed\n"); 270 | _exit(111); 271 | } 272 | _exit(wait_exitcode(wstat)); 273 | } 274 | -------------------------------------------------------------------------------- /ptyio.do: -------------------------------------------------------------------------------- 1 | objs="ttyctrl.o ttymodes.o fdcopy.o libwait.a libsig.a libenv.a libgetopt.a libsubstdio.a liberror.a libstr.a" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /ptyrun.1: -------------------------------------------------------------------------------- 1 | .TH ptyrun 1 2 | .SH NAME 3 | ptyrun \- wrap a pty around a program 4 | .SH SYNOPSIS 5 | .B ptyrun 6 | .I subprogram 7 | [ 8 | .I args ... 9 | ] 10 | .SH DESCRIPTION 11 | .B ptyrun 12 | obtains a new pty and runs 13 | .I subprogram 14 | under it, 15 | transparently forwarding input and output. 16 | .B ptyrun 17 | initializes the pty to sane mode. 18 | 19 | Descriptors 0, 1, and 2 20 | of 21 | .I subprogram 22 | are redirected to the pty; 23 | its controlling terminal is set to the pty; 24 | descriptor 3 is redirected to /dev/tty; 25 | environment variable TTY gives the name of the pty. 26 | 27 | When 28 | .I subprogram 29 | exits, 30 | .B ptyrun 31 | exits with the same exit code. 32 | If 33 | .I subprogram 34 | stops, 35 | .B ptyrun 36 | immediately sends SIGCONT to 37 | .IR subprogram 's 38 | process group. 39 | 40 | .B ptyrun 41 | is a synonym for 42 | .B ptyget 43 | .B ptyio 44 | .BR ptyspawn . 45 | Any 46 | .B ptyspawn 47 | options may be used with 48 | .BR ptyrun . 49 | .SH "SEE ALSO" 50 | ptybandage(1), 51 | ptyget(8), 52 | ptyio(8), 53 | ptyspawn(8) 54 | -------------------------------------------------------------------------------- /ptyrun.do: -------------------------------------------------------------------------------- 1 | dependon warn-auto.sh $1.sh home 2 | cat warn-auto.sh $1.sh | sed s}HOME}`./home`}g 3 | chmod 755 $3 4 | formake cat warn-auto.sh $1.sh '| sed s}HOME}`./home`}g >' $1 5 | formake chmod 755 $1 6 | -------------------------------------------------------------------------------- /ptyrun.sh: -------------------------------------------------------------------------------- 1 | exec HOME/bin/ptyget HOME/bin/ptyio HOME/bin/ptyspawn ${1+"$@"} 2 | -------------------------------------------------------------------------------- /ptyspawn.8: -------------------------------------------------------------------------------- 1 | .TH ptyspawn 8 2 | .SH NAME 3 | ptyspawn \- run a program under a pty 4 | .SH SYNOPSIS 5 | .B ptyspawn 6 | [ 7 | .B \-23x 8 | ] 9 | .I subprogram 10 | [ 11 | .I args ... 12 | ] 13 | .SH DESCRIPTION 14 | .B ptyspawn 15 | runs 16 | .I subprogram 17 | under a pty. 18 | .B ptyspawn 19 | will exit 20 | when 21 | .I subprogram 22 | exits, 23 | with the same exit code. 24 | 25 | .B ptyspawn 26 | must be invoked with descriptor 4 pointing to the pty master, 27 | descriptor 5 pointing to the pty slave, 28 | and environment variable TTY 29 | giving the name of the pty slave. 30 | On POSIX systems, 31 | .B ptyspawn 32 | must not be a process group leader. 33 | 34 | If 35 | .I subprogram 36 | stops, 37 | .B ptyspawn 38 | writes its stop signal, as a single byte, to descriptor 9, 39 | if descriptor 9 is open. 40 | When 41 | .B ptyspawn 42 | receives a 43 | SIGCONT 44 | signal, it sends 45 | SIGCONT 46 | to 47 | .IR subprogram 's 48 | process group. 49 | 50 | .I subprogram 51 | will have descriptors 0, 1, and 2 pointing to the pty slave. 52 | Its controlling tty will be that pty. 53 | Descriptor 3 will point to 54 | .BR /dev/tty . 55 | Descriptors 4, 5, and 9 will be closed. 56 | .I subprogram 57 | will be a process group leader. 58 | .SH OPTIONS 59 | .TP 60 | .B \-2 61 | Preserve descriptor 2 in 62 | .IR subprogram ; 63 | do not replace it with the pty slave. 64 | .TP 65 | .B \-3 66 | Preserve descriptor 3 in 67 | .IR subprogram ; 68 | do not replace it with /dev/tty. 69 | .TP 70 | .B \-x 71 | Reserve the pty for exclusive use. 72 | This prevents all attempts to open the pty, 73 | even through /dev/tty. 74 | .SH "SEE ALSO" 75 | ptyget(8) 76 | -------------------------------------------------------------------------------- /ptyspawn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "fdcopy.h" 6 | #include "sgetopt.h" 7 | #include "exit.h" 8 | #include "fork.h" 9 | #include "wait.h" 10 | #include "env.h" 11 | #include "error.h" 12 | #include "readwrite.h" 13 | #include "strerr.h" 14 | #include "sig.h" 15 | #include 16 | #include /* for TIOCEXCL on Sun */ 17 | 18 | int child; 19 | 20 | void sigcont() 21 | { 22 | /*XXX: use killpg instead? */ 23 | kill(-child,SIGCONT); 24 | } 25 | 26 | #define FATAL "ptyspawn: fatal: " 27 | #define WARNING "ptyspawn: warning: " 28 | 29 | int flagpreserve2 = 0; 30 | int flagpreserve3 = 0; 31 | int flagexcl = 0; 32 | 33 | void main(argc,argv) 34 | int argc; 35 | char **argv; 36 | { 37 | int r; 38 | int wstat; 39 | char *ttyname; 40 | char ch; 41 | int opt; 42 | 43 | while ((opt = getopt(argc,argv,"23x")) != opteof) 44 | switch(opt) { 45 | case '2': flagpreserve2 = 1; break; 46 | case '3': flagpreserve3 = 1; break; 47 | case 'x': flagexcl = 1; break; 48 | case '?': 49 | default: 50 | _exit(1); 51 | } 52 | argc -= optind; 53 | argv += optind; 54 | if (!*argv) 55 | strerr_die1x(1,"ptyspawn: usage: ptyspawn subprogram [ args ... ]"); 56 | 57 | sig_pipeignore(); 58 | 59 | ttyname = env_get("TTY"); 60 | if (!ttyname) 61 | strerr_die2x(1,FATAL,"TTY not set"); 62 | 63 | if (setsid() == -1) 64 | strerr_warn2(WARNING,"unable to setsid",0); 65 | 66 | close(0); 67 | if (open(ttyname,O_RDONLY) != 0) 68 | strerr_die4sys(111,FATAL,"unable to open ",ttyname," for reading: "); 69 | close(1); 70 | if (open(ttyname,O_WRONLY) != 1) 71 | strerr_die4sys(111,FATAL,"unable to open ",ttyname," for writing: "); 72 | if (!flagpreserve2) { 73 | close(2); 74 | if (open(ttyname,O_RDWR) != 2) 75 | _exit(111); 76 | /* now errors go to pty */ 77 | } 78 | 79 | #ifdef TIOCSCTTY /* otherwise, the fd 0 open automatically did it */ 80 | if (ioctl(5,TIOCSCTTY,(char *) 0) == -1) 81 | strerr_warn2(WARNING,"unable to sctty",0); 82 | #endif 83 | 84 | if (!flagpreserve3) { 85 | close(3); 86 | if (open("/dev/tty",O_RDWR) != 3) 87 | strerr_die2sys(111,FATAL,"unable to open /dev/tty: "); 88 | } 89 | 90 | if (flagexcl) 91 | if (ioctl(5,TIOCEXCL,(char *) 0) == -1) 92 | strerr_warn2(WARNING,"unable to set exclusive use",0); 93 | close(5); 94 | close(4); 95 | 96 | switch(child = vfork()) { 97 | case -1: 98 | strerr_die2sys(111,FATAL,"unable to fork: "); 99 | case 0: 100 | close(9); 101 | setpgid(getpid(),getpid()); 102 | sig_block(SIGTTOU); 103 | tcsetpgrp(1,getpid()); 104 | sig_unblock(SIGTTOU); 105 | sig_pipedefault(); 106 | execvp(*argv,argv); 107 | if (error_temp(errno)) 108 | strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); 109 | strerr_die4sys(1,FATAL,"unable to run ",*argv,": "); 110 | } 111 | 112 | sig_contcatch(sigcont); 113 | 114 | for (;;) { 115 | r = wait_stop(&wstat); 116 | if ((r == -1) && (errno == error_intr)) continue; 117 | if (r == -1) 118 | strerr_die2sys(111,FATAL,"impossible wait failure: "); 119 | if (r != child) continue; 120 | if (!wait_stopped(wstat)) { 121 | if (wait_crashed(wstat)) 122 | strerr_die2x(111,FATAL,"child crashed"); 123 | _exit(wait_exitcode(wstat)); 124 | } 125 | 126 | ch = wait_stopsig(wstat); 127 | do 128 | r = write(9,&ch,1); 129 | while ((r == -1) && (errno == error_intr)); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /ptyspawn.do: -------------------------------------------------------------------------------- 1 | objs="libwait.a libsig.a libenv.a libstrerr.a libgetopt.a libsubstdio.a liberror.a libstr.a" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /readwrite.h: -------------------------------------------------------------------------------- 1 | #ifndef READWRITE_H 2 | #define READWRITE_H 3 | 4 | extern int read(); 5 | extern int write(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /select.h.do: -------------------------------------------------------------------------------- 1 | dependon compile trysysel.c select.h1 select.h2 2 | ./compile trysysel.c >/dev/null 2>&1 && cat select.h2 || cat select.h1 3 | rm -f trysysel.o 4 | formake '( ./compile trysysel.c >/dev/null 2>&1 \' 5 | formake '&& cat select.h2 || cat select.h1 ) > select.h' 6 | formake 'rm -f trysysel.o trysysel' 7 | -------------------------------------------------------------------------------- /select.h1: -------------------------------------------------------------------------------- 1 | #ifndef SELECT_H 2 | #define SELECT_H 3 | 4 | #include 5 | #include 6 | extern int select(); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /select.h2: -------------------------------------------------------------------------------- 1 | #ifndef SELECT_H 2 | #define SELECT_H 3 | 4 | #include 5 | #include 6 | #include 7 | extern int select(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /setup.do: -------------------------------------------------------------------------------- 1 | dependon it home ptyget-setup 2 | ./ptyget-setup 3 | formake ./ptyget-setup 4 | -------------------------------------------------------------------------------- /sgetopt.3: -------------------------------------------------------------------------------- 1 | .TH sgetopt 3 2 | .SH NAME 3 | sgetopt \- get option character from command line 4 | .SH SYNTAX 5 | .B #include 6 | .SH DESCRIPTION 7 | The 8 | .B sgetopt 9 | library is just like the 10 | .B getopt 11 | library, 12 | except that it prints errors using 13 | .B substdio 14 | rather than 15 | .BR stdio . 16 | 17 | See 18 | .B getopt(3) 19 | for interface details. 20 | .SH VERSION 21 | sgetopt version 1.9, 931201. 22 | .SH AUTHOR 23 | Placed into the public domain by Daniel J. Bernstein. 24 | .SH "SEE ALSO" 25 | getopt(3), 26 | subgetopt(3), 27 | subfd(3), 28 | substdio(3) 29 | -------------------------------------------------------------------------------- /sgetopt.c: -------------------------------------------------------------------------------- 1 | /* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer 2 | Daniel J. Bernstein, djb@silverton.berkeley.edu. 3 | Depends on subgetopt.h, substdio.h, subfd.h. 4 | No system requirements. 5 | 931201: Baseline. 6 | No known patent problems. 7 | 8 | Documentation in sgetopt.3. 9 | */ 10 | 11 | #include "substdio.h" 12 | #include "subfd.h" 13 | #define SGETOPTNOSHORT 14 | #include "sgetopt.h" 15 | #define SUBGETOPTNOSHORT 16 | #include "subgetopt.h" 17 | 18 | #define getopt sgetoptmine 19 | #define optind subgetoptind 20 | #define opterr sgetopterr 21 | #define optproblem subgetoptproblem 22 | #define optprogname sgetoptprogname 23 | 24 | int opterr = 1; 25 | char *optprogname = 0; 26 | 27 | int getopt(argc,argv,opts) 28 | int argc; 29 | char **argv; 30 | char *opts; 31 | { 32 | int c; 33 | char *s; 34 | 35 | if (!optprogname) 36 | { 37 | optprogname = *argv; 38 | if (!optprogname) /* oh boy */ 39 | optprogname = ""; 40 | for (s = optprogname;*s;++s) 41 | if (*s == '/') 42 | optprogname = s + 1; 43 | } 44 | c = subgetopt(argc,argv,opts); 45 | if (opterr) 46 | if (c == '?') 47 | { 48 | char chp[2]; chp[0] = optproblem; chp[1] = '\n'; 49 | substdio_putsflush(subfderr,optprogname); 50 | if (argv[optind] && (optind < argc)) 51 | substdio_putsflush(subfderr,": illegal option -- "); 52 | else 53 | substdio_putsflush(subfderr,": option requires an argument -- "); 54 | substdio_putflush(subfderr,chp,2); 55 | } 56 | return c; 57 | } 58 | -------------------------------------------------------------------------------- /sgetopt.h: -------------------------------------------------------------------------------- 1 | #ifndef SGETOPT_H 2 | #define SGETOPT_H 3 | 4 | #ifndef SGETOPTNOSHORT 5 | #define getopt sgetoptmine 6 | #define optarg subgetoptarg 7 | #define optind subgetoptind 8 | #define optpos subgetoptpos 9 | #define opterr sgetopterr 10 | #define optproblem subgetoptproblem 11 | #define optprogname sgetoptprogname 12 | #define opteof subgetoptdone 13 | #endif 14 | 15 | #include "subgetopt.h" 16 | 17 | extern int sgetoptmine(); 18 | extern int sgetopterr; 19 | extern char *sgetoptprogname; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /sig.h: -------------------------------------------------------------------------------- 1 | #ifndef SIG_H 2 | #define SIG_H 3 | 4 | extern void sig_catch(); 5 | extern void sig_block(); 6 | extern void sig_unblock(); 7 | 8 | extern void sig_dfl(); 9 | 10 | extern void sig_pipeignore(); 11 | extern void sig_pipedefault(); 12 | 13 | extern void sig_contblock(); 14 | extern void sig_contunblock(); 15 | extern void sig_contcatch(); 16 | extern void sig_contdefault(); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /sig_block.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sig.h" 3 | #include "hassgprm.h" 4 | 5 | void sig_block(sig) 6 | int sig; 7 | { 8 | #ifdef HASSIGPROCMASK 9 | sigset_t ss; 10 | sigemptyset(&ss); 11 | sigaddset(&ss,sig); 12 | sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); 13 | #else 14 | sigblock(1 << (sig - 1)); 15 | #endif 16 | } 17 | 18 | void sig_unblock(sig) 19 | int sig; 20 | { 21 | #ifdef HASSIGPROCMASK 22 | sigset_t ss; 23 | sigemptyset(&ss); 24 | sigaddset(&ss,sig); 25 | sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); 26 | #else 27 | sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); 28 | #endif 29 | } 30 | -------------------------------------------------------------------------------- /sig_catch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sig.h" 3 | #include "hassgact.h" 4 | 5 | void sig_catch(sig,f) 6 | int sig; 7 | void (*f)(); 8 | { 9 | #ifdef HASSIGACTION 10 | struct sigaction sa; 11 | sa.sa_handler = f; 12 | sa.sa_flags = 0; 13 | sigemptyset(&sa.sa_mask); 14 | sigaction(sig,&sa,(struct sigaction *) 0); 15 | #else 16 | signal(sig,f); /* won't work under System V, even nowadays---dorks */ 17 | #endif 18 | } 19 | -------------------------------------------------------------------------------- /sig_cont.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sig.h" 3 | 4 | void sig_contblock() { sig_block(SIGCONT); } 5 | void sig_contunblock() { sig_unblock(SIGCONT); } 6 | void sig_contcatch(f) void (*f)(); { sig_catch(SIGCONT,f); } 7 | void sig_contdefault() { sig_catch(SIGCONT,SIG_DFL); } 8 | -------------------------------------------------------------------------------- /sig_dfl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sig.h" 3 | #include "hassgact.h" 4 | #include "hassgprm.h" 5 | 6 | /* tnx to Chris Torek for some improvements in previous versions */ 7 | 8 | static int flagcont; 9 | 10 | static void sigcont() { flagcont = 1; } 11 | 12 | void sig_dfl(sig) 13 | int sig; 14 | { 15 | #ifdef HASSIGPROCMASK 16 | sigset_t ssorig; 17 | sigset_t ssnew; 18 | #else 19 | int maskorig; 20 | int masknew; 21 | #endif 22 | #ifdef HASSIGACTION 23 | struct sigaction saorig; 24 | struct sigaction sanew; 25 | #else 26 | struct sigvec svorig; 27 | struct sigvec svnew; 28 | #endif 29 | 30 | if (sig == SIGCONT) return; 31 | 32 | #ifdef HASSIGPROCMASK 33 | sigfillset(&ssnew); 34 | sigprocmask(SIG_SETMASK,&ssnew,&ssorig); 35 | #else 36 | masknew = ~0; 37 | maskorig = sigsetmask(masknew); 38 | #endif 39 | 40 | #ifdef HASSIGACTION 41 | sanew.sa_handler = SIG_DFL; 42 | sanew.sa_flags = 0; 43 | sigemptyset(&sanew.sa_mask); 44 | sigaction(sig,&sanew,&saorig); 45 | sanew.sa_handler = sigcont; 46 | sigaction(SIGCONT,&sanew,(struct sigaction *) 0); 47 | #else 48 | svnew.sv_handler = SIG_DFL; 49 | svnew.sv_flags = 0; 50 | svnew.sv_mask = 0; 51 | sigvec(sig,&svnew,&svorig); 52 | svnew.sv_handler = sigcont; 53 | sigvec(SIGCONT,&svnew,(struct sigvec *) 0); 54 | #endif 55 | 56 | flagcont = 0; 57 | if (kill(getpid(),sig) == 0) { 58 | #ifdef HASSIGPROCMASK 59 | sigdelset(&ssnew,sig); 60 | sigdelset(&ssnew,SIGCONT); 61 | while (!flagcont) 62 | sigsuspend(&ssnew); 63 | #else 64 | masknew &= ~(1 << (sig - 1)); 65 | masknew &= ~(1 << (SIGCONT - 1)); 66 | while (!flagcont) 67 | sigpause(masknew); 68 | #endif 69 | } 70 | 71 | #ifdef HASSIGACTION 72 | sigaction(sig,&saorig,(struct sigaction *) 0); 73 | #else 74 | sigvec(sig,&svorig,(struct sigvec *) 0); 75 | #endif 76 | 77 | #ifdef HASSIGPROCMASK 78 | sigprocmask(SIG_SETMASK,&ssorig,(sigset_t *) 0); 79 | #else 80 | sigsetmask(maskorig); 81 | #endif 82 | } 83 | -------------------------------------------------------------------------------- /sig_pipe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sig.h" 3 | 4 | void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); } 5 | void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); } 6 | -------------------------------------------------------------------------------- /str.h: -------------------------------------------------------------------------------- 1 | #ifndef STR_H 2 | #define STR_H 3 | 4 | extern unsigned int str_copy(); 5 | extern int str_diff(); 6 | extern int str_diffn(); 7 | extern unsigned int str_len(); 8 | extern unsigned int str_chr(); 9 | extern unsigned int str_rchr(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /str_chr.c: -------------------------------------------------------------------------------- 1 | #include "str.h" 2 | 3 | unsigned int str_chr(s,c) 4 | register char *s; 5 | int c; 6 | { 7 | register char ch; 8 | register char *t; 9 | 10 | ch = c; 11 | t = s; 12 | for (;;) 13 | { 14 | if (!*t) break; if (*t == ch) break; ++t; 15 | if (!*t) break; if (*t == ch) break; ++t; 16 | if (!*t) break; if (*t == ch) break; ++t; 17 | if (!*t) break; if (*t == ch) break; ++t; 18 | } 19 | return t - s; 20 | } 21 | -------------------------------------------------------------------------------- /str_cpy.c: -------------------------------------------------------------------------------- 1 | #include "str.h" 2 | 3 | unsigned int str_copy(s,t) 4 | register char *s; 5 | register char *t; 6 | { 7 | register int len; 8 | 9 | len = 0; 10 | for (;;) 11 | { 12 | if (!(*s = *t)) return len; ++s; ++t; ++len; 13 | if (!(*s = *t)) return len; ++s; ++t; ++len; 14 | if (!(*s = *t)) return len; ++s; ++t; ++len; 15 | if (!(*s = *t)) return len; ++s; ++t; ++len; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /str_diff.c: -------------------------------------------------------------------------------- 1 | #include "str.h" 2 | 3 | int str_diff(s,t) 4 | register char *s; 5 | register char *t; 6 | { 7 | register char x; 8 | 9 | for (;;) 10 | { 11 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 12 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 13 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 14 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 15 | } 16 | return ((int)(unsigned int)(unsigned char) x) 17 | - ((int)(unsigned int)(unsigned char) *t); 18 | } 19 | -------------------------------------------------------------------------------- /str_diffn.c: -------------------------------------------------------------------------------- 1 | #include "str.h" 2 | 3 | int str_diffn(s,t,len) 4 | register char *s; 5 | register char *t; 6 | unsigned int len; 7 | { 8 | register char x; 9 | 10 | for (;;) 11 | { 12 | if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 13 | if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 14 | if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 15 | if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; 16 | } 17 | return ((int)(unsigned int)(unsigned char) x) 18 | - ((int)(unsigned int)(unsigned char) *t); 19 | } 20 | -------------------------------------------------------------------------------- /str_len.c: -------------------------------------------------------------------------------- 1 | #include "str.h" 2 | 3 | unsigned int str_len(s) 4 | register char *s; 5 | { 6 | register char *t; 7 | 8 | t = s; 9 | for (;;) 10 | { 11 | if (!*t) return t - s; ++t; 12 | if (!*t) return t - s; ++t; 13 | if (!*t) return t - s; ++t; 14 | if (!*t) return t - s; ++t; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /str_rchr.c: -------------------------------------------------------------------------------- 1 | #include "str.h" 2 | 3 | unsigned int str_rchr(s,c) 4 | register char *s; 5 | int c; 6 | { 7 | register char ch; 8 | register char *t; 9 | register char *u; 10 | 11 | ch = c; 12 | t = s; 13 | u = 0; 14 | for (;;) 15 | { 16 | if (!*t) break; if (*t == ch) u = t; ++t; 17 | if (!*t) break; if (*t == ch) u = t; ++t; 18 | if (!*t) break; if (*t == ch) u = t; ++t; 19 | if (!*t) break; if (*t == ch) u = t; ++t; 20 | } 21 | if (!u) u = t; 22 | return u - s; 23 | } 24 | -------------------------------------------------------------------------------- /stralloc.h: -------------------------------------------------------------------------------- 1 | #ifndef STRALLOC_H 2 | #define STRALLOC_H 3 | 4 | #include "gen_alloc.h" 5 | 6 | GEN_ALLOC_typedef(stralloc,char,s,len,a) 7 | 8 | extern int stralloc_ready(); 9 | extern int stralloc_readyplus(); 10 | extern int stralloc_copy(); 11 | extern int stralloc_cat(); 12 | extern int stralloc_copys(); 13 | extern int stralloc_cats(); 14 | extern int stralloc_copyb(); 15 | extern int stralloc_catb(); 16 | extern int stralloc_append(); /* beware: this takes a pointer to 1 char */ 17 | 18 | #define stralloc_0(sa) stralloc_append(sa,"") 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /stralloc_cat.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | #include "stralloc.h" 3 | 4 | int stralloc_cat(sato,safrom) 5 | stralloc *sato; 6 | stralloc *safrom; 7 | { 8 | int i; 9 | if (!sato->s) return stralloc_copy(sato,safrom); 10 | i = safrom->len; 11 | if (!stralloc_readyplus(sato,i)) return 0; 12 | byte_copy(sato->s + sato->len,i,safrom->s); 13 | sato->len += i; 14 | return 1; 15 | } 16 | -------------------------------------------------------------------------------- /stralloc_catb.c: -------------------------------------------------------------------------------- 1 | #include "stralloc.h" 2 | #include "byte.h" 3 | 4 | int stralloc_catb(sa,s,n) 5 | stralloc *sa; 6 | char *s; 7 | unsigned int n; 8 | { 9 | if (!sa->s) return stralloc_copyb(sa,s,n); 10 | if (!stralloc_readyplus(sa,n)) return 0; 11 | byte_copy(sa->s + sa->len,n,s); 12 | sa->len += n; 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /stralloc_cats.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | #include "str.h" 3 | #include "stralloc.h" 4 | 5 | int stralloc_cats(sa,s) 6 | stralloc *sa; 7 | char *s; 8 | { 9 | int i; 10 | if (!sa->s) return stralloc_copys(sa,s); 11 | i = str_len(s); 12 | if (!stralloc_readyplus(sa,i)) return 0; 13 | byte_copy(sa->s + sa->len,i,s); 14 | sa->len += i; 15 | return 1; 16 | } 17 | -------------------------------------------------------------------------------- /stralloc_copy.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | #include "stralloc.h" 3 | 4 | int stralloc_copy(sato,safrom) 5 | stralloc *sato; 6 | stralloc *safrom; 7 | { 8 | int i; 9 | i = safrom->len; 10 | if (!stralloc_ready(sato,i)) return 0; 11 | byte_copy(sato->s,i,safrom->s); 12 | sato->len = i; 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /stralloc_eady.c: -------------------------------------------------------------------------------- 1 | #include "alloc.h" 2 | #include "stralloc.h" 3 | #include "gen_allocdefs.h" 4 | 5 | GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) 6 | GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) 7 | -------------------------------------------------------------------------------- /stralloc_opyb.c: -------------------------------------------------------------------------------- 1 | #include "stralloc.h" 2 | #include "byte.h" 3 | 4 | int stralloc_copyb(sa,s,n) 5 | stralloc *sa; 6 | char *s; 7 | unsigned int n; 8 | { 9 | if (!stralloc_ready(sa,n)) return 0; 10 | byte_copy(sa->s,n,s); 11 | sa->len = n; 12 | return 1; 13 | } 14 | -------------------------------------------------------------------------------- /stralloc_opys.c: -------------------------------------------------------------------------------- 1 | #include "byte.h" 2 | #include "str.h" 3 | #include "stralloc.h" 4 | 5 | int stralloc_copys(sa,s) 6 | stralloc *sa; 7 | char *s; 8 | { 9 | int i; 10 | i = str_len(s); 11 | if (!stralloc_ready(sa,i + 1)) return 0; 12 | byte_copy(sa->s,i + 1,s); 13 | sa->len = i; 14 | sa->s[i] = 'Z'; /* ``offensive programming'' */ 15 | return 1; 16 | } 17 | -------------------------------------------------------------------------------- /stralloc_pend.c: -------------------------------------------------------------------------------- 1 | #include "alloc.h" 2 | #include "stralloc.h" 3 | #include "gen_allocdefs.h" 4 | 5 | GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) 6 | -------------------------------------------------------------------------------- /strerr.c: -------------------------------------------------------------------------------- 1 | #include "stralloc.h" 2 | #include "strerr.h" 3 | 4 | static stralloc sa = {0}; 5 | 6 | char *strerr(se) 7 | struct strerr *se; 8 | { 9 | strerr_sysinit(); 10 | 11 | if (!stralloc_copys(&sa,"")) return "out of memory"; 12 | 13 | while(se) 14 | { 15 | if (se->x) if (!stralloc_cats(&sa,se->x)) return "out of memory"; 16 | if (se->y) if (!stralloc_cats(&sa,se->y)) return "out of memory"; 17 | if (se->z) if (!stralloc_cats(&sa,se->z)) return "out of memory"; 18 | se = se->who; 19 | } 20 | 21 | if (!stralloc_0(&sa)) return "out of memory"; 22 | return sa.s; 23 | } 24 | -------------------------------------------------------------------------------- /strerr.h: -------------------------------------------------------------------------------- 1 | #ifndef STRERR_H 2 | #define STRERR_H 3 | 4 | struct strerr 5 | { 6 | struct strerr *who; 7 | char *x; 8 | char *y; 9 | char *z; 10 | } 11 | ; 12 | 13 | extern struct strerr strerr_sys; 14 | extern void strerr_sysinit(); 15 | 16 | extern char *strerr(); 17 | extern void strerr_warn(); 18 | extern void strerr_die(); 19 | 20 | #define STRERR(r,se,a) \ 21 | { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } 22 | 23 | #define STRERR_SYS(r,se,a) \ 24 | { se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } 25 | #define STRERR_SYS3(r,se,a,b,c) \ 26 | { se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } 27 | 28 | #define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ 29 | strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) 30 | #define strerr_warn5(x1,x2,x3,x4,x5,se) \ 31 | strerr_warn((x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) 32 | #define strerr_warn4(x1,x2,x3,x4,se) \ 33 | strerr_warn((x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) 34 | #define strerr_warn3(x1,x2,x3,se) \ 35 | strerr_warn((x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) 36 | #define strerr_warn2(x1,x2,se) \ 37 | strerr_warn((x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) 38 | #define strerr_warn1(x1,se) \ 39 | strerr_warn((x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) 40 | 41 | #define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ 42 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) 43 | #define strerr_die5(e,x1,x2,x3,x4,x5,se) \ 44 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) 45 | #define strerr_die4(e,x1,x2,x3,x4,se) \ 46 | strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) 47 | #define strerr_die3(e,x1,x2,x3,se) \ 48 | strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) 49 | #define strerr_die2(e,x1,x2,se) \ 50 | strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) 51 | #define strerr_die1(e,x1,se) \ 52 | strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) 53 | 54 | #define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ 55 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) 56 | #define strerr_die5sys(e,x1,x2,x3,x4,x5) \ 57 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,&strerr_sys) 58 | #define strerr_die4sys(e,x1,x2,x3,x4) \ 59 | strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,&strerr_sys) 60 | #define strerr_die3sys(e,x1,x2,x3) \ 61 | strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,&strerr_sys) 62 | #define strerr_die2sys(e,x1,x2) \ 63 | strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) 64 | #define strerr_die1sys(e,x1) \ 65 | strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) 66 | 67 | #define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ 68 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) 0) 69 | #define strerr_die5x(e,x1,x2,x3,x4,x5) \ 70 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) 0) 71 | #define strerr_die4x(e,x1,x2,x3,x4) \ 72 | strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) 0) 73 | #define strerr_die3x(e,x1,x2,x3) \ 74 | strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) 75 | #define strerr_die2x(e,x1,x2) \ 76 | strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) 77 | #define strerr_die1x(e,x1) \ 78 | strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /strerr_die.c: -------------------------------------------------------------------------------- 1 | #include "substdio.h" 2 | #include "subfd.h" 3 | #include "exit.h" 4 | #include "strerr.h" 5 | 6 | void strerr_warn(x1,x2,x3,x4,x5,x6,se) 7 | char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; 8 | struct strerr *se; 9 | { 10 | strerr_sysinit(); 11 | 12 | if (x1) substdio_puts(subfderr,x1); 13 | if (x2) substdio_puts(subfderr,x2); 14 | if (x3) substdio_puts(subfderr,x3); 15 | if (x4) substdio_puts(subfderr,x4); 16 | if (x5) substdio_puts(subfderr,x5); 17 | if (x6) substdio_puts(subfderr,x6); 18 | 19 | while(se) 20 | { 21 | if (se->x) substdio_puts(subfderr,se->x); 22 | if (se->y) substdio_puts(subfderr,se->y); 23 | if (se->z) substdio_puts(subfderr,se->z); 24 | se = se->who; 25 | } 26 | 27 | substdio_puts(subfderr,"\n"); 28 | substdio_flush(subfderr); 29 | } 30 | 31 | void strerr_die(e,x1,x2,x3,x4,x5,x6,se) 32 | int e; 33 | char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; 34 | struct strerr *se; 35 | { 36 | strerr_warn(x1,x2,x3,x4,x5,x6,se); 37 | _exit(e); 38 | } 39 | -------------------------------------------------------------------------------- /strerr_sys.c: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | #include "strerr.h" 3 | 4 | struct strerr strerr_sys; 5 | 6 | void strerr_sysinit() 7 | { 8 | strerr_sys.who = 0; 9 | strerr_sys.x = error_str(errno); 10 | strerr_sys.y = ""; 11 | strerr_sys.z = ""; 12 | } 13 | -------------------------------------------------------------------------------- /subfd.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBFD_H 2 | #define SUBFD_H 3 | 4 | extern struct substdio *subfdin; 5 | extern struct substdio *subfdout; 6 | extern struct substdio *subfderr; 7 | 8 | extern int subfd_read(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /subfderr.c: -------------------------------------------------------------------------------- 1 | #include "readwrite.h" 2 | #include "substdio.h" 3 | #include "subfd.h" 4 | 5 | char subfd_errbuf[32]; 6 | static struct substdio err = SUBSTDIO_FDBUF(write,2,subfd_errbuf,32); 7 | struct substdio *subfderr = &err; 8 | -------------------------------------------------------------------------------- /subfdin.c: -------------------------------------------------------------------------------- 1 | #include "readwrite.h" 2 | #include "substdio.h" 3 | #include "subfd.h" 4 | 5 | int subfd_read(fd,buf,len) int fd; char *buf; int len; 6 | { 7 | if (substdio_flush(subfdout) == -1) return -1; 8 | return read(fd,buf,len); 9 | } 10 | 11 | char subfd_inbuf[SUBSTDIO_INSIZE]; 12 | static struct substdio in = 13 | SUBSTDIO_FDBUF(subfd_read,0,subfd_inbuf,SUBSTDIO_INSIZE); 14 | struct substdio *subfdin = ∈ 15 | -------------------------------------------------------------------------------- /subfdout.c: -------------------------------------------------------------------------------- 1 | #include "readwrite.h" 2 | #include "substdio.h" 3 | #include "subfd.h" 4 | 5 | char subfd_outbuf[SUBSTDIO_OUTSIZE]; 6 | static struct substdio out = 7 | SUBSTDIO_FDBUF(write,1,subfd_outbuf,SUBSTDIO_OUTSIZE); 8 | struct substdio *subfdout = &out; 9 | -------------------------------------------------------------------------------- /subgetopt.3: -------------------------------------------------------------------------------- 1 | .TH subgetopt 3 2 | .SH NAME 3 | subgetopt \- get option character from command line 4 | .SH SYNTAX 5 | .B #include 6 | 7 | char *\fBsgoptarg\fP; 8 | .br 9 | int \fBsgoptind\fP; 10 | .br 11 | int \fBsgoptpos\fP; 12 | .br 13 | int \fBsgoptdone\fP; 14 | .br 15 | int \fBsgoptproblem\fP; 16 | 17 | int \fBsgopt(\fP\fIargc,argv,opts\fR\fB)\fP; 18 | 19 | int \fIargc\fR; 20 | .br 21 | char **\fIargv\fR; 22 | .br 23 | char *\fIopts\fR; 24 | .SH DESCRIPTION 25 | .B sgopt 26 | returns the next valid command-line option character 27 | from 28 | .IR argv . 29 | 30 | Valid option characters are listed in the 31 | .I opts 32 | string. 33 | .I opts 34 | may be empty. 35 | A character in 36 | .I opts 37 | may be followed by a colon, 38 | in which case it 39 | takes an 40 | .I option argument\fR. 41 | Avoid using the characters ?, :, and \- as option characters. 42 | 43 | Below 44 | .I option argument 45 | is abbreviated 46 | as 47 | .I optarg 48 | and 49 | .I command-line argument 50 | is abbreviated as 51 | .IR cmdarg . 52 | 53 | Options are listed in cmdargs which begin with 54 | a minus sign. 55 | Several options which do not take optargs may be combined 56 | into one cmdarg. 57 | 58 | An option which takes an optarg may be handled in two ways. 59 | If it appears at the very end of a cmdarg, 60 | then the entire next cmdarg is the optarg. 61 | But if there are any characters in the cmdarg 62 | after the option character, 63 | then those characters form the optarg. 64 | The optarg is returned in 65 | .BR sgoptarg . 66 | Next time 67 | .B sgopt 68 | looks at the cmdarg which follows the optarg. 69 | 70 | If a cmdarg does not begin with a hyphen, 71 | or if it is a lone hyphen not followed by any characters, 72 | or if it begins with two hyphens, 73 | then it terminates option processing, 74 | and 75 | .B sgopt 76 | returns an appropriate code. 77 | If there are two hyphens, 78 | .B sgopt 79 | will advance attention to the next cmdarg, 80 | so it can be called again to read further options. 81 | .SH "PROPER USAGE" 82 | .B sgoptproblem 83 | should be used only when 84 | .B sgopt 85 | returns ?. 86 | .B sgoptind 87 | and 88 | .B sgoptpos 89 | are defined all the time. 90 | .B sgoptarg 91 | is defined all the time; 92 | it is null unless 93 | .B sgopt 94 | has just returned an option with optarg. 95 | 96 | .B sgopt 97 | is typically used as follows. 98 | 99 | .EX 100 | #include 101 | 102 | main(argc,argv) int argc; char **argv; { int opt; 103 | 104 | while ((opt = sgopt(argc,argv,"a:s")) != sgoptdone) 105 | .br 106 | switch(opt) { 107 | .br 108 | case 'a': 109 | .br 110 | printf("opt a with optarg %s\\n",sgoptarg); break; 111 | .br 112 | case 's': 113 | .br 114 | printf("opt s with no optarg\\n"); break; 115 | .br 116 | case '?': 117 | .br 118 | if (argv[sgoptind] && (sgoptind < argc)) 119 | .br 120 | printf("illegal opt %c\\n",sgoptproblem); 121 | .br 122 | else 123 | .br 124 | printf("missing arg, opt %c\\n",sgoptproblem); 125 | .br 126 | exit(1); 127 | .br 128 | } 129 | 130 | argv += sgoptind; 131 | .br 132 | while (*argv) printf("argument %s\\n",*argv++); 133 | .br 134 | exit(0); 135 | .br 136 | } 137 | .EE 138 | 139 | The end of the command line is 140 | marked by either 141 | .IR argc , 142 | or a null pointer in 143 | .IR argv , 144 | whichever comes first. 145 | Normally 146 | these two markers coincide, 147 | so it is redundant 148 | to test for 149 | both 150 | .I argv\fB[sgoptind] 151 | and 152 | .B sgoptind < \fIargc\fR. 153 | The above code shows both tests as an illustration. 154 | 155 | .B Multiple option sets: 156 | One useful technique is to call 157 | .B sgopt 158 | with a primary 159 | .I opts 160 | until it returns EOF, 161 | then call 162 | .B sgopt 163 | with a secondary 164 | .I opts 165 | until it returns EOF. 166 | The user can provide primary options, then a double hyphen, 167 | and then secondary options. 168 | No special handling is needed if some or all of the options are 169 | omitted. 170 | The same technique can be used for any number of option sets 171 | in series. 172 | 173 | .B Multiple command lines: 174 | Before parsing a new 175 | .BR argv , 176 | make sure to 177 | set 178 | .B sgoptind 179 | and 180 | .B sgoptpos 181 | back to 182 | 1 and 0. 183 | .SH "PARSING STAGES" 184 | .B sgopt 185 | keeps track of its position in 186 | .I argv 187 | with 188 | .B sgoptind 189 | and 190 | .BR sgoptpos , 191 | which are initialized to 1 and 0. 192 | It looks at 193 | .I argv\fB[sgoptind][sgoptpos] 194 | and following characters. 195 | 196 | .B sgopt 197 | indicates 198 | that no more options are available by 199 | returning 200 | .BR sgoptdone , 201 | which is initialized to 202 | .BR SUBGETOPTDONE , 203 | which is defined as \-1. 204 | 205 | .B sgopt 206 | begins by setting 207 | .B optarg 208 | to null. 209 | 210 | .B Ending conditions: 211 | If 212 | .I argv 213 | is null, or 214 | .B sgoptind 215 | is larger than 216 | .IR argc , 217 | or the current cmdarg 218 | .I argv\fB[sgoptind] 219 | is null, 220 | then 221 | .B sgopt 222 | returns 223 | .BR optdone . 224 | 225 | .B Stage one: 226 | If the current character 227 | is zero, 228 | .B sgopt 229 | moves to the beginning of the next cmdarg. 230 | It then checks the ending conditions again. 231 | 232 | .B Stage two: 233 | If 234 | the current position is the begining of the cmdarg, 235 | .B sgopt 236 | checks whether 237 | the current character 238 | is a minus sign. 239 | If not it returns 240 | .BR optdone . 241 | It then 242 | moves 243 | to the next character. 244 | If that character is zero, 245 | .B sgopt 246 | moves 247 | back to the beginning of the cmdarg, 248 | and returns 249 | .BR sgoptdone . 250 | If the character is a minus sign, 251 | .B sgopt 252 | moves to the beginning of the next cmdarg, 253 | and returns 254 | .BR sgoptdone . 255 | 256 | .B Stage three: 257 | .B sgopt 258 | records the current character, 259 | .IR c , 260 | and moves to the next character. 261 | There are three possibilities: 262 | (1) 263 | .I c 264 | is an option character without optarg in 265 | .IR opts , 266 | or 267 | (2) 268 | .I c 269 | is an option character with optarg in 270 | .IR opts , 271 | or 272 | (3) 273 | .I c 274 | does not appear in 275 | .IR opts . 276 | 277 | (1) 278 | If 279 | .I c 280 | appears as an option character without optarg in 281 | .IR opts , 282 | .B sgopt 283 | returns 284 | .IR c . 285 | 286 | (2) 287 | If 288 | .I c 289 | appears as an option character with optarg in 290 | .IR opts , 291 | .B sgopt 292 | sets 293 | .B sgoptarg 294 | to the current position, 295 | and moves to the next cmdarg. 296 | If 297 | .B sgoptarg 298 | is nonempty, 299 | .B sgopt 300 | returns 301 | .IR c . 302 | 303 | Then 304 | .B sgopt 305 | sets 306 | .B sgoptarg 307 | to 308 | the current cmdarg. 309 | If 310 | the current cmdarg is null, 311 | or past 312 | .IR argc , 313 | .B sgopt 314 | sets 315 | .B sgoptproblem 316 | to 317 | .I c 318 | and returns ?. 319 | Otherwise 320 | .B sgopt 321 | moves to the next 322 | argument 323 | and returns 324 | .IR c . 325 | 326 | (2) 327 | If 328 | .I c 329 | does not appear in 330 | .IR opts , 331 | .B sgopt 332 | sets 333 | .B sgoptproblem 334 | to 335 | .I c 336 | and returns ?. 337 | .SH "SYNTAX NOTE" 338 | .B sgopt 339 | is actually a macro abbreviation for 340 | .BR subgetopt . 341 | The external 342 | .B sg 343 | variables are also macros 344 | for 345 | .BR subget . 346 | These macros are defined in 347 | .BR , 348 | unless 349 | .B SUBGETOPTNOSHORT 350 | is defined 351 | when 352 | .B 353 | is included. 354 | .SH VERSION 355 | subgetopt version 0.9, 931129. 356 | .SH AUTHOR 357 | Placed into the public domain by Daniel J. Bernstein. 358 | -------------------------------------------------------------------------------- /subgetopt.c: -------------------------------------------------------------------------------- 1 | /* subgetopt.c, subgetopt.h: (yet another) improved getopt clone, inner layer 2 | Daniel J. Bernstein, djb@silverton.berkeley.edu. 3 | No dependencies. 4 | No system requirements. 5 | 931129: Adapted from getopt.c. 6 | No known patent problems. 7 | 8 | Documentation in subgetopt.3. 9 | */ 10 | 11 | #define SUBGETOPTNOSHORT 12 | #include "subgetopt.h" 13 | 14 | #define sgopt subgetopt 15 | #define optind subgetoptind 16 | #define optpos subgetoptpos 17 | #define optarg subgetoptarg 18 | #define optproblem subgetoptproblem 19 | #define optdone subgetoptdone 20 | 21 | int optind = 1; 22 | int optpos = 0; 23 | char *optarg = 0; 24 | int optproblem = 0; 25 | int optdone = SUBGETOPTDONE; 26 | 27 | int sgopt(argc,argv,opts) 28 | int argc; 29 | char **argv; 30 | char *opts; 31 | { 32 | int c; 33 | char *s; 34 | 35 | optarg = 0; 36 | if (!argv || (optind >= argc) || !argv[optind]) 37 | return optdone; 38 | if (optpos && !argv[optind][optpos]) 39 | { 40 | ++optind; 41 | optpos = 0; 42 | if ((optind >= argc) || !argv[optind]) 43 | return optdone; 44 | } 45 | if (!optpos) 46 | { 47 | if (argv[optind][0] != '-') 48 | return optdone; 49 | ++optpos; 50 | c = argv[optind][1]; 51 | if ((c == '-') || (c == 0)) 52 | { 53 | if (c) 54 | ++optind; 55 | optpos = 0; 56 | return optdone; 57 | } 58 | /* otherwise c is reassigned below */ 59 | } 60 | c = argv[optind][optpos]; 61 | ++optpos; 62 | s = opts; 63 | while (*s) 64 | { 65 | if (c == *s) 66 | { 67 | if (s[1] == ':') 68 | { 69 | optarg = argv[optind] + optpos; 70 | ++optind; 71 | optpos = 0; 72 | if (!*optarg) 73 | { 74 | optarg = argv[optind]; 75 | if ((optind >= argc) || !optarg) /* argument past end */ 76 | { 77 | optproblem = c; 78 | return '?'; 79 | } 80 | ++optind; 81 | } 82 | } 83 | return c; 84 | } 85 | ++s; 86 | if (*s == ':') 87 | ++s; 88 | } 89 | optproblem = c; 90 | return '?'; 91 | } 92 | -------------------------------------------------------------------------------- /subgetopt.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBGETOPT_H 2 | #define SUBGETOPT_H 3 | 4 | #ifndef SUBGETOPTNOSHORT 5 | #define sgopt subgetopt 6 | #define sgoptarg subgetoptarg 7 | #define sgoptind subgetoptind 8 | #define sgoptpos subgetoptpos 9 | #define sgoptproblem subgetoptproblem 10 | #define sgoptprogname subgetoptprogname 11 | #define sgoptdone subgetoptdone 12 | #endif 13 | 14 | #define SUBGETOPTDONE -1 15 | 16 | extern int subgetopt(); 17 | extern char *subgetoptarg; 18 | extern int subgetoptind; 19 | extern int subgetoptpos; 20 | extern int subgetoptproblem; 21 | extern char *subgetoptprogname; 22 | extern int subgetoptdone; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /substdi.c: -------------------------------------------------------------------------------- 1 | #include "substdio.h" 2 | #include "byte.h" 3 | #include "error.h" 4 | 5 | static int oneread(op,fd,buf,len) 6 | register int (*op)(); 7 | register int fd; 8 | register char *buf; 9 | register int len; 10 | { 11 | register int r; 12 | 13 | for (;;) 14 | { 15 | r = op(fd,buf,len); 16 | if (r == -1) 17 | if (errno == error_intr) 18 | continue; 19 | break; 20 | } 21 | return r; 22 | } 23 | 24 | static int fillit(s) 25 | substdio *s; /* empty right-justified buffer */ 26 | { 27 | char *y; 28 | int r; 29 | int q; 30 | 31 | q = s->n; 32 | y = s->x; 33 | 34 | r = oneread(s->op,s->fd,y,q); 35 | if (r <= 0) 36 | return r; 37 | 38 | s->p = r; 39 | q -= r; 40 | s->n = q; 41 | if (q > 0) /* damn, gotta shift */ 42 | byte_copyr(y + q,r,y); 43 | 44 | return r; 45 | } 46 | 47 | static int getthis(s,buf,len) 48 | substdio *s; 49 | char *buf; 50 | int len; 51 | { 52 | char *y; 53 | int r; 54 | int q; 55 | 56 | y = s->x + s->n; 57 | r = s->p; 58 | q = r - len; 59 | if (q > 0) { r = len; s->p = q; } else s->p = 0; 60 | byte_copy(buf,r,y); 61 | s->n += r; 62 | return r; 63 | } 64 | 65 | int substdio_feed(s) 66 | substdio *s; 67 | { 68 | int r; 69 | if (s->p) return 1; 70 | r = fillit(s); 71 | if (r <= 0) return r; 72 | return 1; 73 | } 74 | 75 | int substdio_bget(s,buf,len) 76 | substdio *s; 77 | char *buf; 78 | int len; 79 | { 80 | int r; 81 | 82 | if (s->p > 0) return getthis(s,buf,len); 83 | 84 | r = s->n; if (r <= len) return oneread(s->op,s->fd,buf,r); 85 | 86 | r = fillit(s); if (r <= 0) return r; 87 | return getthis(s,buf,len); 88 | } 89 | 90 | int substdio_get(s,buf,len) 91 | substdio *s; 92 | char *buf; 93 | int len; 94 | { 95 | int r; 96 | 97 | if (s->p > 0) return getthis(s,buf,len); 98 | 99 | if (s->n <= len) return oneread(s->op,s->fd,buf,len); 100 | 101 | r = fillit(s); if (r <= 0) return r; 102 | return getthis(s,buf,len); 103 | } 104 | 105 | char *substdio_peek(s,len) 106 | substdio *s; 107 | int *len; 108 | { 109 | *len = s->p; 110 | return s->x + s->n; 111 | } 112 | 113 | void substdio_seek(s,len) 114 | substdio *s; 115 | int len; 116 | { 117 | s->n += len; 118 | s->p -= len; 119 | } 120 | -------------------------------------------------------------------------------- /substdio.c: -------------------------------------------------------------------------------- 1 | #include "substdio.h" 2 | 3 | void substdio_fdbuf(s,op,fd,buf,len) 4 | register substdio *s; 5 | register int (*op)(); 6 | register int fd; 7 | register char *buf; 8 | register int len; 9 | { 10 | s->x = buf; 11 | s->fd = fd; 12 | s->op = op; 13 | s->p = 0; 14 | s->n = len; 15 | } 16 | -------------------------------------------------------------------------------- /substdio.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBSTDIO_H 2 | #define SUBSTDIO_H 3 | 4 | typedef struct substdio 5 | { 6 | char *x; 7 | int p; 8 | int n; 9 | int fd; 10 | int (*op)(); 11 | } 12 | substdio; 13 | 14 | #define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } 15 | 16 | extern void substdio_fdbuf(); 17 | 18 | extern int substdio_flush(); 19 | extern int substdio_put(); 20 | extern int substdio_bput(); 21 | extern int substdio_putflush(); 22 | extern int substdio_puts(); 23 | extern int substdio_bputs(); 24 | extern int substdio_putsflush(); 25 | 26 | extern int substdio_get(); 27 | extern int substdio_bget(); 28 | extern int substdio_feed(); 29 | 30 | extern char *substdio_peek(); 31 | extern void substdio_seek(); 32 | 33 | #define substdio_fileno(s) ((s)->fd) 34 | 35 | #define SUBSTDIO_INSIZE 8192 36 | #define SUBSTDIO_OUTSIZE 8192 37 | 38 | #define substdio_BPUTC(s,c) \ 39 | ( ((s)->n != (s)->p) \ 40 | ? ( (s)->x[(s)->p++]=(c) , 0 ) \ 41 | : substdio_bput((s),&(c),1) ) 42 | 43 | #define substdio_PEEK(s,len) ( ( *(len) = (s)->p ) , ( (s)->x + (s)->n ) ) 44 | #define substdio_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) 45 | 46 | extern int substdio_copy(); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /substdio_copy.c: -------------------------------------------------------------------------------- 1 | #include "substdio.h" 2 | 3 | int substdio_copy(ssout,ssin) 4 | substdio *ssout; 5 | substdio *ssin; 6 | { 7 | int f; 8 | char *x; 9 | int xlen; 10 | 11 | for (;;) 12 | { 13 | f = substdio_feed(ssin); 14 | if (f < 0) return -2; 15 | if (!f) return 0; 16 | x = substdio_PEEK(ssin,&xlen); 17 | if (substdio_put(ssout,x,xlen) == -1) return -3; 18 | substdio_SEEK(ssin,xlen); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /substdo.c: -------------------------------------------------------------------------------- 1 | #include "substdio.h" 2 | #include "str.h" 3 | #include "byte.h" 4 | #include "error.h" 5 | 6 | static int allwrite(op,fd,buf,len) 7 | register int (*op)(); 8 | register int fd; 9 | register char *buf; 10 | register int len; 11 | { 12 | register int w; 13 | 14 | while (len) 15 | { 16 | w = op(fd,buf,len); 17 | if (w == -1) 18 | { 19 | if (errno == error_intr) 20 | continue; 21 | return -1; /* note that some data may have been written */ 22 | } 23 | if (w == 0) 24 | ; /* luser's fault */ 25 | buf += w; 26 | len -= w; 27 | } 28 | return 0; 29 | } 30 | 31 | int substdio_flush(s) 32 | register substdio *s; 33 | { 34 | register int p; 35 | 36 | p = s->p; 37 | if (!p) 38 | return 0; 39 | 40 | s->p = 0; 41 | 42 | if (allwrite(s->op,s->fd,s->x,p) == -1) 43 | return -1; 44 | return 0; 45 | } 46 | 47 | int substdio_bput(s,buf,len) 48 | register substdio *s; 49 | register char *buf; 50 | register int len; 51 | { 52 | register int n; 53 | 54 | while (len > (n = s->n - s->p)) 55 | { 56 | byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; 57 | if (substdio_flush(s) == -1) 58 | return -1; 59 | } 60 | 61 | /* now len <= s->n - s->p */ 62 | byte_copy(s->x + s->p,len,buf); 63 | s->p += len; 64 | return 0; 65 | } 66 | 67 | int substdio_put(s,buf,len) 68 | register substdio *s; 69 | register char *buf; 70 | register int len; 71 | { 72 | register int n; 73 | 74 | n = s->n; 75 | if (len > n - s->p) 76 | { 77 | if (substdio_flush(s) == -1) 78 | return -1; 79 | /* now s->p == 0 */ 80 | if (n < SUBSTDIO_OUTSIZE) 81 | n = SUBSTDIO_OUTSIZE; 82 | while (len > s->n) 83 | { 84 | if (n > len) 85 | n = len; 86 | if (allwrite(s->op,s->fd,buf,n) == -1) 87 | return -1; 88 | buf += n; 89 | len -= n; 90 | } 91 | } 92 | /* now len <= s->n - s->p */ 93 | byte_copy(s->x + s->p,len,buf); 94 | s->p += len; 95 | return 0; 96 | } 97 | 98 | int substdio_putflush(s,buf,len) 99 | register substdio *s; 100 | register char *buf; 101 | register int len; 102 | { 103 | if (substdio_flush(s) == -1) 104 | return -1; 105 | if (allwrite(s->op,s->fd,buf,len) == -1) 106 | return -1; 107 | return 0; 108 | } 109 | 110 | int substdio_bputs(s,buf) 111 | register substdio *s; 112 | register char *buf; 113 | { 114 | return substdio_bput(s,buf,str_len(buf)); 115 | } 116 | 117 | int substdio_puts(s,buf) 118 | register substdio *s; 119 | register char *buf; 120 | { 121 | return substdio_put(s,buf,str_len(buf)); 122 | } 123 | 124 | int substdio_putsflush(s,buf) 125 | register substdio *s; 126 | register char *buf; 127 | { 128 | return substdio_putflush(s,buf,str_len(buf)); 129 | } 130 | -------------------------------------------------------------------------------- /trycpp.c: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | #ifdef NeXT 4 | printf("nextstep\n"); exit(0); 5 | #endif 6 | printf("unknown\n"); exit(0); 7 | } 8 | -------------------------------------------------------------------------------- /tryptc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() 5 | { 6 | struct stat st; 7 | 8 | if (stat("/dev/ptc",&st) == -1) exit(1); 9 | exit(0); 10 | } 11 | -------------------------------------------------------------------------------- /tryptmx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() 5 | { 6 | struct stat st; 7 | 8 | if (stat("/dev/ptmx",&st) == -1) exit(1); 9 | exit(0); 10 | } 11 | -------------------------------------------------------------------------------- /trysgact.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void main() 4 | { 5 | struct sigaction sa; 6 | sa.sa_handler = 0; 7 | sa.sa_flags = 0; 8 | sigemptyset(&sa.sa_mask); 9 | sigaction(0,&sa,(struct sigaction *) 0); 10 | } 11 | -------------------------------------------------------------------------------- /trysgprm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void main() 4 | { 5 | sigset_t ss; 6 | 7 | sigemptyset(&ss); 8 | sigaddset(&ss,SIGCHLD); 9 | sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); 10 | } 11 | -------------------------------------------------------------------------------- /trysysel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* AIX silliness */ 4 | 5 | void foo() 6 | { 7 | ; 8 | } 9 | -------------------------------------------------------------------------------- /tryvfork.c: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | vfork(); 4 | } 5 | -------------------------------------------------------------------------------- /trywaitp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() 5 | { 6 | waitpid(0,0,0); 7 | } 8 | -------------------------------------------------------------------------------- /ttyctrl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ttyctrl.h" 5 | 6 | int ttyctrl() 7 | { 8 | int fd; 9 | int dummy; 10 | 11 | fd = dup(3); 12 | if (fd != -1) { if (tcgetpgrp(fd) != -1) return fd; close(fd); } 13 | fd = open("/dev/tty",O_RDWR); 14 | if (fd != -1) { if (tcgetpgrp(fd) != -1) return fd; close(fd); } 15 | fd = dup(2); 16 | if (fd != -1) { if (tcgetpgrp(fd) != -1) return fd; close(fd); } 17 | fd = dup(0); 18 | if (fd != -1) { if (tcgetpgrp(fd) != -1) return fd; close(fd); } 19 | fd = dup(1); 20 | if (fd != -1) { if (tcgetpgrp(fd) != -1) return fd; close(fd); } 21 | return -1; 22 | } 23 | -------------------------------------------------------------------------------- /ttyctrl.h: -------------------------------------------------------------------------------- 1 | #ifndef TTYCTRL_H 2 | #define TTYCTRL_H 3 | 4 | extern int ttyctrl(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /ttydetach.1: -------------------------------------------------------------------------------- 1 | .TH ttydetach 1 2 | .SH NAME 3 | ttydetach \- run program without a controlling tty 4 | .SH SYNOPSIS 5 | .B ttydetach 6 | .I subprogram 7 | [ 8 | .I args ... 9 | ] 10 | .SH DESCRIPTION 11 | .B ttydetach 12 | eliminates its controlling tty, 13 | removes any TTY variable from the environment, 14 | and runs 15 | .IR subprogram . 16 | 17 | On POSIX systems, 18 | .B ttydetach 19 | must not be a process group leader. 20 | .SH "SEE ALSO" 21 | background(1) 22 | -------------------------------------------------------------------------------- /ttydetach.c: -------------------------------------------------------------------------------- 1 | #include "env.h" 2 | #include "strerr.h" 3 | 4 | void main(argc,argv) 5 | int argc; 6 | char **argv; 7 | { 8 | if (setsid() == -1) 9 | strerr_warn1("ttydetach: warning: unable to setsid",0); 10 | if (!env_unset("TTY")) 11 | strerr_die2x(111,"ttydetach: fatal: ","out of memory"); 12 | execvp(argv[1],argv + 1); 13 | strerr_die4sys(111,"ttydetach: fatal: ","unable to run ",argv[1],": "); 14 | } 15 | -------------------------------------------------------------------------------- /ttydetach.do: -------------------------------------------------------------------------------- 1 | objs="ttyctrl.o libstrerr.a libsubstdio.a libenv.a liballoc.a liberror.a libstr.a" 2 | dependon load $1.o $objs 3 | directtarget 4 | ./load $1 $objs 5 | formake ./load $1 $objs 6 | -------------------------------------------------------------------------------- /ttymodes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "error.h" 4 | #include 5 | #include "ttymodes.h" 6 | 7 | int ttymodes_gett(tm,fd) 8 | struct ttymodes *tm; 9 | int fd; 10 | { 11 | int r; 12 | do 13 | r = tcgetattr(fd,&tm->ti); 14 | while ((r == -1) && (errno == error_intr)); 15 | return r; 16 | } 17 | 18 | int ttymodes_sett(tm,fd) 19 | struct ttymodes *tm; 20 | int fd; 21 | { 22 | int r; 23 | do 24 | r = tcsetattr(fd,TCSADRAIN,&tm->ti); 25 | while ((r == -1) && (errno == error_intr)); 26 | return r; 27 | } 28 | 29 | int ttymodes_getw(tm,fd) 30 | struct ttymodes *tm; 31 | int fd; 32 | { 33 | int r; 34 | do 35 | r = ioctl(fd,TIOCGWINSZ,&tm->ws); 36 | while ((r == -1) && (errno == error_intr)); 37 | return r; 38 | } 39 | 40 | int ttymodes_setw(tm,fd) 41 | struct ttymodes *tm; 42 | int fd; 43 | { 44 | int r; 45 | do 46 | r = ioctl(fd,TIOCSWINSZ,&tm->ws); 47 | while ((r == -1) && (errno == error_intr)); 48 | return r; 49 | } 50 | 51 | int ttymodes_get(tm,fd) 52 | struct ttymodes *tm; 53 | int fd; 54 | { 55 | if (ttymodes_gett(tm,fd) == -1) return -1; 56 | return ttymodes_getw(tm,fd); 57 | } 58 | 59 | int ttymodes_set(tm,fd) 60 | struct ttymodes *tm; 61 | int fd; 62 | { 63 | if (ttymodes_sett(tm,fd) == -1) return -1; 64 | return ttymodes_setw(tm,fd); 65 | } 66 | 67 | void ttymodes_makeraw(tm) 68 | struct ttymodes *tm; 69 | { 70 | tm->ti.c_iflag &= ~(BRKINT | IGNBRK | IGNPAR | PARMRK); 71 | tm->ti.c_iflag &= ~(ISTRIP | IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL); 72 | tm->ti.c_oflag &= ~OPOST; 73 | tm->ti.c_lflag &= ~(ECHO | ECHONL); 74 | tm->ti.c_lflag &= ~(ICANON | ISIG | IEXTEN); 75 | tm->ti.c_cflag &= ~(CSIZE | PARENB); 76 | tm->ti.c_cflag |= CS8; 77 | tm->ti.c_cc[VMIN] = 1; 78 | tm->ti.c_cc[VTIME] = 0; 79 | } 80 | 81 | void ttymodes_sane(tm) 82 | struct ttymodes *tm; 83 | { 84 | int i; 85 | 86 | for (i = 0;i < sizeof(*tm);++i) 87 | ((char *) tm)[i] = 0; 88 | 89 | for (i = 0;i < sizeof(tm->ti.c_cc) / sizeof(*tm->ti.c_cc);++i) 90 | tm->ti.c_cc[i] = _POSIX_VDISABLE; 91 | 92 | tm->ti.c_iflag = BRKINT | IGNBRK | ICRNL | IXON | IMAXBEL; 93 | tm->ti.c_oflag = OPOST | ONLCR; 94 | tm->ti.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOKE | ECHOCTL; 95 | tm->ti.c_cflag = CS8 | CREAD | HUPCL; 96 | 97 | /* These are critical for Solaris! Otherwise master reads eof upon TCSA. */ 98 | cfsetispeed(&tm->ti,B38400); 99 | cfsetospeed(&tm->ti,B38400); 100 | 101 | tm->ti.c_cc[VMIN] = 1; 102 | tm->ti.c_cc[VTIME] = 0; 103 | tm->ti.c_cc[VINTR] = 3; 104 | tm->ti.c_cc[VQUIT] = 28; 105 | tm->ti.c_cc[VERASE] = 127; 106 | tm->ti.c_cc[VKILL] = 21; 107 | tm->ti.c_cc[VEOF] = 4; 108 | tm->ti.c_cc[VSTART] = 17; 109 | tm->ti.c_cc[VSTOP] = 19; 110 | #ifdef VSUSP 111 | tm->ti.c_cc[VSUSP] = 26; 112 | #endif 113 | #ifdef VDSUSP 114 | tm->ti.c_cc[VDSUSP] = 25; 115 | #endif 116 | #ifdef VREPRINT 117 | tm->ti.c_cc[VREPRINT] = 18; 118 | #endif 119 | #ifdef VDISCARD 120 | tm->ti.c_cc[VDISCARD] = 15; 121 | #endif 122 | #ifdef VWERASE 123 | tm->ti.c_cc[VWERASE] = 23; 124 | #endif 125 | #ifdef VLNEXT 126 | tm->ti.c_cc[VLNEXT] = 22; 127 | #endif 128 | #ifdef VSTATUS 129 | tm->ti.c_cc[VSTATUS] = 20; 130 | #endif 131 | } 132 | -------------------------------------------------------------------------------- /ttymodes.h: -------------------------------------------------------------------------------- 1 | #ifndef TTYMODES_H 2 | #define TTYMODES_H 3 | 4 | #include 5 | #include 6 | 7 | struct ttymodes { 8 | struct termios ti; 9 | struct winsize ws; 10 | } ; 11 | 12 | extern int ttymodes_gett(); 13 | extern int ttymodes_getw(); 14 | extern int ttymodes_get(); 15 | extern int ttymodes_sett(); 16 | extern int ttymodes_setw(); 17 | extern int ttymodes_set(); 18 | 19 | extern void ttymodes_makeraw(); 20 | extern void ttymodes_sane(); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /wait.h: -------------------------------------------------------------------------------- 1 | #ifndef WAIT_H 2 | #define WAIT_H 3 | 4 | extern int wait_pid(); 5 | extern int wait_nohang(); 6 | extern int wait_stop(); 7 | extern int wait_stopnohang(); 8 | 9 | #define wait_crashed(w) ((w) & 127) 10 | #define wait_exitcode(w) ((w) >> 8) 11 | #define wait_stopsig(w) ((w) >> 8) 12 | #define wait_stopped(w) (((w) & 127) == 127) 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /wait_nohang.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "haswaitp.h" 4 | 5 | int wait_nohang(wstat) int *wstat; 6 | { 7 | #ifdef HASWAITPID 8 | return waitpid(-1,wstat,WNOHANG); 9 | #else 10 | return wait3(wstat,WNOHANG,(struct rusage *) 0); 11 | #endif 12 | } 13 | -------------------------------------------------------------------------------- /wait_pid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "error.h" 4 | 5 | /* restriction: you must not care about any other child. */ 6 | int wait_pid(wstat,pid) int *wstat; int pid; 7 | { 8 | int r; 9 | do 10 | r = wait(wstat); 11 | while ((r != pid) && ((r != -1) || (errno == error_intr))); 12 | return r; 13 | } 14 | -------------------------------------------------------------------------------- /wait_snh.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "haswaitp.h" 4 | 5 | int wait_stopnohang(wstat) int *wstat; 6 | { 7 | #ifdef HASWAITPID 8 | return waitpid(-1,wstat,WNOHANG | WUNTRACED); 9 | #else 10 | return wait3(wstat,WNOHANG | WUNTRACED,(struct rusage *) 0); 11 | #endif 12 | } 13 | -------------------------------------------------------------------------------- /wait_stop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "haswaitp.h" 4 | #include "error.h" 5 | 6 | int wait_stop(wstat) int *wstat; 7 | { 8 | int r; 9 | 10 | do 11 | #ifdef HASWAITPID 12 | r = waitpid(-1,wstat,WUNTRACED); 13 | #else 14 | r = wait3(wstat,WUNTRACED,(struct rusage *) 0); 15 | #endif 16 | while ((r == -1) && (errno == error_intr)); 17 | 18 | return r; 19 | } 20 | -------------------------------------------------------------------------------- /warn-auto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # WARNING: This file was auto-generated. Do not edit! 3 | --------------------------------------------------------------------------------