home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3555 < prev    next >
Internet Message Format  |  1991-06-26  |  60KB

  1. From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein)
  2. Newsgroups: alt.sources
  3. Subject: clientserver 0.50 (part 1/2)
  4. Message-ID: <11300.Jun2522.45.0291@kramden.acf.nyu.edu>
  5. Date: 25 Jun 1991 22:45:02 GMT
  6.  
  7. This is clientserver 0.50, a set of three client-server suites
  8. supporting different protocols with the same well-defined interface. Two
  9. of the suites support the TCP and UNDOM protocols for BSD systems; one
  10. supports the NPIPE protocol for System V. (I'd love to hear from anyone
  11. with a System V more modern than a 3B2: Does NPIPE run on your machine?)
  12. All obey the UCSPI (UNIX Client-Server Program Interface) standard, so
  13. you can write programs that work exactly the same way on top of any of
  14. the protocols. You can even use these communications facilities inside
  15. shell scripts.
  16.  
  17. Why do you want to use UCSPI-compliant communications tools? One
  18. advantage is instant portability. By working with the client-server
  19. model given here, you instantly make your programs usable over the
  20. Internet as well as on System V machines. Not only that, but your code
  21. will work with any future communications tools designed to fit the
  22. standard. Imagine supporting DECnet, AT&T's TLI, even Kerberos without
  23. lifting a finger! Another advantage is modularity: you can mix 'n' match
  24. protocols and applications without worrying which program supports which
  25. protocols. Finally, you can skip all those nasty steps of getting
  26. connection information from the operating system. No matter what the
  27. protocol is, UCSPI insists that you be given environment variables
  28. saying who you're talking to.
  29.  
  30. UCSPI also mandates an often ignored aspect of client-server
  31. communications: a standard way to kill the server. You don't have to go
  32. searching through process lists or checking /etc/syslog.pid or sending
  33. HUPS left and right. You stop a server the same way you started it. You
  34. might set up a telnet daemon, for example, with this command:
  35.  
  36.   tcpserver 0 telnet sh -c '/usr/etc/in.telnetd <&6 >&7 6<&- 7>&-' &
  37.  
  38. Here 0 refers to the local machine, and telnet is a port. To kill the
  39. server you just have to know the address:
  40.  
  41.   tcpkiller 0 telnet
  42.  
  43. That's it.
  44.  
  45. Everything here except the UCSPI-91 standard is in the public domain.
  46. Feel free to copy UCSPI as long as you don't modify it. Of course, UCSPI
  47. is just a document laying out some ideas; it's not a real standard until
  48. enough people decide it's worth supporting. Please let me know what you
  49. think!
  50.  
  51. ---Dan Bernstein, brnstnd@nyu.edu
  52.  
  53. #! /bin/sh
  54. # This is a shell archive.  Remove anything before this line, then unpack
  55. # it by saving it into a file and typing "sh file".  To overwrite existing
  56. # files, type "sh file -c".  You can also feed this as standard input via
  57. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  58. # will see the following message at the end:
  59. #        "End of archive 1 (of 2)."
  60. # Contents:  BLURB DESIGN.npipe FILES FORMLETTER Makefile NPIPE README
  61. #   TCP UNDOM authuser.c authuser.h dupdup.c dupdup.h env.c env.h
  62. #   errno.h getopt.h hostname.c hostname.h malloc.h npipekiller.c
  63. #   numeric.c numeric.h numfiles.h portname.c portname.h tcpkiller.c
  64. #   testmain testresult testucspi undomclient.c undomkiller.c
  65. #   username.c username.h
  66. # Wrapped by brnstnd@kramden on Tue Jun 25 18:41:38 1991
  67. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  68. if test -f 'BLURB' -a "${1}" != "-c" ; then 
  69.   echo shar: Will not clobber existing file \"'BLURB'\"
  70. else
  71. echo shar: Extracting \"'BLURB'\" \(2255 characters\)
  72. sed "s/^X//" >'BLURB' <<'END_OF_FILE'
  73. XThis is clientserver 0.50, a set of three client-server suites
  74. Xsupporting different protocols with the same well-defined interface. Two
  75. Xof the suites support the TCP and UNDOM protocols for BSD systems; one
  76. Xsupports the NPIPE protocol for System V. (I'd love to hear from anyone
  77. Xwith a System V more modern than a 3B2: Does NPIPE run on your machine?)
  78. XAll obey the UCSPI (UNIX Client-Server Program Interface) standard, so
  79. Xyou can write programs that work exactly the same way on top of any of
  80. Xthe protocols. You can even use these communications facilities inside
  81. Xshell scripts.
  82. X
  83. XWhy do you want to use UCSPI-compliant communications tools? One
  84. Xadvantage is instant portability. By working with the client-server
  85. Xmodel given here, you instantly make your programs usable over the
  86. XInternet as well as on System V machines. Not only that, but your code
  87. Xwill work with any future communications tools designed to fit the
  88. Xstandard. Imagine supporting DECnet, AT&T's TLI, even Kerberos without
  89. Xlifting a finger! Another advantage is modularity: you can mix 'n' match
  90. Xprotocols and applications without worrying which program supports which
  91. Xprotocols. Finally, you can skip all those nasty steps of getting
  92. Xconnection information from the operating system. No matter what the
  93. Xprotocol is, UCSPI insists that you be given environment variables
  94. Xsaying who you're talking to.
  95. X
  96. XUCSPI also mandates an often ignored aspect of client-server
  97. Xcommunications: a standard way to kill the server. You don't have to go
  98. Xsearching through process lists or checking /etc/syslog.pid or sending
  99. XHUPS left and right. You stop a server the same way you started it. You
  100. Xmight set up a telnet daemon, for example, with this command:
  101. X
  102. X  tcpserver 0 telnet sh -c '/usr/etc/in.telnetd <&6 >&7 6<&- 7>&-' &
  103. X
  104. XHere 0 refers to the local machine, and telnet is a port. To kill the
  105. Xserver you just have to know the address:
  106. X
  107. X  tcpkiller 0 telnet
  108. X
  109. XThat's it.
  110. X
  111. XEverything here except the UCSPI-91 standard is in the public domain.
  112. XFeel free to copy UCSPI as long as you don't modify it. Of course, UCSPI
  113. Xis just a document laying out some ideas; it's not a real standard until
  114. Xenough people decide it's worth supporting. Please let me know what you
  115. Xthink!
  116. X
  117. X---Dan Bernstein, brnstnd@nyu.edu
  118. END_OF_FILE
  119. if test 2255 -ne `wc -c <'BLURB'`; then
  120.     echo shar: \"'BLURB'\" unpacked with wrong size!
  121. fi
  122. # end of 'BLURB'
  123. fi
  124. if test -f 'DESIGN.npipe' -a "${1}" != "-c" ; then 
  125.   echo shar: Will not clobber existing file \"'DESIGN.npipe'\"
  126. else
  127. echo shar: Extracting \"'DESIGN.npipe'\" \(950 characters\)
  128. sed "s/^X//" >'DESIGN.npipe' <<'END_OF_FILE'
  129. XHere's the idea: We create DIR/l.username/service, a mode-000 file. We
  130. Xcreate s.username, a mode-600 named pipe. We then change l.username to
  131. Xmode 600 and open s.username for reading. This blocks. Note that a
  132. Xclient may start writing before we start reading, or vice versa.
  133. X
  134. XMain loop: The client locks l.username. When it receives the lock, it
  135. Xopens s.username for writing, then creates DIR/s2c.pid and DIR/c2s.pid,
  136. Xthen writes pid and its username, then closes s.username, then opens
  137. Xs2c.pid for reading (this blocks) and c2s.pid for writing (this blocks).
  138. XWe read pid and the username, then close and unlink s.username. We then
  139. Xfork. In the parent, we then create s.username, a mode-600 named pipe,
  140. Xthen open s.username for reading; this is back to the original state. In
  141. Xthe child, we open s2c.pid for writing and c2s.pid for reading, then
  142. Xwrite a byte to s2c.pid. The client reads that byte, unlinks s2c.pid and
  143. Xc2s.pid, and unlocks l.username.
  144. END_OF_FILE
  145. if test 950 -ne `wc -c <'DESIGN.npipe'`; then
  146.     echo shar: \"'DESIGN.npipe'\" unpacked with wrong size!
  147. fi
  148. # end of 'DESIGN.npipe'
  149. fi
  150. if test -f 'FILES' -a "${1}" != "-c" ; then 
  151.   echo shar: Will not clobber existing file \"'FILES'\"
  152. else
  153. echo shar: Extracting \"'FILES'\" \(399 characters\)
  154. sed "s/^X//" >'FILES' <<'END_OF_FILE'
  155. XBLURB
  156. XREADME
  157. XFILES
  158. XFORMLETTER
  159. XUCSPI
  160. XTCP
  161. XUNDOM
  162. XNPIPE
  163. XDESIGN.npipe
  164. Xtestmain
  165. Xtestresult
  166. Xtestucspi
  167. XMakefile
  168. Xauthuser.h
  169. Xdupdup.h
  170. Xenv.h
  171. Xerrno.h
  172. Xgetopt.h
  173. Xhostname.h
  174. Xmalloc.h
  175. Xnumeric.h
  176. Xnumfiles.h
  177. Xportname.h
  178. Xusername.h
  179. Xauthuser.c
  180. Xdupdup.c
  181. Xenv.c
  182. Xhostname.c
  183. Xnpipeclient.c
  184. Xnpipeserver.c
  185. Xnpipekiller.c
  186. Xnumeric.c
  187. Xportname.c
  188. Xundomclient.c
  189. Xundomserver.c
  190. Xundomkiller.c
  191. Xusername.c
  192. Xtcpclient.c
  193. Xtcpserver.c
  194. Xtcpkiller.c
  195. END_OF_FILE
  196. if test 399 -ne `wc -c <'FILES'`; then
  197.     echo shar: \"'FILES'\" unpacked with wrong size!
  198. fi
  199. # end of 'FILES'
  200. fi
  201. if test -f 'FORMLETTER' -a "${1}" != "-c" ; then 
  202.   echo shar: Will not clobber existing file \"'FORMLETTER'\"
  203. else
  204. echo shar: Extracting \"'FORMLETTER'\" \(612 characters\)
  205. sed "s/^X//" >'FORMLETTER' <<'END_OF_FILE'
  206. XTo: brnstnd@nyu.edu
  207. XFrom: 
  208. XDate: 
  209. X
  210. XPackage: clientserver 0.50
  211. XObtained from (e.g., uunet.uu.net): 
  212. XObtained by (e.g., ftp): 
  213. X
  214. X1. Machine architecture (e.g., Sun 4/280): 
  215. X2. Operating system (e.g., SunOS 4.1): 
  216. X3. OS vendor (e.g., Sun): 
  217. X4. Does tcp work on your machine so far (yes/no/didn't try)? 
  218. X5. Does undom work on your machine so far (yes/no/didn't try)? 
  219. X6. Does npipe work on your machine so far (yes/no/didn't try)? 
  220. X7. What are CC and CCOPTS in your Makefile?
  221. X   CC=
  222. X   CCOPTS=
  223. X
  224. X8. Describe any problems you've had with clientserver.
  225. X
  226. X
  227. X9. Any further questions, comments, or suggestions?
  228. X
  229. X
  230. XYour name:
  231. END_OF_FILE
  232. if test 612 -ne `wc -c <'FORMLETTER'`; then
  233.     echo shar: \"'FORMLETTER'\" unpacked with wrong size!
  234. fi
  235. # end of 'FORMLETTER'
  236. fi
  237. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  238.   echo shar: Will not clobber existing file \"'Makefile'\"
  239. else
  240. echo shar: Extracting \"'Makefile'\" \(3109 characters\)
  241. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  242. XCC=cc
  243. XCCOPTS=-g -DUNDOMDIR=\"/usr/local/etc/undom\" -DNPIPEDIR=\"/usr/local/etc/npipe\" -DSIGRET=int
  244. XMACHOPTS=
  245. XLIBS=-lresolv   # XXX: only necessary for tcp*
  246. X#
  247. X
  248. Xdefault: undom tcp npipe
  249. X
  250. Xundom: undomserver undomclient undomkiller
  251. X
  252. Xtcp: tcpserver tcpclient tcpkiller
  253. X
  254. Xnpipe: npipeserver npipeclient npipekiller
  255. X
  256. Xnpipekiller: npipekiller.o dupdup.o username.o numeric.o env.o
  257. X    $(CC) $(CCOPTS) $(MACHOPTS) -o npipekiller npipekiller.o dupdup.o username.o numeric.o env.o $(LIBS)
  258. X
  259. Xnpipeserver: npipeserver.o dupdup.o username.o numeric.o env.o
  260. X    $(CC) $(CCOPTS) $(MACHOPTS) -o npipeserver npipeserver.o dupdup.o username.o numeric.o env.o $(LIBS)
  261. X
  262. Xnpipeclient: npipeclient.o dupdup.o username.o numeric.o env.o
  263. X    $(CC) $(CCOPTS) $(MACHOPTS) -o npipeclient npipeclient.o dupdup.o username.o numeric.o env.o $(LIBS)
  264. X
  265. Xundomkiller: undomkiller.o dupdup.o username.o numeric.o env.o
  266. X    $(CC) $(CCOPTS) $(MACHOPTS) -o undomkiller undomkiller.o dupdup.o username.o numeric.o env.o $(LIBS)
  267. X
  268. Xundomserver: undomserver.o dupdup.o username.o numeric.o env.o
  269. X    $(CC) $(CCOPTS) $(MACHOPTS) -o undomserver undomserver.o dupdup.o username.o numeric.o env.o $(LIBS)
  270. X
  271. Xundomclient: undomclient.o dupdup.o username.o numeric.o env.o
  272. X    $(CC) $(CCOPTS) $(MACHOPTS) -o undomclient undomclient.o dupdup.o username.o numeric.o env.o $(LIBS)
  273. X
  274. Xtcpkiller: tcpkiller.o username.o numeric.o portname.o hostname.o env.o
  275. X    $(CC) $(CCOPTS) $(MACHOPTS) -o tcpkiller tcpkiller.o username.o numeric.o portname.o hostname.o env.o $(LIBS)
  276. X
  277. Xtcpserver: tcpserver.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o
  278. X    $(CC) $(CCOPTS) $(MACHOPTS) -o tcpserver tcpserver.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o $(LIBS)
  279. X
  280. Xtcpclient: tcpclient.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o
  281. X    $(CC) $(CCOPTS) $(MACHOPTS) -o tcpclient tcpclient.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o $(LIBS)
  282. X
  283. Xnpipekiller.o: npipekiller.c
  284. X    $(CC) $(CCOPTS) $(MACHOPTS) -c npipekiller.c
  285. X
  286. Xnpipeserver.o: npipeserver.c
  287. X    $(CC) $(CCOPTS) $(MACHOPTS) -c npipeserver.c
  288. X
  289. Xnpipeclient.o: npipeclient.c
  290. X    $(CC) $(CCOPTS) $(MACHOPTS) -c npipeclient.c
  291. X
  292. Xundomkiller.o: undomkiller.c
  293. X    $(CC) $(CCOPTS) $(MACHOPTS) -c undomkiller.c
  294. X
  295. Xundomserver.o: undomserver.c
  296. X    $(CC) $(CCOPTS) $(MACHOPTS) -c undomserver.c
  297. X
  298. Xundomclient.o: undomclient.c
  299. X    $(CC) $(CCOPTS) $(MACHOPTS) -c undomclient.c
  300. X
  301. Xtcpclient.o: tcpclient.c
  302. X    $(CC) $(CCOPTS) $(MACHOPTS) -c tcpclient.c
  303. X
  304. Xtcpkiller.o: tcpkiller.c
  305. X    $(CC) $(CCOPTS) $(MACHOPTS) -c tcpkiller.c
  306. X
  307. Xtcpserver.o: tcpserver.c
  308. X    $(CC) $(CCOPTS) $(MACHOPTS) -c tcpserver.c
  309. X
  310. Xdupdup.o: dupdup.c
  311. X    $(CC) $(CCOPTS) $(MACHOPTS) -c dupdup.c
  312. X
  313. Xusername.o: username.c
  314. X    $(CC) $(CCOPTS) $(MACHOPTS) -c username.c
  315. X
  316. Xportname.o: portname.c
  317. X    $(CC) $(CCOPTS) $(MACHOPTS) -c portname.c
  318. X
  319. Xhostname.o: hostname.c
  320. X    $(CC) $(CCOPTS) $(MACHOPTS) -c hostname.c
  321. X
  322. Xnumeric.o: numeric.c
  323. X    $(CC) $(CCOPTS) $(MACHOPTS) -c numeric.c
  324. X
  325. Xenv.o: env.c
  326. X    $(CC) $(CCOPTS) $(MACHOPTS) -c env.c
  327. X
  328. Xauthuser.o: authuser.c
  329. X    $(CC) $(CCOPTS) $(MACHOPTS) -c authuser.c
  330. X
  331. Xshar:
  332. X    shar `cat FILES` > ucspi.shar
  333. X    chmod 400 ucspi.shar
  334. END_OF_FILE
  335. if test 3109 -ne `wc -c <'Makefile'`; then
  336.     echo shar: \"'Makefile'\" unpacked with wrong size!
  337. fi
  338. # end of 'Makefile'
  339. fi
  340. if test -f 'NPIPE' -a "${1}" != "-c" ; then 
  341.   echo shar: Will not clobber existing file \"'NPIPE'\"
  342. else
  343. echo shar: Extracting \"'NPIPE'\" \(1377 characters\)
  344. sed "s/^X//" >'NPIPE' <<'END_OF_FILE'
  345. XNPIPE
  346. X6/23/91
  347. X
  348. X
  349. XThis document defines the NPIPE protocol for UCSPI programs. A NPIPE
  350. Xclient communicates with a NPIPE server on the same machine through a
  351. Xpair of named pipes.
  352. X
  353. X<address> consists of two arguments: <username> <service>. Neither
  354. Xargument can contain slashes, newlines, or periods. <username> must not
  355. Xcontain colons. Any other character understood by the local machine may
  356. Xappear. <username> is a username on the machine, and <service> is any
  357. Xtext chosen by <username> to represent a service.
  358. X
  359. X<clientaddress> is the username of the client user. <serveraddress> is
  360. X<username>:<service>. Both of these addresses are limited to 100
  361. Xcharacters.
  362. X
  363. XThe descriptors passed to <userprogram> refer to two independent
  364. Xunlinked named pipes (fifos). Descriptor 6 supports only reading and
  365. Xdescriptor 7 supports only writing. The semantics of these pipes are
  366. Xdefined by the local UNIX variant; no operations other than those
  367. Xapplicable to normal pipes may be assumed.
  368. X
  369. XIt must not be possible for one user to set up a service with a
  370. Xdifferent <username>. It must not be possible for a user to conceal or
  371. Xdisguise the username of a client.
  372. X
  373. XAll NPIPE programs have undefined behavior if any username involved
  374. Xshares a uid with a different username.
  375. X
  376. XPreferred executable names: npipeclient, npipeserver, npipekiller.
  377. X
  378. X
  379. XUCSPI Administrator
  380. XDaniel J. Bernstein, brnstnd@nyu.edu
  381. END_OF_FILE
  382. if test 1377 -ne `wc -c <'NPIPE'`; then
  383.     echo shar: \"'NPIPE'\" unpacked with wrong size!
  384. fi
  385. # end of 'NPIPE'
  386. fi
  387. if test -f 'README' -a "${1}" != "-c" ; then 
  388.   echo shar: Will not clobber existing file \"'README'\"
  389. else
  390. echo shar: Extracting \"'README'\" \(2539 characters\)
  391. sed "s/^X//" >'README' <<'END_OF_FILE'
  392. Xclientserver 0.50, 6/25/91, Daniel J. Bernstein, brnstnd@nyu.edu.
  393. XWatch alt.sources.d for patches, comp.sources.unix for the next version.
  394. XLatest version inside stealth.acf.nyu.edu:pub/hier/clientserver/.
  395. X
  396. XThis has been extensively tested under SunOS 4.0.3, Ultrix 4.1, BSD 4.3,
  397. Xand the latest pre-BSD 4.4, and it appears to work on several other
  398. Xsystems. Under gcc you MUST define -fwritable-strings; sorry, old habits
  399. Xdie hard.
  400. X
  401. XModify UNDOMDIR and NPIPEDIR in Makefile for your system. Make some uid,
  402. Xsay undom, with access to UNDOMDIR; make UNDOMDIR mode 700 ownder undom.
  403. XMake some uid, say npipe, with access to NPIPEDIR; make NPIPEDIR mode
  404. X700 owner npipe. Make sure LIBS makes sense for you: most BSD systems
  405. Xneed -lresolv to use the resolver, and if you don't have getopt you'll
  406. Xhave to pick it up and put it into LIBS. That's it for configuration.
  407. X
  408. XMake. On BSD systems without named pipes, you should make only tcp and
  409. Xundom. On System V systems without sockets, you should make npipe. (I
  410. Xhave absolutely no idea whether npipe actually works on any modern
  411. XSystem V machines.) Under SunOS and Ultrix, make everything.
  412. X
  413. XTo test the programs, run testmain in this directory with appropriate
  414. Xarguments. Examples:
  415. X
  416. X  ./testmain NPIPE npipe <yourusername> blah
  417. X  ./testmain UNDOM undom <yourusername> foop
  418. X  ./testmain TCP tcp 0 <randomportnumber>
  419. X
  420. XThe 0 in the last line is an abbreviation for the local host. testmain
  421. Xshould say ``Everything compares okay''; if not, don't panic, because
  422. Xthe test code can report false alarms. (It uses sleep(1) for
  423. Xsynchronization.) Just run it again. To see what's going on, run
  424. Xtestucspi in place of testmain.
  425. X
  426. XInstall tcp{client,server,killer} somewhere, NOT setuid. Install
  427. Xundom{client,server,killer} somewhere, owner undom, mode 4755. Install
  428. Xnpipe{client,server,killer} somewhere, owner npipe, mode 4755. That's
  429. Xit. You might want to have your rc.local remove anything in UNDOMDIR or
  430. XNPIPEDIR.
  431. X
  432. X*PLEASE* fill out FORMLETTER and send it to me if you had problems.
  433. X*PLEASE* fill out FORMLETTER and send it to me if everything worked!
  434. XThanks for being a good sport.
  435. X
  436. XThe best documentation available at the moment is UCSPI and its
  437. Xassociated documents (TCP, UNDOM, NPIPE). Look at testucspi for an
  438. Xexample of how to communicate between independent processes with UCSPI.
  439. X
  440. X
  441. XXXX: handle EINTR better in undomserver.c and npipe*.c
  442. XXXX: restore signals properly?
  443. XXXX: fix all the exit codes
  444. XXXX: write man pages!
  445. XXXX: write a real README! and BLURB
  446. XXXX: provide semi-automatic reboot cleanup stuff?
  447. END_OF_FILE
  448. if test 2539 -ne `wc -c <'README'`; then
  449.     echo shar: \"'README'\" unpacked with wrong size!
  450. fi
  451. # end of 'README'
  452. fi
  453. if test -f 'TCP' -a "${1}" != "-c" ; then 
  454.   echo shar: Will not clobber existing file \"'TCP'\"
  455. else
  456. echo shar: Extracting \"'TCP'\" \(2835 characters\)
  457. sed "s/^X//" >'TCP' <<'END_OF_FILE'
  458. XTCP
  459. X6/19/91
  460. X
  461. X
  462. XThis document defines the TCP protocol for UCSPI programs. A TCP client
  463. Xcommunicates with a TCP server, on the same machine or on a different
  464. Xmachine, via the TCP/IP protocol through an Internet-domain socket.
  465. X
  466. X<address> consists of two arguments: <hostname> <port>. <hostname> may
  467. Xeither be a dotted IP address (such as 128.122.128.2) or a name which,
  468. Xon the local machine, somehow represents such an address. (For example,
  469. Xdomain names understood by DNS or by a local NIC-style host table might
  470. Xbe valid <hostname>s.) <hostname> may also be the single character 0,
  471. Xreferring to the local machine. <port> may either be a numeric TCP port
  472. Xnumber (such as 25, the standard SMTP port) or a name which, on the
  473. Xlocal machine, somehow represents a port number. Any character may
  474. Xappear in <hostname> or <port>.
  475. X
  476. X<clientaddress> and <serveraddress> share a single format:
  477. X<username>@<hostnumber>(<hostname>):<port>. <username> is a username on
  478. Xthe machine in question: inside TCPLOCAL, <username> is the real
  479. Xusername of the process, and inside TCPREMOTE, <username> is the
  480. Xusername returned by the other machine via RFC 931, or blank if the
  481. Xother machine does not support RFC 931. The client and server must take
  482. Xa -R option to turn off RFC 931 checking, and -r to turn it back on.
  483. XUnder -R, <username> will always be blank inside TCPREMOTE. <hostnumber>
  484. Xis the IP address of the communicating host. <hostname> is either that
  485. Xaddress or, if available, a name representing that address. <port> is
  486. Xthe relevant TCP port.
  487. X
  488. XNote that this address format is ambiguous, except in <port>. <hostname>
  489. Xdepends on local name lookup conventions, <username> may be blank, and
  490. X<hostnumber> might refer to the same machine through special numbers
  491. Xsuch as 127.0.0.1 and 0.0.0.0. Application programs which use
  492. X<clientaddress> and <serveraddress> should keep these caveats in mind.
  493. X
  494. XThe descriptors passed to <userprogram> refer to an INET-domain stream
  495. Xsocket, dup()ed from a single connect() or accept(). The semantics of
  496. Xthis socket are defined by the local UNIX variant, but it is expected
  497. Xthat it will support out-of-band data as in BSD systems past 4.2,
  498. Xsubject to the restrictions of RFC 1122 and RFC 1123.
  499. X
  500. XIf <port> is 0, the server must choose an available port number or
  501. Xreport an error. The client must take a -p <locport> option to set a
  502. Xdesired TCP port on the local side of the connection; if it cannot
  503. Xsatisfy this request, it must report an error.
  504. X
  505. XThe killer must not work upon a server running on a different machine.
  506. XThe killer and the server may communicate through files stored in the
  507. Xhome directory of the invoking user, as specified by environment
  508. Xvariable TCPHOME, or HOME if TCPHOME is not set.
  509. X
  510. XPreferred executable names: tcpclient, tcpserver, tcpkiller.
  511. X
  512. X
  513. XUCSPI Administrator
  514. XDaniel J. Bernstein, brnstnd@nyu.edu
  515. END_OF_FILE
  516. if test 2835 -ne `wc -c <'TCP'`; then
  517.     echo shar: \"'TCP'\" unpacked with wrong size!
  518. fi
  519. # end of 'TCP'
  520. fi
  521. if test -f 'UNDOM' -a "${1}" != "-c" ; then 
  522.   echo shar: Will not clobber existing file \"'UNDOM'\"
  523. else
  524. echo shar: Extracting \"'UNDOM'\" \(1409 characters\)
  525. sed "s/^X//" >'UNDOM' <<'END_OF_FILE'
  526. XUNDOM
  527. X6/16/91
  528. X
  529. X
  530. XThis document defines the UNDOM protocol for UCSPI programs. A UNDOM
  531. Xclient communicates with a UNDOM server on the same machine through a
  532. XUNIX-domain socket.
  533. X
  534. X<address> consists of two arguments: <username> <service>. Neither
  535. Xargument can contain slashes, newlines, or periods. <username> must not
  536. Xcontain colons. Any other character understood by the local machine may
  537. Xappear. <username> is a username on the machine, and <service> is any
  538. Xtext chosen by <username> to represent a service.
  539. X
  540. X<clientaddress> is the username of the client user. <serveraddress> is
  541. X<username>:<service>. Both of these addresses are limited to 100
  542. Xcharacters.
  543. X
  544. XThe descriptors passed to <userprogram> refer to a UNIX-domain stream
  545. Xsocket whose name is a function of <username> and <service>; they are
  546. Xdup()ed from a single connect() or accept(). The semantics of this
  547. Xsocket are defined by the local UNIX variant, but it is expected that it
  548. Xwill support file descriptor passing as in BSD systems past 4.2.
  549. X
  550. XIt must not be possible for one user to set up a service with a
  551. Xdifferent <username>. It must not be possible for a user to conceal or
  552. Xdisguise the username of a client.
  553. X
  554. XAll UNDOM programs have undefined behavior if any username involved
  555. Xshares a uid with a different username.
  556. X
  557. XPreferred executable names: undomclient, undomserver, undomkiller.
  558. X
  559. X
  560. XUCSPI Administrator
  561. XDaniel J. Bernstein, brnstnd@nyu.edu
  562. END_OF_FILE
  563. if test 1409 -ne `wc -c <'UNDOM'`; then
  564.     echo shar: \"'UNDOM'\" unpacked with wrong size!
  565. fi
  566. # end of 'UNDOM'
  567. fi
  568. if test -f 'authuser.c' -a "${1}" != "-c" ; then 
  569.   echo shar: Will not clobber existing file \"'authuser.c'\"
  570. else
  571. echo shar: Extracting \"'authuser.c'\" \(3622 characters\)
  572. sed "s/^X//" >'authuser.c' <<'END_OF_FILE'
  573. X/*
  574. X5/6/91 DJB baseline authuser 3.1. Public domain.
  575. X*/
  576. X
  577. X#include <stdio.h>
  578. X#include <sys/types.h>
  579. X#include <sys/socket.h>
  580. X#include <netinet/in.h>
  581. X#include <arpa/inet.h>
  582. X#include <netdb.h>
  583. X#include <errno.h>
  584. X#include <ctype.h>
  585. Xextern int errno;
  586. X#include "authuser.h"
  587. X
  588. Xunsigned short auth_tcpport = 113;
  589. X
  590. X#define SIZ 500 /* various buffers */
  591. X
  592. Xstatic int usercmp(u,v)
  593. Xregister char *u;
  594. Xregister char *v;
  595. X{
  596. X /* is it correct to consider Foo and fOo the same user? yes */
  597. X /* but the function of this routine may change later */
  598. X while (*u && *v)
  599. X   if (tolower(*u) != tolower(*v))
  600. X     return tolower(*u) - tolower(*v);
  601. X   else
  602. X     ++u,++v;
  603. X return *u || *v;
  604. X}
  605. X
  606. Xstatic char authline[SIZ];
  607. X
  608. Xchar *auth_xline(user,fd,in)
  609. Xregister char *user; /* the supposed name of the user, NULL if unknown */
  610. Xregister int fd; /* the file descriptor of the connection */
  611. Xregister unsigned long *in;
  612. X{
  613. X unsigned short local;
  614. X unsigned short remote;
  615. X register char *ruser;
  616. X
  617. X if (auth_fd(fd,in,&local,&remote) == -1)
  618. X   return 0;
  619. X ruser = auth_tcpuser(*in,local,remote);
  620. X if (!ruser)
  621. X   return 0;
  622. X if (!user)
  623. X   user = ruser; /* forces X-Auth-User */
  624. X (void) sprintf(authline,
  625. X     (usercmp(ruser,user) ? "X-Forgery-By: %s" : "X-Auth-User: %s"),
  626. X     ruser);
  627. X return authline;
  628. X}
  629. X
  630. Xint auth_fd(fd,in,local,remote)
  631. Xregister int fd;
  632. Xregister unsigned long *in;
  633. Xregister unsigned short *local;
  634. Xregister unsigned short *remote;
  635. X{
  636. X struct sockaddr_in sa;
  637. X int dummy;
  638. X
  639. X dummy = sizeof(sa);
  640. X if (getsockname(fd,&sa,&dummy) == -1)
  641. X   return -1;
  642. X if (sa.sin_family != AF_INET)
  643. X  {
  644. X   errno = EAFNOSUPPORT;
  645. X   return -1;
  646. X  }
  647. X *local = ntohs(sa.sin_port);
  648. X dummy = sizeof(sa);
  649. X if (getpeername(fd,&sa,&dummy) == -1)
  650. X   return -1;
  651. X *remote = ntohs(sa.sin_port);
  652. X *in = sa.sin_addr.s_addr;
  653. X return 0;
  654. X}
  655. X
  656. Xstatic char ruser[SIZ];
  657. Xstatic char realbuf[SIZ];
  658. Xstatic char *buf;
  659. X
  660. Xchar *auth_tcpuser(in,local,remote)
  661. Xregister unsigned long in;
  662. Xregister unsigned short local;
  663. Xregister unsigned short remote;
  664. X{
  665. X struct sockaddr_in sa;
  666. X register int s;
  667. X register int buflen;
  668. X register int w;
  669. X register int saveerrno;
  670. X char ch;
  671. X unsigned short rlocal;
  672. X unsigned short rremote;
  673. X
  674. X if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1)
  675. X   return 0;
  676. X sa.sin_family = AF_INET;
  677. X sa.sin_port = htons(auth_tcpport);
  678. X sa.sin_addr.s_addr = in;
  679. X if (connect(s,&sa,sizeof(sa)) == -1)
  680. X  {
  681. X   saveerrno = errno;
  682. X   (void) close(s);
  683. X   errno = saveerrno;
  684. X   return 0;
  685. X  }
  686. X
  687. X buf = realbuf;
  688. X (void) sprintf(buf,"%u , %u\r\n",(unsigned int) remote,(unsigned int) local);
  689. X /* note the reversed order---the example in the RFC is misleading */
  690. X buflen = strlen(buf);
  691. X while ((w = write(s,buf,buflen)) < buflen)
  692. X   if (w == -1) /* should we worry about 0 as well? */
  693. X    {
  694. X     saveerrno = errno;
  695. X     (void) close(s);
  696. X     errno = saveerrno;
  697. X     return 0;
  698. X    }
  699. X   else
  700. X    {
  701. X     buf += w;
  702. X     buflen -= w;
  703. X    }
  704. X buf = realbuf;
  705. X while ((w = read(s,&ch,1)) == 1)
  706. X  {
  707. X   *buf = ch;
  708. X   if ((ch != ' ') && (ch != '\t') && (ch != '\r'))
  709. X     ++buf;
  710. X   if ((buf - realbuf == sizeof(realbuf) - 1) || (ch == '\n'))
  711. X     break;
  712. X  }
  713. X if (w == -1)
  714. X  {
  715. X   saveerrno = errno;
  716. X   (void) close(s);
  717. X   errno = saveerrno;
  718. X   return 0;
  719. X  }
  720. X *buf = '\0';
  721. X
  722. X if (sscanf(realbuf,"%hd,%hd: USERID :%*[^:]:%s",&rremote,&rlocal,ruser) < 3)
  723. X  {
  724. X   (void) close(s);
  725. X   errno = EIO;
  726. X   /* makes sense, right? well, not when USERID failed to match ERROR */
  727. X   /* but there's no good error to return in that case */
  728. X   return 0;
  729. X  }
  730. X if ((remote != rremote) || (local != rlocal))
  731. X  {
  732. X   (void) close(s);
  733. X   errno = EIO;
  734. X   return 0;
  735. X  }
  736. X /* XXX: we're not going to do any backslash processing */
  737. X (void) close(s);
  738. X return ruser;
  739. X}
  740. END_OF_FILE
  741. if test 3622 -ne `wc -c <'authuser.c'`; then
  742.     echo shar: \"'authuser.c'\" unpacked with wrong size!
  743. fi
  744. # end of 'authuser.c'
  745. fi
  746. if test -f 'authuser.h' -a "${1}" != "-c" ; then 
  747.   echo shar: Will not clobber existing file \"'authuser.h'\"
  748. else
  749. echo shar: Extracting \"'authuser.h'\" \(161 characters\)
  750. sed "s/^X//" >'authuser.h' <<'END_OF_FILE'
  751. X#ifndef AUTHUSER_H
  752. X#define AUTHUSER_H
  753. X
  754. Xextern unsigned short auth_tcpport;
  755. Xextern char *auth_xline();
  756. Xextern int auth_fd();
  757. Xextern char *auth_tcpuser();
  758. X
  759. X#endif
  760. END_OF_FILE
  761. if test 161 -ne `wc -c <'authuser.h'`; then
  762.     echo shar: \"'authuser.h'\" unpacked with wrong size!
  763. fi
  764. # end of 'authuser.h'
  765. fi
  766. if test -f 'dupdup.c' -a "${1}" != "-c" ; then 
  767.   echo shar: Will not clobber existing file \"'dupdup.c'\"
  768. else
  769. echo shar: Extracting \"'dupdup.c'\" \(2174 characters\)
  770. sed "s/^X//" >'dupdup.c' <<'END_OF_FILE'
  771. X/* Public domain. */
  772. X
  773. X#include <fcntl.h>
  774. X#include "dupdup.h"
  775. X
  776. Xstatic int dupit(old,new)
  777. Xint old;
  778. Xint new;
  779. X{
  780. X/* What follows is roughly equivalent to the following:
  781. X      if (dup2(old,new) == -1) return -1; close(old); return 0;
  782. X   Differences: errno can be different; this works under System V;
  783. X   this is about twice as slow.
  784. X*/
  785. X if (old == new) /* shouldn't happen */
  786. X   return 0;
  787. X if (fcntl(old,F_GETFL,0) == -1) /* old is bad */
  788. X   return -1;
  789. X close(new); /* XXX: check error codes? */
  790. X if (fcntl(old,F_DUPFD,new) == -1) /* can't dup */
  791. X   return -1;
  792. X close(old); /*XXX*/
  793. X return 0;
  794. X}
  795. X
  796. Xint dupdup(d,n)
  797. Xint *d;
  798. Xint n;
  799. X{
  800. X int i;
  801. X int j;
  802. X int k;
  803. X int l;
  804. X
  805. X /* Descriptor i will become descriptor d[i], if d[i] != -1. */
  806. X /* The original descriptor d[i] will disappear. */
  807. X /* The array d[i] may be mangled freely. */
  808. X /* n is the size of d[]. */
  809. X /* No guarantees if i and j both become k. */
  810. X /* errno is set properly on a -1 return. */
  811. X
  812. X for (i = 0;i < n;++i)
  813. X   if (d[i] != -1)
  814. X    {
  815. X     for (j = d[i];(j != -1) && (j != i) && (j != d[j]);j = d[j])
  816. X       ;
  817. X     if ((j == -1) || (j == d[j]))
  818. X       if (j == i)
  819. X     ; /* self-loop */
  820. X       else
  821. X    { /* no cycle */
  822. X     if (j != -1)
  823. X       d[j] = -1;
  824. X     if (d[d[i]] == -1) /*XXX*/
  825. X      {
  826. X       if (dupit(i,d[i]) == -1)
  827. X         return -1;
  828. X       d[i] = -1;
  829. X      }
  830. X     else
  831. X      {
  832. X       k = i; j = d[i];
  833. X       do
  834. X        {
  835. X         l = d[j]; d[j] = k; k = j; j = l;
  836. X        }
  837. X       while (j != -1);
  838. X       for (j = k;j != i;j = k)
  839. X        {
  840. X         if (dupit(d[j],j) == -1)
  841. X           return -1;
  842. X         k = d[j];
  843. X         d[j] = -1;
  844. X        }
  845. X       d[i] = -1;
  846. X      }
  847. X    }
  848. X     else
  849. X      { /* cycle */
  850. X       if (dupit(i,n) == -1)
  851. X     return -1;
  852. X       if (d[d[i]] == i) /*XXX*/
  853. X    {
  854. X     if (dupit(d[i],i) == -1)
  855. X       return -1;
  856. X     if (dupit(n,d[i]) == -1)
  857. X       return -1;
  858. X     d[d[i]] = -1;
  859. X     d[i] = -1;
  860. X    }
  861. X       else
  862. X        {
  863. X         k = i; j = d[i];
  864. X         do
  865. X          {
  866. X           l = d[j]; d[j] = k; k = j; j = l;
  867. X          }
  868. X         while (j != i);
  869. X         for (j = k;j != i;j = k)
  870. X          {
  871. X       if (dupit(d[j],j) == -1)
  872. X         return -1;
  873. X       k = d[j];
  874. X           d[j] = -1;
  875. X          }
  876. X         d[i] = -1;
  877. X     if (dupit(n,k) == -1)
  878. X       return -1;
  879. X        }
  880. X      }
  881. X    }
  882. X return 0;
  883. X}
  884. END_OF_FILE
  885. if test 2174 -ne `wc -c <'dupdup.c'`; then
  886.     echo shar: \"'dupdup.c'\" unpacked with wrong size!
  887. fi
  888. # end of 'dupdup.c'
  889. fi
  890. if test -f 'dupdup.h' -a "${1}" != "-c" ; then 
  891.   echo shar: Will not clobber existing file \"'dupdup.h'\"
  892. else
  893. echo shar: Extracting \"'dupdup.h'\" \(64 characters\)
  894. sed "s/^X//" >'dupdup.h' <<'END_OF_FILE'
  895. X#ifndef DUPDUP_H
  896. X#define DUPDUP_H
  897. X
  898. Xextern int dupdup();
  899. X
  900. X#endif
  901. END_OF_FILE
  902. if test 64 -ne `wc -c <'dupdup.h'`; then
  903.     echo shar: \"'dupdup.h'\" unpacked with wrong size!
  904. fi
  905. # end of 'dupdup.h'
  906. fi
  907. if test -f 'env.c' -a "${1}" != "-c" ; then 
  908.   echo shar: Will not clobber existing file \"'env.c'\"
  909. else
  910. echo shar: Extracting \"'env.c'\" \(2157 characters\)
  911. sed "s/^X//" >'env.c' <<'END_OF_FILE'
  912. X/* Public domain. */
  913. X
  914. X/*
  915. XThese are portable versions of putenv(). env_put("FOO=BAR") is like
  916. XFOO=BAR inside sh; env_unset("FOO") unsets any variable FOO. env_init()
  917. Xis optional initialization. env_get is just like getenv. Of course, all
  918. Xchanges are tracked through environ, so execvp() and friends will pick
  919. Xup the new variables.
  920. X*/
  921. X
  922. X/* uses environ, malloc, free, strlen, strncmp */
  923. X
  924. X#include "env.h"
  925. X#include "malloc.h"
  926. X
  927. Xextern char **environ;
  928. Xstatic int init = 0;
  929. Xstatic int numenv;
  930. Xstatic int allocenv;
  931. X
  932. Xextern char *env_get(s)
  933. Xchar *s;
  934. X{
  935. X int i;
  936. X int slen;
  937. X
  938. X if (!init)
  939. X   if (env_init())
  940. X     return 0;
  941. X
  942. X slen = strlen(s);
  943. X for (i = 0;i < numenv;++i)
  944. X   if ((!strncmp(s,environ[i],slen)) && (environ[i][slen] == '='))
  945. X     return environ[i] + slen + 1;
  946. X return 0;
  947. X}
  948. X
  949. Xextern int env_unset(s)
  950. Xchar *s;
  951. X{
  952. X int i;
  953. X int slen;
  954. X if (!init)
  955. X   if (env_init())
  956. X     return -1;
  957. X slen = strlen(s);
  958. X for (i = 0;i < numenv;++i)
  959. X   if ((!strncmp(s,environ[i],slen)) && (environ[i][slen] == '='))
  960. X    {
  961. X     if (i < --numenv)
  962. X       environ[i] = environ[numenv];
  963. X     environ[numenv] = 0;
  964. X    }
  965. X return 0;
  966. X}
  967. X
  968. Xstatic int env_realloc()
  969. X{
  970. X char **envp;
  971. X
  972. X allocenv = numenv + 30;
  973. X envp = environ;
  974. X environ = (char **) malloc(allocenv * (int) sizeof(char *));
  975. X if (!environ)
  976. X  {
  977. X   environ = envp;
  978. X   allocenv = numenv;
  979. X   return -1;
  980. X  }
  981. X numenv = 0;
  982. X while (*envp)
  983. X  {
  984. X   environ[numenv] = *envp;
  985. X   ++numenv;
  986. X   ++envp;
  987. X  }
  988. X environ[numenv] = 0;
  989. X free((char *) (envp - numenv));
  990. X return 0;
  991. X}
  992. X
  993. Xstatic int env_add(s)
  994. Xchar *s;
  995. X{
  996. X char *t;
  997. X for (t = s;*t;++t)
  998. X   if (*t == '=')
  999. X     break;
  1000. X if (*t)
  1001. X  {
  1002. X   *t = 0;
  1003. X   if (env_unset(s))
  1004. X     return -1;
  1005. X   *t = '=';
  1006. X  }
  1007. X if (numenv == allocenv)
  1008. X   if (env_realloc())
  1009. X     return -1;
  1010. X environ[numenv] = s;
  1011. X ++numenv;
  1012. X environ[numenv] = 0;
  1013. X return 0;
  1014. X}
  1015. X
  1016. Xint env_init()
  1017. X{
  1018. X char **envp;
  1019. X
  1020. X numenv = 0;
  1021. X allocenv = 0;
  1022. X envp = environ;
  1023. X environ = (char **) malloc(sizeof(char *));
  1024. X if (!environ)
  1025. X  {
  1026. X   environ = envp;
  1027. X   return -1;
  1028. X  }
  1029. X init = 1;
  1030. X while (*envp)
  1031. X  {
  1032. X   if (env_add(*envp))
  1033. X     return -1;
  1034. X   ++envp;
  1035. X  }
  1036. X return 0;
  1037. X}
  1038. X
  1039. Xint env_put(s)
  1040. Xchar *s;
  1041. X{
  1042. X if (!init)
  1043. X   if (env_init())
  1044. X     return -1;
  1045. X return env_add(s);
  1046. X}
  1047. END_OF_FILE
  1048. if test 2157 -ne `wc -c <'env.c'`; then
  1049.     echo shar: \"'env.c'\" unpacked with wrong size!
  1050. fi
  1051. # end of 'env.c'
  1052. fi
  1053. if test -f 'env.h' -a "${1}" != "-c" ; then 
  1054.   echo shar: Will not clobber existing file \"'env.h'\"
  1055. else
  1056. echo shar: Extracting \"'env.h'\" \(153 characters\)
  1057. sed "s/^X//" >'env.h' <<'END_OF_FILE'
  1058. X#ifndef ENV_H
  1059. X#define ENV_H
  1060. X
  1061. Xextern int env_init();
  1062. Xextern int env_put();
  1063. Xextern int env_unset();
  1064. Xextern char *env_get(); /* for completeness */
  1065. X
  1066. X#endif
  1067. END_OF_FILE
  1068. if test 153 -ne `wc -c <'env.h'`; then
  1069.     echo shar: \"'env.h'\" unpacked with wrong size!
  1070. fi
  1071. # end of 'env.h'
  1072. fi
  1073. if test -f 'errno.h' -a "${1}" != "-c" ; then 
  1074.   echo shar: Will not clobber existing file \"'errno.h'\"
  1075. else
  1076. echo shar: Extracting \"'errno.h'\" \(78 characters\)
  1077. sed "s/^X//" >'errno.h' <<'END_OF_FILE'
  1078. X#ifndef ERRNO_H
  1079. X#define ERRNO_H
  1080. X
  1081. X#include <errno.h>
  1082. Xextern int errno;
  1083. X
  1084. X#endif
  1085. END_OF_FILE
  1086. if test 78 -ne `wc -c <'errno.h'`; then
  1087.     echo shar: \"'errno.h'\" unpacked with wrong size!
  1088. fi
  1089. # end of 'errno.h'
  1090. fi
  1091. if test -f 'getopt.h' -a "${1}" != "-c" ; then 
  1092.   echo shar: Will not clobber existing file \"'getopt.h'\"
  1093. else
  1094. echo shar: Extracting \"'getopt.h'\" \(298 characters\)
  1095. sed "s/^X//" >'getopt.h' <<'END_OF_FILE'
  1096. X#ifndef GETOPT_H
  1097. X#define GETOPT_H
  1098. X
  1099. X/* I'm trusting the user to acquire a getopt library, rather than
  1100. Xproviding one myself. This is probably a mistake. */
  1101. X
  1102. X/* The following should be in /usr/include/getopt.h but often aren't. */
  1103. X
  1104. Xextern int getopt();
  1105. Xextern char *optarg;
  1106. Xextern int optind;
  1107. X
  1108. X#endif
  1109. END_OF_FILE
  1110. if test 298 -ne `wc -c <'getopt.h'`; then
  1111.     echo shar: \"'getopt.h'\" unpacked with wrong size!
  1112. fi
  1113. # end of 'getopt.h'
  1114. fi
  1115. if test -f 'hostname.c' -a "${1}" != "-c" ; then 
  1116.   echo shar: Will not clobber existing file \"'hostname.c'\"
  1117. else
  1118. echo shar: Extracting \"'hostname.c'\" \(1191 characters\)
  1119. sed "s/^X//" >'hostname.c' <<'END_OF_FILE'
  1120. X/* History:
  1121. X5/1/91 DJB baseline public domain. todo: cache hosts.
  1122. X*/
  1123. X
  1124. X#include <sys/types.h>
  1125. X#include <sys/socket.h>
  1126. X#include <netdb.h>
  1127. X#include <netinet/in.h>
  1128. X#include "hostname.h"
  1129. X#include "numeric.h"
  1130. X
  1131. Xint inaddr2hostname(inaddr,hostname)
  1132. Xstruct in_addr inaddr;
  1133. Xchar **hostname;
  1134. X{
  1135. X struct hostent *he;
  1136. X static char hn[30];
  1137. X unsigned char *x;
  1138. X
  1139. X if (he = gethostbyaddr(&inaddr,sizeof(inaddr),AF_INET))
  1140. X  {
  1141. X   *hostname = he->h_name;
  1142. X   return 0;
  1143. X  }
  1144. X x = (unsigned char *) &inaddr;
  1145. X sprintf(hn,"%d.%d.%d.%d"
  1146. X   ,(int) (unsigned int) x[0],(int) (unsigned int) x[1]
  1147. X   ,(int) (unsigned int) x[2],(int) (unsigned int) x[3]
  1148. X  );
  1149. X *hostname = hn;
  1150. X return 1;
  1151. X}
  1152. X
  1153. Xint hostname2inaddr(hostname,inaddr)
  1154. Xchar *hostname;
  1155. Xstruct in_addr *inaddr;
  1156. X{
  1157. X struct hostent *he;
  1158. X char *x;
  1159. X int h1; int h2; int h3; int h4;
  1160. X
  1161. X x = (char *) inaddr;
  1162. X if (numericdots(hostname) == 3)
  1163. X   if (sscanf(hostname,"%d.%d.%d.%d",&h1,&h2,&h3,&h4) == 4)
  1164. X    {
  1165. X     x[0] = h1; x[1] = h2; x[2] = h3; x[3] = h4;
  1166. X     return 1;
  1167. X    }
  1168. X /* could use inet_ntoa here */
  1169. X he = gethostbyname(hostname);
  1170. X if (!he)
  1171. X   return -1; /*XXX*/
  1172. X x[0] = he->h_addr[0];
  1173. X x[1] = he->h_addr[1];
  1174. X x[2] = he->h_addr[2];
  1175. X x[3] = he->h_addr[3];
  1176. X return 0;
  1177. X}
  1178. END_OF_FILE
  1179. if test 1191 -ne `wc -c <'hostname.c'`; then
  1180.     echo shar: \"'hostname.c'\" unpacked with wrong size!
  1181. fi
  1182. # end of 'hostname.c'
  1183. fi
  1184. if test -f 'hostname.h' -a "${1}" != "-c" ; then 
  1185.   echo shar: Will not clobber existing file \"'hostname.h'\"
  1186. else
  1187. echo shar: Extracting \"'hostname.h'\" \(107 characters\)
  1188. sed "s/^X//" >'hostname.h' <<'END_OF_FILE'
  1189. X#ifndef HOSTNAME_H
  1190. X#define HOSTNAME_H
  1191. X
  1192. Xextern int inaddr2hostname();
  1193. Xextern int hostname2inaddr();
  1194. X
  1195. X#endif
  1196. END_OF_FILE
  1197. if test 107 -ne `wc -c <'hostname.h'`; then
  1198.     echo shar: \"'hostname.h'\" unpacked with wrong size!
  1199. fi
  1200. # end of 'hostname.h'
  1201. fi
  1202. if test -f 'malloc.h' -a "${1}" != "-c" ; then 
  1203.   echo shar: Will not clobber existing file \"'malloc.h'\"
  1204. else
  1205. echo shar: Extracting \"'malloc.h'\" \(66 characters\)
  1206. sed "s/^X//" >'malloc.h' <<'END_OF_FILE'
  1207. X#ifndef MALLOC_H
  1208. X#define MALLOC_H
  1209. X
  1210. Xextern char *malloc();
  1211. X
  1212. X#endif
  1213. END_OF_FILE
  1214. if test 66 -ne `wc -c <'malloc.h'`; then
  1215.     echo shar: \"'malloc.h'\" unpacked with wrong size!
  1216. fi
  1217. # end of 'malloc.h'
  1218. fi
  1219. if test -f 'npipekiller.c' -a "${1}" != "-c" ; then 
  1220.   echo shar: Will not clobber existing file \"'npipekiller.c'\"
  1221. else
  1222. echo shar: Extracting \"'npipekiller.c'\" \(3207 characters\)
  1223. sed "s/^X//" >'npipekiller.c' <<'END_OF_FILE'
  1224. X/* Public domain. */
  1225. X
  1226. X#include <stdio.h>
  1227. X#include <sys/types.h>
  1228. X#include <sys/file.h>
  1229. X#include <signal.h>
  1230. X#include <fcntl.h>
  1231. X#include "dupdup.h"
  1232. X#include "malloc.h"
  1233. X#include "errno.h"
  1234. X#include "username.h"
  1235. X#include "env.h"
  1236. X#include "getopt.h"
  1237. X#include "numfiles.h"
  1238. X
  1239. X#ifndef F_LOCK
  1240. X#define F_LOCK 1
  1241. X#endif
  1242. X#ifndef O_RDONLY
  1243. X#define O_RDONLY 0
  1244. X#endif
  1245. X#ifndef O_WRONLY
  1246. X#define O_WRONLY 1
  1247. X#endif
  1248. X#ifndef O_RDWR
  1249. X#define O_RDWR 2
  1250. X#endif
  1251. X
  1252. Xstatic int flagverbose = 1;
  1253. X
  1254. Xstatic char errbuf[500];
  1255. Xvoid die(n,s) int n; char *s;
  1256. X{ if (flagverbose) fprintf(stderr,"npipekiller: fatal: %s\n",s); exit(n); }
  1257. Xvoid dies(n,s,t) int n; char *s; char *t;
  1258. X{ if (flagverbose) fprintf(stderr,"npipekiller: fatal: %s%s\n",s,t); exit(n); }
  1259. Xvoid diep(n,s) int n; char *s;
  1260. X{ if (flagverbose) sprintf(errbuf,"npipekiller: fatal: %s",s); perror(errbuf); exit(n); }
  1261. Xvoid warnp(s) char *s;
  1262. X{ if (flagverbose) sprintf(errbuf,"npipekiller: warning: %s",s); perror(errbuf); }
  1263. Xvoid warnsp(s,t) char *s; char *t;
  1264. X{ if (flagverbose) sprintf(errbuf,"npipekiller: warning: %s%s",s,t); perror(errbuf); }
  1265. X
  1266. Xmain(argc,argv,envp)
  1267. Xint argc;
  1268. Xchar *argv[];
  1269. Xchar *envp[];
  1270. X{
  1271. X int arguid;
  1272. X int uid;
  1273. X int i;
  1274. X int fdserv;
  1275. X int fdlock;
  1276. X char fnlock[200];
  1277. X char fnserv[200];
  1278. X int m;
  1279. X int n;
  1280. X int r;
  1281. X char buf[100];
  1282. X char *uname;
  1283. X int opt;
  1284. X
  1285. X while ((opt = getopt(argc,argv,"qQ")) != EOF)
  1286. X   switch(opt)
  1287. X    {
  1288. X     case 'q':
  1289. X       flagverbose = 0; break;
  1290. X     case 'Q':
  1291. X       flagverbose = 1; break;
  1292. X     case '?':
  1293. X       break; /*XXX*/
  1294. X     default:
  1295. X       break; /*XXX*/
  1296. X    }
  1297. X argc -= optind; argv += optind;
  1298. X
  1299. X if (argc < 2)
  1300. X   die(1,"need at least two arguments");
  1301. X
  1302. X uid = getuid();
  1303. X if (username2uid(argv[0],&arguid) == -1)
  1304. X   dies(2,"cannot figure out username ",argv[0]);
  1305. X
  1306. X if (arguid != uid)
  1307. X   dies(1,"permission denied by ",argv[0]);
  1308. X
  1309. X for (i = 0;argv[0][i];++i)
  1310. X   if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
  1311. X     dies(4,"illegal characters in username ",argv[0]);
  1312. X for (i = 0;argv[1][i];++i)
  1313. X   if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
  1314. X     dies(5,"illegal characters in service ",argv[1]);
  1315. X
  1316. X signal(SIGPIPE,SIG_IGN);
  1317. X
  1318. X if (uid2username(uid,&uname) == -1) /* will never happen */
  1319. X   die(2,"cannot figure out my own username");
  1320. X
  1321. X if (strlen(NPIPEDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 90) /*XXX*/
  1322. X   die(8,"server filenames too long");
  1323. X sprintf(fnserv,"%s/%ds%s",NPIPEDIR,arguid,argv[1]);
  1324. X sprintf(fnlock,"%s/%dl%s",NPIPEDIR,arguid,argv[1]);
  1325. X sprintf(buf,"%d",0);
  1326. X n = strlen(buf);
  1327. X if (n + strlen(uname) + 10 > sizeof(buf))
  1328. X   die(8,"username too long");
  1329. X strcpy(buf + n + 1,uname);
  1330. X n += strlen(uname) + 2;
  1331. X
  1332. X fdlock = open(fnlock,O_RDWR,0);
  1333. X if (fdlock == -1)
  1334. X   diep(1,"cannot open lock file");
  1335. X /* Here's the tricky bit: file locking. :-( */
  1336. X /* XXX: We assume that anyone with named pipes also has lockf(). */
  1337. X if (lockf(fdlock,F_LOCK,1) == -1)
  1338. X   diep(1,"cannot wait for lock on lock file");
  1339. X
  1340. X fdserv = open(fnserv,O_WRONLY,0);
  1341. X if (fdserv == -1)
  1342. X   diep(1,"cannot open server's named pipe");
  1343. X
  1344. X m = 0;
  1345. X r = 0;
  1346. X while ((m < n) && ((r = write(fdserv,buf + m,n - m)) > 0))
  1347. X   m += r;
  1348. X if (r <= 0)
  1349. X   die(1,"cannot tell server to kill itself");
  1350. X
  1351. X exit(0);
  1352. X}
  1353. END_OF_FILE
  1354. if test 3207 -ne `wc -c <'npipekiller.c'`; then
  1355.     echo shar: \"'npipekiller.c'\" unpacked with wrong size!
  1356. fi
  1357. # end of 'npipekiller.c'
  1358. fi
  1359. if test -f 'numeric.c' -a "${1}" != "-c" ; then 
  1360.   echo shar: Will not clobber existing file \"'numeric.c'\"
  1361. else
  1362. echo shar: Extracting \"'numeric.c'\" \(782 characters\)
  1363. sed "s/^X//" >'numeric.c' <<'END_OF_FILE'
  1364. X/* History:
  1365. X6/19/91 DJB added numericdots()
  1366. X5/1/91 DJB baseline public domain
  1367. X*/
  1368. X
  1369. X/*
  1370. X
  1371. Xint numeric(s) char *s; returns 1 if s is entirely composed of the
  1372. Xdigits 0 through 9, 0 otherwise.
  1373. X
  1374. X*/
  1375. X
  1376. X#include "numeric.h"
  1377. X
  1378. Xint numeric(s)
  1379. Xchar *s;
  1380. X{
  1381. X while (*s)
  1382. X  {
  1383. X   if ((*s != '0') && (*s != '1') && (*s != '2') && (*s != '3') && (*s != '4')
  1384. X    && (*s != '5') && (*s != '6') && (*s != '7') && (*s != '8') && (*s != '9'))
  1385. X     return 0;
  1386. X   ++s;
  1387. X  }
  1388. X return 1;
  1389. X}
  1390. X
  1391. Xint numericdots(s)
  1392. Xchar *s;
  1393. X{
  1394. X int dots;
  1395. X
  1396. X dots = 0;
  1397. X while (*s)
  1398. X  {
  1399. X   if ((*s != '0') && (*s != '1') && (*s != '2') && (*s != '3') && (*s != '4')
  1400. X    && (*s != '5') && (*s != '6') && (*s != '7') && (*s != '8') && (*s != '9')
  1401. X    && (*s != '.')
  1402. X    )
  1403. X     return -1;
  1404. X   if (*s == '.')
  1405. X     ++dots;
  1406. X   ++s;
  1407. X  }
  1408. X return dots;
  1409. X}
  1410. END_OF_FILE
  1411. if test 782 -ne `wc -c <'numeric.c'`; then
  1412.     echo shar: \"'numeric.c'\" unpacked with wrong size!
  1413. fi
  1414. # end of 'numeric.c'
  1415. fi
  1416. if test -f 'numeric.h' -a "${1}" != "-c" ; then 
  1417.   echo shar: Will not clobber existing file \"'numeric.h'\"
  1418. else
  1419. echo shar: Extracting \"'numeric.h'\" \(93 characters\)
  1420. sed "s/^X//" >'numeric.h' <<'END_OF_FILE'
  1421. X#ifndef NUMERIC_H
  1422. X#define NUMERIC_H
  1423. X
  1424. Xextern int numeric();
  1425. Xextern int numericdots();
  1426. X
  1427. X#endif
  1428. END_OF_FILE
  1429. if test 93 -ne `wc -c <'numeric.h'`; then
  1430.     echo shar: \"'numeric.h'\" unpacked with wrong size!
  1431. fi
  1432. # end of 'numeric.h'
  1433. fi
  1434. if test -f 'numfiles.h' -a "${1}" != "-c" ; then 
  1435.   echo shar: Will not clobber existing file \"'numfiles.h'\"
  1436. else
  1437. echo shar: Extracting \"'numfiles.h'\" \(82 characters\)
  1438. sed "s/^X//" >'numfiles.h' <<'END_OF_FILE'
  1439. X#ifndef NUMFILES_H
  1440. X#define NUMFILES_H
  1441. X
  1442. X#define NUMFILES (getdtablesize())
  1443. X
  1444. X#endif
  1445. END_OF_FILE
  1446. if test 82 -ne `wc -c <'numfiles.h'`; then
  1447.     echo shar: \"'numfiles.h'\" unpacked with wrong size!
  1448. fi
  1449. # end of 'numfiles.h'
  1450. fi
  1451. if test -f 'portname.c' -a "${1}" != "-c" ; then 
  1452.   echo shar: Will not clobber existing file \"'portname.c'\"
  1453. else
  1454. echo shar: Extracting \"'portname.c'\" \(764 characters\)
  1455. sed "s/^X//" >'portname.c' <<'END_OF_FILE'
  1456. X/* History:
  1457. X6/20/91 DJB added proto arg
  1458. X5/9/91 DJB fixed for backwards architectures, tnx VA
  1459. X5/1/91 DJB baseline public domain
  1460. X*/
  1461. X
  1462. X#include "portname.h"
  1463. X#include "numeric.h"
  1464. X#include <netdb.h>
  1465. X
  1466. X/* XXX: cache */
  1467. X
  1468. Xint port2portname(port,pop,proto)
  1469. Xint port;
  1470. Xchar **pop;
  1471. Xchar *proto;
  1472. X{
  1473. X struct servent *se;
  1474. X static char po[20];
  1475. X
  1476. X if (se = getservbyport(port,proto))
  1477. X  {
  1478. X   *pop = se->s_name;
  1479. X   return 0;
  1480. X  }
  1481. X sprintf(po,"%d",port);
  1482. X *pop = po;
  1483. X return 1;
  1484. X}
  1485. X
  1486. Xint portname2port(po,port,proto)
  1487. Xchar *po;
  1488. Xint *port;
  1489. Xchar *proto;
  1490. X{
  1491. X struct servent *se;
  1492. X
  1493. X if (numeric(po))
  1494. X  {
  1495. X   *port = atoi(po);
  1496. X   return 1;
  1497. X  }
  1498. X se = getservbyname(po,proto);
  1499. X if (!se)
  1500. X   return -1; /*XXX*/
  1501. X *port = ntohs(se->s_port);
  1502. X   /* XXX: stupidity alert: se->s_port is an int! */
  1503. X return 0;
  1504. X}
  1505. END_OF_FILE
  1506. if test 764 -ne `wc -c <'portname.c'`; then
  1507.     echo shar: \"'portname.c'\" unpacked with wrong size!
  1508. fi
  1509. # end of 'portname.c'
  1510. fi
  1511. if test -f 'portname.h' -a "${1}" != "-c" ; then 
  1512.   echo shar: Will not clobber existing file \"'portname.h'\"
  1513. else
  1514. echo shar: Extracting \"'portname.h'\" \(103 characters\)
  1515. sed "s/^X//" >'portname.h' <<'END_OF_FILE'
  1516. X#ifndef PORTNAME_H
  1517. X#define PORTNAME_H
  1518. X
  1519. Xextern int port2portname();
  1520. Xextern int portname2port();
  1521. X
  1522. X#endif
  1523. END_OF_FILE
  1524. if test 103 -ne `wc -c <'portname.h'`; then
  1525.     echo shar: \"'portname.h'\" unpacked with wrong size!
  1526. fi
  1527. # end of 'portname.h'
  1528. fi
  1529. if test -f 'tcpkiller.c' -a "${1}" != "-c" ; then 
  1530.   echo shar: Will not clobber existing file \"'tcpkiller.c'\"
  1531. else
  1532. echo shar: Extracting \"'tcpkiller.c'\" \(2818 characters\)
  1533. sed "s/^X//" >'tcpkiller.c' <<'END_OF_FILE'
  1534. X/* Public domain. */
  1535. X
  1536. X#include <stdio.h>
  1537. X#include <sys/types.h>
  1538. X#include <sys/param.h>
  1539. X#include <sys/file.h>
  1540. X#include <sys/socket.h>
  1541. X#include <signal.h>
  1542. X#include <netinet/in.h>
  1543. X#include "errno.h"
  1544. X#include "username.h"
  1545. X#include "hostname.h"
  1546. X#include "portname.h"
  1547. X#include "getopt.h"
  1548. X#include "malloc.h"
  1549. X#include "env.h"
  1550. X
  1551. X#ifndef MAXHOSTNAMELEN
  1552. X#define MAXHOSTNAMELEN 64
  1553. X#endif
  1554. X
  1555. Xstatic int flagverbose = 1;
  1556. X
  1557. Xstatic char errbuf[500];
  1558. Xvoid die(n,s) int n; char *s;
  1559. X{ if (flagverbose) fprintf(stderr,"tcpkiller: fatal: %s\n",s); exit(n); }
  1560. Xvoid dies(n,s,t) int n; char *s; char *t;
  1561. X{ if (flagverbose) fprintf(stderr,"tcpkiller: fatal: %s%s\n",s,t); exit(n); }
  1562. Xvoid diep(n,s) int n; char *s;
  1563. X{ if (flagverbose) sprintf(errbuf,"tcpkiller: fatal: %s",s); perror(errbuf); exit(n); }
  1564. Xvoid warnp(s) char *s;
  1565. X{ if (flagverbose) sprintf(errbuf,"tcpkiller: warning: %s",s); perror(errbuf); }
  1566. Xvoid warnsp(s,t) char *s; char *t;
  1567. X{ if (flagverbose) sprintf(errbuf,"tcpkiller: warning: %s%s",s,t); perror(errbuf); }
  1568. X
  1569. Xmain(argc,argv,envp)
  1570. Xint argc;
  1571. Xchar *argv[];
  1572. Xchar *envp[];
  1573. X{
  1574. X int uid;
  1575. X int opt;
  1576. X char lochost[MAXHOSTNAMELEN];
  1577. X int locport;
  1578. X char *home;
  1579. X char *fnrecord;
  1580. X char pidstr[50];
  1581. X int pid;
  1582. X int fd;
  1583. X
  1584. X while ((opt = getopt(argc,argv,"qQ")) != EOF)
  1585. X   switch(opt)
  1586. X    {
  1587. X     case 'q':
  1588. X       flagverbose = 0; break;
  1589. X     case 'Q':
  1590. X       flagverbose = 1; break;
  1591. X     case '?':
  1592. X       break; /*XXX*/
  1593. X     default:
  1594. X       break; /*XXX*/
  1595. X    }
  1596. X argc -= optind; argv += optind;
  1597. X
  1598. X if (argc < 2)
  1599. X   die(1,"need at least two arguments");
  1600. X
  1601. X uid = getuid();
  1602. X
  1603. X gethostname(lochost,sizeof(lochost));
  1604. X
  1605. X if ((argv[0][0] == '0') && (argv[0][1] == 0))
  1606. X   ; /* local host, fine */
  1607. X else
  1608. X  {
  1609. X   struct in_addr inaddr1;
  1610. X   struct in_addr inaddr2;
  1611. X   if (hostname2inaddr(argv[0],&inaddr1) == -1)
  1612. X     dies(2,"cannot figure out hostname ",argv[0]);
  1613. X   if (hostname2inaddr(lochost,&inaddr2) == -1)
  1614. X     die(2,"cannot figure out my own hostname");
  1615. X   /* XXX: this doesn't allow 127.1 */
  1616. X   if (inaddr1.s_addr != inaddr2.s_addr)
  1617. X     dies(2,"host does not match local host ",argv[0]);
  1618. X  }
  1619. X
  1620. X if (portname2port(argv[1],&locport,"tcp") == -1)
  1621. X   dies(2,"cannot figure out portname ",argv[1]);
  1622. X locport = locport & 65535;
  1623. X
  1624. X home = env_get("TCPHOME");
  1625. X if (!home)
  1626. X  {
  1627. X   home = env_get("HOME");
  1628. X   if (!home)
  1629. X     die(1,"cannot find TCPHOME or HOME in environment");
  1630. X  }
  1631. X fnrecord = malloc(strlen(home) + strlen(lochost) + 100);
  1632. X if (!fnrecord)
  1633. X   die(1,"out of memory");
  1634. X sprintf(fnrecord,"%s/.tcpserver.%s.%d.%d",home,lochost,uid,locport);
  1635. X
  1636. X fd = open(fnrecord,O_RDONLY,0400);
  1637. X if (fd == -1)
  1638. X   dies(1,"cannot open ",fnrecord);
  1639. X
  1640. X read(fd,pidstr,sizeof(pidstr)); /* XXX: check for partial reads */
  1641. X if (sscanf(pidstr,"%d",&pid) != 1)
  1642. X   die(1,"cannot figure out pid of tcpserver");
  1643. X
  1644. X close(fd);
  1645. X
  1646. X kill(pid,SIGTERM); /*XXX: report errors? */
  1647. X
  1648. X exit(0);
  1649. X}
  1650. END_OF_FILE
  1651. if test 2818 -ne `wc -c <'tcpkiller.c'`; then
  1652.     echo shar: \"'tcpkiller.c'\" unpacked with wrong size!
  1653. fi
  1654. # end of 'tcpkiller.c'
  1655. fi
  1656. if test -f 'testmain' -a "${1}" != "-c" ; then 
  1657.   echo shar: Will not clobber existing file \"'testmain'\"
  1658. else
  1659. echo shar: Extracting \"'testmain'\" \(269 characters\)
  1660. sed "s/^X//" >'testmain' <<'END_OF_FILE'
  1661. X#!/bin/sh
  1662. X# testmain args
  1663. X./testucspi ${1+"$@"} | sed 's/=.*//' > .ucspi.$$
  1664. X./testresult ${1+"$@"} | sed 's/=.*//' > .result.$$
  1665. Xif cmp .ucspi.$$ .result.$$ >/dev/null 2>&1
  1666. Xthen echo 'Everything compares okay.'
  1667. Xelse echo 'Aaack! Test failed.'
  1668. Xfi
  1669. Xrm .ucspi.$$ .result.$$
  1670. END_OF_FILE
  1671. if test 269 -ne `wc -c <'testmain'`; then
  1672.     echo shar: \"'testmain'\" unpacked with wrong size!
  1673. fi
  1674. chmod +x 'testmain'
  1675. # end of 'testmain'
  1676. fi
  1677. if test -f 'testresult' -a "${1}" != "-c" ; then 
  1678.   echo shar: Will not clobber existing file \"'testresult'\"
  1679. else
  1680. echo shar: Extracting \"'testresult'\" \(915 characters\)
  1681. sed "s/^X//" >'testresult' <<'END_OF_FILE'
  1682. X#!/bin/sh
  1683. X# testresult proto prog address
  1684. X# XXX: test args
  1685. Xproto="$1"; shift; export proto
  1686. Xprog="$1"; shift
  1687. Xclient=./"$prog"client; export client
  1688. Xserver=./"$prog"server; export server
  1689. Xkiller=./"$prog"killer; export killer
  1690. Xecho "$server started, ${proto}LOCAL=(depends on the protocol)"
  1691. Xecho "$client started"
  1692. Xecho "$client connected to ${proto}REMOTE=(depends on the protocol)"
  1693. Xecho "$client reading line from server..."
  1694. Xecho "$server accepted connection from ${proto}REMOTE=(depends on the protocol)"
  1695. Xecho "$server writing line to client..."
  1696. Xecho "$client received from server: is anybody out there..."
  1697. Xecho "$client writing line to server..."
  1698. Xecho "$server reading line from client..."
  1699. Xecho "$server received from client: is anybody in there..."
  1700. Xecho "$server done with connection"
  1701. Xecho "$client done with connection"
  1702. Xecho "$client finished"
  1703. Xecho "$killer started"
  1704. Xecho "$server finished"
  1705. Xecho "$killer finished"
  1706. END_OF_FILE
  1707. if test 915 -ne `wc -c <'testresult'`; then
  1708.     echo shar: \"'testresult'\" unpacked with wrong size!
  1709. fi
  1710. chmod +x 'testresult'
  1711. # end of 'testresult'
  1712. fi
  1713. if test -f 'testucspi' -a "${1}" != "-c" ; then 
  1714.   echo shar: Will not clobber existing file \"'testucspi'\"
  1715. else
  1716. echo shar: Extracting \"'testucspi'\" \(1220 characters\)
  1717. sed "s/^X//" >'testucspi' <<'END_OF_FILE'
  1718. X#!/bin/sh
  1719. X# testucspi proto prog address
  1720. X# XXX: test args
  1721. Xproto="$1"; shift; export proto
  1722. Xprog="$1"; shift
  1723. Xclient=./"$prog"client; export client
  1724. Xserver=./"$prog"server; export server
  1725. Xkiller=./"$prog"killer; export killer
  1726. X
  1727. X( 
  1728. Xecho "$server started, ${proto}LOCAL=" | tr -d '\012'
  1729. X# blessed be the shells that allow "$server" here
  1730. X$server -4 "$@" sh -c '
  1731. X  exec <&6
  1732. X  sleep 5
  1733. X  echo "$server accepted connection from ${proto}REMOTE=" | tr -d "\012"
  1734. X  printenv ${proto}REMOTE
  1735. X  echo "$server writing line to client..."
  1736. X  echo "is anybody out there..." >&7
  1737. X  sleep 5
  1738. X  echo "$server reading line from client..."
  1739. X  read i
  1740. X  echo "$server received from client: $i"
  1741. X  echo "$server done with connection"
  1742. X' 4>&1 
  1743. Xecho "$server finished"
  1744. X) &
  1745. X
  1746. Xsleep 5
  1747. X
  1748. Xecho "$client started"
  1749. X$client "$@" sh -c '
  1750. X  exec <&6
  1751. X  sleep 1
  1752. X  echo "$client connected to ${proto}REMOTE=" | tr -d "\012"
  1753. X  printenv ${proto}REMOTE
  1754. X  echo "$client reading line from server..."
  1755. X  read i
  1756. X  echo "$client received from server: $i"
  1757. X  echo "$client writing line to server..."
  1758. X  echo "is anybody in there..." >&7
  1759. X  sleep 5
  1760. X  echo "$client done with connection"
  1761. X'
  1762. Xecho "$client finished"
  1763. X
  1764. Xecho "$killer started"
  1765. Xeval "$killer" "$@"
  1766. Xsleep 2
  1767. Xecho "$killer finished"
  1768. END_OF_FILE
  1769. if test 1220 -ne `wc -c <'testucspi'`; then
  1770.     echo shar: \"'testucspi'\" unpacked with wrong size!
  1771. fi
  1772. chmod +x 'testucspi'
  1773. # end of 'testucspi'
  1774. fi
  1775. if test -f 'undomclient.c' -a "${1}" != "-c" ; then 
  1776.   echo shar: Will not clobber existing file \"'undomclient.c'\"
  1777. else
  1778. echo shar: Extracting \"'undomclient.c'\" \(3980 characters\)
  1779. sed "s/^X//" >'undomclient.c' <<'END_OF_FILE'
  1780. X/* Public domain. */
  1781. X
  1782. X#include <stdio.h>
  1783. X#include <sys/types.h>
  1784. X#include <sys/socket.h>
  1785. X#include <sys/un.h>
  1786. X#include <signal.h>
  1787. X#include "dupdup.h"
  1788. X#include "malloc.h"
  1789. X#include "errno.h"
  1790. X#include "username.h"
  1791. X#include "env.h"
  1792. X#include "getopt.h"
  1793. X#include "numfiles.h"
  1794. X
  1795. Xstatic int flagverbose = 1;
  1796. Xstatic struct sockaddr_un sa;
  1797. X
  1798. Xstatic char errbuf[500];
  1799. Xvoid die(n,s) int n; char *s;
  1800. X{ if (flagverbose) fprintf(stderr,"undomclient: fatal: %s\n",s); exit(n); }
  1801. Xvoid dies(n,s,t) int n; char *s; char *t;
  1802. X{ if (flagverbose) fprintf(stderr,"undomclient: fatal: %s%s\n",s,t); exit(n); }
  1803. Xvoid diep(n,s) int n; char *s;
  1804. X{ if (flagverbose) sprintf(errbuf,"undomclient: fatal: %s",s); perror(errbuf); exit(n); }
  1805. Xvoid warnp(s) char *s;
  1806. X{ if (flagverbose) sprintf(errbuf,"undomclient: warning: %s",s); perror(errbuf); }
  1807. Xvoid warnsp(s,t) char *s; char *t;
  1808. X{ if (flagverbose) sprintf(errbuf,"undomclient: warning: %s%s",s,t); perror(errbuf); }
  1809. X
  1810. Xmain(argc,argv,envp)
  1811. Xint argc;
  1812. Xchar *argv[];
  1813. Xchar *envp[];
  1814. X{
  1815. X int t;
  1816. X int *d;
  1817. X int tdup;
  1818. X int numfiles;
  1819. X int arguid;
  1820. X int uid;
  1821. X int i;
  1822. X static char undomlocal[200];
  1823. X static char undomremote[300];
  1824. X unsigned char urlen;
  1825. X char *uname;
  1826. X int opt;
  1827. X
  1828. X while ((opt = getopt(argc,argv,"qQ")) != EOF)
  1829. X   switch(opt)
  1830. X    {
  1831. X     case 'q':
  1832. X       flagverbose = 0; break;
  1833. X     case 'Q':
  1834. X       flagverbose = 1; break;
  1835. X     case '?':
  1836. X       break; /*XXX*/
  1837. X     default:
  1838. X       break; /*XXX*/
  1839. X    }
  1840. X argc -= optind; argv += optind;
  1841. X
  1842. X if (argc < 3)
  1843. X   die(1,"need at least three arguments");
  1844. X
  1845. X uid = getuid();
  1846. X if (username2uid(argv[0],&arguid) == -1)
  1847. X   dies(2,"cannot figure out username ",argv[0]);
  1848. X /* XXX: any permission checks? */
  1849. X
  1850. X for (i = 0;argv[0][i];++i)
  1851. X   if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
  1852. X     dies(4,"illegal characters in username ",argv[0]);
  1853. X for (i = 0;argv[1][i];++i)
  1854. X   if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
  1855. X     dies(5,"illegal characters in service ",argv[1]);
  1856. X
  1857. X close(6);
  1858. X close(7); /* XXX: these have implications that should be documented */
  1859. X
  1860. X signal(SIGPIPE,SIG_IGN);
  1861. X
  1862. X if (uid2username(uid,&uname) == -1) /* will never happen */
  1863. X   die(2,"cannot figure out my own username");
  1864. X urlen = strlen(uname) + 1;
  1865. X
  1866. X numfiles = NUMFILES;
  1867. X d = (int *) malloc(numfiles * sizeof(int));
  1868. X if (!d)
  1869. X   die(6,"cannot malloc");
  1870. X for (i = 0;i < numfiles;++i)
  1871. X   d[i] = -1;
  1872. X
  1873. X if (strlen(UNDOMDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 100) /*XXX*/
  1874. X   die(8,"server socket name too long");
  1875. X sprintf(sa.sun_path,"%s/%s:%s",UNDOMDIR,argv[0],argv[1]);
  1876. X
  1877. X if (env_init() == -1)
  1878. X   die(11,"cannot init environment");
  1879. X if (env_put("PROTO=UNDOM") == -1)
  1880. X   die(11,"out of memory putting PROTO into environment");
  1881. X sprintf(undomlocal,"UNDOMLOCAL=%s",uname);
  1882. X if (env_put(undomlocal) == -1)
  1883. X   die(11,"out of memory putting UNDOMLOCAL into environment");
  1884. X sprintf(undomremote,"UNDOMREMOTE=%s:%s",argv[0],argv[1]);
  1885. X if (env_put(undomremote) == -1)
  1886. X   die(11,"out of memory putting UNDOMREMOTE into environment");
  1887. X
  1888. X t = socket(AF_UNIX,SOCK_STREAM,0);
  1889. X if (t == -1)
  1890. X   diep(7,"cannot create client socket");
  1891. X sa.sun_family = AF_UNIX;
  1892. X if (connect(t,&sa,sizeof(sa)) == -1)
  1893. X   diep(9,"cannot connect to server");
  1894. X
  1895. X /* XXX: fork? not necessary here */
  1896. X
  1897. X if ((i = write(t,&urlen,1)) == -1)
  1898. X   diep(1,"cannot write length of local username");
  1899. X if (!i) /* ever? */
  1900. X   die(1,"cannot write length of local username");
  1901. X if (write(t,uname,urlen) < urlen)
  1902. X   die(1,"cannot write local username");
  1903. X
  1904. X tdup = dup(t);
  1905. X if (tdup == -1)
  1906. X   diep(10,"cannot dup connection to server");
  1907. X
  1908. X /* Now put t into descriptor 6 and tdup into descriptor 7. */
  1909. X /* XXX: should check that t and tdup are small enough */
  1910. X d[t] = 6;
  1911. X d[tdup] = 7;
  1912. X if (dupdup(d,numfiles) == -1)
  1913. X   diep(10,"cannot dup connection to server");
  1914. X
  1915. X if (setreuid(uid,uid) == -1)
  1916. X   diep(1,"cannot setreuid"); /* will never happen */
  1917. X signal(SIGPIPE,SIG_DFL);
  1918. X execvp(argv[2],argv + 2);
  1919. X warnsp("cannot exec ",argv[2]);
  1920. X exit(1);
  1921. X}
  1922. END_OF_FILE
  1923. if test 3980 -ne `wc -c <'undomclient.c'`; then
  1924.     echo shar: \"'undomclient.c'\" unpacked with wrong size!
  1925. fi
  1926. # end of 'undomclient.c'
  1927. fi
  1928. if test -f 'undomkiller.c' -a "${1}" != "-c" ; then 
  1929.   echo shar: Will not clobber existing file \"'undomkiller.c'\"
  1930. else
  1931. echo shar: Extracting \"'undomkiller.c'\" \(2703 characters\)
  1932. sed "s/^X//" >'undomkiller.c' <<'END_OF_FILE'
  1933. X/* Public domain. */
  1934. X
  1935. X#include <stdio.h>
  1936. X#include <sys/types.h>
  1937. X#include <sys/socket.h>
  1938. X#include <sys/un.h>
  1939. X#include <signal.h>
  1940. X#include "errno.h"
  1941. X#include "username.h"
  1942. X#include "getopt.h"
  1943. X
  1944. Xstatic int flagverbose = 1;
  1945. Xstatic struct sockaddr_un sa;
  1946. X
  1947. Xstatic char errbuf[500];
  1948. Xvoid die(n,s) int n; char *s;
  1949. X{ if (flagverbose) fprintf(stderr,"undomkiller: fatal: %s\n",s); exit(n); }
  1950. Xvoid dies(n,s,t) int n; char *s; char *t;
  1951. X{ if (flagverbose) fprintf(stderr,"undomkiller: fatal: %s%s\n",s,t); exit(n); }
  1952. Xvoid diep(n,s) int n; char *s;
  1953. X{ if (flagverbose) sprintf(errbuf,"undomkiller: fatal: %s",s); perror(errbuf); exit(n); }
  1954. Xvoid warnp(s) char *s;
  1955. X{ if (flagverbose) sprintf(errbuf,"undomkiller: warning: %s",s); perror(errbuf); }
  1956. Xvoid warnsp(s,t) char *s; char *t;
  1957. X{ if (flagverbose) sprintf(errbuf,"undomkiller: warning: %s%s",s,t); perror(errbuf); }
  1958. X
  1959. Xmain(argc,argv,envp)
  1960. Xint argc;
  1961. Xchar *argv[];
  1962. Xchar *envp[];
  1963. X{
  1964. X int t;
  1965. X int arguid;
  1966. X int uid;
  1967. X int i;
  1968. X unsigned char urlen;
  1969. X char *uname;
  1970. X int opt;
  1971. X
  1972. X while ((opt = getopt(argc,argv,"qQ")) != EOF)
  1973. X   switch(opt)
  1974. X    {
  1975. X     case 'q':
  1976. X       flagverbose = 0; break;
  1977. X     case 'Q':
  1978. X       flagverbose = 1; break;
  1979. X     case '?':
  1980. X       break; /*XXX*/
  1981. X     default:
  1982. X       break; /*XXX*/
  1983. X    }
  1984. X argc -= optind; argv += optind;
  1985. X
  1986. X if (argc < 2)
  1987. X   die(1,"need at least two arguments");
  1988. X
  1989. X uid = getuid();
  1990. X if (username2uid(argv[0],&arguid) == -1)
  1991. X   dies(2,"cannot figure out username ",argv[0]);
  1992. X
  1993. X if (arguid != uid)
  1994. X   dies(15,"permission denied by ",argv[0]);
  1995. X /* XXX: special-case root? more checks? */
  1996. X /* This is enough to prevent one user from wasting another's CPU time. */
  1997. X
  1998. X for (i = 0;argv[0][i];++i)
  1999. X   if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
  2000. X     dies(4,"illegal characters in username ",argv[0]);
  2001. X for (i = 0;argv[1][i];++i)
  2002. X   if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
  2003. X     dies(5,"illegal characters in service ",argv[1]);
  2004. X
  2005. X if (uid2username(uid,&uname) == -1) /* will never happen */
  2006. X   die(2,"cannot figure out my own username");
  2007. X urlen = strlen(uname) + 1;
  2008. X
  2009. X if (strlen(UNDOMDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 100) /*XXX*/
  2010. X   die(8,"server socket name too long");
  2011. X sprintf(sa.sun_path,"%s/%s:%s",UNDOMDIR,argv[0],argv[1]);
  2012. X
  2013. X t = socket(AF_UNIX,SOCK_STREAM,0);
  2014. X if (t == -1)
  2015. X   diep(7,"cannot create killer socket");
  2016. X sa.sun_family = AF_UNIX;
  2017. X if (connect(t,&sa,sizeof(sa)) == -1)
  2018. X   diep(9,"cannot connect to server");
  2019. X
  2020. X signal(SIGPIPE,SIG_IGN);
  2021. X
  2022. X urlen = 0; /* XXX: this signals server to clean up and die */
  2023. X if ((i = write(t,&urlen,1)) == -1)
  2024. X   diep(1,"cannot kill server");
  2025. X if (!i) /* ever? */
  2026. X   die(1,"cannot kill server");
  2027. X
  2028. X exit(0);
  2029. X}
  2030. END_OF_FILE
  2031. if test 2703 -ne `wc -c <'undomkiller.c'`; then
  2032.     echo shar: \"'undomkiller.c'\" unpacked with wrong size!
  2033. fi
  2034. # end of 'undomkiller.c'
  2035. fi
  2036. if test -f 'username.c' -a "${1}" != "-c" ; then 
  2037.   echo shar: Will not clobber existing file \"'username.c'\"
  2038. else
  2039. echo shar: Extracting \"'username.c'\" \(549 characters\)
  2040. sed "s/^X//" >'username.c' <<'END_OF_FILE'
  2041. X/* History:
  2042. X5/1/91 DJB baseline public domain
  2043. X*/
  2044. X
  2045. X#include <pwd.h>
  2046. X#include "username.h"
  2047. X#include "numeric.h"
  2048. X
  2049. X/*XXX: cache */
  2050. X
  2051. Xint uid2username(uid,unp)
  2052. Xint uid;
  2053. Xchar **unp;
  2054. X{
  2055. X struct passwd *pw;
  2056. X static char un[20];
  2057. X
  2058. X if (pw = getpwuid(uid))
  2059. X  {
  2060. X   *unp = pw->pw_name;
  2061. X   return 0;
  2062. X  }
  2063. X sprintf(un,"%d",uid);
  2064. X *unp = un;
  2065. X return 1;
  2066. X}
  2067. X
  2068. Xint username2uid(un,uid)
  2069. Xchar *un;
  2070. Xint *uid;
  2071. X{
  2072. X struct passwd *pw;
  2073. X
  2074. X if (numeric(un))
  2075. X  {
  2076. X   *uid = atoi(un);
  2077. X   return 1;
  2078. X  }
  2079. X pw = getpwnam(un);
  2080. X if (!pw)
  2081. X   return -1; /*XXX*/
  2082. X *uid = pw->pw_uid;
  2083. X return 0;
  2084. X}
  2085. END_OF_FILE
  2086. if test 549 -ne `wc -c <'username.c'`; then
  2087.     echo shar: \"'username.c'\" unpacked with wrong size!
  2088. fi
  2089. # end of 'username.c'
  2090. fi
  2091. if test -f 'username.h' -a "${1}" != "-c" ; then 
  2092.   echo shar: Will not clobber existing file \"'username.h'\"
  2093. else
  2094. echo shar: Extracting \"'username.h'\" \(101 characters\)
  2095. sed "s/^X//" >'username.h' <<'END_OF_FILE'
  2096. X#ifndef USERNAME_H
  2097. X#define USERNAME_H
  2098. X
  2099. Xextern int uid2username();
  2100. Xextern int username2uid();
  2101. X
  2102. X#endif
  2103. END_OF_FILE
  2104. if test 101 -ne `wc -c <'username.h'`; then
  2105.     echo shar: \"'username.h'\" unpacked with wrong size!
  2106. fi
  2107. # end of 'username.h'
  2108. fi
  2109. echo shar: End of archive 1 \(of 2\).
  2110. cp /dev/null ark1isdone
  2111. MISSING=""
  2112. for I in 1 2 ; do
  2113.     if test ! -f ark${I}isdone ; then
  2114.     MISSING="${MISSING} ${I}"
  2115.     fi
  2116. done
  2117. if test "${MISSING}" = "" ; then
  2118.     echo You have unpacked both archives.
  2119.     rm -f ark[1-9]isdone
  2120. else
  2121.     echo You still need to unpack the following archives:
  2122.     echo "        " ${MISSING}
  2123. fi
  2124. ##  End of shell archive.
  2125. exit 0
  2126.