home *** CD-ROM | disk | FTP | other *** search
- From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein)
- Newsgroups: alt.sources
- Subject: clientserver 0.50 (part 1/2)
- Message-ID: <11300.Jun2522.45.0291@kramden.acf.nyu.edu>
- Date: 25 Jun 1991 22:45:02 GMT
-
- This is clientserver 0.50, a set of three client-server suites
- supporting different protocols with the same well-defined interface. Two
- of the suites support the TCP and UNDOM protocols for BSD systems; one
- supports the NPIPE protocol for System V. (I'd love to hear from anyone
- with a System V more modern than a 3B2: Does NPIPE run on your machine?)
- All obey the UCSPI (UNIX Client-Server Program Interface) standard, so
- you can write programs that work exactly the same way on top of any of
- the protocols. You can even use these communications facilities inside
- shell scripts.
-
- Why do you want to use UCSPI-compliant communications tools? One
- advantage is instant portability. By working with the client-server
- model given here, you instantly make your programs usable over the
- Internet as well as on System V machines. Not only that, but your code
- will work with any future communications tools designed to fit the
- standard. Imagine supporting DECnet, AT&T's TLI, even Kerberos without
- lifting a finger! Another advantage is modularity: you can mix 'n' match
- protocols and applications without worrying which program supports which
- protocols. Finally, you can skip all those nasty steps of getting
- connection information from the operating system. No matter what the
- protocol is, UCSPI insists that you be given environment variables
- saying who you're talking to.
-
- UCSPI also mandates an often ignored aspect of client-server
- communications: a standard way to kill the server. You don't have to go
- searching through process lists or checking /etc/syslog.pid or sending
- HUPS left and right. You stop a server the same way you started it. You
- might set up a telnet daemon, for example, with this command:
-
- tcpserver 0 telnet sh -c '/usr/etc/in.telnetd <&6 >&7 6<&- 7>&-' &
-
- Here 0 refers to the local machine, and telnet is a port. To kill the
- server you just have to know the address:
-
- tcpkiller 0 telnet
-
- That's it.
-
- Everything here except the UCSPI-91 standard is in the public domain.
- Feel free to copy UCSPI as long as you don't modify it. Of course, UCSPI
- is just a document laying out some ideas; it's not a real standard until
- enough people decide it's worth supporting. Please let me know what you
- think!
-
- ---Dan Bernstein, brnstnd@nyu.edu
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 2)."
- # Contents: BLURB DESIGN.npipe FILES FORMLETTER Makefile NPIPE README
- # TCP UNDOM authuser.c authuser.h dupdup.c dupdup.h env.c env.h
- # errno.h getopt.h hostname.c hostname.h malloc.h npipekiller.c
- # numeric.c numeric.h numfiles.h portname.c portname.h tcpkiller.c
- # testmain testresult testucspi undomclient.c undomkiller.c
- # username.c username.h
- # Wrapped by brnstnd@kramden on Tue Jun 25 18:41:38 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'BLURB' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'BLURB'\"
- else
- echo shar: Extracting \"'BLURB'\" \(2255 characters\)
- sed "s/^X//" >'BLURB' <<'END_OF_FILE'
- XThis is clientserver 0.50, a set of three client-server suites
- Xsupporting different protocols with the same well-defined interface. Two
- Xof the suites support the TCP and UNDOM protocols for BSD systems; one
- Xsupports the NPIPE protocol for System V. (I'd love to hear from anyone
- Xwith a System V more modern than a 3B2: Does NPIPE run on your machine?)
- XAll obey the UCSPI (UNIX Client-Server Program Interface) standard, so
- Xyou can write programs that work exactly the same way on top of any of
- Xthe protocols. You can even use these communications facilities inside
- Xshell scripts.
- X
- XWhy do you want to use UCSPI-compliant communications tools? One
- Xadvantage is instant portability. By working with the client-server
- Xmodel given here, you instantly make your programs usable over the
- XInternet as well as on System V machines. Not only that, but your code
- Xwill work with any future communications tools designed to fit the
- Xstandard. Imagine supporting DECnet, AT&T's TLI, even Kerberos without
- Xlifting a finger! Another advantage is modularity: you can mix 'n' match
- Xprotocols and applications without worrying which program supports which
- Xprotocols. Finally, you can skip all those nasty steps of getting
- Xconnection information from the operating system. No matter what the
- Xprotocol is, UCSPI insists that you be given environment variables
- Xsaying who you're talking to.
- X
- XUCSPI also mandates an often ignored aspect of client-server
- Xcommunications: a standard way to kill the server. You don't have to go
- Xsearching through process lists or checking /etc/syslog.pid or sending
- XHUPS left and right. You stop a server the same way you started it. You
- Xmight set up a telnet daemon, for example, with this command:
- X
- X tcpserver 0 telnet sh -c '/usr/etc/in.telnetd <&6 >&7 6<&- 7>&-' &
- X
- XHere 0 refers to the local machine, and telnet is a port. To kill the
- Xserver you just have to know the address:
- X
- X tcpkiller 0 telnet
- X
- XThat's it.
- X
- XEverything here except the UCSPI-91 standard is in the public domain.
- XFeel free to copy UCSPI as long as you don't modify it. Of course, UCSPI
- Xis just a document laying out some ideas; it's not a real standard until
- Xenough people decide it's worth supporting. Please let me know what you
- Xthink!
- X
- X---Dan Bernstein, brnstnd@nyu.edu
- END_OF_FILE
- if test 2255 -ne `wc -c <'BLURB'`; then
- echo shar: \"'BLURB'\" unpacked with wrong size!
- fi
- # end of 'BLURB'
- fi
- if test -f 'DESIGN.npipe' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'DESIGN.npipe'\"
- else
- echo shar: Extracting \"'DESIGN.npipe'\" \(950 characters\)
- sed "s/^X//" >'DESIGN.npipe' <<'END_OF_FILE'
- XHere's the idea: We create DIR/l.username/service, a mode-000 file. We
- Xcreate s.username, a mode-600 named pipe. We then change l.username to
- Xmode 600 and open s.username for reading. This blocks. Note that a
- Xclient may start writing before we start reading, or vice versa.
- X
- XMain loop: The client locks l.username. When it receives the lock, it
- Xopens s.username for writing, then creates DIR/s2c.pid and DIR/c2s.pid,
- Xthen writes pid and its username, then closes s.username, then opens
- Xs2c.pid for reading (this blocks) and c2s.pid for writing (this blocks).
- XWe read pid and the username, then close and unlink s.username. We then
- Xfork. In the parent, we then create s.username, a mode-600 named pipe,
- Xthen open s.username for reading; this is back to the original state. In
- Xthe child, we open s2c.pid for writing and c2s.pid for reading, then
- Xwrite a byte to s2c.pid. The client reads that byte, unlinks s2c.pid and
- Xc2s.pid, and unlocks l.username.
- END_OF_FILE
- if test 950 -ne `wc -c <'DESIGN.npipe'`; then
- echo shar: \"'DESIGN.npipe'\" unpacked with wrong size!
- fi
- # end of 'DESIGN.npipe'
- fi
- if test -f 'FILES' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'FILES'\"
- else
- echo shar: Extracting \"'FILES'\" \(399 characters\)
- sed "s/^X//" >'FILES' <<'END_OF_FILE'
- XBLURB
- XREADME
- XFILES
- XFORMLETTER
- XUCSPI
- XTCP
- XUNDOM
- XNPIPE
- XDESIGN.npipe
- Xtestmain
- Xtestresult
- Xtestucspi
- XMakefile
- Xauthuser.h
- Xdupdup.h
- Xenv.h
- Xerrno.h
- Xgetopt.h
- Xhostname.h
- Xmalloc.h
- Xnumeric.h
- Xnumfiles.h
- Xportname.h
- Xusername.h
- Xauthuser.c
- Xdupdup.c
- Xenv.c
- Xhostname.c
- Xnpipeclient.c
- Xnpipeserver.c
- Xnpipekiller.c
- Xnumeric.c
- Xportname.c
- Xundomclient.c
- Xundomserver.c
- Xundomkiller.c
- Xusername.c
- Xtcpclient.c
- Xtcpserver.c
- Xtcpkiller.c
- END_OF_FILE
- if test 399 -ne `wc -c <'FILES'`; then
- echo shar: \"'FILES'\" unpacked with wrong size!
- fi
- # end of 'FILES'
- fi
- if test -f 'FORMLETTER' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'FORMLETTER'\"
- else
- echo shar: Extracting \"'FORMLETTER'\" \(612 characters\)
- sed "s/^X//" >'FORMLETTER' <<'END_OF_FILE'
- XTo: brnstnd@nyu.edu
- XFrom:
- XDate:
- X
- XPackage: clientserver 0.50
- XObtained from (e.g., uunet.uu.net):
- XObtained by (e.g., ftp):
- X
- X1. Machine architecture (e.g., Sun 4/280):
- X2. Operating system (e.g., SunOS 4.1):
- X3. OS vendor (e.g., Sun):
- X4. Does tcp work on your machine so far (yes/no/didn't try)?
- X5. Does undom work on your machine so far (yes/no/didn't try)?
- X6. Does npipe work on your machine so far (yes/no/didn't try)?
- X7. What are CC and CCOPTS in your Makefile?
- X CC=
- X CCOPTS=
- X
- X8. Describe any problems you've had with clientserver.
- X
- X
- X9. Any further questions, comments, or suggestions?
- X
- X
- XYour name:
- END_OF_FILE
- if test 612 -ne `wc -c <'FORMLETTER'`; then
- echo shar: \"'FORMLETTER'\" unpacked with wrong size!
- fi
- # end of 'FORMLETTER'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(3109 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- XCC=cc
- XCCOPTS=-g -DUNDOMDIR=\"/usr/local/etc/undom\" -DNPIPEDIR=\"/usr/local/etc/npipe\" -DSIGRET=int
- XMACHOPTS=
- XLIBS=-lresolv # XXX: only necessary for tcp*
- X#
- X
- Xdefault: undom tcp npipe
- X
- Xundom: undomserver undomclient undomkiller
- X
- Xtcp: tcpserver tcpclient tcpkiller
- X
- Xnpipe: npipeserver npipeclient npipekiller
- X
- Xnpipekiller: npipekiller.o dupdup.o username.o numeric.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o npipekiller npipekiller.o dupdup.o username.o numeric.o env.o $(LIBS)
- X
- Xnpipeserver: npipeserver.o dupdup.o username.o numeric.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o npipeserver npipeserver.o dupdup.o username.o numeric.o env.o $(LIBS)
- X
- Xnpipeclient: npipeclient.o dupdup.o username.o numeric.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o npipeclient npipeclient.o dupdup.o username.o numeric.o env.o $(LIBS)
- X
- Xundomkiller: undomkiller.o dupdup.o username.o numeric.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o undomkiller undomkiller.o dupdup.o username.o numeric.o env.o $(LIBS)
- X
- Xundomserver: undomserver.o dupdup.o username.o numeric.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o undomserver undomserver.o dupdup.o username.o numeric.o env.o $(LIBS)
- X
- Xundomclient: undomclient.o dupdup.o username.o numeric.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o undomclient undomclient.o dupdup.o username.o numeric.o env.o $(LIBS)
- X
- Xtcpkiller: tcpkiller.o username.o numeric.o portname.o hostname.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o tcpkiller tcpkiller.o username.o numeric.o portname.o hostname.o env.o $(LIBS)
- X
- Xtcpserver: tcpserver.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o tcpserver tcpserver.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o $(LIBS)
- X
- Xtcpclient: tcpclient.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o
- X $(CC) $(CCOPTS) $(MACHOPTS) -o tcpclient tcpclient.o dupdup.o username.o numeric.o authuser.o portname.o hostname.o env.o $(LIBS)
- X
- Xnpipekiller.o: npipekiller.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c npipekiller.c
- X
- Xnpipeserver.o: npipeserver.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c npipeserver.c
- X
- Xnpipeclient.o: npipeclient.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c npipeclient.c
- X
- Xundomkiller.o: undomkiller.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c undomkiller.c
- X
- Xundomserver.o: undomserver.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c undomserver.c
- X
- Xundomclient.o: undomclient.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c undomclient.c
- X
- Xtcpclient.o: tcpclient.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c tcpclient.c
- X
- Xtcpkiller.o: tcpkiller.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c tcpkiller.c
- X
- Xtcpserver.o: tcpserver.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c tcpserver.c
- X
- Xdupdup.o: dupdup.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c dupdup.c
- X
- Xusername.o: username.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c username.c
- X
- Xportname.o: portname.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c portname.c
- X
- Xhostname.o: hostname.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c hostname.c
- X
- Xnumeric.o: numeric.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c numeric.c
- X
- Xenv.o: env.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c env.c
- X
- Xauthuser.o: authuser.c
- X $(CC) $(CCOPTS) $(MACHOPTS) -c authuser.c
- X
- Xshar:
- X shar `cat FILES` > ucspi.shar
- X chmod 400 ucspi.shar
- END_OF_FILE
- if test 3109 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'NPIPE' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'NPIPE'\"
- else
- echo shar: Extracting \"'NPIPE'\" \(1377 characters\)
- sed "s/^X//" >'NPIPE' <<'END_OF_FILE'
- XNPIPE
- X6/23/91
- X
- X
- XThis document defines the NPIPE protocol for UCSPI programs. A NPIPE
- Xclient communicates with a NPIPE server on the same machine through a
- Xpair of named pipes.
- X
- X<address> consists of two arguments: <username> <service>. Neither
- Xargument can contain slashes, newlines, or periods. <username> must not
- Xcontain colons. Any other character understood by the local machine may
- Xappear. <username> is a username on the machine, and <service> is any
- Xtext chosen by <username> to represent a service.
- X
- X<clientaddress> is the username of the client user. <serveraddress> is
- X<username>:<service>. Both of these addresses are limited to 100
- Xcharacters.
- X
- XThe descriptors passed to <userprogram> refer to two independent
- Xunlinked named pipes (fifos). Descriptor 6 supports only reading and
- Xdescriptor 7 supports only writing. The semantics of these pipes are
- Xdefined by the local UNIX variant; no operations other than those
- Xapplicable to normal pipes may be assumed.
- X
- XIt must not be possible for one user to set up a service with a
- Xdifferent <username>. It must not be possible for a user to conceal or
- Xdisguise the username of a client.
- X
- XAll NPIPE programs have undefined behavior if any username involved
- Xshares a uid with a different username.
- X
- XPreferred executable names: npipeclient, npipeserver, npipekiller.
- X
- X
- XUCSPI Administrator
- XDaniel J. Bernstein, brnstnd@nyu.edu
- END_OF_FILE
- if test 1377 -ne `wc -c <'NPIPE'`; then
- echo shar: \"'NPIPE'\" unpacked with wrong size!
- fi
- # end of 'NPIPE'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(2539 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- Xclientserver 0.50, 6/25/91, Daniel J. Bernstein, brnstnd@nyu.edu.
- XWatch alt.sources.d for patches, comp.sources.unix for the next version.
- XLatest version inside stealth.acf.nyu.edu:pub/hier/clientserver/.
- X
- XThis has been extensively tested under SunOS 4.0.3, Ultrix 4.1, BSD 4.3,
- Xand the latest pre-BSD 4.4, and it appears to work on several other
- Xsystems. Under gcc you MUST define -fwritable-strings; sorry, old habits
- Xdie hard.
- X
- XModify UNDOMDIR and NPIPEDIR in Makefile for your system. Make some uid,
- Xsay undom, with access to UNDOMDIR; make UNDOMDIR mode 700 ownder undom.
- XMake some uid, say npipe, with access to NPIPEDIR; make NPIPEDIR mode
- X700 owner npipe. Make sure LIBS makes sense for you: most BSD systems
- Xneed -lresolv to use the resolver, and if you don't have getopt you'll
- Xhave to pick it up and put it into LIBS. That's it for configuration.
- X
- XMake. On BSD systems without named pipes, you should make only tcp and
- Xundom. On System V systems without sockets, you should make npipe. (I
- Xhave absolutely no idea whether npipe actually works on any modern
- XSystem V machines.) Under SunOS and Ultrix, make everything.
- X
- XTo test the programs, run testmain in this directory with appropriate
- Xarguments. Examples:
- X
- X ./testmain NPIPE npipe <yourusername> blah
- X ./testmain UNDOM undom <yourusername> foop
- X ./testmain TCP tcp 0 <randomportnumber>
- X
- XThe 0 in the last line is an abbreviation for the local host. testmain
- Xshould say ``Everything compares okay''; if not, don't panic, because
- Xthe test code can report false alarms. (It uses sleep(1) for
- Xsynchronization.) Just run it again. To see what's going on, run
- Xtestucspi in place of testmain.
- X
- XInstall tcp{client,server,killer} somewhere, NOT setuid. Install
- Xundom{client,server,killer} somewhere, owner undom, mode 4755. Install
- Xnpipe{client,server,killer} somewhere, owner npipe, mode 4755. That's
- Xit. You might want to have your rc.local remove anything in UNDOMDIR or
- XNPIPEDIR.
- X
- X*PLEASE* fill out FORMLETTER and send it to me if you had problems.
- X*PLEASE* fill out FORMLETTER and send it to me if everything worked!
- XThanks for being a good sport.
- X
- XThe best documentation available at the moment is UCSPI and its
- Xassociated documents (TCP, UNDOM, NPIPE). Look at testucspi for an
- Xexample of how to communicate between independent processes with UCSPI.
- X
- X
- XXXX: handle EINTR better in undomserver.c and npipe*.c
- XXXX: restore signals properly?
- XXXX: fix all the exit codes
- XXXX: write man pages!
- XXXX: write a real README! and BLURB
- XXXX: provide semi-automatic reboot cleanup stuff?
- END_OF_FILE
- if test 2539 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'TCP' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'TCP'\"
- else
- echo shar: Extracting \"'TCP'\" \(2835 characters\)
- sed "s/^X//" >'TCP' <<'END_OF_FILE'
- XTCP
- X6/19/91
- X
- X
- XThis document defines the TCP protocol for UCSPI programs. A TCP client
- Xcommunicates with a TCP server, on the same machine or on a different
- Xmachine, via the TCP/IP protocol through an Internet-domain socket.
- X
- X<address> consists of two arguments: <hostname> <port>. <hostname> may
- Xeither be a dotted IP address (such as 128.122.128.2) or a name which,
- Xon the local machine, somehow represents such an address. (For example,
- Xdomain names understood by DNS or by a local NIC-style host table might
- Xbe valid <hostname>s.) <hostname> may also be the single character 0,
- Xreferring to the local machine. <port> may either be a numeric TCP port
- Xnumber (such as 25, the standard SMTP port) or a name which, on the
- Xlocal machine, somehow represents a port number. Any character may
- Xappear in <hostname> or <port>.
- X
- X<clientaddress> and <serveraddress> share a single format:
- X<username>@<hostnumber>(<hostname>):<port>. <username> is a username on
- Xthe machine in question: inside TCPLOCAL, <username> is the real
- Xusername of the process, and inside TCPREMOTE, <username> is the
- Xusername returned by the other machine via RFC 931, or blank if the
- Xother machine does not support RFC 931. The client and server must take
- Xa -R option to turn off RFC 931 checking, and -r to turn it back on.
- XUnder -R, <username> will always be blank inside TCPREMOTE. <hostnumber>
- Xis the IP address of the communicating host. <hostname> is either that
- Xaddress or, if available, a name representing that address. <port> is
- Xthe relevant TCP port.
- X
- XNote that this address format is ambiguous, except in <port>. <hostname>
- Xdepends on local name lookup conventions, <username> may be blank, and
- X<hostnumber> might refer to the same machine through special numbers
- Xsuch as 127.0.0.1 and 0.0.0.0. Application programs which use
- X<clientaddress> and <serveraddress> should keep these caveats in mind.
- X
- XThe descriptors passed to <userprogram> refer to an INET-domain stream
- Xsocket, dup()ed from a single connect() or accept(). The semantics of
- Xthis socket are defined by the local UNIX variant, but it is expected
- Xthat it will support out-of-band data as in BSD systems past 4.2,
- Xsubject to the restrictions of RFC 1122 and RFC 1123.
- X
- XIf <port> is 0, the server must choose an available port number or
- Xreport an error. The client must take a -p <locport> option to set a
- Xdesired TCP port on the local side of the connection; if it cannot
- Xsatisfy this request, it must report an error.
- X
- XThe killer must not work upon a server running on a different machine.
- XThe killer and the server may communicate through files stored in the
- Xhome directory of the invoking user, as specified by environment
- Xvariable TCPHOME, or HOME if TCPHOME is not set.
- X
- XPreferred executable names: tcpclient, tcpserver, tcpkiller.
- X
- X
- XUCSPI Administrator
- XDaniel J. Bernstein, brnstnd@nyu.edu
- END_OF_FILE
- if test 2835 -ne `wc -c <'TCP'`; then
- echo shar: \"'TCP'\" unpacked with wrong size!
- fi
- # end of 'TCP'
- fi
- if test -f 'UNDOM' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'UNDOM'\"
- else
- echo shar: Extracting \"'UNDOM'\" \(1409 characters\)
- sed "s/^X//" >'UNDOM' <<'END_OF_FILE'
- XUNDOM
- X6/16/91
- X
- X
- XThis document defines the UNDOM protocol for UCSPI programs. A UNDOM
- Xclient communicates with a UNDOM server on the same machine through a
- XUNIX-domain socket.
- X
- X<address> consists of two arguments: <username> <service>. Neither
- Xargument can contain slashes, newlines, or periods. <username> must not
- Xcontain colons. Any other character understood by the local machine may
- Xappear. <username> is a username on the machine, and <service> is any
- Xtext chosen by <username> to represent a service.
- X
- X<clientaddress> is the username of the client user. <serveraddress> is
- X<username>:<service>. Both of these addresses are limited to 100
- Xcharacters.
- X
- XThe descriptors passed to <userprogram> refer to a UNIX-domain stream
- Xsocket whose name is a function of <username> and <service>; they are
- Xdup()ed from a single connect() or accept(). The semantics of this
- Xsocket are defined by the local UNIX variant, but it is expected that it
- Xwill support file descriptor passing as in BSD systems past 4.2.
- X
- XIt must not be possible for one user to set up a service with a
- Xdifferent <username>. It must not be possible for a user to conceal or
- Xdisguise the username of a client.
- X
- XAll UNDOM programs have undefined behavior if any username involved
- Xshares a uid with a different username.
- X
- XPreferred executable names: undomclient, undomserver, undomkiller.
- X
- X
- XUCSPI Administrator
- XDaniel J. Bernstein, brnstnd@nyu.edu
- END_OF_FILE
- if test 1409 -ne `wc -c <'UNDOM'`; then
- echo shar: \"'UNDOM'\" unpacked with wrong size!
- fi
- # end of 'UNDOM'
- fi
- if test -f 'authuser.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'authuser.c'\"
- else
- echo shar: Extracting \"'authuser.c'\" \(3622 characters\)
- sed "s/^X//" >'authuser.c' <<'END_OF_FILE'
- X/*
- X5/6/91 DJB baseline authuser 3.1. Public domain.
- X*/
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <netdb.h>
- X#include <errno.h>
- X#include <ctype.h>
- Xextern int errno;
- X#include "authuser.h"
- X
- Xunsigned short auth_tcpport = 113;
- X
- X#define SIZ 500 /* various buffers */
- X
- Xstatic int usercmp(u,v)
- Xregister char *u;
- Xregister char *v;
- X{
- X /* is it correct to consider Foo and fOo the same user? yes */
- X /* but the function of this routine may change later */
- X while (*u && *v)
- X if (tolower(*u) != tolower(*v))
- X return tolower(*u) - tolower(*v);
- X else
- X ++u,++v;
- X return *u || *v;
- X}
- X
- Xstatic char authline[SIZ];
- X
- Xchar *auth_xline(user,fd,in)
- Xregister char *user; /* the supposed name of the user, NULL if unknown */
- Xregister int fd; /* the file descriptor of the connection */
- Xregister unsigned long *in;
- X{
- X unsigned short local;
- X unsigned short remote;
- X register char *ruser;
- X
- X if (auth_fd(fd,in,&local,&remote) == -1)
- X return 0;
- X ruser = auth_tcpuser(*in,local,remote);
- X if (!ruser)
- X return 0;
- X if (!user)
- X user = ruser; /* forces X-Auth-User */
- X (void) sprintf(authline,
- X (usercmp(ruser,user) ? "X-Forgery-By: %s" : "X-Auth-User: %s"),
- X ruser);
- X return authline;
- X}
- X
- Xint auth_fd(fd,in,local,remote)
- Xregister int fd;
- Xregister unsigned long *in;
- Xregister unsigned short *local;
- Xregister unsigned short *remote;
- X{
- X struct sockaddr_in sa;
- X int dummy;
- X
- X dummy = sizeof(sa);
- X if (getsockname(fd,&sa,&dummy) == -1)
- X return -1;
- X if (sa.sin_family != AF_INET)
- X {
- X errno = EAFNOSUPPORT;
- X return -1;
- X }
- X *local = ntohs(sa.sin_port);
- X dummy = sizeof(sa);
- X if (getpeername(fd,&sa,&dummy) == -1)
- X return -1;
- X *remote = ntohs(sa.sin_port);
- X *in = sa.sin_addr.s_addr;
- X return 0;
- X}
- X
- Xstatic char ruser[SIZ];
- Xstatic char realbuf[SIZ];
- Xstatic char *buf;
- X
- Xchar *auth_tcpuser(in,local,remote)
- Xregister unsigned long in;
- Xregister unsigned short local;
- Xregister unsigned short remote;
- X{
- X struct sockaddr_in sa;
- X register int s;
- X register int buflen;
- X register int w;
- X register int saveerrno;
- X char ch;
- X unsigned short rlocal;
- X unsigned short rremote;
- X
- X if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1)
- X return 0;
- X sa.sin_family = AF_INET;
- X sa.sin_port = htons(auth_tcpport);
- X sa.sin_addr.s_addr = in;
- X if (connect(s,&sa,sizeof(sa)) == -1)
- X {
- X saveerrno = errno;
- X (void) close(s);
- X errno = saveerrno;
- X return 0;
- X }
- X
- X buf = realbuf;
- X (void) sprintf(buf,"%u , %u\r\n",(unsigned int) remote,(unsigned int) local);
- X /* note the reversed order---the example in the RFC is misleading */
- X buflen = strlen(buf);
- X while ((w = write(s,buf,buflen)) < buflen)
- X if (w == -1) /* should we worry about 0 as well? */
- X {
- X saveerrno = errno;
- X (void) close(s);
- X errno = saveerrno;
- X return 0;
- X }
- X else
- X {
- X buf += w;
- X buflen -= w;
- X }
- X buf = realbuf;
- X while ((w = read(s,&ch,1)) == 1)
- X {
- X *buf = ch;
- X if ((ch != ' ') && (ch != '\t') && (ch != '\r'))
- X ++buf;
- X if ((buf - realbuf == sizeof(realbuf) - 1) || (ch == '\n'))
- X break;
- X }
- X if (w == -1)
- X {
- X saveerrno = errno;
- X (void) close(s);
- X errno = saveerrno;
- X return 0;
- X }
- X *buf = '\0';
- X
- X if (sscanf(realbuf,"%hd,%hd: USERID :%*[^:]:%s",&rremote,&rlocal,ruser) < 3)
- X {
- X (void) close(s);
- X errno = EIO;
- X /* makes sense, right? well, not when USERID failed to match ERROR */
- X /* but there's no good error to return in that case */
- X return 0;
- X }
- X if ((remote != rremote) || (local != rlocal))
- X {
- X (void) close(s);
- X errno = EIO;
- X return 0;
- X }
- X /* XXX: we're not going to do any backslash processing */
- X (void) close(s);
- X return ruser;
- X}
- END_OF_FILE
- if test 3622 -ne `wc -c <'authuser.c'`; then
- echo shar: \"'authuser.c'\" unpacked with wrong size!
- fi
- # end of 'authuser.c'
- fi
- if test -f 'authuser.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'authuser.h'\"
- else
- echo shar: Extracting \"'authuser.h'\" \(161 characters\)
- sed "s/^X//" >'authuser.h' <<'END_OF_FILE'
- X#ifndef AUTHUSER_H
- X#define AUTHUSER_H
- X
- Xextern unsigned short auth_tcpport;
- Xextern char *auth_xline();
- Xextern int auth_fd();
- Xextern char *auth_tcpuser();
- X
- X#endif
- END_OF_FILE
- if test 161 -ne `wc -c <'authuser.h'`; then
- echo shar: \"'authuser.h'\" unpacked with wrong size!
- fi
- # end of 'authuser.h'
- fi
- if test -f 'dupdup.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dupdup.c'\"
- else
- echo shar: Extracting \"'dupdup.c'\" \(2174 characters\)
- sed "s/^X//" >'dupdup.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X#include <fcntl.h>
- X#include "dupdup.h"
- X
- Xstatic int dupit(old,new)
- Xint old;
- Xint new;
- X{
- X/* What follows is roughly equivalent to the following:
- X if (dup2(old,new) == -1) return -1; close(old); return 0;
- X Differences: errno can be different; this works under System V;
- X this is about twice as slow.
- X*/
- X if (old == new) /* shouldn't happen */
- X return 0;
- X if (fcntl(old,F_GETFL,0) == -1) /* old is bad */
- X return -1;
- X close(new); /* XXX: check error codes? */
- X if (fcntl(old,F_DUPFD,new) == -1) /* can't dup */
- X return -1;
- X close(old); /*XXX*/
- X return 0;
- X}
- X
- Xint dupdup(d,n)
- Xint *d;
- Xint n;
- X{
- X int i;
- X int j;
- X int k;
- X int l;
- X
- X /* Descriptor i will become descriptor d[i], if d[i] != -1. */
- X /* The original descriptor d[i] will disappear. */
- X /* The array d[i] may be mangled freely. */
- X /* n is the size of d[]. */
- X /* No guarantees if i and j both become k. */
- X /* errno is set properly on a -1 return. */
- X
- X for (i = 0;i < n;++i)
- X if (d[i] != -1)
- X {
- X for (j = d[i];(j != -1) && (j != i) && (j != d[j]);j = d[j])
- X ;
- X if ((j == -1) || (j == d[j]))
- X if (j == i)
- X ; /* self-loop */
- X else
- X { /* no cycle */
- X if (j != -1)
- X d[j] = -1;
- X if (d[d[i]] == -1) /*XXX*/
- X {
- X if (dupit(i,d[i]) == -1)
- X return -1;
- X d[i] = -1;
- X }
- X else
- X {
- X k = i; j = d[i];
- X do
- X {
- X l = d[j]; d[j] = k; k = j; j = l;
- X }
- X while (j != -1);
- X for (j = k;j != i;j = k)
- X {
- X if (dupit(d[j],j) == -1)
- X return -1;
- X k = d[j];
- X d[j] = -1;
- X }
- X d[i] = -1;
- X }
- X }
- X else
- X { /* cycle */
- X if (dupit(i,n) == -1)
- X return -1;
- X if (d[d[i]] == i) /*XXX*/
- X {
- X if (dupit(d[i],i) == -1)
- X return -1;
- X if (dupit(n,d[i]) == -1)
- X return -1;
- X d[d[i]] = -1;
- X d[i] = -1;
- X }
- X else
- X {
- X k = i; j = d[i];
- X do
- X {
- X l = d[j]; d[j] = k; k = j; j = l;
- X }
- X while (j != i);
- X for (j = k;j != i;j = k)
- X {
- X if (dupit(d[j],j) == -1)
- X return -1;
- X k = d[j];
- X d[j] = -1;
- X }
- X d[i] = -1;
- X if (dupit(n,k) == -1)
- X return -1;
- X }
- X }
- X }
- X return 0;
- X}
- END_OF_FILE
- if test 2174 -ne `wc -c <'dupdup.c'`; then
- echo shar: \"'dupdup.c'\" unpacked with wrong size!
- fi
- # end of 'dupdup.c'
- fi
- if test -f 'dupdup.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dupdup.h'\"
- else
- echo shar: Extracting \"'dupdup.h'\" \(64 characters\)
- sed "s/^X//" >'dupdup.h' <<'END_OF_FILE'
- X#ifndef DUPDUP_H
- X#define DUPDUP_H
- X
- Xextern int dupdup();
- X
- X#endif
- END_OF_FILE
- if test 64 -ne `wc -c <'dupdup.h'`; then
- echo shar: \"'dupdup.h'\" unpacked with wrong size!
- fi
- # end of 'dupdup.h'
- fi
- if test -f 'env.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'env.c'\"
- else
- echo shar: Extracting \"'env.c'\" \(2157 characters\)
- sed "s/^X//" >'env.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X/*
- XThese are portable versions of putenv(). env_put("FOO=BAR") is like
- XFOO=BAR inside sh; env_unset("FOO") unsets any variable FOO. env_init()
- Xis optional initialization. env_get is just like getenv. Of course, all
- Xchanges are tracked through environ, so execvp() and friends will pick
- Xup the new variables.
- X*/
- X
- X/* uses environ, malloc, free, strlen, strncmp */
- X
- X#include "env.h"
- X#include "malloc.h"
- X
- Xextern char **environ;
- Xstatic int init = 0;
- Xstatic int numenv;
- Xstatic int allocenv;
- X
- Xextern char *env_get(s)
- Xchar *s;
- X{
- X int i;
- X int slen;
- X
- X if (!init)
- X if (env_init())
- X return 0;
- X
- X slen = strlen(s);
- X for (i = 0;i < numenv;++i)
- X if ((!strncmp(s,environ[i],slen)) && (environ[i][slen] == '='))
- X return environ[i] + slen + 1;
- X return 0;
- X}
- X
- Xextern int env_unset(s)
- Xchar *s;
- X{
- X int i;
- X int slen;
- X
- X if (!init)
- X if (env_init())
- X return -1;
- X slen = strlen(s);
- X for (i = 0;i < numenv;++i)
- X if ((!strncmp(s,environ[i],slen)) && (environ[i][slen] == '='))
- X {
- X if (i < --numenv)
- X environ[i] = environ[numenv];
- X environ[numenv] = 0;
- X }
- X return 0;
- X}
- X
- Xstatic int env_realloc()
- X{
- X char **envp;
- X
- X allocenv = numenv + 30;
- X envp = environ;
- X environ = (char **) malloc(allocenv * (int) sizeof(char *));
- X if (!environ)
- X {
- X environ = envp;
- X allocenv = numenv;
- X return -1;
- X }
- X numenv = 0;
- X while (*envp)
- X {
- X environ[numenv] = *envp;
- X ++numenv;
- X ++envp;
- X }
- X environ[numenv] = 0;
- X free((char *) (envp - numenv));
- X return 0;
- X}
- X
- Xstatic int env_add(s)
- Xchar *s;
- X{
- X char *t;
- X for (t = s;*t;++t)
- X if (*t == '=')
- X break;
- X if (*t)
- X {
- X *t = 0;
- X if (env_unset(s))
- X return -1;
- X *t = '=';
- X }
- X if (numenv == allocenv)
- X if (env_realloc())
- X return -1;
- X environ[numenv] = s;
- X ++numenv;
- X environ[numenv] = 0;
- X return 0;
- X}
- X
- Xint env_init()
- X{
- X char **envp;
- X
- X numenv = 0;
- X allocenv = 0;
- X envp = environ;
- X environ = (char **) malloc(sizeof(char *));
- X if (!environ)
- X {
- X environ = envp;
- X return -1;
- X }
- X init = 1;
- X while (*envp)
- X {
- X if (env_add(*envp))
- X return -1;
- X ++envp;
- X }
- X return 0;
- X}
- X
- Xint env_put(s)
- Xchar *s;
- X{
- X if (!init)
- X if (env_init())
- X return -1;
- X return env_add(s);
- X}
- END_OF_FILE
- if test 2157 -ne `wc -c <'env.c'`; then
- echo shar: \"'env.c'\" unpacked with wrong size!
- fi
- # end of 'env.c'
- fi
- if test -f 'env.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'env.h'\"
- else
- echo shar: Extracting \"'env.h'\" \(153 characters\)
- sed "s/^X//" >'env.h' <<'END_OF_FILE'
- X#ifndef ENV_H
- X#define ENV_H
- X
- Xextern int env_init();
- Xextern int env_put();
- Xextern int env_unset();
- Xextern char *env_get(); /* for completeness */
- X
- X#endif
- END_OF_FILE
- if test 153 -ne `wc -c <'env.h'`; then
- echo shar: \"'env.h'\" unpacked with wrong size!
- fi
- # end of 'env.h'
- fi
- if test -f 'errno.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'errno.h'\"
- else
- echo shar: Extracting \"'errno.h'\" \(78 characters\)
- sed "s/^X//" >'errno.h' <<'END_OF_FILE'
- X#ifndef ERRNO_H
- X#define ERRNO_H
- X
- X#include <errno.h>
- Xextern int errno;
- X
- X#endif
- END_OF_FILE
- if test 78 -ne `wc -c <'errno.h'`; then
- echo shar: \"'errno.h'\" unpacked with wrong size!
- fi
- # end of 'errno.h'
- fi
- if test -f 'getopt.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'getopt.h'\"
- else
- echo shar: Extracting \"'getopt.h'\" \(298 characters\)
- sed "s/^X//" >'getopt.h' <<'END_OF_FILE'
- X#ifndef GETOPT_H
- X#define GETOPT_H
- X
- X/* I'm trusting the user to acquire a getopt library, rather than
- Xproviding one myself. This is probably a mistake. */
- X
- X/* The following should be in /usr/include/getopt.h but often aren't. */
- X
- Xextern int getopt();
- Xextern char *optarg;
- Xextern int optind;
- X
- X#endif
- END_OF_FILE
- if test 298 -ne `wc -c <'getopt.h'`; then
- echo shar: \"'getopt.h'\" unpacked with wrong size!
- fi
- # end of 'getopt.h'
- fi
- if test -f 'hostname.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hostname.c'\"
- else
- echo shar: Extracting \"'hostname.c'\" \(1191 characters\)
- sed "s/^X//" >'hostname.c' <<'END_OF_FILE'
- X/* History:
- X5/1/91 DJB baseline public domain. todo: cache hosts.
- X*/
- X
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netdb.h>
- X#include <netinet/in.h>
- X#include "hostname.h"
- X#include "numeric.h"
- X
- Xint inaddr2hostname(inaddr,hostname)
- Xstruct in_addr inaddr;
- Xchar **hostname;
- X{
- X struct hostent *he;
- X static char hn[30];
- X unsigned char *x;
- X
- X if (he = gethostbyaddr(&inaddr,sizeof(inaddr),AF_INET))
- X {
- X *hostname = he->h_name;
- X return 0;
- X }
- X x = (unsigned char *) &inaddr;
- X sprintf(hn,"%d.%d.%d.%d"
- X ,(int) (unsigned int) x[0],(int) (unsigned int) x[1]
- X ,(int) (unsigned int) x[2],(int) (unsigned int) x[3]
- X );
- X *hostname = hn;
- X return 1;
- X}
- X
- Xint hostname2inaddr(hostname,inaddr)
- Xchar *hostname;
- Xstruct in_addr *inaddr;
- X{
- X struct hostent *he;
- X char *x;
- X int h1; int h2; int h3; int h4;
- X
- X x = (char *) inaddr;
- X if (numericdots(hostname) == 3)
- X if (sscanf(hostname,"%d.%d.%d.%d",&h1,&h2,&h3,&h4) == 4)
- X {
- X x[0] = h1; x[1] = h2; x[2] = h3; x[3] = h4;
- X return 1;
- X }
- X /* could use inet_ntoa here */
- X he = gethostbyname(hostname);
- X if (!he)
- X return -1; /*XXX*/
- X x[0] = he->h_addr[0];
- X x[1] = he->h_addr[1];
- X x[2] = he->h_addr[2];
- X x[3] = he->h_addr[3];
- X return 0;
- X}
- END_OF_FILE
- if test 1191 -ne `wc -c <'hostname.c'`; then
- echo shar: \"'hostname.c'\" unpacked with wrong size!
- fi
- # end of 'hostname.c'
- fi
- if test -f 'hostname.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hostname.h'\"
- else
- echo shar: Extracting \"'hostname.h'\" \(107 characters\)
- sed "s/^X//" >'hostname.h' <<'END_OF_FILE'
- X#ifndef HOSTNAME_H
- X#define HOSTNAME_H
- X
- Xextern int inaddr2hostname();
- Xextern int hostname2inaddr();
- X
- X#endif
- END_OF_FILE
- if test 107 -ne `wc -c <'hostname.h'`; then
- echo shar: \"'hostname.h'\" unpacked with wrong size!
- fi
- # end of 'hostname.h'
- fi
- if test -f 'malloc.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'malloc.h'\"
- else
- echo shar: Extracting \"'malloc.h'\" \(66 characters\)
- sed "s/^X//" >'malloc.h' <<'END_OF_FILE'
- X#ifndef MALLOC_H
- X#define MALLOC_H
- X
- Xextern char *malloc();
- X
- X#endif
- END_OF_FILE
- if test 66 -ne `wc -c <'malloc.h'`; then
- echo shar: \"'malloc.h'\" unpacked with wrong size!
- fi
- # end of 'malloc.h'
- fi
- if test -f 'npipekiller.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'npipekiller.c'\"
- else
- echo shar: Extracting \"'npipekiller.c'\" \(3207 characters\)
- sed "s/^X//" >'npipekiller.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <signal.h>
- X#include <fcntl.h>
- X#include "dupdup.h"
- X#include "malloc.h"
- X#include "errno.h"
- X#include "username.h"
- X#include "env.h"
- X#include "getopt.h"
- X#include "numfiles.h"
- X
- X#ifndef F_LOCK
- X#define F_LOCK 1
- X#endif
- X#ifndef O_RDONLY
- X#define O_RDONLY 0
- X#endif
- X#ifndef O_WRONLY
- X#define O_WRONLY 1
- X#endif
- X#ifndef O_RDWR
- X#define O_RDWR 2
- X#endif
- X
- Xstatic int flagverbose = 1;
- X
- Xstatic char errbuf[500];
- Xvoid die(n,s) int n; char *s;
- X{ if (flagverbose) fprintf(stderr,"npipekiller: fatal: %s\n",s); exit(n); }
- Xvoid dies(n,s,t) int n; char *s; char *t;
- X{ if (flagverbose) fprintf(stderr,"npipekiller: fatal: %s%s\n",s,t); exit(n); }
- Xvoid diep(n,s) int n; char *s;
- X{ if (flagverbose) sprintf(errbuf,"npipekiller: fatal: %s",s); perror(errbuf); exit(n); }
- Xvoid warnp(s) char *s;
- X{ if (flagverbose) sprintf(errbuf,"npipekiller: warning: %s",s); perror(errbuf); }
- Xvoid warnsp(s,t) char *s; char *t;
- X{ if (flagverbose) sprintf(errbuf,"npipekiller: warning: %s%s",s,t); perror(errbuf); }
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X int arguid;
- X int uid;
- X int i;
- X int fdserv;
- X int fdlock;
- X char fnlock[200];
- X char fnserv[200];
- X int m;
- X int n;
- X int r;
- X char buf[100];
- X char *uname;
- X int opt;
- X
- X while ((opt = getopt(argc,argv,"qQ")) != EOF)
- X switch(opt)
- X {
- X case 'q':
- X flagverbose = 0; break;
- X case 'Q':
- X flagverbose = 1; break;
- X case '?':
- X break; /*XXX*/
- X default:
- X break; /*XXX*/
- X }
- X argc -= optind; argv += optind;
- X
- X if (argc < 2)
- X die(1,"need at least two arguments");
- X
- X uid = getuid();
- X if (username2uid(argv[0],&arguid) == -1)
- X dies(2,"cannot figure out username ",argv[0]);
- X
- X if (arguid != uid)
- X dies(1,"permission denied by ",argv[0]);
- X
- X for (i = 0;argv[0][i];++i)
- X if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
- X dies(4,"illegal characters in username ",argv[0]);
- X
- X for (i = 0;argv[1][i];++i)
- X if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
- X dies(5,"illegal characters in service ",argv[1]);
- X
- X signal(SIGPIPE,SIG_IGN);
- X
- X if (uid2username(uid,&uname) == -1) /* will never happen */
- X die(2,"cannot figure out my own username");
- X
- X if (strlen(NPIPEDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 90) /*XXX*/
- X die(8,"server filenames too long");
- X sprintf(fnserv,"%s/%ds%s",NPIPEDIR,arguid,argv[1]);
- X sprintf(fnlock,"%s/%dl%s",NPIPEDIR,arguid,argv[1]);
- X sprintf(buf,"%d",0);
- X n = strlen(buf);
- X if (n + strlen(uname) + 10 > sizeof(buf))
- X die(8,"username too long");
- X strcpy(buf + n + 1,uname);
- X n += strlen(uname) + 2;
- X
- X fdlock = open(fnlock,O_RDWR,0);
- X if (fdlock == -1)
- X diep(1,"cannot open lock file");
- X /* Here's the tricky bit: file locking. :-( */
- X /* XXX: We assume that anyone with named pipes also has lockf(). */
- X if (lockf(fdlock,F_LOCK,1) == -1)
- X diep(1,"cannot wait for lock on lock file");
- X
- X fdserv = open(fnserv,O_WRONLY,0);
- X if (fdserv == -1)
- X diep(1,"cannot open server's named pipe");
- X
- X m = 0;
- X r = 0;
- X while ((m < n) && ((r = write(fdserv,buf + m,n - m)) > 0))
- X m += r;
- X if (r <= 0)
- X die(1,"cannot tell server to kill itself");
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 3207 -ne `wc -c <'npipekiller.c'`; then
- echo shar: \"'npipekiller.c'\" unpacked with wrong size!
- fi
- # end of 'npipekiller.c'
- fi
- if test -f 'numeric.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'numeric.c'\"
- else
- echo shar: Extracting \"'numeric.c'\" \(782 characters\)
- sed "s/^X//" >'numeric.c' <<'END_OF_FILE'
- X/* History:
- X6/19/91 DJB added numericdots()
- X5/1/91 DJB baseline public domain
- X*/
- X
- X/*
- X
- Xint numeric(s) char *s; returns 1 if s is entirely composed of the
- Xdigits 0 through 9, 0 otherwise.
- X
- X*/
- X
- X#include "numeric.h"
- X
- Xint numeric(s)
- Xchar *s;
- X{
- X while (*s)
- X {
- X if ((*s != '0') && (*s != '1') && (*s != '2') && (*s != '3') && (*s != '4')
- X && (*s != '5') && (*s != '6') && (*s != '7') && (*s != '8') && (*s != '9'))
- X return 0;
- X ++s;
- X }
- X return 1;
- X}
- X
- Xint numericdots(s)
- Xchar *s;
- X{
- X int dots;
- X
- X dots = 0;
- X while (*s)
- X {
- X if ((*s != '0') && (*s != '1') && (*s != '2') && (*s != '3') && (*s != '4')
- X && (*s != '5') && (*s != '6') && (*s != '7') && (*s != '8') && (*s != '9')
- X && (*s != '.')
- X )
- X return -1;
- X if (*s == '.')
- X ++dots;
- X ++s;
- X }
- X return dots;
- X}
- END_OF_FILE
- if test 782 -ne `wc -c <'numeric.c'`; then
- echo shar: \"'numeric.c'\" unpacked with wrong size!
- fi
- # end of 'numeric.c'
- fi
- if test -f 'numeric.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'numeric.h'\"
- else
- echo shar: Extracting \"'numeric.h'\" \(93 characters\)
- sed "s/^X//" >'numeric.h' <<'END_OF_FILE'
- X#ifndef NUMERIC_H
- X#define NUMERIC_H
- X
- Xextern int numeric();
- Xextern int numericdots();
- X
- X#endif
- END_OF_FILE
- if test 93 -ne `wc -c <'numeric.h'`; then
- echo shar: \"'numeric.h'\" unpacked with wrong size!
- fi
- # end of 'numeric.h'
- fi
- if test -f 'numfiles.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'numfiles.h'\"
- else
- echo shar: Extracting \"'numfiles.h'\" \(82 characters\)
- sed "s/^X//" >'numfiles.h' <<'END_OF_FILE'
- X#ifndef NUMFILES_H
- X#define NUMFILES_H
- X
- X#define NUMFILES (getdtablesize())
- X
- X#endif
- END_OF_FILE
- if test 82 -ne `wc -c <'numfiles.h'`; then
- echo shar: \"'numfiles.h'\" unpacked with wrong size!
- fi
- # end of 'numfiles.h'
- fi
- if test -f 'portname.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'portname.c'\"
- else
- echo shar: Extracting \"'portname.c'\" \(764 characters\)
- sed "s/^X//" >'portname.c' <<'END_OF_FILE'
- X/* History:
- X6/20/91 DJB added proto arg
- X5/9/91 DJB fixed for backwards architectures, tnx VA
- X5/1/91 DJB baseline public domain
- X*/
- X
- X#include "portname.h"
- X#include "numeric.h"
- X#include <netdb.h>
- X
- X/* XXX: cache */
- X
- Xint port2portname(port,pop,proto)
- Xint port;
- Xchar **pop;
- Xchar *proto;
- X{
- X struct servent *se;
- X static char po[20];
- X
- X if (se = getservbyport(port,proto))
- X {
- X *pop = se->s_name;
- X return 0;
- X }
- X sprintf(po,"%d",port);
- X *pop = po;
- X return 1;
- X}
- X
- Xint portname2port(po,port,proto)
- Xchar *po;
- Xint *port;
- Xchar *proto;
- X{
- X struct servent *se;
- X
- X if (numeric(po))
- X {
- X *port = atoi(po);
- X return 1;
- X }
- X se = getservbyname(po,proto);
- X if (!se)
- X return -1; /*XXX*/
- X *port = ntohs(se->s_port);
- X /* XXX: stupidity alert: se->s_port is an int! */
- X return 0;
- X}
- END_OF_FILE
- if test 764 -ne `wc -c <'portname.c'`; then
- echo shar: \"'portname.c'\" unpacked with wrong size!
- fi
- # end of 'portname.c'
- fi
- if test -f 'portname.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'portname.h'\"
- else
- echo shar: Extracting \"'portname.h'\" \(103 characters\)
- sed "s/^X//" >'portname.h' <<'END_OF_FILE'
- X#ifndef PORTNAME_H
- X#define PORTNAME_H
- X
- Xextern int port2portname();
- Xextern int portname2port();
- X
- X#endif
- END_OF_FILE
- if test 103 -ne `wc -c <'portname.h'`; then
- echo shar: \"'portname.h'\" unpacked with wrong size!
- fi
- # end of 'portname.h'
- fi
- if test -f 'tcpkiller.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tcpkiller.c'\"
- else
- echo shar: Extracting \"'tcpkiller.c'\" \(2818 characters\)
- sed "s/^X//" >'tcpkiller.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/file.h>
- X#include <sys/socket.h>
- X#include <signal.h>
- X#include <netinet/in.h>
- X#include "errno.h"
- X#include "username.h"
- X#include "hostname.h"
- X#include "portname.h"
- X#include "getopt.h"
- X#include "malloc.h"
- X#include "env.h"
- X
- X#ifndef MAXHOSTNAMELEN
- X#define MAXHOSTNAMELEN 64
- X#endif
- X
- Xstatic int flagverbose = 1;
- X
- Xstatic char errbuf[500];
- Xvoid die(n,s) int n; char *s;
- X{ if (flagverbose) fprintf(stderr,"tcpkiller: fatal: %s\n",s); exit(n); }
- Xvoid dies(n,s,t) int n; char *s; char *t;
- X{ if (flagverbose) fprintf(stderr,"tcpkiller: fatal: %s%s\n",s,t); exit(n); }
- Xvoid diep(n,s) int n; char *s;
- X{ if (flagverbose) sprintf(errbuf,"tcpkiller: fatal: %s",s); perror(errbuf); exit(n); }
- Xvoid warnp(s) char *s;
- X{ if (flagverbose) sprintf(errbuf,"tcpkiller: warning: %s",s); perror(errbuf); }
- Xvoid warnsp(s,t) char *s; char *t;
- X{ if (flagverbose) sprintf(errbuf,"tcpkiller: warning: %s%s",s,t); perror(errbuf); }
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X int uid;
- X int opt;
- X char lochost[MAXHOSTNAMELEN];
- X int locport;
- X char *home;
- X char *fnrecord;
- X char pidstr[50];
- X int pid;
- X int fd;
- X
- X while ((opt = getopt(argc,argv,"qQ")) != EOF)
- X switch(opt)
- X {
- X case 'q':
- X flagverbose = 0; break;
- X case 'Q':
- X flagverbose = 1; break;
- X case '?':
- X break; /*XXX*/
- X default:
- X break; /*XXX*/
- X }
- X argc -= optind; argv += optind;
- X
- X if (argc < 2)
- X die(1,"need at least two arguments");
- X
- X uid = getuid();
- X
- X gethostname(lochost,sizeof(lochost));
- X
- X if ((argv[0][0] == '0') && (argv[0][1] == 0))
- X ; /* local host, fine */
- X else
- X {
- X struct in_addr inaddr1;
- X struct in_addr inaddr2;
- X if (hostname2inaddr(argv[0],&inaddr1) == -1)
- X dies(2,"cannot figure out hostname ",argv[0]);
- X if (hostname2inaddr(lochost,&inaddr2) == -1)
- X die(2,"cannot figure out my own hostname");
- X /* XXX: this doesn't allow 127.1 */
- X if (inaddr1.s_addr != inaddr2.s_addr)
- X dies(2,"host does not match local host ",argv[0]);
- X }
- X
- X if (portname2port(argv[1],&locport,"tcp") == -1)
- X dies(2,"cannot figure out portname ",argv[1]);
- X locport = locport & 65535;
- X
- X home = env_get("TCPHOME");
- X if (!home)
- X {
- X home = env_get("HOME");
- X if (!home)
- X die(1,"cannot find TCPHOME or HOME in environment");
- X }
- X fnrecord = malloc(strlen(home) + strlen(lochost) + 100);
- X if (!fnrecord)
- X die(1,"out of memory");
- X sprintf(fnrecord,"%s/.tcpserver.%s.%d.%d",home,lochost,uid,locport);
- X
- X fd = open(fnrecord,O_RDONLY,0400);
- X if (fd == -1)
- X dies(1,"cannot open ",fnrecord);
- X
- X read(fd,pidstr,sizeof(pidstr)); /* XXX: check for partial reads */
- X if (sscanf(pidstr,"%d",&pid) != 1)
- X die(1,"cannot figure out pid of tcpserver");
- X
- X close(fd);
- X
- X kill(pid,SIGTERM); /*XXX: report errors? */
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 2818 -ne `wc -c <'tcpkiller.c'`; then
- echo shar: \"'tcpkiller.c'\" unpacked with wrong size!
- fi
- # end of 'tcpkiller.c'
- fi
- if test -f 'testmain' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'testmain'\"
- else
- echo shar: Extracting \"'testmain'\" \(269 characters\)
- sed "s/^X//" >'testmain' <<'END_OF_FILE'
- X#!/bin/sh
- X# testmain args
- X./testucspi ${1+"$@"} | sed 's/=.*//' > .ucspi.$$
- X./testresult ${1+"$@"} | sed 's/=.*//' > .result.$$
- Xif cmp .ucspi.$$ .result.$$ >/dev/null 2>&1
- Xthen echo 'Everything compares okay.'
- Xelse echo 'Aaack! Test failed.'
- Xfi
- Xrm .ucspi.$$ .result.$$
- END_OF_FILE
- if test 269 -ne `wc -c <'testmain'`; then
- echo shar: \"'testmain'\" unpacked with wrong size!
- fi
- chmod +x 'testmain'
- # end of 'testmain'
- fi
- if test -f 'testresult' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'testresult'\"
- else
- echo shar: Extracting \"'testresult'\" \(915 characters\)
- sed "s/^X//" >'testresult' <<'END_OF_FILE'
- X#!/bin/sh
- X# testresult proto prog address
- X# XXX: test args
- Xproto="$1"; shift; export proto
- Xprog="$1"; shift
- Xclient=./"$prog"client; export client
- Xserver=./"$prog"server; export server
- Xkiller=./"$prog"killer; export killer
- Xecho "$server started, ${proto}LOCAL=(depends on the protocol)"
- Xecho "$client started"
- Xecho "$client connected to ${proto}REMOTE=(depends on the protocol)"
- Xecho "$client reading line from server..."
- Xecho "$server accepted connection from ${proto}REMOTE=(depends on the protocol)"
- Xecho "$server writing line to client..."
- Xecho "$client received from server: is anybody out there..."
- Xecho "$client writing line to server..."
- Xecho "$server reading line from client..."
- Xecho "$server received from client: is anybody in there..."
- Xecho "$server done with connection"
- Xecho "$client done with connection"
- Xecho "$client finished"
- Xecho "$killer started"
- Xecho "$server finished"
- Xecho "$killer finished"
- END_OF_FILE
- if test 915 -ne `wc -c <'testresult'`; then
- echo shar: \"'testresult'\" unpacked with wrong size!
- fi
- chmod +x 'testresult'
- # end of 'testresult'
- fi
- if test -f 'testucspi' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'testucspi'\"
- else
- echo shar: Extracting \"'testucspi'\" \(1220 characters\)
- sed "s/^X//" >'testucspi' <<'END_OF_FILE'
- X#!/bin/sh
- X# testucspi proto prog address
- X# XXX: test args
- Xproto="$1"; shift; export proto
- Xprog="$1"; shift
- Xclient=./"$prog"client; export client
- Xserver=./"$prog"server; export server
- Xkiller=./"$prog"killer; export killer
- X
- X(
- Xecho "$server started, ${proto}LOCAL=" | tr -d '\012'
- X# blessed be the shells that allow "$server" here
- X$server -4 "$@" sh -c '
- X exec <&6
- X sleep 5
- X echo "$server accepted connection from ${proto}REMOTE=" | tr -d "\012"
- X printenv ${proto}REMOTE
- X echo "$server writing line to client..."
- X echo "is anybody out there..." >&7
- X sleep 5
- X echo "$server reading line from client..."
- X read i
- X echo "$server received from client: $i"
- X echo "$server done with connection"
- X' 4>&1
- Xecho "$server finished"
- X) &
- X
- Xsleep 5
- X
- Xecho "$client started"
- X$client "$@" sh -c '
- X exec <&6
- X sleep 1
- X echo "$client connected to ${proto}REMOTE=" | tr -d "\012"
- X printenv ${proto}REMOTE
- X echo "$client reading line from server..."
- X read i
- X echo "$client received from server: $i"
- X echo "$client writing line to server..."
- X echo "is anybody in there..." >&7
- X sleep 5
- X echo "$client done with connection"
- X'
- Xecho "$client finished"
- X
- Xecho "$killer started"
- Xeval "$killer" "$@"
- Xsleep 2
- Xecho "$killer finished"
- END_OF_FILE
- if test 1220 -ne `wc -c <'testucspi'`; then
- echo shar: \"'testucspi'\" unpacked with wrong size!
- fi
- chmod +x 'testucspi'
- # end of 'testucspi'
- fi
- if test -f 'undomclient.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'undomclient.c'\"
- else
- echo shar: Extracting \"'undomclient.c'\" \(3980 characters\)
- sed "s/^X//" >'undomclient.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <sys/un.h>
- X#include <signal.h>
- X#include "dupdup.h"
- X#include "malloc.h"
- X#include "errno.h"
- X#include "username.h"
- X#include "env.h"
- X#include "getopt.h"
- X#include "numfiles.h"
- X
- Xstatic int flagverbose = 1;
- Xstatic struct sockaddr_un sa;
- X
- Xstatic char errbuf[500];
- Xvoid die(n,s) int n; char *s;
- X{ if (flagverbose) fprintf(stderr,"undomclient: fatal: %s\n",s); exit(n); }
- Xvoid dies(n,s,t) int n; char *s; char *t;
- X{ if (flagverbose) fprintf(stderr,"undomclient: fatal: %s%s\n",s,t); exit(n); }
- Xvoid diep(n,s) int n; char *s;
- X{ if (flagverbose) sprintf(errbuf,"undomclient: fatal: %s",s); perror(errbuf); exit(n); }
- Xvoid warnp(s) char *s;
- X{ if (flagverbose) sprintf(errbuf,"undomclient: warning: %s",s); perror(errbuf); }
- Xvoid warnsp(s,t) char *s; char *t;
- X{ if (flagverbose) sprintf(errbuf,"undomclient: warning: %s%s",s,t); perror(errbuf); }
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X int t;
- X int *d;
- X int tdup;
- X int numfiles;
- X int arguid;
- X int uid;
- X int i;
- X static char undomlocal[200];
- X static char undomremote[300];
- X unsigned char urlen;
- X char *uname;
- X int opt;
- X
- X while ((opt = getopt(argc,argv,"qQ")) != EOF)
- X switch(opt)
- X {
- X case 'q':
- X flagverbose = 0; break;
- X case 'Q':
- X flagverbose = 1; break;
- X case '?':
- X break; /*XXX*/
- X default:
- X break; /*XXX*/
- X }
- X argc -= optind; argv += optind;
- X
- X if (argc < 3)
- X die(1,"need at least three arguments");
- X
- X uid = getuid();
- X if (username2uid(argv[0],&arguid) == -1)
- X dies(2,"cannot figure out username ",argv[0]);
- X /* XXX: any permission checks? */
- X
- X for (i = 0;argv[0][i];++i)
- X if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
- X dies(4,"illegal characters in username ",argv[0]);
- X
- X for (i = 0;argv[1][i];++i)
- X if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
- X dies(5,"illegal characters in service ",argv[1]);
- X
- X close(6);
- X close(7); /* XXX: these have implications that should be documented */
- X
- X signal(SIGPIPE,SIG_IGN);
- X
- X if (uid2username(uid,&uname) == -1) /* will never happen */
- X die(2,"cannot figure out my own username");
- X urlen = strlen(uname) + 1;
- X
- X numfiles = NUMFILES;
- X d = (int *) malloc(numfiles * sizeof(int));
- X if (!d)
- X die(6,"cannot malloc");
- X for (i = 0;i < numfiles;++i)
- X d[i] = -1;
- X
- X if (strlen(UNDOMDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 100) /*XXX*/
- X die(8,"server socket name too long");
- X sprintf(sa.sun_path,"%s/%s:%s",UNDOMDIR,argv[0],argv[1]);
- X
- X if (env_init() == -1)
- X die(11,"cannot init environment");
- X if (env_put("PROTO=UNDOM") == -1)
- X die(11,"out of memory putting PROTO into environment");
- X sprintf(undomlocal,"UNDOMLOCAL=%s",uname);
- X if (env_put(undomlocal) == -1)
- X die(11,"out of memory putting UNDOMLOCAL into environment");
- X sprintf(undomremote,"UNDOMREMOTE=%s:%s",argv[0],argv[1]);
- X if (env_put(undomremote) == -1)
- X die(11,"out of memory putting UNDOMREMOTE into environment");
- X
- X t = socket(AF_UNIX,SOCK_STREAM,0);
- X if (t == -1)
- X diep(7,"cannot create client socket");
- X sa.sun_family = AF_UNIX;
- X if (connect(t,&sa,sizeof(sa)) == -1)
- X diep(9,"cannot connect to server");
- X
- X /* XXX: fork? not necessary here */
- X
- X if ((i = write(t,&urlen,1)) == -1)
- X diep(1,"cannot write length of local username");
- X if (!i) /* ever? */
- X die(1,"cannot write length of local username");
- X if (write(t,uname,urlen) < urlen)
- X die(1,"cannot write local username");
- X
- X tdup = dup(t);
- X if (tdup == -1)
- X diep(10,"cannot dup connection to server");
- X
- X /* Now put t into descriptor 6 and tdup into descriptor 7. */
- X /* XXX: should check that t and tdup are small enough */
- X d[t] = 6;
- X d[tdup] = 7;
- X if (dupdup(d,numfiles) == -1)
- X diep(10,"cannot dup connection to server");
- X
- X if (setreuid(uid,uid) == -1)
- X diep(1,"cannot setreuid"); /* will never happen */
- X signal(SIGPIPE,SIG_DFL);
- X execvp(argv[2],argv + 2);
- X warnsp("cannot exec ",argv[2]);
- X exit(1);
- X}
- END_OF_FILE
- if test 3980 -ne `wc -c <'undomclient.c'`; then
- echo shar: \"'undomclient.c'\" unpacked with wrong size!
- fi
- # end of 'undomclient.c'
- fi
- if test -f 'undomkiller.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'undomkiller.c'\"
- else
- echo shar: Extracting \"'undomkiller.c'\" \(2703 characters\)
- sed "s/^X//" >'undomkiller.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <sys/un.h>
- X#include <signal.h>
- X#include "errno.h"
- X#include "username.h"
- X#include "getopt.h"
- X
- Xstatic int flagverbose = 1;
- Xstatic struct sockaddr_un sa;
- X
- Xstatic char errbuf[500];
- Xvoid die(n,s) int n; char *s;
- X{ if (flagverbose) fprintf(stderr,"undomkiller: fatal: %s\n",s); exit(n); }
- Xvoid dies(n,s,t) int n; char *s; char *t;
- X{ if (flagverbose) fprintf(stderr,"undomkiller: fatal: %s%s\n",s,t); exit(n); }
- Xvoid diep(n,s) int n; char *s;
- X{ if (flagverbose) sprintf(errbuf,"undomkiller: fatal: %s",s); perror(errbuf); exit(n); }
- Xvoid warnp(s) char *s;
- X{ if (flagverbose) sprintf(errbuf,"undomkiller: warning: %s",s); perror(errbuf); }
- Xvoid warnsp(s,t) char *s; char *t;
- X{ if (flagverbose) sprintf(errbuf,"undomkiller: warning: %s%s",s,t); perror(errbuf); }
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X int t;
- X int arguid;
- X int uid;
- X int i;
- X unsigned char urlen;
- X char *uname;
- X int opt;
- X
- X while ((opt = getopt(argc,argv,"qQ")) != EOF)
- X switch(opt)
- X {
- X case 'q':
- X flagverbose = 0; break;
- X case 'Q':
- X flagverbose = 1; break;
- X case '?':
- X break; /*XXX*/
- X default:
- X break; /*XXX*/
- X }
- X argc -= optind; argv += optind;
- X
- X if (argc < 2)
- X die(1,"need at least two arguments");
- X
- X uid = getuid();
- X if (username2uid(argv[0],&arguid) == -1)
- X dies(2,"cannot figure out username ",argv[0]);
- X
- X if (arguid != uid)
- X dies(15,"permission denied by ",argv[0]);
- X /* XXX: special-case root? more checks? */
- X /* This is enough to prevent one user from wasting another's CPU time. */
- X
- X for (i = 0;argv[0][i];++i)
- X if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
- X dies(4,"illegal characters in username ",argv[0]);
- X
- X for (i = 0;argv[1][i];++i)
- X if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
- X dies(5,"illegal characters in service ",argv[1]);
- X
- X if (uid2username(uid,&uname) == -1) /* will never happen */
- X die(2,"cannot figure out my own username");
- X urlen = strlen(uname) + 1;
- X
- X if (strlen(UNDOMDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 100) /*XXX*/
- X die(8,"server socket name too long");
- X sprintf(sa.sun_path,"%s/%s:%s",UNDOMDIR,argv[0],argv[1]);
- X
- X t = socket(AF_UNIX,SOCK_STREAM,0);
- X if (t == -1)
- X diep(7,"cannot create killer socket");
- X sa.sun_family = AF_UNIX;
- X if (connect(t,&sa,sizeof(sa)) == -1)
- X diep(9,"cannot connect to server");
- X
- X signal(SIGPIPE,SIG_IGN);
- X
- X urlen = 0; /* XXX: this signals server to clean up and die */
- X if ((i = write(t,&urlen,1)) == -1)
- X diep(1,"cannot kill server");
- X if (!i) /* ever? */
- X die(1,"cannot kill server");
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 2703 -ne `wc -c <'undomkiller.c'`; then
- echo shar: \"'undomkiller.c'\" unpacked with wrong size!
- fi
- # end of 'undomkiller.c'
- fi
- if test -f 'username.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'username.c'\"
- else
- echo shar: Extracting \"'username.c'\" \(549 characters\)
- sed "s/^X//" >'username.c' <<'END_OF_FILE'
- X/* History:
- X5/1/91 DJB baseline public domain
- X*/
- X
- X#include <pwd.h>
- X#include "username.h"
- X#include "numeric.h"
- X
- X/*XXX: cache */
- X
- Xint uid2username(uid,unp)
- Xint uid;
- Xchar **unp;
- X{
- X struct passwd *pw;
- X static char un[20];
- X
- X if (pw = getpwuid(uid))
- X {
- X *unp = pw->pw_name;
- X return 0;
- X }
- X sprintf(un,"%d",uid);
- X *unp = un;
- X return 1;
- X}
- X
- Xint username2uid(un,uid)
- Xchar *un;
- Xint *uid;
- X{
- X struct passwd *pw;
- X
- X if (numeric(un))
- X {
- X *uid = atoi(un);
- X return 1;
- X }
- X pw = getpwnam(un);
- X if (!pw)
- X return -1; /*XXX*/
- X *uid = pw->pw_uid;
- X return 0;
- X}
- END_OF_FILE
- if test 549 -ne `wc -c <'username.c'`; then
- echo shar: \"'username.c'\" unpacked with wrong size!
- fi
- # end of 'username.c'
- fi
- if test -f 'username.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'username.h'\"
- else
- echo shar: Extracting \"'username.h'\" \(101 characters\)
- sed "s/^X//" >'username.h' <<'END_OF_FILE'
- X#ifndef USERNAME_H
- X#define USERNAME_H
- X
- Xextern int uid2username();
- Xextern int username2uid();
- X
- X#endif
- END_OF_FILE
- if test 101 -ne `wc -c <'username.h'`; then
- echo shar: \"'username.h'\" unpacked with wrong size!
- fi
- # end of 'username.h'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-