home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-07 | 51.0 KB | 1,974 lines |
- 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
-
- <nickel@cs.tu-berlin.de>
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: BLURB CHANGES COPYRIGHT Dependencies INSTALL Makefile
- # README fingerd.sh globals.h io.c patchlevel.h rfinger.sh siglist.c
- # so_release.c socket.1 socket.c socketp.c utils.c
- # Wrapped by vixie@cognition.pa.dec.com on Wed Sep 9 11:28:43 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'BLURB' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'BLURB'\"
- else
- echo shar: Extracting \"'BLURB'\" \(879 characters\)
- sed "s/^X//" >'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 <nickel@cs.tu-berlin.de>
- 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 <nickel@cs.tu-berlin.de>
- 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 <nickel@cs.tu-berlin.de>
- 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 <nickel@cs.tu-berlin.de>
- Please read the file COPYRIGHT for further details.
- X
- X*/
- X
- X#define _BSD /* AIX *loves* this */
- X
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#ifdef ISC
- X#include <sys/bsdtypes.h>
- X#endif
- X#include <errno.h>
- X#include <stdio.h>
- 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 <nickel@cs.tu-berlin.de> 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 <stdio.h>
- X#include <signal.h>
- 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 <nickel@cs.tu-berlin.de>
- 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 <nickel@cs.tu-berlin.de>
- 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 <nickel@cs.tu-berlin.de>
- Please read the file COPYRIGHT for further details.
- X
- X*/
- X
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <errno.h>
- X#include <stdio.h>
- X#ifdef SEQUENT
- X#include <strings.h>
- X#else
- X#include <string.h>
- 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 <nickel@cs.tu-berlin.de>
- Please read the file COPYRIGHT for further details.
- X
- X*/
- X
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <sys/errno.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <stdio.h>
- 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 <nickel@cs.tu-berlin.de>
- 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 <stdio.h>
- X#include <signal.h>
- X#include <sys/wait.h>
- X#include <sys/time.h>
- X#include <fcntl.h>
- X#include <sys/ioctl.h>
- X#ifdef ISC
- X#define WNOHANG 1
- X#else
- X#include <sys/resource.h>
- 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
-