Newsgroups: comp.sources.unix From: nickel@cs.tu-berlin.de (Juergen Nickelsen) Subject: v26i075: socket - shell-level interface to IP/TCP sockets (V1.1) Sender: unix-sources-moderator@pa.dec.com Approved: vixie@pa.dec.com Submitted-By: nickel@cs.tu-berlin.de (Juergen Nickelsen) Posting-Number: Volume 26, Issue 75 Archive-Name: socket This is release 1.1 of the Socket(1) program. Socket(1) implements an interface to TCP sockets at shell level. Client and server sockets can be used from shell scripts or interactively. Socket can also run a program with stdin, stdout, and stderr connected to the socket connection. Sample shell scripts implementing a finger client (remote only) and a finger daemon are included. Socket-1.1 runs on these platforms: - AT 386, ISC 3.0 (*) - CDC 4680, EP/IX 1.4.1. (*) - DECstation 3100, Ultrix 4.0 - HP-UX 7.0, 8.0 (*) - IBM RS 6000, AIX 3.1.5 - MicroVAX II, 4.3 BSD (*) - SGI Iris, Irix 3.3.1 - Sequent, DYNIX v.3.0.7 (*) - Sun SPARCstation II, SunOS 4.1.2 - System V Rel. 4 (*) The platforms marked with "(*)" require minor editing of the Makefile. Please send any comments, suggestions, bug reports etc. to me: Juergen Nickelsen Sekr. FR 5-6 TU Berlin Franklinstr. 28-29 1000 Berlin 10 Germany #! /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 'BLURB' <<'END_OF_FILE' This is release 1.1 of the Socket(1) program. X Socket(1) implements an interface to TCP sockets at shell level. Client and server sockets can be used from shell scripts or interactively. Socket can also run a program with stdin, stdout, and stderr connected to the socket connection. Sample shell scripts implementing a finger client (remote only) and a finger daemon are included. X Socket-1.1 runs on these platforms: X X - AT 386, ISC 3.0 (*) X - CDC 4680, EP/IX 1.4.1. (*) X - DECstation 3100, Ultrix 4.0 X - HP-UX 7.0, 8.0 (*) X - IBM RS 6000, AIX 3.1.5 X - MicroVAX II, 4.3 BSD (*) X - SGI Iris, Irix 3.3.1 X - Sequent, DYNIX v.3.0.7 (*) X - Sun SPARCstation II, SunOS 4.1.2 X - System V Rel. 4 (*) X The platforms marked with "(*)" require minor editing of the Makefile. END_OF_FILE if test 879 -ne `wc -c <'BLURB'`; then echo shar: \"'BLURB'\" unpacked with wrong size! fi # end of 'BLURB' fi if test -f 'CHANGES' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'CHANGES'\" else echo shar: Extracting \"'CHANGES'\" \(489 characters\) sed "s/^X//" >'CHANGES' <<'END_OF_FILE' X-*-text-*- X User-visible changes in Socket version 1.1: X X - Ported to more Platforms (SGI Irix, IBM AIX, CDC EP/IX, ISC 3.0, X System V R4, Sequent) X X - fixed getopt()-related bug in main() (opt declared as int now). X X - fixed SIGWINCH-related bug (socket no longer exits on SIGWINCH). X X - Background mode (-b option) X X - -f option to fork child X X - fixed bug in server mode concerning the "Connection from..." X message X X - slightly more adequate signal handling and messages END_OF_FILE if test 489 -ne `wc -c <'CHANGES'`; then echo shar: \"'CHANGES'\" unpacked with wrong size! fi # end of 'CHANGES' fi if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'COPYRIGHT'\" else echo shar: Extracting \"'COPYRIGHT'\" \(932 characters\) sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE' X-*- text -*- X Copyright (C) 1992 by Juergen Nickelsen except the file siglist.c, which is Copyright (C) 1989 Free Software XFoundation, Inc. X This applies to the Socket program, release Socket-1.1. X Socket is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the XFree Software Foundation; either version 1, or (at your option) any later version. X It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or XFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. X You may have received a copy of the GNU General Public License along with GNU Emacs or another GNU program; see the file COPYING. If not, write to me at the electronic mail address given above or to Juergen Nickelsen, Hertzbergstr. 28, 1000 Berlin 44, Germany. END_OF_FILE if test 932 -ne `wc -c <'COPYRIGHT'`; then echo shar: \"'COPYRIGHT'\" unpacked with wrong size! fi # end of 'COPYRIGHT' fi if test -f 'Dependencies' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Dependencies'\" else echo shar: Extracting \"'Dependencies'\" \(296 characters\) sed "s/^X//" >'Dependencies' <<'END_OF_FILE' io.o: ./globals.h io.o: ./patchlevel.h io.o: io.c siglist.o: siglist.c so_release.o: so_release.c socket.o: ./globals.h socket.o: ./patchlevel.h socket.o: socket.c socketp.o: ./globals.h socketp.o: ./patchlevel.h socketp.o: socketp.c utils.o: ./globals.h utils.o: ./patchlevel.h utils.o: utils.c END_OF_FILE if test 296 -ne `wc -c <'Dependencies'`; then echo shar: \"'Dependencies'\" unpacked with wrong size! fi # end of 'Dependencies' fi if test -f 'INSTALL' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'INSTALL'\" else echo shar: Extracting \"'INSTALL'\" \(1141 characters\) sed "s/^X//" >'INSTALL' <<'END_OF_FILE' X-*- text -*- X Socket-1.1 runs on these platforms: X X - AT 386, ISC 3.0 (*) X - CDC 4680, EP/IX 1.4.1. (*) X - DECstation 3100, Ultrix 4.0 X - HP-UX 7.0, 8.0 (*) X - IBM RS 6000, AIX 3.1.5 X - MicroVAX II, 4.3 BSD (*) X - SGI Iris, Irix 3.3.1 X - Sequent, DYNIX v.3.0.7 (*) X - Sun SPARCstation II, SunOS 4.1.2 X - System V Rel. 4 (*) X The platforms marked with "(*)" require minor editing of the Makefile. Instructions are included near the beginning of the Makefile. Edit as necessary and type "make install". This builds the program and installs the executable as /usr/local/bin/socket and the manual page as /usr/local/man/man1/socket.1. X Socket relies on some Berkeleyisms in signal, process, and IO handling, so porting it to (other) non-BSD-derived platforms may be difficult. I am interested in any changes you make to port the program to a new platform. Please send them back to me so I can merge them into a later release. X The Makefile is not suitable for development since it doesn't include the dependencies. (I use the Shape Toolkit for development.) To correct this, include the file Dependencies into the Makefile. END_OF_FILE if test 1141 -ne `wc -c <'INSTALL'`; then echo shar: \"'INSTALL'\" unpacked with wrong size! fi # end of 'INSTALL' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(4564 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# Makefile for Socket X# X# $Header: Makefile[1.23] Wed Sep 9 19:03:26 1992 nickel@cs.tu-berlin.de proposed $ X# X X### adjust these to your taste X### This is set up to install socket as /usr/local/bin/socket and X### socket.1 in /usr/local/man/man1/socket.1 X### Make sure the target directories exist before doing a "make install". X INSTALLBASE = /usr/local INSTALLBINPATH = $(INSTALLBASE)/bin INSTALLBINMODE = 755 INSTALLMANPATH = $(INSTALLBASE)/man INSTALLMANMODE = 444 CC = cc CFLAGS = $(SWITCHES) -O LDFLAGS = $(SWITCHES) -s X X### You may need to uncomment some lines below for your operating X### system: X X### 4.3 BSD: X# SWITCHES = -DNOSETSID X X### HP-UX: X# SYSLIBS = -lBSD X X### ISC 3.0: X# SYSLIBS = -linet -lcposix X# SWITCHES = -DISC X X### System V Rel. 4: X# SYSLIBS = -lc -lsocket -lnsl -L/usr/ucblib -lucb X# SWITCHES = -I/usr/ucbinclude X X### Sequent: X# SYSLIBS = -lseq X# SWITCHES = -Dstrrchr=rindex -DSEQUENT -DNOSETSID X### (I have been reported troubles with the "installmanuals" target on X### a Sequent, so you might have to copy the manual page yourself.) X X### CDC 4680 EP/IX: (I know it *has* setsid(2), but not with bsd43) X# SWITCHES = -systype bsd43 -DNOSETSID X X X X### It should not be necessary to change anything below this line. X################################################################## X MAKE = make SHELL = /bin/sh BASE = /home/stone/nickel/src NODEPATH = socket NODENAME = "Socket" TARGET = socket VERSIONFILE = so_release.c VERSIONOBJECT = so_release.o PROGSOURCES = socket.c siglist.c io.c utils.c socketp.c SOURCES = BLURB README COPYRIGHT INSTALL CHANGES \ X socket.1 \ X $(PROGSOURCES) \ X rfinger.sh fingerd.sh HEADERS = globals.h patchlevel.h MANUALS = $(MAN1) MAN1 = socket.1 COMPONENTS = $(SOURCES) $(HEADERS) $(MANUALS) Makefile Dependencies OBJECTS = $(VERSIONOBJECT) socket.o siglist.o io.o utils.o socketp.o X all: +all $(ALLTARGETS) X targets: $(TARGET) X X$(TARGET): $(LOCALLIBS) $(OBJECTS) X $(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LOCALLIBS) $(SYSLIBS) X tags: TAGS TAGS: $(PROGSOURCES) $(HEADERS) X etags $(PROGSOURCES) $(HEADERS) X installtargets: $(INSTALLBINPATH)/$(TARGET) installmanuals X X$(INSTALLBINPATH)/$(TARGET): $(TARGET) X @-echo "installing $(TARGET) in $(INSTALLBINPATH)"; \ X if [ -f $(INSTALLBINPATH)/$(TARGET) ] && \ X [ ! -w $(INSTALLBINPATH)/$(TARGET) ]; \ X then \ X chmod u+w $(INSTALLBINPATH)/$(TARGET); \ X fi; \ X cp $(TARGET) $(INSTALLBINPATH)/$(TARGET); \ X chmod $(INSTALLBINMODE) $(INSTALLBINPATH)/$(TARGET) X installmanuals: $(MANUALS) X @-_manuals="$(MAN1)"; \ X for i in $$_manuals; \ X do \ X echo "installing $$i in $(INSTALLMANPATH)/man1"; \ X if [ -f $(INSTALLMANPATH)/man1/$$i ] && \ X [ ! -w $(INSTALLMANPATH)/man1/$$i ]; \ X then \ X chmod u+w $(INSTALLMANPATH)/man1/$$i; \ X fi; \ X cp $$i $(INSTALLMANPATH)/man1/$$i; \ X chmod $(INSTALLMANMODE) $(INSTALLMANPATH)/man1/$$i; \ X done X doclean: X rm -f $(TARGET) $(ALIASES) $(OBJECTS) core *~ X X## X## following internals of shapeTools Release Management System X subsystems: # none X install: +install $(ALLTARGETS) X clean: +clean $(ALLTARGETS) X X+all: X @-if [ -n "$(ALLTARGETS)" ]; \ X then : ; \ X else \ X $(MAKE) ALLTARGETS="subsystems targets" MAINTARGET=all \ X BASE=$(BASE) \ X SWITCHES="$(SWITCHES)" \ X INSTALLBASE=$(INSTALLBASE) \ X INSTALLBINPATH=$(INSTALLBINPATH) \ X INSTALLBINMODE=$(INSTALLBINMODE) \ X INSTALLMANPATH=$(INSTALLMANPATH) \ X INSTALLMANMODE=$(INSTALLMANMODE) \ X MAKE="$(MAKE)" \ X SHELL="$(SHELL)" \ X CC="$(CC)" \ X CFLAGS="$(CFLAGS)" \ X LDFLAGS="$(LDFLAGS)" \ X SYSLIBS="$(SYSLIBS)" all; \ X fi X X+install: X @-if [ -n "$(ALLTARGETS)" ]; \ X then : ; \ X else \ X $(MAKE) ALLTARGETS="subsystems installtargets" \ X MAINTARGET=install \ X BASE=$(BASE) \ X SWITCHES="$(SWITCHES)" \ X INSTALLBASE=$(INSTALLBASE) \ X INSTALLBINPATH=$(INSTALLBINPATH) \ X INSTALLBINMODE=$(INSTALLBINMODE) \ X INSTALLMANPATH=$(INSTALLMANPATH) \ X INSTALLMANMODE=$(INSTALLMANMODE) \ X MAKE="$(MAKE)" \ X SHELL="$(SHELL)" \ X CC="$(CC)" \ X CFLAGS="$(CFLAGS)" \ X LDFLAGS="$(LDFLAGS)" \ X SYSLIBS="$(SYSLIBS)" install; \ X fi X X+clean: X @-if [ -n "$(ALLTARGETS)" ]; \ X then : ; \ X else \ X $(MAKE) ALLTARGETS="subsystems doclean" MAINTARGET=clean \ X BASE=$(BASE) \ X SWITCHES="$(SWITCHES)" \ X INSTALLBASE=$(INSTALLBASE) \ X INSTALLBINPATH=$(INSTALLBINPATH) \ X INSTALLBINMODE=$(INSTALLBINMODE) \ X INSTALLMANPATH=$(INSTALLMANPATH) \ X INSTALLMANMODE=$(INSTALLMANMODE) \ X INCLUDEPATH=$(INCLUDEPATH) \ X MAKE="$(MAKE)" \ X SHELL="$(SHELL)" \ X CC="$(CC)" \ X CFLAGS="$(CFLAGS)" \ X LDFLAGS="$(LDFLAGS)" \ X SYSLIBS="$(SYSLIBS)" clean; \ X fi END_OF_FILE if test 4564 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(6043 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' Hey Emacs, this is -*- text -*-. X This is the README file for Socket-1.1. X XFor information on how to build and install Socket, read the file INSTALL. Please read the file COPYRIGHT about the terms under which this program is licensed to you. X X What is it? X The program Socket implements access to TCP sockets from shell level. XFirst written for the need to open a server socket and read and write to the socket interactively for testing purposes, it quickly evolved into a generic tool providing the socket interface for shell script and interactive use. X X Client mode X In client mode (which is the default) it connects to a given port at a given host. Data read from the socket is written to stdout, data read from stdin is written to the socket. When the peer closes the connection or a signal is received, the program terminates. An example for this is the following command: X X % socket coma.cs.tu-berlin.de nntp X This connects to the host coma.cs.tu-berlin.de at the nntp port X(provided these two names can be resolved through gethostbyname(3) and getservbyname(3)). The user can now issue commands to the NNTP server, any output from the server is written to the user's terminal. X X Server mode X In server mode (indicated by the "-s" command line switch) it binds a server socket to the given port on the local host and accepts a connection. When a client connects to this socket, all data read from the socket is written to stdout, data read from stdin is written to the socket. For example, the command X X % socket -s 3917 X accepts a connection on port 3917. X X Restricting data flow X It is not always desirable to have data flow in both directions, e.g. when the program is running in the background, it would be stopped if it tried to read from the terminal. So the user can advise the program only to read from the socket ("-r") or only to write to the socket X("-w"). Especially when Socket executes a program (see below), it is important *not* to write to the program's stdin if the program doesn't read it. This is the main reason why I added this option. X X Closing connection on EOF X XFor non-interactive use it is not always clear when to close the network connection; this is still an unsolved problem. But often it will be enough to close the connection when some data has been written to the socket. In this case the "quit" switch ("-q") can be used: when an end-of-file condition on stdin occurs, Socket closes the connection. X X XExecuting a program X An interesting use of a server socket is to execute a program when a client connects to it. This done with the "-p" switch. Stdin, stdout, and stderr of the program are read from resp. written to the socket. Since the server is usually expected to accept another connection after a connection has been closed, the "loop" switch X("-l") makes it do exactly that. X X CRLF conversion X The Internet protocols specify a CRLF sequence (Carriage Return Linefeed) to terminate a line, whereas UNIX uses only a single LF. If the user specifies the "crlf" switch ("-c"), all CRLF sequences that are read from the socket are converted to a single LF on output. All single LFs on input are converted to a CRLF sequence when written to the socket. X X Background mode X It may be desirable for a server program to run in background. For that purpose the "background" switch ("-b") is provided. If it is set, Socket runs in background, detaches itself from the controlling tty, closes the file descriptors associated with the tty, and changes it current directory to the root directory. It is still possible to redirect the standard file descriptors to a file. X X XForking child to handle connection X Often one wants the server to be able to respond to another client immediately, even before the connection to the previous client has been closed. For this case, Socket can fork a client to handle a connection while the father process already accepts the next connection. To get this behaviour, specify the "-f" option. X X With all these options, a typical server call would look like X X % socket -bcfslqp program port X Gee, I know that's a lot of options for the standard case, but I really want to make all these things *optional*. X X Verbose X At last, there is also a "verbose" option ("-v"). If this option is specified, a message is given for each opening and closing of a connection. This is convenient especially in interactive use, but can also provide some kind of logging. See fingerd.sh for an example. X X WARNING X Nothing prevents you from using Socket like this: X X % socket -slqp sh 5678 X THIS IS DANGEROUS! If your machine is connected to the Internet, X*anyone* on the Internet can connect to this server and issue shell commands to your shell. These commands are executed with your user ID. Some people may think of this program as a BAD THING, because it allows its user to open his machine for world-wide access to all kinds of malicious crackers, crashers, etc. I don't know if I should consider this as a real security risk or not. Anyway, it is not my program which is so dangerous -- anyone with moderate programming skill can write a something like this. X Another problem is that any server program that uses Socket may not be secure. I tried to avoid any holes -- especially that one that made fingerd vulnerable to the attack of Morris' Internet Worm, but I don't give any warranty. Also the program run by Socket may have security holes. X I would like to hear your opinion about this topic. Do you consider it a security risk to have a program like Socket around? X X Sample programs X I included two sample programs, which mimic the behavior of finger(1) and fingerd(8), implemented as shell scripts using Socket. rfinger.sh can only finger remote hosts. fingerd.sh is RFC 1288 compliant and can be used independently of inetd(8). X X Comments X Please send any comments, suggestions, bug reports etc. to me: X X Juergen Nickelsen X Sekr. FR 5-6 X TU Berlin X Franklinstr. 28-29 X 1000 Berlin 10 X Germany X X END_OF_FILE if test 6043 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'fingerd.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fingerd.sh'\" else echo shar: Extracting \"'fingerd.sh'\" \(371 characters\) sed "s/^X//" >'fingerd.sh' <<'END_OF_FILE' X#!/bin/sh X# $Header: fingerd.sh[1.3] Sun Aug 9 03:48:06 1992 nickel@cs.tu-berlin.de proposed $ X# X# finger daemon program using socket(1) with primitive logging. X# Set LOGFILE to a file of your choice. X LOGFILE=/dev/null X socket -sqlvcp '/usr/ucb/finger `head -1 | sed "s|/[Ww]|-l|"`' \ X finger 2>&1 | X while read line ; do X echo -n $line:\ ; date ; X done > $LOGFILE END_OF_FILE if test 371 -ne `wc -c <'fingerd.sh'`; then echo shar: \"'fingerd.sh'\" unpacked with wrong size! fi chmod +x 'fingerd.sh' # end of 'fingerd.sh' fi if test -f 'globals.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'globals.h'\" else echo shar: Extracting \"'globals.h'\" \(1397 characters\) sed "s/^X//" >'globals.h' <<'END_OF_FILE' X/* X X$Header: globals.h[1.10] Sun Aug 30 21:13:41 1992 nickel@cs.tu-berlin.de proposed $ This file is part of socket(1). Copyright (C) 1992 by Juergen Nickelsen Please read the file COPYRIGHT for further details. X X*/ X X#include "patchlevel.h" X X/* globals for socket */ X X#define IN 0 /* standard input */ X#define OUT 1 /* standard output */ X X#define LLEN 100 /* buffer size fo perror2() */ X X#ifdef __STDC__ X#define A(args) args X#else X#define A(args) () X#endif X int create_server_socket A((int port, int queue_length)) ; int create_client_socket A((char **hostname, int port)) ; int resolve_service A((char *name_or_number, char *protocol, char **name)) ; void catchsig A((int sig)) ; void usage A((void)) ; int do_read_write A((int from, int to)) ; int do_write A((char *buffer, int size, int to)) ; char *so_release A((void)) ; void open_pipes A((char *prog)) ; void wait_for_children A((void)) ; void perror2 A((char *s)) ; void add_crs A((char *from, char *to, int *sizep)) ; void strip_crs A((char *from, char *to, int *sizep)) ; void background A((void)) ; X extern int errno ; X X/* global variables */ extern int serverflag ; extern int loopflag ; extern int verboseflag ; extern int readonlyflag ; extern int writeonlyflag ; extern int quitflag ; extern int crlfflag ; extern int active_socket ; extern char *progname ; extern char *sys_errlist[], *sys_siglist[] ; END_OF_FILE if test 1397 -ne `wc -c <'globals.h'`; then echo shar: \"'globals.h'\" unpacked with wrong size! fi # end of 'globals.h' fi if test -f 'io.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'io.c'\" else echo shar: Extracting \"'io.c'\" \(3030 characters\) sed "s/^X//" >'io.c' <<'END_OF_FILE' X/* X X$Header: io.c[1.10] Sun Aug 30 19:21:18 1992 nickel@cs.tu-berlin.de proposed $ This file is part of socket(1). Copyright (C) 1992 by Juergen Nickelsen Please read the file COPYRIGHT for further details. X X*/ X X#define _BSD /* AIX *loves* this */ X X#include X#include X#ifdef ISC X#include X#endif X#include X#include X#include "globals.h" X X/* read from from, write to to. select(2) has returned, so input X * must be available. */ int do_read_write(from, to) int from, to ; X{ X int size ; X char input_buffer[BUFSIZ] ; X X if ((size = read(from, input_buffer, BUFSIZ)) == -1) { X perror2("read") ; X return -1 ; X } X if (size == 0) { /* end-of-file condition */ X if (from == active_socket) { X /* if it was the socket, the connection is closed */ X if (verboseflag) { X fprintf(stderr, "connection closed by peer\n") ; X } X return -1 ; X } else { X if (quitflag) { X /* we close connection later */ X if (verboseflag) { X fprintf(stderr, "connection closed\n") ; X } X return -1 ; X } else if (verboseflag) { X fprintf(stderr, "end of input on stdin\n") ; X } X readonlyflag = 1 ; X return 1 ; X } X } X return do_write(input_buffer, size, to) ; X X} X X/* write the buffer; in successive pieces, if necessary. */ int do_write(buffer, size, to) char *buffer ; int size, to ; X{ X char buffer2[2 * BUFSIZ] ; /* expanding lf's to crlf's can X * make the block twice as big at most */ X int written ; X X if (crlfflag) { X if (to == active_socket) { X add_crs(buffer, buffer2, &size) ; X } else { X strip_crs(buffer, buffer2, &size) ; X } X } else { X bcopy(buffer, buffer2, size) ; X } X while (size > 0) { X written = write(to, buffer2, size) ; X if (written == -1) { X /* this should not happen */ X perror2("write") ; X fprintf(stderr, "%s: error writing to %s\n", X progname, X to == active_socket ? "socket" : "stdout") ; X return -1 ; X } X size -= written ; X } X return 1 ; X} X X/* all IO to and from the socket is handled here. The main part is X * a loop around select(2). */ do_io() X{ X fd_set readfds ; X int fdset_width ; X int selret ; X X fdset_width = (IN > active_socket ? IN : active_socket) + 1 ; X while (1) { /* this loop is exited sideways */ X /* set up file descriptor set for select(2) */ X FD_ZERO(&readfds) ; X if (!readonlyflag) { X FD_SET(IN, &readfds) ; X } X if (!writeonlyflag) { X FD_SET(active_socket, &readfds) ; X } X X do { X /* wait until input is available */ X selret = select(fdset_width, &readfds, NULL, NULL, NULL) ; X /* EINTR happens when the process is stopped */ X if (selret < 0 && errno != EINTR) { X perror2("select") ; X exit(1) ; X } X } while (selret <= 0) ; X X /* do the appropriate read and write */ X if (FD_ISSET(active_socket, &readfds)) { X if (do_read_write(active_socket, OUT) < 0) { X break ; X } X } else { X if (do_read_write(IN, active_socket) < 0) { X break ; X } X } X } X} END_OF_FILE if test 3030 -ne `wc -c <'io.c'`; then echo shar: \"'io.c'\" unpacked with wrong size! fi # end of 'io.c' fi if test -f 'patchlevel.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'patchlevel.h'\" else echo shar: Extracting \"'patchlevel.h'\" \(21 characters\) sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE' X#define PATCHLEVEL 0 END_OF_FILE if test 21 -ne `wc -c <'patchlevel.h'`; then echo shar: \"'patchlevel.h'\" unpacked with wrong size! fi # end of 'patchlevel.h' fi if test -f 'rfinger.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rfinger.sh'\" else echo shar: Extracting \"'rfinger.sh'\" \(623 characters\) sed "s/^X//" >'rfinger.sh' <<'END_OF_FILE' X#!/bin/sh X# $Header: rfinger.sh[1.2] Sun Aug 30 18:04:21 1992 nickel@cs.tu-berlin.de proposed $ X# X# remote finger program using socket(1). Works similar to finger(1), X# but can do only remote fingers. X X# If you have my nslook program, you can determine the official name X# of the host. X#NSLOOK="nslook -o" NSLOOK=echo X if [ "$1" = -l ] ; then X long=/W ; shift fi X host=`echo $1 | sed -n 's/^.*@\([^@]*\)$/\1/p'` X if [ $# != 1 -o ! "$host" ] ; then X echo Usage: `basename $0` '[-l] [user]@host' X exit 1 fi X ohost=`$NSLOOK $host` echo \[$ohost\] echo `echo $1 | sed -n 's/^\(.*\)@[^@]*$/\1/p'` $long | socket -c $host finger END_OF_FILE if test 623 -ne `wc -c <'rfinger.sh'`; then echo shar: \"'rfinger.sh'\" unpacked with wrong size! fi chmod +x 'rfinger.sh' # end of 'rfinger.sh' fi if test -f 'siglist.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'siglist.c'\" else echo shar: Extracting \"'siglist.c'\" \(4647 characters\) sed "s/^X//" >'siglist.c' <<'END_OF_FILE' X/* siglist.c -- signal list for those machines that don't have one. */ X X/* Copyright (C) 1989 Free Software Foundation, Inc. X This file is part of GNU Bash, the Bourne Again SHell. X Modified by Juergen Nickelsen for use with Socket-1.1. X Bash is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. X Bash is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or XFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. X You should have received a copy of the GNU General Public License along with Bash; see the file COPYING. If not, write to the Free Software XFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#include X#include X X#if !defined (NSIG) X# if defined (_NSIG) X# define NSIG _NSIG X# else X# define NSIG 64 X# endif /* !_NSIG */ X#endif /* !NSIG */ X char *sys_siglist[NSIG]; X extern *malloc (); X initialize_siglist () X{ X register int i; X X for (i = 0; i < NSIG; i++) X sys_siglist[i] = (char *)0x0; X X sys_siglist[0] = "Bogus signal"; X X#if defined (SIGHUP) X sys_siglist[SIGHUP] = "Hangup signal"; X#endif X X#if defined (SIGINT) X sys_siglist[SIGINT] = "Interrupt"; X#endif X X#if defined (SIGQUIT) X sys_siglist[SIGQUIT] = "Quit signal"; X#endif X X#if defined (SIGILL) X sys_siglist[SIGILL] = "Illegal instruction"; X#endif X X#if defined (SIGTRAP) X sys_siglist[SIGTRAP] = "BPT trace/trap"; X#endif X X#if defined (SIGIOT) && !defined (SIGABRT) X#define SIGABRT SIGIOT X#endif X X#if defined (SIGABRT) X sys_siglist[SIGABRT] = "ABORT instruction"; X#endif X X#if defined (SIGEMT) X sys_siglist[SIGEMT] = "EMT instruction"; X#endif X X#if defined (SIGFPE) X sys_siglist[SIGFPE] = "Floating point exception"; X#endif X X#if defined (SIGKILL) X sys_siglist[SIGKILL] = "Kill signal"; X#endif X X#if defined (SIGBUS) X sys_siglist[SIGBUS] = "Bus error"; X#endif X X#if defined (SIGSEGV) X sys_siglist[SIGSEGV] = "Segmentation fault"; X#endif X X#if defined (SIGSYS) X sys_siglist[SIGSYS] = "Bad system call"; X#endif X X#if defined (SIGPIPE) X sys_siglist[SIGPIPE] = "Broken pipe condition"; X#endif X X#if defined (SIGALRM) X sys_siglist[SIGALRM] = "Alarm clock signal"; X#endif X X#if defined (SIGTERM) X sys_siglist[SIGTERM] = "Termination signal"; X#endif X X#if defined (SIGURG) X sys_siglist[SIGURG] = "Urgent IO condition"; X#endif X X#if defined (SIGSTOP) X sys_siglist[SIGSTOP] = "Stop signal"; X#endif X X#if defined (SIGTSTP) X sys_siglist[SIGTSTP] = "Stopped"; X#endif X X#if defined (SIGCONT) X sys_siglist[SIGCONT] = "Continue signal"; X#endif X X#if !defined (SIGCHLD) && defined (SIGCLD) X#define SIGCHLD SIGCLD X#endif X X#if defined (SIGCHLD) X sys_siglist[SIGCHLD] = "Child signal"; X#endif X X#if defined (SIGTTIN) X sys_siglist[SIGTTIN] = "Stop (tty input) signal"; X#endif X X#if defined (SIGTTOU) X sys_siglist[SIGTTOU] = "Stop (tty output) signal"; X#endif X X#if defined (SIGIO) X sys_siglist[SIGIO] = "I/O ready signal"; X#endif X X#if defined (SIGXCPU) X sys_siglist[SIGXCPU] = "CPU limit exceeded"; X#endif X X#if defined (SIGXFSZ) X sys_siglist[SIGXFSZ] = "File limit exceeded"; X#endif X X#if defined (SIGVTALRM) X sys_siglist[SIGVTALRM] = "Alarm (virtual)"; X#endif X X#if defined (SIGPROF) X sys_siglist[SIGPROF] = "Alarm (profile)"; X#endif X X#if defined (SIGWINCH) X sys_siglist[SIGWINCH] = "Window change"; X#endif X X#if defined (SIGLOST) X sys_siglist[SIGLOST] = "Record lock signal"; X#endif X X#if defined (SIGUSR1) X sys_siglist[SIGUSR1] = "User signal 1"; X#endif X X#if defined (SIGUSR2) X sys_siglist[SIGUSR2] = "User signal 2"; X#endif X X#if defined (SIGMSG) X sys_siglist[SIGMSG] = "HFT input data pending signal"; X#endif X X#if defined (SIGPWR) X sys_siglist[SIGPWR] = "power failure imminent signal"; X#endif X X#if defined (SIGDANGER) X sys_siglist[SIGDANGER] = "system crash imminent signal"; X#endif X X#if defined (SIGMIGRATE) X sys_siglist[SIGMIGRATE] = "Process migration"; X#endif X X#if defined (SIGPRE) X sys_siglist[SIGPRE] = "Programming error signal"; X#endif X X#if defined (SIGGRANT) X sys_siglist[SIGGRANT] = "HFT monitor mode granted signal"; X#endif X X#if defined (SIGRETRACT) X sys_siglist[SIGRETRACT] = "HFT monitor mode retracted signal"; X#endif X X#if defined (SIGSOUND) X sys_siglist[SIGSOUND] = "HFT sound sequence has completed signal"; X#endif X X for (i = 0; i < NSIG; i++) X { X if (!sys_siglist[i]) X { X sys_siglist[i] = X (char *) malloc (10 + strlen ("Unknown Signal #")); X X sprintf (sys_siglist[i], "Unknown Signal #%d", i); X } X } X} END_OF_FILE if test 4647 -ne `wc -c <'siglist.c'`; then echo shar: \"'siglist.c'\" unpacked with wrong size! fi # end of 'siglist.c' fi if test -f 'so_release.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'so_release.c'\" else echo shar: Extracting \"'so_release.c'\" \(135 characters\) sed "s/^X//" >'so_release.c' <<'END_OF_FILE' char *so_release () { X static char release[] = "Socket-1.1 (Wed Sep 9 19:11:19 1992 by nickel@cs.tu-berlin.de)"; X return release; X} END_OF_FILE if test 135 -ne `wc -c <'so_release.c'`; then echo shar: \"'so_release.c'\" unpacked with wrong size! fi # end of 'so_release.c' fi if test -f 'socket.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'socket.1'\" else echo shar: Extracting \"'socket.1'\" \(4029 characters\) sed "s/^X//" >'socket.1' <<'END_OF_FILE' X.\" -*- nroff -*- X.ig X$Header: socket.1[1.13] Wed Sep 9 16:46:30 1992 nickel@cs.tu-berlin.de proposed $ This file is part of socket(1). Copyright (C) 1992 by Juergen Nickelsen Please read the file COPYRIGHT for further details. X.. X.TH SOCKET 1 "Aug 6, 1992" X.SH NAME socket \- create tcp socket and connect to stdin/out X.SH SYNOPSIS X.B socket X[ X.B \-bcfqrvw X] X[ X.B \-p X.I command X] X.I host port X.br X.B socket X[ X.B \-bcfqrvw X] X[ X.B \-p X.I command X] X.B \-s X[ X.B \-l X] X.I port X.SH DESCRIPTION X.B Socket creates an Internet domain TCP socket and connects it to stdin and stdout. The X.I host argument can be an Internet number in dot-notation (like X``130.149.28.10'') or a domain name. In this case it must be possible to resolve the name to a valid Internet address with X.IR gethostbyname (3). The X.I port argument can be a port number or a service name which can be mapped to a port number by X.IR getservbyname (3). X.SH OPTIONS X.TP X.BR "\-b " (background) The program forks itself into the background, detaches from its controlling tty, closes the file descriptors associated with the tty, and changes its current directory to the root directory. X.TP X.BR "\-c " (crlf) Linefeed characters (LF) are converted to a Carriage Return Linefeed sequence (CRLF) when written to the socket. CRLF sequences read from the socket are converted to a single LF. X.TP X.BR "\-f " (fork) When a server connection has been accepted, a separate process is forked to handle the connection in background. X.TP X.BR "\-l " (loop) X(only valid with X.BR \-s ) After a connection has been closed, another connection is accepted. X.TP X.BR "\-p " (program) The specified X.I command is executed for each connection. Its standard input, standard output, and standard error channels are connected to the socket. X.I Command can be any shell command since it is passed to \fC/bin/sh\fP. X.TP X.BR "\-q " (quit) The connection is closed when an end-of-file condition occurs on standard input. X.TP X.BR "\-r " "(read only)" No data is read from standard input and written to the socket. X.TP X.BR "\-s " (server) A server socket is created. A X.I hostname argument is not required. X.TP X.BR "\-v " (verbose) Messages about connections etc. are issued to stderr. X.TP X.BR "\-w " "(write only)" No data is read from the socket and written to the standard output. X.TP X.B \-version X.B Socket prints its version ID and terminates. This must be the first argument to have an effect. X.SH EXAMPLES The command X.IP X\fCsocket -v coma.cs.tu-berlin.de nntp\fP X.LP connects to the nntp port (port 119) of coma.cs.tu-berlin.de X(130.149.28.10). X.br The command X.IP X\fCsocket \-sl 3425\fP X.LP creates a server socket on port 3425 on the local host and waits for a connection. After a connection has been closed, a new connection is accepted. X.br The command X.IP X\fCsocket \-wslqvp "echo Socket! " 1938\fP X.LP creates a server socket on port 1938 on the local host and waits for a connection. When a connection is accepted, the string "Socket!" is written to the socket. No data is read from the socket and written to the \fCfinger\fP program. The connection is closed when an end-of-file condition at the standard output of the program occurs. Then a new connection is accepted. X.SH DIAGNOSTICS Lots of diagnostics for failed system calls. X.TP X.BI "unknown host " host X.IR host 's address could not be resolved. X.TP X.B Signal \fIsignal\fP caught, exiting X.B Socket exits on any signal other than SIGTSTP, SIGCONT, SIGCLD, SIGQUIT. X.LP A non-zero exit code is returned if X.B socket terminates due to an error condition or a signal. X.SH SEE ALSO X.BR accept (2), X.BR bind (2), X.BR connect (2), X.BR socket (2), X.BR gethostbyname (3), X.BR getservbyname (3) X.SH BUGS X\fCsocket \-p\fP terminates due to a SIGPIPE signal when there is more data from the socket available than the executed program wants to read. X.LP Please report any other bugs to the author. X.SH VERSION This manual page describes Socket\-1.1. X.SH AUTHOR Juergen Nickelsen END_OF_FILE if test 4029 -ne `wc -c <'socket.1'`; then echo shar: \"'socket.1'\" unpacked with wrong size! fi # end of 'socket.1' fi if test -f 'socket.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'socket.c'\" else echo shar: Extracting \"'socket.c'\" \(6160 characters\) sed "s/^X//" >'socket.c' <<'END_OF_FILE' X/* X X$Header: socket.c[1.17] Wed Sep 9 16:23:14 1992 nickel@cs.tu-berlin.de proposed $ This file is part of socket(1). Copyright (C) 1992 by Juergen Nickelsen Please read the file COPYRIGHT for further details. X X*/ X X#include X#include X#include X#include X#include X#include X#ifdef SEQUENT X#include X#else X#include X#endif X#include "globals.h" X X/* global variables */ int forkflag = 0 ; /* server forks on connection */ int serverflag = 0 ; /* create server socket */ int loopflag = 0 ; /* loop server */ int verboseflag = 0 ; /* give messages */ int readonlyflag = 0 ; /* only read from socket */ int writeonlyflag = 0 ; /* only write to socket */ int quitflag = 0 ; /* quit connection on EOF */ int crlfflag = 0 ; /* socket expects and delivers CRLF */ int backgflag = 0 ; /* put yourself in background */ int active_socket ; /* socket with connection */ char *progname ; /* name of the game */ char *pipe_program = NULL ; /* program to execute in two-way pipe */ X void server A((int port, char *service_name)) ; void handle_server_connection A((void)) ; void client A((char *host, int port, char *service_name)) ; X int main(argc, argv) int argc ; char **argv ; X{ X char *cp ; /* to point to '/' in argv[0] */ X int opt ; /* option character */ X int error = 0 ; /* usage error occurred */ X extern int optind ; /* from getopt() */ X char *host ; /* name of remote host */ X int port ; /* port number for socket */ X char *service_name ; /* name of service for port */ X X /* print version ID if requested */ X if (argv[1] && !strcmp(argv[1], "-version")) { X puts(so_release()) ; X exit(0) ; X } X X /* set up progname for later use */ X progname = argv[0] ; X if (cp = strrchr(progname, '/')) progname = cp + 1 ; X X /* parse options */ X while ((opt = getopt(argc, argv, "bcflp:qrsvw?")) != -1) { X switch (opt) { X case 'f': X forkflag = 1 ; X break ; X case 'c': X crlfflag = 1 ; X break ; X case 'w': X writeonlyflag = 1 ; X break ; X case 'p': X pipe_program = argv[optind - 1] ; X break ; X case 'q': X quitflag = 1 ; X break ; X case 'r': X readonlyflag = 1 ; X break ; X case 's': X serverflag = 1 ; X break ; X case 'v': X verboseflag = 1 ; X break ; X case 'l': X loopflag = 1 ; X break ; X case 'b': X backgflag = 1 ; X break ; X default: X error++ ; X } X } X if (error || /* usage error? */ X argc - optind + serverflag != 2) { /* number of args ok? */ X usage() ; X exit(15) ; X } X X /* check some option combinations */ X#define senseless(s1, s2) \ X fprintf(stderr, "It does not make sense to set %s and %s.\n", (s1), (s2)) X X if (writeonlyflag && readonlyflag) { X senseless("-r", "-w") ; X exit(15) ; X } X if (loopflag && !serverflag) { X senseless("-l", "not -s") ; X exit(15) ; X } X if (backgflag && !serverflag) { X senseless("-b", "not -s") ; X exit(15) ; X } X if (forkflag && !serverflag) { X senseless("-f", "not -s") ; X } X X /* set up signal handling */ X init_signals() ; X X /* get port number */ X port = resolve_service(argv[optind + 1 - serverflag], X "tcp", &service_name) ; X if (port < 0) { X fprintf(stderr, "%s: unknown service\n", progname) ; X exit(5) ; X } X X /* and go */ X if (serverflag) { X if (backgflag) { X background() ; X } X server(port, service_name) ; X } else { X client(argv[optind], port, service_name) ; X } X exit(0) ; X} X X void server(port, service_name) int port ; char *service_name ; X{ X int socket_handle, alen ; X X /* allocate server socket */ X socket_handle = create_server_socket(port, 1) ; X if (socket_handle < 0) { X perror2("server socket") ; X exit(1) ; X } X if (verboseflag) { X fprintf(stderr, "listening on port %d", port) ; X if (service_name) { X fprintf(stderr, " (%s)", service_name) ; X } X fprintf(stderr, "\n") ; X } X X /* server loop */ X do { X struct sockaddr_in sa ; X X alen = sizeof(sa) ; X X /* accept a connection */ X if ((active_socket = accept(socket_handle, X (struct sockaddr *) &sa, X &alen)) == -1) { X perror2("accept") ; X } else { X /* if verbose, get name of peer and give message */ X if (verboseflag) { X struct hostent *he ; X long norder ; X char dotted[20] ; X X he = gethostbyaddr(&sa.sin_addr.s_addr, X sizeof(sa.sin_addr.s_addr), AF_INET) ; X if (!he) { X norder = htonl(sa.sin_addr.s_addr) ; X sprintf(dotted, "%d.%d.%d.%d", X (norder >> 24) & 0xff, X (norder >> 16) & 0xff, X (norder >> 8) & 0xff, X norder & 0xff) ; X } X fprintf(stderr, "connection from %s\n", X (he ? he->h_name : dotted)) ; X } X if (forkflag) { X switch (fork()) { X case 0: X handle_server_connection() ; X exit(0) ; X case -1: X perror2("fork") ; X break ; X default: X close(active_socket) ; X wait_for_children() ; X } X } else { X handle_server_connection() ; X } X } X } while (loopflag) ; X} X X void handle_server_connection() X{ X /* open pipes to program, if requested */ X if (pipe_program != NULL) { X open_pipes(pipe_program) ; X } X /* enter IO loop */ X do_io() ; X /* connection is closed now */ X close(active_socket) ; X if (pipe_program) { X /* remove zombies */ X wait_for_children() ; X } X} X X void client(host, port, service_name) char *host ; int port ; char *service_name ; X{ X /* get connection */ X active_socket = create_client_socket(&host, port) ; X if (active_socket == -1) { X perror2("client socket") ; X exit(errno) ; X } else if (active_socket == -2) { X fprintf(stderr, "%s: unknown host %s\n", progname, host) ; X exit(13) ; X } X if (verboseflag) { X fprintf(stderr, "connected to %s port %d", host, port) ; X if (service_name) { X fprintf(stderr, " (%s)", service_name) ; X } X fprintf(stderr, "\n") ; X } X X /* open pipes to program if requested */ X if (pipe_program != NULL) { X open_pipes(pipe_program) ; X } X /* enter IO loop */ X do_io() ; X /* connection is closed now */ X close(active_socket) ; X} X X/*EOF*/ END_OF_FILE if test 6160 -ne `wc -c <'socket.c'`; then echo shar: \"'socket.c'\" unpacked with wrong size! fi # end of 'socket.c' fi if test -f 'socketp.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'socketp.c'\" else echo shar: Extracting \"'socketp.c'\" \(2633 characters\) sed "s/^X//" >'socketp.c' <<'END_OF_FILE' X/* X X$Header: socketp.c[1.4] Sun Aug 9 03:48:03 1992 nickel@cs.tu-berlin.de proposed $ This file is part of socket(1). Copyright (C) 1992 by Juergen Nickelsen Please read the file COPYRIGHT for further details. X X*/ X X#include X#include X#include X#include X#include X#include X#include "globals.h" X X/* X * create a server socket on PORT accepting QUEUE_LENGTH connections X */ int create_server_socket(port, queue_length) int port ; int queue_length ; X{ X struct sockaddr_in sa ; X int s; X X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { X return -1 ; X } X X bzero((char *) &sa, sizeof(sa)) ; X sa.sin_family = AF_INET ; X sa.sin_addr.s_addr = htonl(INADDR_ANY) ; X sa.sin_port = htons(port) ; X X if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { X return -1 ; X } X if (listen(s, 1) < 0) { X return -1 ; X } X X return s ; X} X X X/* create a client socket connected to PORT on HOSTNAME */ int create_client_socket(hostname, port) char **hostname ; int port ; X{ X struct sockaddr_in sa ; X struct hostent *hp ; X int a, s ; X long addr ; X X X bzero(&sa, sizeof(sa)) ; X if ((addr = inet_addr(*hostname)) != -1) { X /* is Internet addr in octet notation */ X bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */ X sa.sin_family = AF_INET ; X } else { X /* do we know the host's address? */ X if ((hp = gethostbyname(*hostname)) == NULL) { X return -2 ; X } X *hostname = hp->h_name ; X bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; X sa.sin_family = hp->h_addrtype ; X } X X sa.sin_port = htons((u_short) port) ; X X if ((s = socket(sa.sin_family, SOCK_STREAM, 0)) < 0) { /* get socket */ X return -1 ; X } X if (connect(s, &sa, sizeof(sa)) < 0) { /* connect */ X close(s) ; X return -1 ; X } X return s ; X} X X/* return the port number for service NAME_OR_NUMBER. If NAME is non-null, X * the name is the service is written there. X */ int resolve_service(name_or_number, protocol, name) char *name_or_number ; char *protocol ; char **name ; X{ X struct servent *servent ; X int port ; X X if (is_number(name_or_number)) { X port = atoi(name_or_number) ; X if (name != NULL) { X servent = getservbyport(htons(port), "tcp") ; X if (servent != NULL) { X *name = servent->s_name ; X } else { X *name = NULL ; X } X } X return port ; X } else { X servent = getservbyname(name_or_number, "tcp") ; X if (servent == NULL) { X return -1 ; X } X if (name != NULL) { X *name = servent->s_name ; X } X return ntohs(servent->s_port) ; X } X} X X/*EOF*/ END_OF_FILE if test 2633 -ne `wc -c <'socketp.c'`; then echo shar: \"'socketp.c'\" unpacked with wrong size! fi # end of 'socketp.c' fi if test -f 'utils.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'utils.c'\" else echo shar: Extracting \"'utils.c'\" \(4989 characters\) sed "s/^X//" >'utils.c' <<'END_OF_FILE' X/* X X$Header: utils.c[1.14] Wed Sep 9 16:34:03 1992 nickel@cs.tu-berlin.de proposed $ This file is part of socket(1). Copyright (C) 1992 by Juergen Nickelsen Please read the file COPYRIGHT for further details. X X*/ X X#ifdef sgi X#define _BSD_SIGNALS X#define SIG_HANDLER_RET int X#else /* !sgi */ X#define SIG_HANDLER_RET void X#endif X X#include X#include X#include X#include X#include X#include X#ifdef ISC X#define WNOHANG 1 X#else X#include X#endif X#include "globals.h" X X X/* Signal handler, print message and exit */ SIG_HANDLER_RET exitsig(sig) int sig ; X{ X if (sig != SIGUSR1) { X fprintf(stderr, "\n%s occured, exiting\n", sys_siglist[sig]) ; X } X exit(-sig) ; X} X X/* Give usage message */ void usage() X{ X static char ustring[] = X "Usage: %s [-bclqrvw] [-p prog] [-s | host] port\n" ; X X fprintf(stderr, ustring, progname) ; X} X X/* perror with progname */ void perror2(s) char *s ; X{ X fprintf(stderr, "%s: ", progname) ; X perror(s) ; X} X X/* is s a number? */ int is_number(s) char *s ; X{ X while (*s) { X if (*s < '0' || *s > '9') { X return 0 ; X } X s++ ; X } X return 1 ; X} X X/* set up signal handling. All except TSTP, CONT, CLD, and QUIT X * are caught with exitsig(). */ init_signals() X{ X int i ; X#ifdef SIG_SETMASK /* only with BSD signals */ X static struct sigvec svec = { exitsig, ~0, 0 } ; X#endif X X initialize_siglist() ; /* shamelessly stolen from BASH */ X X for (i = 0; i < NSIG; i++) { X switch (i) { X#ifdef SIGTSTP X case SIGTSTP: X case SIGTTOU: X case SIGTTIN: X case SIGSTOP: X case SIGCONT: X continue ; X#endif X#if !defined (SIGCHLD) && defined (SIGCLD) X#define SIGCHLD SIGCLD X#endif X#ifdef SIGCHLD X case SIGCHLD: X continue ; X#endif X#ifdef SIGWINCH X case SIGWINCH: /* it is ridiculous to exit on WINCH */ X continue ; X#endif X case SIGQUIT: /* if the user wants a core dump, */ X continue ; /* they can have it. */ X default: X#ifdef SIG_SETMASK X sigvec(i, &svec, NULL) ; X#else X signal(i, exitsig) ; X#endif X } X } X} X X/* connect stdin with prog's stdout/stderr and stdout X * with prog's stdin. */ void open_pipes(prog) char *prog ; X{ X int from_cld[2] ; /* from child process */ X int to_cld[2] ; /* to child process */ X X /* create pipes */ X if (pipe(from_cld) == -1) { X perror2("pipe") ; X exit(errno) ; X } X if (pipe(to_cld) == -1) { X perror2("pipe") ; X exit(errno) ; X } X X /* for child process */ X switch (fork()) { X case 0: /* this is the child process */ X /* connect stdin to pipe */ X close(0) ; X close(to_cld[1]) ; X dup2(to_cld[0], 0) ; X close(to_cld[0]) ; X /* connect stdout to pipe */ X close(1) ; X close(from_cld[0]) ; X dup2(from_cld[1], 1) ; X /* connect stderr to pipe */ X close(2) ; X dup2(from_cld[1], 2) ; X close(from_cld[1]) ; X /* call program via sh */ X execl("/bin/sh", "sh", "-c", prog, NULL) ; X perror2("exec /bin/sh") ; X /* terminate parent silently */ X kill(getppid(), SIGUSR1) ; X exit(255) ; X case -1: X perror2("fork") ; /* fork failed */ X exit(errno) ; X default: /* parent process */ X /* connect stderr to pipe */ X close(0) ; X close(from_cld[1]) ; X dup2(from_cld[0], 0) ; X close(from_cld[0]) ; X /* connect stderr to pipe */ X close(1) ; X close(to_cld[0]) ; X dup2(to_cld[1], 1) ; X close(to_cld[1]) ; X } X} X X/* remove zombie child processes */ void wait_for_children() X{ X int wret, status ; X#ifndef ISC X struct rusage rusage ; X#endif X X /* Just do a wait, forget result */ X#ifndef ISC X while ((wret = wait3(&status, WNOHANG, &rusage)) > 0) ; X#else X while ((wret = waitpid(-1, &status, WNOHANG)) > 0) ; X#endif X} X X/* expand LF characters to CRLF and adjust *sizep */ void add_crs(from, to, sizep) char *from, *to ; /* *from is copied to *to */ int *sizep ; X{ X int countdown ; /* counter */ X X countdown = *sizep ; X while (countdown) { X if (*from == '\n') { X *to++ = '\r' ; X (*sizep)++ ; X } X *to++ = *from++ ; X countdown-- ; X } X} X X/* strip CR characters from buffer and adjust *sizep */ void strip_crs(from, to, sizep) char *from, *to ; /* *from is copied to *to */ int *sizep ; X{ X X int countdown ; /* counter */ X X countdown = *sizep ; X while (countdown) { X if (*from == '\r') { X from++ ; X (*sizep)-- ; X } else { X *to++ = *from++ ; X } X countdown-- ; X } X} X X#define NULL_DEVICE "/dev/null" X X/* put yourself in the background */ void background() X{ X int child_pid ; /* PID of child process */ X int nulldev_fd ; /* file descriptor for null device */ X X child_pid = fork() ; X switch (child_pid) { X case -1: X perror2("fork") ; X exit(1) ; X case 0: X#ifdef NOSETSID X ioctl(0, TIOCNOTTY, 0) ; X#else X setsid() ; X#endif X chdir("/") ; X if ((nulldev_fd = open(NULL_DEVICE, O_RDWR, 0)) != -1) { X int i ; X X for (i = 0; i < 3; i++) { X if (isatty(i)) { X dup2(nulldev_fd, i) ; X } X } X close(nulldev_fd) ; X } X break ; X default: X exit(0) ; X } X} END_OF_FILE if test 4989 -ne `wc -c <'utils.c'`; then echo shar: \"'utils.c'\" unpacked with wrong size! fi # end of 'utils.c' fi echo shar: End of shell archive. exit 0