home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / socket < prev    next >
Encoding:
Text File  |  1992-09-07  |  51.0 KB  |  1,974 lines

  1. Newsgroups: comp.sources.unix
  2. From: nickel@cs.tu-berlin.de (Juergen Nickelsen)
  3. Subject: v26i075: socket - shell-level interface to IP/TCP sockets (V1.1)
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: nickel@cs.tu-berlin.de (Juergen Nickelsen)
  8. Posting-Number: Volume 26, Issue 75
  9. Archive-Name: socket
  10.  
  11. This is release 1.1 of the Socket(1) program.
  12.  
  13. Socket(1) implements an interface to TCP sockets at shell level.  Client and
  14. server sockets can be used from shell scripts or interactively.  Socket can
  15. also run a program with stdin, stdout, and stderr connected to the socket
  16. connection.  Sample shell scripts implementing a finger client (remote only)
  17. and a finger daemon are included.
  18.  
  19. Socket-1.1 runs on these platforms:
  20.  
  21.   - AT 386, ISC 3.0                     (*)
  22.   - CDC 4680, EP/IX 1.4.1.              (*)
  23.   - DECstation 3100, Ultrix 4.0
  24.   - HP-UX 7.0, 8.0                      (*)
  25.   - IBM RS 6000, AIX 3.1.5
  26.   - MicroVAX II, 4.3 BSD                (*)
  27.   - SGI Iris, Irix 3.3.1
  28.   - Sequent, DYNIX v.3.0.7              (*)
  29.   - Sun SPARCstation II, SunOS 4.1.2
  30.   - System V Rel. 4                     (*)
  31.  
  32. The platforms marked with "(*)" require minor editing of the Makefile.
  33.  
  34. Please send any comments, suggestions, bug reports etc. to me:
  35.  
  36.     Juergen Nickelsen
  37.     Sekr. FR 5-6
  38.     TU Berlin
  39.     Franklinstr. 28-29
  40.     1000 Berlin 10
  41.     Germany
  42.  
  43.     <nickel@cs.tu-berlin.de>
  44.  
  45. #! /bin/sh
  46. # This is a shell archive.  Remove anything before this line, then unpack
  47. # it by saving it into a file and typing "sh file".  To overwrite existing
  48. # files, type "sh file -c".  You can also feed this as standard input via
  49. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  50. # will see the following message at the end:
  51. #        "End of shell archive."
  52. # Contents:  BLURB CHANGES COPYRIGHT Dependencies INSTALL Makefile
  53. #   README fingerd.sh globals.h io.c patchlevel.h rfinger.sh siglist.c
  54. #   so_release.c socket.1 socket.c socketp.c utils.c
  55. # Wrapped by vixie@cognition.pa.dec.com on Wed Sep  9 11:28:43 1992
  56. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  57. if test -f 'BLURB' -a "${1}" != "-c" ; then 
  58.   echo shar: Will not clobber existing file \"'BLURB'\"
  59. else
  60. echo shar: Extracting \"'BLURB'\" \(879 characters\)
  61. sed "s/^X//" >'BLURB' <<'END_OF_FILE'
  62. This is release 1.1 of the Socket(1) program.
  63. X
  64. Socket(1) implements an interface to TCP sockets at shell level.
  65. Client and server sockets can be used from shell scripts or
  66. interactively.  Socket can also run a program with stdin, stdout, and
  67. stderr connected to the socket connection.  Sample shell scripts
  68. implementing a finger client (remote only) and a finger daemon are
  69. included.
  70. X
  71. Socket-1.1 runs on these platforms:
  72. X
  73. X  - AT 386, ISC 3.0                     (*)
  74. X  - CDC 4680, EP/IX 1.4.1.              (*)
  75. X  - DECstation 3100, Ultrix 4.0
  76. X  - HP-UX 7.0, 8.0                      (*)
  77. X  - IBM RS 6000, AIX 3.1.5
  78. X  - MicroVAX II, 4.3 BSD                (*)
  79. X  - SGI Iris, Irix 3.3.1
  80. X  - Sequent, DYNIX v.3.0.7              (*)
  81. X  - Sun SPARCstation II, SunOS 4.1.2
  82. X  - System V Rel. 4                     (*)
  83. X
  84. The platforms marked with "(*)" require minor editing of the Makefile.
  85. END_OF_FILE
  86. if test 879 -ne `wc -c <'BLURB'`; then
  87.     echo shar: \"'BLURB'\" unpacked with wrong size!
  88. fi
  89. # end of 'BLURB'
  90. fi
  91. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  92.   echo shar: Will not clobber existing file \"'CHANGES'\"
  93. else
  94. echo shar: Extracting \"'CHANGES'\" \(489 characters\)
  95. sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  96. X-*-text-*-
  97. X
  98. User-visible changes in Socket version 1.1:
  99. X
  100. X  - Ported to more Platforms (SGI Irix, IBM AIX, CDC EP/IX, ISC 3.0,
  101. X    System V R4, Sequent)
  102. X
  103. X  - fixed getopt()-related bug in main() (opt declared as int now).
  104. X
  105. X  - fixed SIGWINCH-related bug (socket no longer exits on SIGWINCH).
  106. X
  107. X  - Background mode (-b option)
  108. X
  109. X  - -f option to fork child 
  110. X
  111. X  - fixed bug in server mode concerning the "Connection from..."
  112. X    message
  113. X
  114. X  - slightly more adequate signal handling and messages
  115. END_OF_FILE
  116. if test 489 -ne `wc -c <'CHANGES'`; then
  117.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  118. fi
  119. # end of 'CHANGES'
  120. fi
  121. if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  122.   echo shar: Will not clobber existing file \"'COPYRIGHT'\"
  123. else
  124. echo shar: Extracting \"'COPYRIGHT'\" \(932 characters\)
  125. sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
  126. X-*- text -*- 
  127. X
  128. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  129. except the file siglist.c, which is Copyright (C) 1989 Free Software
  130. XFoundation, Inc.
  131. X
  132. This applies to the Socket program, release Socket-1.1.
  133. X
  134. Socket is free software; you can redistribute it and/or modify it
  135. under the terms of the GNU General Public License as published by the
  136. XFree Software Foundation; either version 1, or (at your option) any
  137. later version.
  138. X
  139. It is distributed in the hope that it will be useful, but WITHOUT ANY
  140. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  141. XFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  142. for more details.
  143. X
  144. You may have received a copy of the GNU General Public License along
  145. with GNU Emacs or another GNU program; see the file COPYING.  If not,
  146. write to me at the electronic mail address given above or to 
  147. Juergen Nickelsen, Hertzbergstr. 28, 1000 Berlin 44, Germany.
  148. END_OF_FILE
  149. if test 932 -ne `wc -c <'COPYRIGHT'`; then
  150.     echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
  151. fi
  152. # end of 'COPYRIGHT'
  153. fi
  154. if test -f 'Dependencies' -a "${1}" != "-c" ; then 
  155.   echo shar: Will not clobber existing file \"'Dependencies'\"
  156. else
  157. echo shar: Extracting \"'Dependencies'\" \(296 characters\)
  158. sed "s/^X//" >'Dependencies' <<'END_OF_FILE'
  159. io.o: ./globals.h
  160. io.o: ./patchlevel.h
  161. io.o: io.c
  162. siglist.o: siglist.c
  163. so_release.o: so_release.c
  164. socket.o: ./globals.h
  165. socket.o: ./patchlevel.h
  166. socket.o: socket.c
  167. socketp.o: ./globals.h
  168. socketp.o: ./patchlevel.h
  169. socketp.o: socketp.c
  170. utils.o: ./globals.h
  171. utils.o: ./patchlevel.h
  172. utils.o: utils.c
  173. END_OF_FILE
  174. if test 296 -ne `wc -c <'Dependencies'`; then
  175.     echo shar: \"'Dependencies'\" unpacked with wrong size!
  176. fi
  177. # end of 'Dependencies'
  178. fi
  179. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  180.   echo shar: Will not clobber existing file \"'INSTALL'\"
  181. else
  182. echo shar: Extracting \"'INSTALL'\" \(1141 characters\)
  183. sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  184. X-*- text -*-
  185. X
  186. Socket-1.1 runs on these platforms:
  187. X
  188. X  - AT 386, ISC 3.0            (*)
  189. X  - CDC 4680, EP/IX 1.4.1.        (*)
  190. X  - DECstation 3100, Ultrix 4.0
  191. X  - HP-UX 7.0, 8.0            (*)
  192. X  - IBM RS 6000, AIX 3.1.5
  193. X  - MicroVAX II, 4.3 BSD        (*)
  194. X  - SGI Iris, Irix 3.3.1
  195. X  - Sequent, DYNIX v.3.0.7        (*)
  196. X  - Sun SPARCstation II, SunOS 4.1.2
  197. X  - System V Rel. 4            (*)
  198. X
  199. The platforms marked with "(*)" require minor editing of the Makefile.
  200. Instructions are included near the beginning of the Makefile. Edit as
  201. necessary and type "make install". This builds the program and
  202. installs the executable as /usr/local/bin/socket and the manual page
  203. as /usr/local/man/man1/socket.1.
  204. X
  205. Socket relies on some Berkeleyisms in signal, process, and IO
  206. handling, so porting it to (other) non-BSD-derived platforms may be
  207. difficult.  I am interested in any changes you make to port the
  208. program to a new platform.  Please send them back to me so I can merge
  209. them into a later release.
  210. X
  211. The Makefile is not suitable for development since it doesn't include
  212. the dependencies. (I use the Shape Toolkit for development.)
  213. To correct this, include the file Dependencies into the Makefile.
  214. END_OF_FILE
  215. if test 1141 -ne `wc -c <'INSTALL'`; then
  216.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  217. fi
  218. # end of 'INSTALL'
  219. fi
  220. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  221.   echo shar: Will not clobber existing file \"'Makefile'\"
  222. else
  223. echo shar: Extracting \"'Makefile'\" \(4564 characters\)
  224. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  225. X# Makefile for Socket
  226. X#
  227. X# $Header: Makefile[1.23] Wed Sep  9 19:03:26 1992 nickel@cs.tu-berlin.de proposed $
  228. X#
  229. X
  230. X### adjust these to your taste
  231. X### This is set up to install socket as /usr/local/bin/socket and
  232. X### socket.1 in /usr/local/man/man1/socket.1
  233. X### Make sure the target directories exist before doing a "make install".
  234. X
  235. INSTALLBASE = /usr/local
  236. INSTALLBINPATH = $(INSTALLBASE)/bin
  237. INSTALLBINMODE = 755
  238. INSTALLMANPATH = $(INSTALLBASE)/man
  239. INSTALLMANMODE = 444
  240. CC = cc
  241. CFLAGS  = $(SWITCHES) -O
  242. LDFLAGS = $(SWITCHES) -s
  243. X
  244. X### You may need to uncomment some lines below for your operating
  245. X### system:
  246. X
  247. X### 4.3 BSD:
  248. X# SWITCHES = -DNOSETSID
  249. X
  250. X### HP-UX:
  251. X# SYSLIBS  = -lBSD
  252. X
  253. X### ISC 3.0:
  254. X# SYSLIBS  = -linet -lcposix
  255. X# SWITCHES = -DISC
  256. X
  257. X### System V Rel. 4:
  258. X# SYSLIBS  = -lc -lsocket -lnsl -L/usr/ucblib -lucb
  259. X# SWITCHES = -I/usr/ucbinclude
  260. X
  261. X### Sequent:
  262. X# SYSLIBS  = -lseq
  263. X# SWITCHES = -Dstrrchr=rindex -DSEQUENT -DNOSETSID
  264. X### (I have been reported troubles with the "installmanuals" target on
  265. X### a Sequent, so you might have to copy the manual page yourself.)
  266. X
  267. X### CDC 4680 EP/IX: (I know it *has* setsid(2), but not with bsd43)
  268. X# SWITCHES = -systype bsd43 -DNOSETSID
  269. X
  270. X
  271. X
  272. X### It should not be necessary to change anything below this line.
  273. X##################################################################
  274. X
  275. MAKE = make
  276. SHELL = /bin/sh
  277. BASE = /home/stone/nickel/src
  278. NODEPATH = socket
  279. NODENAME = "Socket"
  280. TARGET = socket
  281. VERSIONFILE =     so_release.c
  282. VERSIONOBJECT =    so_release.o
  283. PROGSOURCES = socket.c siglist.c io.c utils.c socketp.c
  284. SOURCES = BLURB README COPYRIGHT INSTALL CHANGES \
  285. X    socket.1 \
  286. X    $(PROGSOURCES) \
  287. X    rfinger.sh fingerd.sh
  288. HEADERS = globals.h patchlevel.h
  289. MANUALS = $(MAN1)
  290. MAN1 = socket.1
  291. COMPONENTS = $(SOURCES) $(HEADERS) $(MANUALS) Makefile Dependencies
  292. OBJECTS = $(VERSIONOBJECT) socket.o siglist.o io.o utils.o socketp.o
  293. X
  294. all: +all $(ALLTARGETS)
  295. X
  296. targets: $(TARGET)
  297. X
  298. X$(TARGET): $(LOCALLIBS) $(OBJECTS)
  299. X    $(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LOCALLIBS) $(SYSLIBS)
  300. X
  301. tags: TAGS
  302. TAGS: $(PROGSOURCES) $(HEADERS)
  303. X    etags $(PROGSOURCES) $(HEADERS)
  304. X
  305. installtargets: $(INSTALLBINPATH)/$(TARGET) installmanuals
  306. X
  307. X$(INSTALLBINPATH)/$(TARGET): $(TARGET)
  308. X    @-echo "installing $(TARGET) in $(INSTALLBINPATH)"; \
  309. X    if [ -f $(INSTALLBINPATH)/$(TARGET) ] && \
  310. X       [ ! -w $(INSTALLBINPATH)/$(TARGET) ]; \
  311. X    then \
  312. X      chmod u+w $(INSTALLBINPATH)/$(TARGET); \
  313. X    fi; \
  314. X    cp $(TARGET) $(INSTALLBINPATH)/$(TARGET); \
  315. X    chmod $(INSTALLBINMODE) $(INSTALLBINPATH)/$(TARGET)
  316. X
  317. installmanuals: $(MANUALS)
  318. X    @-_manuals="$(MAN1)"; \
  319. X    for i in $$_manuals; \
  320. X    do \
  321. X      echo "installing $$i in $(INSTALLMANPATH)/man1"; \
  322. X      if [ -f $(INSTALLMANPATH)/man1/$$i ] && \
  323. X         [ ! -w $(INSTALLMANPATH)/man1/$$i ]; \
  324. X      then \
  325. X        chmod u+w $(INSTALLMANPATH)/man1/$$i; \
  326. X      fi; \
  327. X      cp $$i $(INSTALLMANPATH)/man1/$$i; \
  328. X      chmod $(INSTALLMANMODE) $(INSTALLMANPATH)/man1/$$i; \
  329. X    done
  330. X
  331. doclean:
  332. X    rm -f $(TARGET) $(ALIASES) $(OBJECTS) core *~
  333. X
  334. X##
  335. X## following internals of shapeTools Release Management System
  336. X
  337. subsystems: # none
  338. X
  339. install: +install $(ALLTARGETS)
  340. X
  341. clean: +clean $(ALLTARGETS)
  342. X
  343. X+all:
  344. X    @-if [ -n "$(ALLTARGETS)" ]; \
  345. X    then : ; \
  346. X    else \
  347. X      $(MAKE) ALLTARGETS="subsystems targets" MAINTARGET=all \
  348. X        BASE=$(BASE) \
  349. X        SWITCHES="$(SWITCHES)" \
  350. X        INSTALLBASE=$(INSTALLBASE) \
  351. X        INSTALLBINPATH=$(INSTALLBINPATH) \
  352. X        INSTALLBINMODE=$(INSTALLBINMODE) \
  353. X        INSTALLMANPATH=$(INSTALLMANPATH) \
  354. X        INSTALLMANMODE=$(INSTALLMANMODE) \
  355. X        MAKE="$(MAKE)" \
  356. X        SHELL="$(SHELL)" \
  357. X        CC="$(CC)" \
  358. X        CFLAGS="$(CFLAGS)" \
  359. X        LDFLAGS="$(LDFLAGS)" \
  360. X        SYSLIBS="$(SYSLIBS)" all; \
  361. X    fi
  362. X
  363. X+install:
  364. X    @-if [ -n "$(ALLTARGETS)" ]; \
  365. X    then : ; \
  366. X    else \
  367. X      $(MAKE) ALLTARGETS="subsystems installtargets" \
  368. X        MAINTARGET=install \
  369. X        BASE=$(BASE) \
  370. X        SWITCHES="$(SWITCHES)" \
  371. X        INSTALLBASE=$(INSTALLBASE) \
  372. X        INSTALLBINPATH=$(INSTALLBINPATH) \
  373. X        INSTALLBINMODE=$(INSTALLBINMODE) \
  374. X        INSTALLMANPATH=$(INSTALLMANPATH) \
  375. X        INSTALLMANMODE=$(INSTALLMANMODE) \
  376. X        MAKE="$(MAKE)" \
  377. X        SHELL="$(SHELL)" \
  378. X        CC="$(CC)" \
  379. X        CFLAGS="$(CFLAGS)" \
  380. X        LDFLAGS="$(LDFLAGS)" \
  381. X        SYSLIBS="$(SYSLIBS)" install; \
  382. X    fi
  383. X
  384. X+clean:
  385. X    @-if [ -n "$(ALLTARGETS)" ]; \
  386. X    then : ; \
  387. X    else \
  388. X      $(MAKE) ALLTARGETS="subsystems doclean" MAINTARGET=clean \
  389. X        BASE=$(BASE) \
  390. X        SWITCHES="$(SWITCHES)" \
  391. X        INSTALLBASE=$(INSTALLBASE) \
  392. X        INSTALLBINPATH=$(INSTALLBINPATH) \
  393. X        INSTALLBINMODE=$(INSTALLBINMODE) \
  394. X        INSTALLMANPATH=$(INSTALLMANPATH) \
  395. X        INSTALLMANMODE=$(INSTALLMANMODE) \
  396. X        INCLUDEPATH=$(INCLUDEPATH) \
  397. X        MAKE="$(MAKE)" \
  398. X        SHELL="$(SHELL)" \
  399. X        CC="$(CC)" \
  400. X        CFLAGS="$(CFLAGS)" \
  401. X        LDFLAGS="$(LDFLAGS)" \
  402. X        SYSLIBS="$(SYSLIBS)" clean; \
  403. X    fi
  404. END_OF_FILE
  405. if test 4564 -ne `wc -c <'Makefile'`; then
  406.     echo shar: \"'Makefile'\" unpacked with wrong size!
  407. fi
  408. # end of 'Makefile'
  409. fi
  410. if test -f 'README' -a "${1}" != "-c" ; then 
  411.   echo shar: Will not clobber existing file \"'README'\"
  412. else
  413. echo shar: Extracting \"'README'\" \(6043 characters\)
  414. sed "s/^X//" >'README' <<'END_OF_FILE'
  415. Hey Emacs, this is -*- text -*-.
  416. X
  417. This is the README file for Socket-1.1.  
  418. X
  419. XFor information on how to build and install Socket, read the file
  420. INSTALL.  Please read the file COPYRIGHT about the terms under which
  421. this program is licensed to you.
  422. X
  423. X
  424. What is it?
  425. X
  426. The program Socket implements access to TCP sockets from shell level.
  427. XFirst written for the need to open a server socket and read and write
  428. to the socket interactively for testing purposes, it quickly evolved
  429. into a generic tool providing the socket interface for shell script
  430. and interactive use.
  431. X
  432. X
  433. Client mode
  434. X
  435. In client mode (which is the default) it connects to a given port at a
  436. given host.  Data read from the socket is written to stdout, data read
  437. from stdin is written to the socket.  When the peer closes the
  438. connection or a signal is received, the program terminates.  An
  439. example for this is the following command:
  440. X
  441. X    % socket coma.cs.tu-berlin.de nntp
  442. X
  443. This connects to the host coma.cs.tu-berlin.de at the nntp port
  444. X(provided these two names can be resolved through gethostbyname(3) and
  445. getservbyname(3)).  The user can now issue commands to the NNTP
  446. server, any output from the server is written to the user's terminal.
  447. X
  448. X
  449. Server mode
  450. X
  451. In server mode (indicated by the "-s" command line switch) it binds a
  452. server socket to the given port on the local host and accepts a
  453. connection.  When a client connects to this socket, all data read from
  454. the socket is written to stdout, data read from stdin is written to
  455. the socket.  For example, the command
  456. X
  457. X    % socket -s 3917
  458. X
  459. accepts a connection on port 3917.  
  460. X
  461. X
  462. Restricting data flow
  463. X
  464. It is not always desirable to have data flow in both directions, e.g.
  465. when the program is running in the background, it would be stopped if
  466. it tried to read from the terminal.  So the user can advise the program
  467. only to read from the socket ("-r") or only to write to the socket
  468. X("-w").  Especially when Socket executes a program (see below), it is
  469. important *not* to write to the program's stdin if the program doesn't
  470. read it.  This is the main reason why I added this option.
  471. X
  472. X
  473. Closing connection on EOF
  474. X
  475. XFor non-interactive use it is not always clear when to close the
  476. network connection; this is still an unsolved problem.  But often it
  477. will be enough to close the connection when some data has been written
  478. to the socket.  In this case the "quit" switch ("-q") can be used:
  479. when an end-of-file condition on stdin occurs, Socket closes the
  480. connection.
  481. X
  482. X
  483. XExecuting a program
  484. X
  485. An interesting use of a server socket is to execute a program when a
  486. client connects to it.  This done with the "-p" switch.  Stdin,
  487. stdout, and stderr of the program are read from resp. written to the
  488. socket.  Since the server is usually expected to accept another
  489. connection after a connection has been closed, the "loop" switch
  490. X("-l") makes it do exactly that.
  491. X
  492. X
  493. CRLF conversion
  494. X
  495. The Internet protocols specify a CRLF sequence (Carriage Return
  496. Linefeed) to terminate a line, whereas UNIX uses only a single LF.  If
  497. the user specifies the "crlf" switch ("-c"), all CRLF sequences that
  498. are read from the socket are converted to a single LF on output.  All
  499. single LFs on input are converted to a CRLF sequence when written to
  500. the socket.
  501. X
  502. X
  503. Background mode
  504. X
  505. It may be desirable for a server program to run in background. For
  506. that purpose the "background" switch ("-b") is provided.  If it is
  507. set, Socket runs in background, detaches itself from the controlling
  508. tty, closes the file descriptors associated with the tty, and changes
  509. it current directory to the root directory.  It is still possible to
  510. redirect the standard file descriptors to a file.
  511. X
  512. X
  513. XForking child to handle connection
  514. X
  515. Often one wants the server to be able to respond to another client
  516. immediately, even before the connection to the previous client has
  517. been closed.  For this case, Socket can fork a client to handle a
  518. connection while the father process already accepts the next
  519. connection.  To get this behaviour, specify the "-f" option.
  520. X
  521. X
  522. With all these options, a typical server call would look like
  523. X
  524. X    % socket -bcfslqp program port
  525. X
  526. Gee, I know that's a lot of options for the standard case, but I
  527. really want to make all these things *optional*.
  528. X
  529. X
  530. Verbose
  531. X
  532. At last, there is also a "verbose" option ("-v"). If this option is
  533. specified, a message is given for each opening and closing of a
  534. connection.  This is convenient especially in interactive use, but can
  535. also provide some kind of logging.  See fingerd.sh for an example.
  536. X
  537. X
  538. WARNING
  539. X
  540. Nothing prevents you from using Socket like this:
  541. X
  542. X    % socket -slqp sh 5678
  543. X
  544. THIS IS DANGEROUS! If your machine is connected to the Internet,
  545. X*anyone* on the Internet can connect to this server and issue shell
  546. commands to your shell.  These commands are executed with your user
  547. ID.  Some people may think of this program as a BAD THING, because it
  548. allows its user to open his machine for world-wide access to all kinds
  549. of malicious crackers, crashers, etc.  I don't know if I should
  550. consider this as a real security risk or not.  Anyway, it is not my
  551. program which is so dangerous -- anyone with moderate programming
  552. skill can write a something like this.
  553. X
  554. Another problem is that any server program that uses Socket may not be
  555. secure.  I tried to avoid any holes -- especially that one that made
  556. fingerd vulnerable to the attack of Morris' Internet Worm, but I don't
  557. give any warranty.  Also the program run by Socket may have security
  558. holes.
  559. X
  560. I would like to hear your opinion about this topic.  Do you consider it
  561. a security risk to have a program like Socket around?
  562. X
  563. X
  564. Sample programs
  565. X
  566. I included two sample programs, which mimic the behavior of finger(1)
  567. and fingerd(8), implemented as shell scripts using Socket.  rfinger.sh
  568. can only finger remote hosts.  fingerd.sh is RFC 1288 compliant and
  569. can be used independently of inetd(8).
  570. X
  571. X
  572. Comments
  573. X
  574. Please send any comments, suggestions, bug reports etc. to me:
  575. X
  576. X    Juergen Nickelsen
  577. X    Sekr. FR 5-6
  578. X    TU Berlin
  579. X    Franklinstr. 28-29
  580. X    1000 Berlin 10
  581. X    Germany
  582. X
  583. X    <nickel@cs.tu-berlin.de>
  584. END_OF_FILE
  585. if test 6043 -ne `wc -c <'README'`; then
  586.     echo shar: \"'README'\" unpacked with wrong size!
  587. fi
  588. # end of 'README'
  589. fi
  590. if test -f 'fingerd.sh' -a "${1}" != "-c" ; then 
  591.   echo shar: Will not clobber existing file \"'fingerd.sh'\"
  592. else
  593. echo shar: Extracting \"'fingerd.sh'\" \(371 characters\)
  594. sed "s/^X//" >'fingerd.sh' <<'END_OF_FILE'
  595. X#!/bin/sh
  596. X# $Header: fingerd.sh[1.3] Sun Aug  9 03:48:06 1992 nickel@cs.tu-berlin.de proposed $
  597. X#
  598. X# finger daemon program using socket(1) with primitive logging.
  599. X# Set LOGFILE to a file of your choice.
  600. X
  601. LOGFILE=/dev/null
  602. X
  603. socket -sqlvcp '/usr/ucb/finger `head -1 | sed "s|/[Ww]|-l|"`' \
  604. X        finger 2>&1 | 
  605. X    while read line ; do 
  606. X        echo -n $line:\ ; date ;
  607. X    done > $LOGFILE
  608. END_OF_FILE
  609. if test 371 -ne `wc -c <'fingerd.sh'`; then
  610.     echo shar: \"'fingerd.sh'\" unpacked with wrong size!
  611. fi
  612. chmod +x 'fingerd.sh'
  613. # end of 'fingerd.sh'
  614. fi
  615. if test -f 'globals.h' -a "${1}" != "-c" ; then 
  616.   echo shar: Will not clobber existing file \"'globals.h'\"
  617. else
  618. echo shar: Extracting \"'globals.h'\" \(1397 characters\)
  619. sed "s/^X//" >'globals.h' <<'END_OF_FILE'
  620. X/*
  621. X  
  622. X$Header: globals.h[1.10] Sun Aug 30 21:13:41 1992 nickel@cs.tu-berlin.de proposed $
  623. This file is part of socket(1).
  624. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  625. Please read the file COPYRIGHT for further details.
  626. X
  627. X*/
  628. X
  629. X#include "patchlevel.h"
  630. X
  631. X/* globals for socket */
  632. X
  633. X#define IN    0        /* standard input */
  634. X#define OUT    1        /* standard output */
  635. X
  636. X#define LLEN    100        /* buffer size fo perror2() */
  637. X
  638. X#ifdef __STDC__
  639. X#define A(args) args
  640. X#else
  641. X#define A(args) ()
  642. X#endif
  643. X
  644. int create_server_socket A((int port, int queue_length)) ;
  645. int create_client_socket A((char **hostname, int port)) ;
  646. int resolve_service A((char *name_or_number, char *protocol, char **name)) ;
  647. void catchsig A((int sig)) ;
  648. void usage A((void)) ;
  649. int do_read_write A((int from, int to)) ;
  650. int do_write A((char *buffer, int size, int to)) ;
  651. char *so_release A((void)) ;
  652. void open_pipes A((char *prog)) ;
  653. void wait_for_children A((void)) ;
  654. void perror2 A((char *s)) ;
  655. void add_crs A((char *from, char *to, int *sizep)) ;
  656. void strip_crs A((char *from, char *to, int *sizep)) ;
  657. void background A((void)) ;
  658. X
  659. extern int errno ;
  660. X
  661. X/* global variables */
  662. extern int serverflag ;
  663. extern int loopflag ;
  664. extern int verboseflag ;
  665. extern int readonlyflag ;
  666. extern int writeonlyflag ;
  667. extern int quitflag ;
  668. extern int crlfflag ;
  669. extern int active_socket ;
  670. extern char *progname ;
  671. extern char *sys_errlist[], *sys_siglist[] ;
  672. END_OF_FILE
  673. if test 1397 -ne `wc -c <'globals.h'`; then
  674.     echo shar: \"'globals.h'\" unpacked with wrong size!
  675. fi
  676. # end of 'globals.h'
  677. fi
  678. if test -f 'io.c' -a "${1}" != "-c" ; then 
  679.   echo shar: Will not clobber existing file \"'io.c'\"
  680. else
  681. echo shar: Extracting \"'io.c'\" \(3030 characters\)
  682. sed "s/^X//" >'io.c' <<'END_OF_FILE'
  683. X/*
  684. X
  685. X$Header: io.c[1.10] Sun Aug 30 19:21:18 1992 nickel@cs.tu-berlin.de proposed $
  686. This file is part of socket(1).
  687. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  688. Please read the file COPYRIGHT for further details.
  689. X
  690. X*/
  691. X
  692. X#define _BSD            /* AIX *loves* this */
  693. X
  694. X#include <sys/types.h>
  695. X#include <sys/time.h>
  696. X#ifdef ISC
  697. X#include <sys/bsdtypes.h>
  698. X#endif
  699. X#include <errno.h>
  700. X#include <stdio.h>
  701. X#include "globals.h"
  702. X
  703. X/* read from from, write to to. select(2) has returned, so input
  704. X * must be available. */
  705. int do_read_write(from, to)
  706. int from, to ;
  707. X{
  708. X    int size ;
  709. X    char input_buffer[BUFSIZ] ;
  710. X    
  711. X    if ((size = read(from, input_buffer, BUFSIZ)) == -1) {
  712. X    perror2("read") ;
  713. X    return -1 ;
  714. X    }
  715. X    if (size == 0) {        /* end-of-file condition */
  716. X    if (from == active_socket) {
  717. X        /* if it was the socket, the connection is closed */
  718. X        if (verboseflag) {
  719. X        fprintf(stderr, "connection closed by peer\n") ;
  720. X        }
  721. X        return -1 ;
  722. X    } else {
  723. X        if (quitflag) {
  724. X        /* we close connection later */
  725. X        if (verboseflag) {
  726. X            fprintf(stderr, "connection closed\n") ;
  727. X        }
  728. X        return -1 ;
  729. X        } else if (verboseflag) {
  730. X        fprintf(stderr, "end of input on stdin\n") ;
  731. X        }
  732. X        readonlyflag = 1 ;
  733. X        return 1 ;
  734. X    }
  735. X    }
  736. X    return do_write(input_buffer, size, to) ;
  737. X
  738. X}
  739. X
  740. X/* write the buffer; in successive pieces, if necessary. */
  741. int do_write(buffer, size, to)
  742. char *buffer ;
  743. int size, to ;
  744. X{
  745. X    char buffer2[2 * BUFSIZ] ;    /* expanding lf's to crlf's can
  746. X                 * make the block twice as big at most */
  747. X    int written ;
  748. X
  749. X    if (crlfflag) {
  750. X    if (to == active_socket) {
  751. X        add_crs(buffer, buffer2, &size) ;
  752. X    } else {
  753. X        strip_crs(buffer, buffer2, &size) ;
  754. X    }
  755. X    } else {
  756. X    bcopy(buffer, buffer2, size) ;
  757. X    }
  758. X    while (size > 0) {
  759. X    written = write(to, buffer2, size) ;
  760. X    if (written == -1) {
  761. X        /* this should not happen */
  762. X        perror2("write") ;
  763. X        fprintf(stderr, "%s: error writing to %s\n",
  764. X            progname,
  765. X            to == active_socket ? "socket" : "stdout") ;
  766. X        return -1 ;
  767. X    }
  768. X    size -= written ;
  769. X    }
  770. X    return 1 ;
  771. X}
  772. X
  773. X/* all IO to and from the socket is handled here. The main part is
  774. X * a loop around select(2). */
  775. do_io()
  776. X{
  777. X    fd_set readfds ;
  778. X    int fdset_width ;
  779. X    int selret ;
  780. X
  781. X    fdset_width = (IN > active_socket ? IN : active_socket) + 1 ;
  782. X    while (1) {            /* this loop is exited sideways */
  783. X    /* set up file descriptor set for select(2) */
  784. X    FD_ZERO(&readfds) ;
  785. X    if (!readonlyflag) {
  786. X        FD_SET(IN, &readfds) ;
  787. X    }
  788. X    if (!writeonlyflag) {
  789. X        FD_SET(active_socket, &readfds) ;
  790. X    }
  791. X
  792. X    do {
  793. X        /* wait until input is available */
  794. X        selret = select(fdset_width, &readfds, NULL, NULL, NULL) ;
  795. X        /* EINTR happens when the process is stopped */
  796. X        if (selret < 0 && errno != EINTR) {
  797. X        perror2("select") ;
  798. X        exit(1) ;
  799. X        }
  800. X    } while (selret <= 0) ;
  801. X
  802. X    /* do the appropriate read and write */
  803. X    if (FD_ISSET(active_socket, &readfds)) {
  804. X        if (do_read_write(active_socket, OUT) < 0) {
  805. X        break ;
  806. X        }
  807. X    } else {
  808. X        if (do_read_write(IN, active_socket) < 0) {
  809. X        break ;
  810. X        }
  811. X    }
  812. X    }
  813. X}
  814. END_OF_FILE
  815. if test 3030 -ne `wc -c <'io.c'`; then
  816.     echo shar: \"'io.c'\" unpacked with wrong size!
  817. fi
  818. # end of 'io.c'
  819. fi
  820. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  821.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  822. else
  823. echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
  824. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  825. X#define PATCHLEVEL 0
  826. END_OF_FILE
  827. if test 21 -ne `wc -c <'patchlevel.h'`; then
  828.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  829. fi
  830. # end of 'patchlevel.h'
  831. fi
  832. if test -f 'rfinger.sh' -a "${1}" != "-c" ; then 
  833.   echo shar: Will not clobber existing file \"'rfinger.sh'\"
  834. else
  835. echo shar: Extracting \"'rfinger.sh'\" \(623 characters\)
  836. sed "s/^X//" >'rfinger.sh' <<'END_OF_FILE'
  837. X#!/bin/sh
  838. X# $Header: rfinger.sh[1.2] Sun Aug 30 18:04:21 1992 nickel@cs.tu-berlin.de proposed $
  839. X#
  840. X# remote finger program using socket(1). Works similar to finger(1),
  841. X# but can do only remote fingers.
  842. X
  843. X# If you have my nslook program, you can determine the official name
  844. X# of the host.
  845. X#NSLOOK="nslook -o"
  846. NSLOOK=echo
  847. X
  848. if [ "$1" = -l ] ; then
  849. X    long=/W ; shift
  850. fi
  851. X
  852. host=`echo $1 | sed -n 's/^.*@\([^@]*\)$/\1/p'`
  853. X
  854. if [ $# != 1 -o ! "$host" ] ; then
  855. X    echo Usage: `basename $0` '[-l] [user]@host'
  856. X    exit 1
  857. fi
  858. X
  859. ohost=`$NSLOOK $host`
  860. echo \[$ohost\]
  861. echo `echo $1 | sed -n 's/^\(.*\)@[^@]*$/\1/p'` $long | socket -c $host finger
  862. END_OF_FILE
  863. if test 623 -ne `wc -c <'rfinger.sh'`; then
  864.     echo shar: \"'rfinger.sh'\" unpacked with wrong size!
  865. fi
  866. chmod +x 'rfinger.sh'
  867. # end of 'rfinger.sh'
  868. fi
  869. if test -f 'siglist.c' -a "${1}" != "-c" ; then 
  870.   echo shar: Will not clobber existing file \"'siglist.c'\"
  871. else
  872. echo shar: Extracting \"'siglist.c'\" \(4647 characters\)
  873. sed "s/^X//" >'siglist.c' <<'END_OF_FILE'
  874. X/* siglist.c -- signal list for those machines that don't have one. */
  875. X
  876. X/* Copyright (C) 1989 Free Software Foundation, Inc.
  877. X
  878. This file is part of GNU Bash, the Bourne Again SHell.
  879. X
  880. Modified by Juergen Nickelsen <nickel@cs.tu-berlin.de> for use with
  881. Socket-1.1.
  882. X
  883. Bash is free software; you can redistribute it and/or modify it under
  884. the terms of the GNU General Public License as published by the Free
  885. Software Foundation; either version 1, or (at your option) any later
  886. version.
  887. X
  888. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  889. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  890. XFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  891. for more details.
  892. X
  893. You should have received a copy of the GNU General Public License along
  894. with Bash; see the file COPYING.  If not, write to the Free Software
  895. XFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  896. X
  897. X#include <stdio.h>
  898. X#include <signal.h>
  899. X
  900. X#if !defined (NSIG)
  901. X#  if defined (_NSIG)
  902. X#    define NSIG _NSIG
  903. X#  else
  904. X#    define NSIG 64
  905. X#  endif /* !_NSIG */
  906. X#endif /* !NSIG */
  907. X
  908. char *sys_siglist[NSIG];
  909. X
  910. extern *malloc ();
  911. X
  912. initialize_siglist ()
  913. X{
  914. X  register int i;
  915. X
  916. X  for (i = 0; i < NSIG; i++)
  917. X    sys_siglist[i] = (char *)0x0;
  918. X
  919. X  sys_siglist[0] = "Bogus signal";
  920. X
  921. X#if defined (SIGHUP)
  922. X  sys_siglist[SIGHUP] = "Hangup signal";
  923. X#endif
  924. X
  925. X#if defined (SIGINT)
  926. X  sys_siglist[SIGINT] = "Interrupt";
  927. X#endif
  928. X
  929. X#if defined (SIGQUIT)
  930. X  sys_siglist[SIGQUIT] = "Quit signal";
  931. X#endif
  932. X
  933. X#if defined (SIGILL)
  934. X  sys_siglist[SIGILL] = "Illegal instruction";
  935. X#endif
  936. X
  937. X#if defined (SIGTRAP)
  938. X  sys_siglist[SIGTRAP] = "BPT trace/trap";
  939. X#endif
  940. X
  941. X#if defined (SIGIOT) && !defined (SIGABRT)
  942. X#define SIGABRT SIGIOT
  943. X#endif
  944. X
  945. X#if defined (SIGABRT)
  946. X  sys_siglist[SIGABRT] = "ABORT instruction";
  947. X#endif
  948. X
  949. X#if defined (SIGEMT)
  950. X  sys_siglist[SIGEMT] = "EMT instruction";
  951. X#endif
  952. X
  953. X#if defined (SIGFPE)
  954. X  sys_siglist[SIGFPE] = "Floating point exception";
  955. X#endif
  956. X
  957. X#if defined (SIGKILL)
  958. X  sys_siglist[SIGKILL] = "Kill signal";
  959. X#endif
  960. X
  961. X#if defined (SIGBUS)
  962. X  sys_siglist[SIGBUS] = "Bus error";
  963. X#endif
  964. X
  965. X#if defined (SIGSEGV)
  966. X  sys_siglist[SIGSEGV] = "Segmentation fault";
  967. X#endif
  968. X
  969. X#if defined (SIGSYS)
  970. X  sys_siglist[SIGSYS] = "Bad system call";
  971. X#endif
  972. X
  973. X#if defined (SIGPIPE)
  974. X  sys_siglist[SIGPIPE] = "Broken pipe condition";
  975. X#endif
  976. X
  977. X#if defined (SIGALRM)
  978. X  sys_siglist[SIGALRM] = "Alarm clock signal";
  979. X#endif
  980. X
  981. X#if defined (SIGTERM)
  982. X  sys_siglist[SIGTERM] = "Termination signal";
  983. X#endif
  984. X
  985. X#if defined (SIGURG)
  986. X  sys_siglist[SIGURG] = "Urgent IO condition";
  987. X#endif
  988. X
  989. X#if defined (SIGSTOP)
  990. X  sys_siglist[SIGSTOP] = "Stop signal";
  991. X#endif
  992. X
  993. X#if defined (SIGTSTP)
  994. X  sys_siglist[SIGTSTP] = "Stopped";
  995. X#endif
  996. X
  997. X#if defined (SIGCONT)
  998. X  sys_siglist[SIGCONT] = "Continue signal";
  999. X#endif
  1000. X
  1001. X#if !defined (SIGCHLD) && defined (SIGCLD)
  1002. X#define SIGCHLD SIGCLD
  1003. X#endif
  1004. X
  1005. X#if defined (SIGCHLD)
  1006. X  sys_siglist[SIGCHLD] = "Child signal";
  1007. X#endif
  1008. X
  1009. X#if defined (SIGTTIN)
  1010. X  sys_siglist[SIGTTIN] = "Stop (tty input) signal";
  1011. X#endif
  1012. X
  1013. X#if defined (SIGTTOU)
  1014. X  sys_siglist[SIGTTOU] = "Stop (tty output) signal";
  1015. X#endif
  1016. X
  1017. X#if defined (SIGIO)
  1018. X  sys_siglist[SIGIO] = "I/O ready signal";
  1019. X#endif
  1020. X
  1021. X#if defined (SIGXCPU)
  1022. X  sys_siglist[SIGXCPU] = "CPU limit exceeded";
  1023. X#endif
  1024. X
  1025. X#if defined (SIGXFSZ)
  1026. X  sys_siglist[SIGXFSZ] = "File limit exceeded";
  1027. X#endif
  1028. X
  1029. X#if defined (SIGVTALRM)
  1030. X  sys_siglist[SIGVTALRM] = "Alarm (virtual)";
  1031. X#endif
  1032. X
  1033. X#if defined (SIGPROF)
  1034. X  sys_siglist[SIGPROF] = "Alarm (profile)";
  1035. X#endif
  1036. X
  1037. X#if defined (SIGWINCH)
  1038. X  sys_siglist[SIGWINCH] = "Window change";
  1039. X#endif
  1040. X
  1041. X#if defined (SIGLOST)
  1042. X  sys_siglist[SIGLOST] = "Record lock signal";
  1043. X#endif
  1044. X
  1045. X#if defined (SIGUSR1)
  1046. X  sys_siglist[SIGUSR1] = "User signal 1";
  1047. X#endif
  1048. X
  1049. X#if defined (SIGUSR2)
  1050. X  sys_siglist[SIGUSR2] = "User signal 2";
  1051. X#endif
  1052. X
  1053. X#if defined (SIGMSG)
  1054. X  sys_siglist[SIGMSG] = "HFT input data pending signal";
  1055. X#endif 
  1056. X
  1057. X#if defined (SIGPWR)
  1058. X  sys_siglist[SIGPWR] = "power failure imminent signal";
  1059. X#endif 
  1060. X
  1061. X#if defined (SIGDANGER)
  1062. X  sys_siglist[SIGDANGER] = "system crash imminent signal";
  1063. X#endif 
  1064. X
  1065. X#if defined (SIGMIGRATE)
  1066. X  sys_siglist[SIGMIGRATE] = "Process migration";
  1067. X#endif 
  1068. X
  1069. X#if defined (SIGPRE)
  1070. X  sys_siglist[SIGPRE] = "Programming error signal";
  1071. X#endif 
  1072. X
  1073. X#if defined (SIGGRANT)
  1074. X  sys_siglist[SIGGRANT] = "HFT monitor mode granted signal";
  1075. X#endif 
  1076. X
  1077. X#if defined (SIGRETRACT)
  1078. X  sys_siglist[SIGRETRACT] = "HFT monitor mode retracted signal";
  1079. X#endif 
  1080. X
  1081. X#if defined (SIGSOUND)
  1082. X  sys_siglist[SIGSOUND] = "HFT sound sequence has completed signal";
  1083. X#endif 
  1084. X
  1085. X  for (i = 0; i < NSIG; i++)
  1086. X    {
  1087. X      if (!sys_siglist[i])
  1088. X    {
  1089. X      sys_siglist[i] =
  1090. X        (char *) malloc (10 + strlen ("Unknown Signal #"));
  1091. X
  1092. X      sprintf (sys_siglist[i], "Unknown Signal #%d", i);
  1093. X    }
  1094. X    }
  1095. X}
  1096. END_OF_FILE
  1097. if test 4647 -ne `wc -c <'siglist.c'`; then
  1098.     echo shar: \"'siglist.c'\" unpacked with wrong size!
  1099. fi
  1100. # end of 'siglist.c'
  1101. fi
  1102. if test -f 'so_release.c' -a "${1}" != "-c" ; then 
  1103.   echo shar: Will not clobber existing file \"'so_release.c'\"
  1104. else
  1105. echo shar: Extracting \"'so_release.c'\" \(135 characters\)
  1106. sed "s/^X//" >'so_release.c' <<'END_OF_FILE'
  1107. char *so_release () {
  1108. X  static char release[] = "Socket-1.1 (Wed Sep  9 19:11:19 1992 by nickel@cs.tu-berlin.de)";
  1109. X  return release;
  1110. X}
  1111. END_OF_FILE
  1112. if test 135 -ne `wc -c <'so_release.c'`; then
  1113.     echo shar: \"'so_release.c'\" unpacked with wrong size!
  1114. fi
  1115. # end of 'so_release.c'
  1116. fi
  1117. if test -f 'socket.1' -a "${1}" != "-c" ; then 
  1118.   echo shar: Will not clobber existing file \"'socket.1'\"
  1119. else
  1120. echo shar: Extracting \"'socket.1'\" \(4029 characters\)
  1121. sed "s/^X//" >'socket.1' <<'END_OF_FILE'
  1122. X.\" -*- nroff -*-
  1123. X.ig
  1124. X$Header: socket.1[1.13] Wed Sep  9 16:46:30 1992 nickel@cs.tu-berlin.de proposed $
  1125. This file is part of socket(1).
  1126. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  1127. Please read the file COPYRIGHT for further details.
  1128. X..
  1129. X.TH SOCKET 1 "Aug  6, 1992"
  1130. X.SH NAME
  1131. socket \- create tcp socket and connect to stdin/out
  1132. X.SH SYNOPSIS
  1133. X.B socket
  1134. X[
  1135. X.B \-bcfqrvw
  1136. X]
  1137. X[
  1138. X.B \-p
  1139. X.I command
  1140. X]
  1141. X.I host port
  1142. X.br
  1143. X.B socket
  1144. X[
  1145. X.B \-bcfqrvw
  1146. X]
  1147. X[
  1148. X.B \-p
  1149. X.I command
  1150. X]
  1151. X.B \-s 
  1152. X[
  1153. X.B \-l
  1154. X]
  1155. X.I port
  1156. X.SH DESCRIPTION
  1157. X.B Socket
  1158. creates an Internet domain TCP socket and connects it to stdin and stdout.
  1159. The 
  1160. X.I host
  1161. argument can be an Internet number in dot-notation (like
  1162. X``130.149.28.10'') or a domain name. In this case it must be possible
  1163. to resolve the name to a valid Internet address with
  1164. X.IR gethostbyname (3).
  1165. The 
  1166. X.I port
  1167. argument can be a port number or a service name which can be mapped to
  1168. a port number by
  1169. X.IR getservbyname (3).
  1170. X.SH OPTIONS
  1171. X.TP
  1172. X.BR "\-b " (background)
  1173. The program forks itself into the background, detaches from its
  1174. controlling tty, closes the file descriptors associated with the tty,
  1175. and changes its current directory to the root directory.
  1176. X.TP
  1177. X.BR "\-c " (crlf)
  1178. Linefeed characters (LF) are converted to a Carriage Return Linefeed
  1179. sequence (CRLF) when written to the socket.
  1180. CRLF sequences read from the socket are converted to a single LF.
  1181. X.TP
  1182. X.BR "\-f " (fork)
  1183. When a server connection has been accepted, a separate process is
  1184. forked to handle the connection in background.
  1185. X.TP
  1186. X.BR "\-l " (loop)
  1187. X(only valid with
  1188. X.BR \-s )
  1189. After a connection has been closed,
  1190. another connection is accepted.
  1191. X.TP
  1192. X.BR "\-p " (program)
  1193. The specified 
  1194. X.I command
  1195. is executed for each connection. Its standard input, standard output,
  1196. and standard error channels are connected to the socket.
  1197. X.I Command
  1198. can be any shell command since it is passed to \fC/bin/sh\fP.
  1199. X.TP
  1200. X.BR "\-q " (quit)
  1201. The connection is closed when an end-of-file condition occurs on standard
  1202. input.
  1203. X.TP
  1204. X.BR "\-r " "(read only)"
  1205. No data is read from standard input and written to the socket.
  1206. X.TP
  1207. X.BR "\-s " (server)
  1208. A server socket is created.
  1209. A
  1210. X.I hostname 
  1211. argument is not required.
  1212. X.TP
  1213. X.BR "\-v " (verbose)
  1214. Messages about connections etc. are issued to stderr.
  1215. X.TP
  1216. X.BR "\-w " "(write only)"
  1217. No data is read from the socket and written to the standard output.
  1218. X.TP
  1219. X.B \-version
  1220. X.B Socket
  1221. prints its version ID and terminates. 
  1222. This must be the first argument to have an effect.
  1223. X.SH EXAMPLES
  1224. The command
  1225. X.IP
  1226. X\fCsocket -v coma.cs.tu-berlin.de nntp\fP
  1227. X.LP
  1228. connects to the nntp port (port 119) of coma.cs.tu-berlin.de
  1229. X(130.149.28.10).
  1230. X.br
  1231. The command
  1232. X.IP
  1233. X\fCsocket \-sl 3425\fP
  1234. X.LP
  1235. creates a server socket on port 3425 on the local host and waits for a
  1236. connection.
  1237. After a connection has been closed, a new connection is accepted. 
  1238. X.br
  1239. The command
  1240. X.IP
  1241. X\fCsocket \-wslqvp "echo Socket! " 1938\fP
  1242. X.LP
  1243. creates a server socket on port 1938 on the local host and waits for a
  1244. connection.
  1245. When a connection is accepted, the string "Socket!" is written to the
  1246. socket.
  1247. No data is read from the socket and written to the \fCfinger\fP
  1248. program.
  1249. The connection is closed when an end-of-file condition at the standard
  1250. output of the program  occurs.
  1251. Then a new connection is accepted.
  1252. X.SH DIAGNOSTICS
  1253. Lots of diagnostics for failed system calls.
  1254. X.TP
  1255. X.BI "unknown host " host
  1256. X.IR host 's
  1257. address could not be resolved.
  1258. X.TP
  1259. X.B Signal \fIsignal\fP caught, exiting
  1260. X.B Socket
  1261. exits on any signal other than SIGTSTP, SIGCONT, SIGCLD, SIGQUIT.
  1262. X.LP
  1263. A non-zero exit code is returned if 
  1264. X.B socket
  1265. terminates due to an error condition or a signal.
  1266. X.SH SEE ALSO
  1267. X.BR accept (2),
  1268. X.BR bind (2),
  1269. X.BR connect (2), 
  1270. X.BR socket (2),
  1271. X.BR gethostbyname (3),
  1272. X.BR getservbyname (3)
  1273. X.SH BUGS
  1274. X\fCsocket \-p\fP terminates due to a SIGPIPE signal when there is more
  1275. data from the socket available than the executed program wants to
  1276. read.
  1277. X.LP
  1278. Please report any other bugs to the author.
  1279. X.SH VERSION
  1280. This manual page describes Socket\-1.1.
  1281. X.SH AUTHOR
  1282. Juergen Nickelsen <nickel@cs.tu-berlin.de>
  1283. END_OF_FILE
  1284. if test 4029 -ne `wc -c <'socket.1'`; then
  1285.     echo shar: \"'socket.1'\" unpacked with wrong size!
  1286. fi
  1287. # end of 'socket.1'
  1288. fi
  1289. if test -f 'socket.c' -a "${1}" != "-c" ; then 
  1290.   echo shar: Will not clobber existing file \"'socket.c'\"
  1291. else
  1292. echo shar: Extracting \"'socket.c'\" \(6160 characters\)
  1293. sed "s/^X//" >'socket.c' <<'END_OF_FILE'
  1294. X/*
  1295. X
  1296. X$Header: socket.c[1.17] Wed Sep  9 16:23:14 1992 nickel@cs.tu-berlin.de proposed $
  1297. This file is part of socket(1).
  1298. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  1299. Please read the file COPYRIGHT for further details.
  1300. X
  1301. X*/
  1302. X
  1303. X#include <sys/types.h>
  1304. X#include <sys/socket.h>
  1305. X#include <netinet/in.h>
  1306. X#include <netdb.h>
  1307. X#include <errno.h>
  1308. X#include <stdio.h>
  1309. X#ifdef SEQUENT
  1310. X#include <strings.h>
  1311. X#else
  1312. X#include <string.h>
  1313. X#endif
  1314. X#include "globals.h"
  1315. X
  1316. X/* global variables */
  1317. int forkflag = 0 ;        /* server forks on connection */
  1318. int serverflag = 0 ;        /* create server socket */
  1319. int loopflag = 0 ;        /* loop server */
  1320. int verboseflag = 0 ;        /* give messages */
  1321. int readonlyflag = 0 ;        /* only read from socket */
  1322. int writeonlyflag = 0 ;        /* only write to socket */
  1323. int quitflag = 0 ;        /* quit connection on EOF */
  1324. int crlfflag = 0 ;        /* socket expects and delivers CRLF */
  1325. int backgflag = 0 ;        /* put yourself in background */
  1326. int active_socket ;        /* socket with connection */
  1327. char *progname ;        /* name of the game */
  1328. char *pipe_program = NULL ;    /* program to execute in two-way pipe */
  1329. X
  1330. void server A((int port, char *service_name)) ;
  1331. void handle_server_connection A((void)) ;
  1332. void client A((char *host, int port, char *service_name)) ;
  1333. X
  1334. int main(argc, argv)
  1335. int argc ;
  1336. char **argv ;
  1337. X{
  1338. X    char *cp ;            /* to point to '/' in argv[0] */
  1339. X    int opt ;            /* option character */
  1340. X    int error = 0 ;        /* usage error occurred */
  1341. X    extern int optind ;        /* from getopt() */
  1342. X    char *host ;        /* name of remote host */
  1343. X    int port ;            /* port number for socket */
  1344. X    char *service_name ;    /* name of service for port */
  1345. X
  1346. X    /* print version ID if requested */
  1347. X    if (argv[1] && !strcmp(argv[1], "-version")) {
  1348. X    puts(so_release()) ;
  1349. X    exit(0) ;
  1350. X    }
  1351. X
  1352. X    /* set up progname for later use */
  1353. X    progname = argv[0] ;
  1354. X    if (cp = strrchr(progname, '/')) progname = cp + 1 ;
  1355. X
  1356. X    /* parse options */
  1357. X    while ((opt = getopt(argc, argv, "bcflp:qrsvw?")) != -1) {
  1358. X    switch (opt) {
  1359. X      case 'f':
  1360. X        forkflag = 1 ;
  1361. X        break ;
  1362. X      case 'c':
  1363. X        crlfflag = 1 ;
  1364. X        break ;
  1365. X      case 'w':
  1366. X        writeonlyflag = 1 ;
  1367. X        break ;
  1368. X      case 'p':
  1369. X        pipe_program = argv[optind - 1] ;
  1370. X        break ;
  1371. X      case 'q':
  1372. X        quitflag = 1 ;
  1373. X        break ;
  1374. X      case 'r':
  1375. X        readonlyflag = 1 ;
  1376. X        break ;
  1377. X      case 's':
  1378. X        serverflag = 1 ;
  1379. X        break ;
  1380. X      case 'v':
  1381. X        verboseflag = 1 ;
  1382. X        break ;
  1383. X      case 'l':
  1384. X        loopflag = 1 ;
  1385. X        break ;
  1386. X      case 'b':
  1387. X        backgflag = 1 ;
  1388. X        break ;
  1389. X      default:
  1390. X        error++ ;
  1391. X    }
  1392. X    }
  1393. X    if (error ||        /* usage error? */
  1394. X    argc - optind + serverflag != 2) { /* number of args ok? */
  1395. X    usage() ;
  1396. X    exit(15) ;
  1397. X    }
  1398. X
  1399. X    /* check some option combinations */
  1400. X#define senseless(s1, s2) \
  1401. X    fprintf(stderr, "It does not make sense to set %s and %s.\n", (s1), (s2))
  1402. X
  1403. X    if (writeonlyflag && readonlyflag) {
  1404. X    senseless("-r", "-w") ;
  1405. X    exit(15) ;
  1406. X    }
  1407. X    if (loopflag && !serverflag) {
  1408. X    senseless("-l", "not -s") ;
  1409. X    exit(15) ;
  1410. X    }
  1411. X    if (backgflag && !serverflag) {
  1412. X     senseless("-b", "not -s") ;
  1413. X     exit(15) ;
  1414. X    }
  1415. X    if (forkflag && !serverflag) {
  1416. X    senseless("-f", "not -s") ;
  1417. X    }
  1418. X    /* set up signal handling */
  1419. X    init_signals() ;
  1420. X
  1421. X    /* get port number */
  1422. X    port = resolve_service(argv[optind + 1 - serverflag],
  1423. X               "tcp", &service_name) ;
  1424. X    if (port < 0) {
  1425. X    fprintf(stderr, "%s: unknown service\n", progname) ;
  1426. X    exit(5) ;
  1427. X    }
  1428. X
  1429. X    /* and go */
  1430. X    if (serverflag) {
  1431. X    if (backgflag) {
  1432. X        background() ;
  1433. X    }
  1434. X    server(port, service_name) ;
  1435. X    } else {
  1436. X    client(argv[optind], port, service_name) ;
  1437. X    }           
  1438. X    exit(0) ;
  1439. X}
  1440. X
  1441. X
  1442. void server(port, service_name)
  1443. int port ;
  1444. char *service_name ;
  1445. X{
  1446. X    int socket_handle, alen ;
  1447. X
  1448. X    /* allocate server socket */
  1449. X    socket_handle = create_server_socket(port, 1) ;
  1450. X    if (socket_handle < 0) {
  1451. X    perror2("server socket") ;
  1452. X    exit(1) ;
  1453. X    }
  1454. X    if (verboseflag) {
  1455. X    fprintf(stderr, "listening on port %d", port) ;
  1456. X    if (service_name) {
  1457. X        fprintf(stderr, " (%s)", service_name) ;
  1458. X    }
  1459. X    fprintf(stderr, "\n") ;
  1460. X    }
  1461. X
  1462. X    /* server loop */
  1463. X    do {
  1464. X    struct sockaddr_in sa ;
  1465. X        
  1466. X    alen = sizeof(sa) ;
  1467. X
  1468. X    /* accept a connection */
  1469. X    if ((active_socket = accept(socket_handle,
  1470. X              (struct sockaddr *) &sa,
  1471. X              &alen)) == -1) {
  1472. X        perror2("accept") ;
  1473. X    } else {
  1474. X        /* if verbose, get name of peer and give message */
  1475. X        if (verboseflag) {
  1476. X        struct hostent *he ;
  1477. X        long norder ;
  1478. X        char dotted[20] ;
  1479. X
  1480. X        he = gethostbyaddr(&sa.sin_addr.s_addr,
  1481. X                   sizeof(sa.sin_addr.s_addr), AF_INET) ;
  1482. X        if (!he) {
  1483. X            norder = htonl(sa.sin_addr.s_addr) ;
  1484. X            sprintf(dotted, "%d.%d.%d.%d",
  1485. X                (norder >> 24) & 0xff,
  1486. X                (norder >> 16) & 0xff,
  1487. X                (norder >>  8) & 0xff,
  1488. X                norder & 0xff) ;
  1489. X        }
  1490. X        fprintf(stderr, "connection from %s\n",
  1491. X            (he ? he->h_name : dotted)) ;
  1492. X        }
  1493. X        if (forkflag) {
  1494. X        switch (fork()) {
  1495. X          case 0:
  1496. X            handle_server_connection() ;
  1497. X            exit(0) ;
  1498. X          case -1:
  1499. X            perror2("fork") ;
  1500. X            break ;
  1501. X          default:
  1502. X            close(active_socket) ;
  1503. X            wait_for_children() ;
  1504. X        }
  1505. X        } else {
  1506. X        handle_server_connection() ;
  1507. X        }
  1508. X    }
  1509. X    } while (loopflag) ;
  1510. X}
  1511. X
  1512. X
  1513. void handle_server_connection()
  1514. X{
  1515. X    /* open pipes to program, if requested */
  1516. X    if (pipe_program != NULL) {
  1517. X    open_pipes(pipe_program) ;
  1518. X    }
  1519. X    /* enter IO loop */
  1520. X    do_io() ;
  1521. X    /* connection is closed now */
  1522. X    close(active_socket) ;
  1523. X    if (pipe_program) {
  1524. X    /* remove zombies */
  1525. X    wait_for_children() ;
  1526. X    }
  1527. X}
  1528. X
  1529. X
  1530. void client(host, port, service_name)
  1531. char *host ;
  1532. int port ;
  1533. char *service_name ;
  1534. X{
  1535. X    /* get connection */
  1536. X    active_socket = create_client_socket(&host, port) ;
  1537. X    if (active_socket == -1) {
  1538. X    perror2("client socket") ;
  1539. X    exit(errno) ;
  1540. X    } else if (active_socket == -2) {
  1541. X    fprintf(stderr, "%s: unknown host %s\n", progname, host) ;
  1542. X    exit(13) ;
  1543. X    }
  1544. X    if (verboseflag) {
  1545. X    fprintf(stderr, "connected to %s port %d", host, port) ;
  1546. X    if (service_name) {
  1547. X        fprintf(stderr, " (%s)", service_name) ;
  1548. X    }
  1549. X    fprintf(stderr, "\n") ;
  1550. X    }
  1551. X
  1552. X    /* open pipes to program if requested */
  1553. X    if (pipe_program != NULL) {
  1554. X    open_pipes(pipe_program) ;
  1555. X    }
  1556. X    /* enter IO loop */
  1557. X    do_io() ;
  1558. X    /* connection is closed now */
  1559. X    close(active_socket) ;
  1560. X}
  1561. X
  1562. X/*EOF*/
  1563. END_OF_FILE
  1564. if test 6160 -ne `wc -c <'socket.c'`; then
  1565.     echo shar: \"'socket.c'\" unpacked with wrong size!
  1566. fi
  1567. # end of 'socket.c'
  1568. fi
  1569. if test -f 'socketp.c' -a "${1}" != "-c" ; then 
  1570.   echo shar: Will not clobber existing file \"'socketp.c'\"
  1571. else
  1572. echo shar: Extracting \"'socketp.c'\" \(2633 characters\)
  1573. sed "s/^X//" >'socketp.c' <<'END_OF_FILE'
  1574. X/*
  1575. X
  1576. X$Header: socketp.c[1.4] Sun Aug  9 03:48:03 1992 nickel@cs.tu-berlin.de proposed $
  1577. This file is part of socket(1).
  1578. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  1579. Please read the file COPYRIGHT for further details.
  1580. X
  1581. X*/
  1582. X
  1583. X#include <sys/types.h>
  1584. X#include <sys/socket.h>
  1585. X#include <sys/errno.h>
  1586. X#include <netinet/in.h>
  1587. X#include <netdb.h>
  1588. X#include <stdio.h>
  1589. X#include "globals.h"
  1590. X
  1591. X/*
  1592. X * create a server socket on PORT accepting QUEUE_LENGTH connections
  1593. X */
  1594. int create_server_socket(port, queue_length)
  1595. int port ;
  1596. int queue_length ;
  1597. X{
  1598. X    struct sockaddr_in sa ;
  1599. X    int s;
  1600. X
  1601. X    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1602. X    return -1 ;
  1603. X    }
  1604. X
  1605. X    bzero((char *) &sa, sizeof(sa)) ;
  1606. X    sa.sin_family = AF_INET ;
  1607. X    sa.sin_addr.s_addr = htonl(INADDR_ANY) ;
  1608. X    sa.sin_port = htons(port) ;
  1609. X
  1610. X    if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
  1611. X    return -1 ;
  1612. X    }
  1613. X    if (listen(s, 1) < 0) {
  1614. X    return -1 ;
  1615. X    }
  1616. X
  1617. X    return s ;
  1618. X}
  1619. X
  1620. X
  1621. X/* create a client socket connected to PORT on HOSTNAME */
  1622. int create_client_socket(hostname, port)
  1623. char **hostname ;
  1624. int port ;
  1625. X{
  1626. X    struct sockaddr_in sa ;
  1627. X    struct hostent *hp ;
  1628. X    int a, s ;
  1629. X    long addr ;
  1630. X
  1631. X
  1632. X    bzero(&sa, sizeof(sa)) ;
  1633. X    if ((addr = inet_addr(*hostname)) != -1) {
  1634. X    /* is Internet addr in octet notation */
  1635. X    bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */
  1636. X    sa.sin_family = AF_INET ;
  1637. X    } else {
  1638. X    /* do we know the host's address? */
  1639. X    if ((hp = gethostbyname(*hostname)) == NULL) {
  1640. X        return -2 ;
  1641. X    }
  1642. X    *hostname = hp->h_name ;
  1643. X    bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ;
  1644. X    sa.sin_family = hp->h_addrtype ;
  1645. X    }
  1646. X
  1647. X    sa.sin_port = htons((u_short) port) ;
  1648. X
  1649. X    if ((s = socket(sa.sin_family, SOCK_STREAM, 0)) < 0) { /* get socket */
  1650. X    return -1 ;
  1651. X    }
  1652. X    if (connect(s, &sa, sizeof(sa)) < 0) {                  /* connect */
  1653. X    close(s) ;
  1654. X    return -1 ;
  1655. X    }
  1656. X    return s ;
  1657. X}
  1658. X
  1659. X/* return the port number for service NAME_OR_NUMBER. If NAME is non-null,
  1660. X * the name is the service is written there.
  1661. X */
  1662. int resolve_service(name_or_number, protocol, name)
  1663. char *name_or_number ;
  1664. char *protocol ;
  1665. char **name ;
  1666. X{
  1667. X    struct servent *servent ;
  1668. X    int port ;
  1669. X
  1670. X    if (is_number(name_or_number)) {
  1671. X    port = atoi(name_or_number) ;
  1672. X    if (name != NULL) {
  1673. X        servent = getservbyport(htons(port), "tcp") ;
  1674. X        if (servent != NULL) {
  1675. X        *name = servent->s_name ;
  1676. X        } else {
  1677. X        *name = NULL ;
  1678. X        }
  1679. X    }
  1680. X    return port ;
  1681. X    } else {
  1682. X    servent = getservbyname(name_or_number, "tcp") ;
  1683. X    if (servent == NULL) {
  1684. X        return -1 ;
  1685. X    }
  1686. X    if (name != NULL) {
  1687. X        *name = servent->s_name ;
  1688. X    }
  1689. X    return ntohs(servent->s_port) ;
  1690. X    }
  1691. X}
  1692. X
  1693. X/*EOF*/
  1694. END_OF_FILE
  1695. if test 2633 -ne `wc -c <'socketp.c'`; then
  1696.     echo shar: \"'socketp.c'\" unpacked with wrong size!
  1697. fi
  1698. # end of 'socketp.c'
  1699. fi
  1700. if test -f 'utils.c' -a "${1}" != "-c" ; then 
  1701.   echo shar: Will not clobber existing file \"'utils.c'\"
  1702. else
  1703. echo shar: Extracting \"'utils.c'\" \(4989 characters\)
  1704. sed "s/^X//" >'utils.c' <<'END_OF_FILE'
  1705. X/*
  1706. X
  1707. X$Header: utils.c[1.14] Wed Sep  9 16:34:03 1992 nickel@cs.tu-berlin.de proposed $
  1708. This file is part of socket(1).
  1709. Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
  1710. Please read the file COPYRIGHT for further details.
  1711. X
  1712. X*/
  1713. X
  1714. X#ifdef sgi
  1715. X#define _BSD_SIGNALS
  1716. X#define SIG_HANDLER_RET int
  1717. X#else /* !sgi */
  1718. X#define SIG_HANDLER_RET void
  1719. X#endif
  1720. X
  1721. X#include <stdio.h>
  1722. X#include <signal.h>
  1723. X#include <sys/wait.h>
  1724. X#include <sys/time.h>
  1725. X#include <fcntl.h>
  1726. X#include <sys/ioctl.h>
  1727. X#ifdef ISC
  1728. X#define WNOHANG 1
  1729. X#else
  1730. X#include <sys/resource.h>
  1731. X#endif
  1732. X#include "globals.h"
  1733. X
  1734. X
  1735. X/* Signal handler, print message and exit */
  1736. SIG_HANDLER_RET exitsig(sig)
  1737. int sig ;
  1738. X{
  1739. X    if (sig != SIGUSR1) {
  1740. X    fprintf(stderr, "\n%s occured, exiting\n", sys_siglist[sig]) ;
  1741. X    }
  1742. X    exit(-sig) ;
  1743. X}
  1744. X
  1745. X/* Give usage message */
  1746. void usage()
  1747. X{
  1748. X    static char ustring[] =
  1749. X    "Usage: %s [-bclqrvw] [-p prog] [-s | host] port\n" ;
  1750. X
  1751. X    fprintf(stderr, ustring, progname) ;
  1752. X}
  1753. X
  1754. X/* perror with progname */
  1755. void perror2(s)
  1756. char *s ;
  1757. X{
  1758. X    fprintf(stderr, "%s: ", progname) ;
  1759. X    perror(s) ;
  1760. X}
  1761. X
  1762. X/* is s a number? */
  1763. int is_number(s)
  1764. char *s ;
  1765. X{
  1766. X    while (*s) {
  1767. X    if (*s < '0' || *s > '9') {
  1768. X        return 0 ;
  1769. X    }
  1770. X    s++ ;
  1771. X    }
  1772. X    return 1 ;
  1773. X}
  1774. X
  1775. X/* set up signal handling. All except TSTP, CONT, CLD, and QUIT
  1776. X * are caught with exitsig(). */
  1777. init_signals()
  1778. X{
  1779. X    int i ;
  1780. X#ifdef SIG_SETMASK        /* only with BSD signals */
  1781. X    static struct sigvec svec = { exitsig, ~0, 0 } ;
  1782. X#endif
  1783. X
  1784. X    initialize_siglist() ;    /* shamelessly stolen from BASH */
  1785. X    
  1786. X    for (i = 0; i < NSIG; i++) {
  1787. X    switch (i) {
  1788. X#ifdef SIGTSTP
  1789. X      case SIGTSTP:
  1790. X      case SIGTTOU:
  1791. X      case SIGTTIN:
  1792. X      case SIGSTOP:
  1793. X      case SIGCONT:
  1794. X        continue ;
  1795. X#endif
  1796. X#if !defined (SIGCHLD) && defined (SIGCLD)
  1797. X#define SIGCHLD SIGCLD
  1798. X#endif
  1799. X#ifdef SIGCHLD
  1800. X      case SIGCHLD:
  1801. X        continue ;
  1802. X#endif
  1803. X#ifdef SIGWINCH
  1804. X      case SIGWINCH:    /* it is ridiculous to exit on WINCH */
  1805. X        continue ;
  1806. X#endif
  1807. X      case SIGQUIT:        /* if the user wants a core dump, */
  1808. X        continue ;        /* they can have it. */
  1809. X      default:        
  1810. X#ifdef SIG_SETMASK
  1811. X        sigvec(i, &svec, NULL) ;
  1812. X#else
  1813. X        signal(i, exitsig) ;
  1814. X#endif
  1815. X    }
  1816. X    }
  1817. X}
  1818. X
  1819. X/* connect stdin with prog's stdout/stderr and stdout
  1820. X * with prog's stdin. */
  1821. void open_pipes(prog)
  1822. char *prog ;
  1823. X{
  1824. X    int from_cld[2] ;        /* from child process */
  1825. X    int to_cld[2] ;        /* to child process */
  1826. X
  1827. X    /* create pipes */
  1828. X    if (pipe(from_cld) == -1) {
  1829. X    perror2("pipe") ;
  1830. X    exit(errno) ;
  1831. X    }
  1832. X    if (pipe(to_cld) == -1) {
  1833. X    perror2("pipe") ;
  1834. X    exit(errno) ;
  1835. X    }
  1836. X
  1837. X    /* for child process */
  1838. X    switch (fork()) {
  1839. X      case 0:            /* this is the child process */
  1840. X    /* connect stdin to pipe */
  1841. X    close(0) ;
  1842. X    close(to_cld[1]) ;
  1843. X    dup2(to_cld[0], 0) ;
  1844. X    close(to_cld[0]) ;
  1845. X    /* connect stdout to pipe */
  1846. X    close(1) ;
  1847. X    close(from_cld[0]) ;
  1848. X    dup2(from_cld[1], 1) ;
  1849. X    /* connect stderr to pipe */
  1850. X    close(2) ;
  1851. X    dup2(from_cld[1], 2) ;
  1852. X    close(from_cld[1]) ;
  1853. X    /* call program via sh */
  1854. X    execl("/bin/sh", "sh", "-c", prog, NULL) ;
  1855. X    perror2("exec /bin/sh") ;
  1856. X    /* terminate parent silently */
  1857. X    kill(getppid(), SIGUSR1) ;
  1858. X    exit(255) ;
  1859. X      case -1:
  1860. X    perror2("fork") ;    /* fork failed */
  1861. X    exit(errno) ;
  1862. X      default:            /* parent process */
  1863. X    /* connect stderr to pipe */
  1864. X    close(0) ;
  1865. X    close(from_cld[1]) ;
  1866. X    dup2(from_cld[0], 0) ;
  1867. X    close(from_cld[0]) ;
  1868. X    /* connect stderr to pipe */
  1869. X    close(1) ;
  1870. X    close(to_cld[0]) ;
  1871. X    dup2(to_cld[1], 1) ;
  1872. X    close(to_cld[1]) ;
  1873. X    }
  1874. X}
  1875. X
  1876. X/* remove zombie child processes */
  1877. void wait_for_children()
  1878. X{
  1879. X    int wret, status ;
  1880. X#ifndef ISC
  1881. X    struct rusage rusage ;
  1882. X#endif
  1883. X
  1884. X    /* Just do a wait, forget result */
  1885. X#ifndef ISC
  1886. X    while ((wret = wait3(&status, WNOHANG, &rusage)) > 0) ;
  1887. X#else
  1888. X    while ((wret = waitpid(-1, &status, WNOHANG)) > 0) ;
  1889. X#endif
  1890. X}
  1891. X
  1892. X/* expand LF characters to CRLF and adjust *sizep */
  1893. void add_crs(from, to, sizep)
  1894. char *from, *to ;        /* *from is copied to *to */
  1895. int *sizep ;
  1896. X{
  1897. X    int countdown ;        /* counter */
  1898. X
  1899. X    countdown = *sizep ;
  1900. X    while (countdown) {
  1901. X    if (*from == '\n') {
  1902. X        *to++ = '\r' ;
  1903. X        (*sizep)++ ;
  1904. X    }
  1905. X    *to++ = *from++ ;
  1906. X    countdown-- ;
  1907. X    }
  1908. X}
  1909. X
  1910. X/* strip CR characters from buffer and adjust *sizep */
  1911. void strip_crs(from, to, sizep)
  1912. char *from, *to ;        /* *from is copied to *to */
  1913. int *sizep ;
  1914. X{
  1915. X
  1916. X    int countdown ;        /* counter */
  1917. X
  1918. X    countdown = *sizep ;
  1919. X    while (countdown) {
  1920. X    if (*from == '\r') {
  1921. X        from++ ;
  1922. X        (*sizep)-- ;
  1923. X    } else {
  1924. X        *to++ = *from++ ;
  1925. X    }
  1926. X    countdown-- ;
  1927. X    }
  1928. X}
  1929. X
  1930. X#define NULL_DEVICE "/dev/null"
  1931. X
  1932. X/* put yourself in the background */
  1933. void background()
  1934. X{
  1935. X    int child_pid ;        /* PID of child process */
  1936. X    int nulldev_fd ;        /* file descriptor for null device */
  1937. X
  1938. X    child_pid = fork() ;
  1939. X    switch (child_pid) {
  1940. X      case -1:
  1941. X    perror2("fork") ;
  1942. X    exit(1) ;
  1943. X      case 0:
  1944. X#ifdef NOSETSID
  1945. X    ioctl(0, TIOCNOTTY, 0) ;
  1946. X#else
  1947. X    setsid() ;
  1948. X#endif
  1949. X    chdir("/") ;
  1950. X    if ((nulldev_fd = open(NULL_DEVICE, O_RDWR, 0)) != -1) {
  1951. X        int i ;
  1952. X
  1953. X        for (i = 0; i < 3; i++) {
  1954. X        if (isatty(i)) {
  1955. X            dup2(nulldev_fd, i) ;
  1956. X        }
  1957. X        }
  1958. X        close(nulldev_fd) ;
  1959. X    }
  1960. X    break ;
  1961. X      default:
  1962. X    exit(0) ;
  1963. X    }
  1964. X}
  1965. END_OF_FILE
  1966. if test 4989 -ne `wc -c <'utils.c'`; then
  1967.     echo shar: \"'utils.c'\" unpacked with wrong size!
  1968. fi
  1969. # end of 'utils.c'
  1970. fi
  1971. echo shar: End of shell archive.
  1972. exit 0
  1973.