home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i083: A "shell" for CU, Kermit, etc.
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: bsmith@csuchico.EDU (Bennett Smith)
- Posting-number: Volume 15, Issue 83
- Archive-name: cu-shell
-
- This program attempts to solve some of the problems with having kermit
- cu, and uucp sharing the same lines. It also keeps a log of all connections
- that are made. Access to costly resources such as phone lines may be
- restricted by way of a Call-sys file. It will not allow the use of cu or
- kermit directly, thus a user cannot specify a phone number.
-
- Hope this helps. Chico State University has been using it for about one
- month, and it seems to solve most of their problems. Have Fun.
-
- Bennett (bsmith@csuchico.EDU)
-
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # Makefile
- # call.c
- # call.1L
- # Call-sys
- export PATH; PATH=/bin:$PATH
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- # Copyright (c) 1988 Cascade Research
- # All Rights Reserved
- #
- # THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF CASCADE RESEARCH
- # The copyright notice above does not evidence any actual or
- # intended publication of such source code
- #
- # @(#)Makefile 1.2 */
- #
- # WHO MODIFICATION DATE DONE
- # --- ------------------------------------- ---------
- # cbs Creation of Makefile for call.c 12-Apr-88
-
- # Comment out if you don't have HonneyDANBER lockfiles.
- HDB = 1
-
- # Full path to file containing list of valid systems for call.
- CALLFILE = /usr/lib/uucp/Call-sys
-
- # Full path to call log file.
- LOGFILE = /usr/lib/uucp/Call-log
-
- # Sprintf string for pathname of lockfile.
- LOCKFILE = /usr/spool/locks/LCK..%s
-
- # Full path to kermit executable.
- KERMIT = /usr/local/bin/kermit
-
- # Full path to cu executable.
- CU = /usr/bin/cu
-
- # User and group id for uucp (used to chown the device back after call).
- UIDUUCP = 5
- GIDUUCP = 5
-
- # Mode of device for kermit and uucp/cu (used to chmod the device during call).
- MODKER = 00600
- MODUUCP = 00622
-
- DEFS = -DHDB=\"$(HDB)\" -DCALLFILE=\"$(CALLFILE)\" \
- -DLOGFILE=\"$(LOGFILE)\" -DLOCKFILE=\"$(LOCKFILE)\" \
- -DKERMIT=\"$(KERMIT)\" -DCU=\"$(CU)\" \
- -DUIDUUCP=\"$(UIDUUCP)\" -DGIDUUCP=\"$(GIDUUCP)\" \
- -DMODKER=\"$(MODKER)\" -DMODUUCP=\"$(MODUUCP)\"
-
- # Directory for call executable
- BINDIR = /usr/local/bin
-
- # Directory for call manual page ([nt]roff form)
- MANDIR = /usr/man/l_man/man1
-
- ############################################################################
-
- SRC = call.c
- OBJ = call.o
- MAN = call.1L
- CFLAGS = -O ${DEFS}
- LFLAGS =
- LINTFLAGS = ${DEFS}
- ROFF = psroff -man
- LP = remsh bugs rlp pluto
-
- call: $(OBJ)
- cc $(LFLAGS) $(OBJ) -o call
-
- man:
- $(ROFF) $(MAN)
- print:
- pr Makefile call.c | $(LP)
- $(ROFF) $(MAN) | $(LP)
- clean:
- -rm -f $(OBJ) call
-
- install:
- -cp call $(BINDIR)
- -cp Call-sys $(CALLFILE)
- -cp call.1 $(MANDIR)
- -chmod 4555 $(BINDIR)/call
- -chown root $(BINDIR)/call
- -chgrp bin $(BINDIR)/call
- -chmod 600 $(CALLFILE)
- -chown root $(CALLFILE)
- -chgrp bin $(CALLFILE)
- -chmod 444 $(MANDIR)/call.1
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'call.c'
- then
- echo shar: will not over-write existing file "'call.c'"
- else
- cat << \SHAR_EOF > 'call.c'
-
- /* Copyright (c) 1988 Cascade Research */
- /* All Rights Reserved */
-
- /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF CASCADE RESEARCH */
- /* The copyright notice above does not evidence any actual or */
- /* intended publication of such source code */
-
- /* @(#)call.c 1.2 */
-
- /* WHO MODIFICATION DATE DONE */
- /* --- ------------------------------------- --------- */
- /* cbs Initial creation of call.c program. 05-Apr-88 */
- /* cbs Added code for the -d option. 07-Apr-88 */
- /* cbs Added -l with no machine name to show 07-Apr-88 */
- /* entire contents of log file. */
- /* cbs Added code to set the HUPCL value for 12-Apr-88 */
- /* the device to be connected to. */
-
- /* Call allows the invocation of cu or kermit in a more */
- /* restrictive environment. It allows for the monitoring */
- /* of callers, and the duration of their connections to */
- /* various machines. Call gets a list of available */
- /* machines from the Call-devices file which is located */
- /* in the /usr/lib/uucp directory. The log file of all */
- /* actions is in /usr/adm/Call-log. */
-
- /* Call must run setuid(root). It respects the HDB type */
- /* lock files as well as the v7 ones. It will set the */
- /* permissions and ownerships of the appropriate device */
- /* for the duration of the call. */
-
- #include <fcntl.h>
- #include <termio.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <time.h>
-
- /* The following are the defaults. If you wish to make changes, do so */
- /* in the Makefile, not here. */
-
- #ifndef CALLFILE
- #define CALLFILE "/usr/lib/uucp/Call-sys"
- #endif
- #ifndef LOGFILE
- #define LOGFILE "/usr/lib/uucp/Call-log"
- #endif
- #ifndef LOCKFILE
- #define LOCKFILE "/usr/spool/locks/LCK..%s"
- #endif
- #ifndef KERMIT
- #define KERMIT "/usr/local/bin/kermit"
- #endif
- #ifndef CU
- #define CU "/usr/bin/cu"
- #endif
- #ifndef UIDUUCP
- #define UIDUUCP 5
- #endif
- #ifndef GIDUUCP
- #define GIDUUCP 5
- #endif
- #ifndef MODKER
- #define MODKER 00600
- #endif
- #ifndef MODUUCP
- #define MODUUCP 00622
- #endif
-
- struct calldev {
- char *name; /* name of system */
- char *dev; /* device attached to */
- char *baud; /* baud rate to connect at */
- char *mdmtype; /* modem type */
- char *telno; /* telephone number */
- struct calldev *next; /* pointer to next available device */
- };
-
- struct calldev *callhead, *callcur, *match, *getcall();
- char *pname, *getlogin(), typecall[50], whocall[50];
-
- struct termio *devparam;
- int fd;
-
- int errflg,kflg,cflg,lflg,sflg,dflg;
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- extern char *optarg;
- extern int optind,opterr;
- int c;
- char *callsys, cmd[100];
- FILE *cf, *fopen();
-
- devparam = (struct termio *)malloc(sizeof(struct termio));
-
- pname=(char *)malloc(sizeof(argv[0])+1);
- strcpy(pname,argv[0]);
- strcpy(typecall,"?????");
- strcpy(whocall,"?????");
- dflg=sflg=errflg=kflg=lflg=0;
- cflg=1;
-
- while ((c=getopt(argc,argv,"dckls"))!=EOF)
- switch (c) {
- case 'd': dflg++;
- break;
- case 'c': cflg++;
- if (kflg) kflg=0;
- break;
- case 'k': kflg++;
- if (cflg) cflg=0;
- break;
- case 'l': lflg++;
- break;
- case 's': sflg++;
- break;
- case '?': errflg++;
- }
-
- if (errflg || argc < 2) {
- fprintf(stderr,"usage: %s [-d] [-c|-k|-l] system | [-s]\n",pname);
- exit (2);
- }
-
- callsys = argv[optind];
-
- if ((cf=fopen(CALLFILE,"r"))==(FILE *)NULL) {
- fprintf(stderr,"%s: cannot open %s\n",pname,CALLFILE);
- exit (2);
- }
- callhead = getcall(cf); /* load the call structure from the CALLFILE */
-
- if (sflg) {
- strcpy(typecall,"SYSTEM LIST");
- for (callcur=callhead; callcur!=(struct calldev *)NULL; callcur=callcur->next)
- printf("%s\n",callcur->name);
- exit(0);
- }
-
- if (lflg && (optind==argc)) {
- sprintf(cmd,"/bin/cat %s 2>/dev/null",LOGFILE);
- system(cmd);
- exit(0);
- }
-
- match=(struct calldev *)NULL;
- for (callcur=callhead; callcur!=(struct calldev *)NULL; callcur=callcur->next)
- if (strcmp(callsys,callcur->name)==0) match=callcur;
- if (match==(struct calldev *)NULL) {
- if (!lflg)
- fprintf(stderr,"%s: %s is not a valid system\n",pname,callsys);
- else
- fprintf(stderr,"%s: must specify system for log viewing\n",pname);
- exit (2);
- }
- strcpy(whocall,match->name);
- if (!lflg) {
- exit (kflg?dokermit(match):docu(match));
- } else if (lflg)
- exit (showlog(match));
- exit(0);
- }
-
- /* showlog() - display the log for the specified match to CALLFILE */
-
- int showlog(where)
- struct calldev *where;
- {
- char cmd[100];
- sprintf(cmd,"/bin/grep %s %s 2>/dev/null",where->name,LOGFILE);
- system(cmd);
- return (0);
- }
-
- /* dokermit() - invoke KERMIT for the specified match to CALLFILE */
-
- int dokermit(where)
- struct calldev *where;
- {
- char line[35],rmlck[70];
-
- strcpy(typecall,"KERMIT");
- fprintf(stderr,"Calling with kermit\n");
- if(checklock(where->dev)==0) {
- sprintf(rmlck,"rm -f ");
- sprintf(line,LOCKFILE,where->dev);
- strcat(rmlck,line);
- strcat(rmlck," 2>&1 1>/dev/null");
- if (dflg)
- fprintf(stderr,"%s: removing invalid lock file [%s]\n",pname,line);
- system(rmlck);
- sprintf(line,"/dev/%s",where->dev);
- if (chown(line,getuid(),getgid())<0) {
- fprintf(stderr,"%s: cannot chown %s for kermit\n",pname,line);
- writelog("CHOWN FAILED");
- exit(2);
- }
- if (chmod(line,MODKER)<0) {
- fprintf(stderr,"%s: cannot chmod %s for kermit\n",pname,line);
- writelog("CHMOD FAILED");
- exit(2);
- }
- ioctl((fd=open(line,O_RDONLY)),devparam,TCGETA);
- devparam->c_cflag=devparam->c_cflag||HUPCL;
- ioctl(fd,devparam,TCSETA);
- close(fd);
- writelog("CONNECT");
- if (fork() == 0) {
- setuid(getuid());
- if (dflg)
- execlp(KERMIT,"kermit","-d","-l",line,"-b",where->baud,(char *)0);
- else
- execlp(KERMIT,"kermit","-l",line,"-b",where->baud,(char *)0);
- fprintf(stderr,"%s: cannot execute kermit\n",pname);
- exit(2);
- }
- wait((int *)0);
- writelog("DISCONNECT");
- if (chown(line,UIDUUCP,GIDUUCP)<0) {
- fprintf(stderr,"%s: cannot reset %s\n",pname,line);
- writelog("CHOWN FAILED");
- exit(2);
- }
- if (chmod(line,MODUUCP)<0) {
- fprintf(stderr,"%s: cannot reset %s\n",pname,line);
- writelog("CHMOD FAILED");
- exit(2);
- }
- return (0);
- } else {
- fprintf(stderr,"%s: line busy - try later\n",pname);
- return (1);
- }
- }
-
- /* docu() - invoke CU for the specified match to CALLFILE */
-
- int docu(where)
- struct calldev *where;
- {
- char line[35];
-
- strcpy(typecall,"CU");
- fprintf(stderr,"Calling with cu\n");
- if(checklock(where->dev)==0) {
- sprintf(line,LOCKFILE,where->dev);
- ioctl((fd=open(line,O_RDONLY)),devparam,TCGETA);
- devparam->c_cflag=devparam->c_cflag||HUPCL;
- ioctl(fd,devparam,TCSETA);
- close(fd);
- writelog("CONNECT");
- if (fork() == 0) {
- if (dflg)
- execlp(CU,"cu","-d",where->name,(char *)0); /* run cu */
- else
- execlp(CU,"cu",where->name,(char *)0); /* run cu */
- fprintf(stderr,"%s: cannot execute cu\n",pname);
- exit(2);
- }
- wait((int *)0); /* wait for cu to disconnect */
- writelog("DISCONNECT");
- return (0);
- } else {
- fprintf(stderr,"%s: line busy - try later\n",pname);
- return (1);
- }
- }
-
- /* writelog() - write a line into the call logfile */
-
- int writelog(desc)
- char *desc;
- {
- FILE *fopen(), *log;
- long clock;
-
- if ((log=fopen(LOGFILE,"a"))==(FILE *)NULL) {
- fprintf(stderr,"%s: could not open log file\n",pname);
- exit(2);
- }
- clock=time((long *)0);
- if (dflg)
- fprintf(stderr,"%-10s %-10s %-10s %-20s %s",whocall,getlogin(),typecall,desc,asctime(localtime(&clock)));
- fprintf(log,"%-10s %-10s %-10s %-20s %s",whocall,getlogin(),typecall,desc,asctime(localtime(&clock)));
- fclose(log);
- return (0);
- }
-
- /* checklock() - check that the device which we want is available */
- /* return: 0=ok 1=device in use */
-
- int checklock(dev)
- char *dev;
- {
- char lckfile[100];
- int lkpid;
- FILE *lf;
-
- sprintf(lckfile,LOCKFILE,dev);
- if (access(lckfile,0)==0) { /* check if lockfile exists */
- #ifdef HDB
- if ((lf=fopen(lckfile,"r"))!=(FILE *)NULL) {
- fscanf(lf,"%d",&lkpid);
- if (kill(lkpid,0)==(-1)) /* check if line avail */
- return(0); /* pid is invalid, line avail */
- else return (1); /* valid pid, line busy */
- }
- #endif
- return(1);
- }
- return(0);
- }
-
- /* getcall() - read and parse the CALLFILE and setup the linked list */
- /* of allowed connections */
-
- struct calldev *getcall(cf)
- FILE *cf;
- {
- struct calldev *head, *cur;
- int c;
- char tname[25], tdev[25], tbaud[25], tmdmtype[25], ttelno[25];
-
- cur=head=(struct calldev *)NULL;
- while ((c=fgetc(cf))!=EOF)
- if (c=='#' || c==' ' || c=='\t' || c=='\n')
- while ((c=fgetc(cf))!='\n');
- else {
- ungetc(c,cf);
- fscanf(cf,"%s %s %s %s %s\n",tname,tdev,tbaud,tmdmtype,ttelno);
- if (cur==(struct calldev *)NULL) {
- head=(struct calldev *)malloc(sizeof(struct calldev));
- cur=head;
- } else {
- cur->next=(struct calldev *)malloc(sizeof(struct calldev));
- cur=cur->next;
- }
- cur->name=(char *)malloc(strlen(tname)+1);
- strcpy(cur->name,tname);
- cur->dev=(char *)malloc(strlen(tdev)+1);
- strcpy(cur->dev,tdev);
- cur->baud=(char *)malloc(strlen(tbaud)+1);
- strcpy(cur->baud,tbaud);
- cur->mdmtype=(char *)malloc(strlen(tmdmtype)+1);
- strcpy(cur->mdmtype,tmdmtype);
- cur->telno=(char *)malloc(strlen(ttelno)+1);
- strcpy(cur->telno,ttelno);
- }
- fclose(cf);
- return (head);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'call.1L'
- then
- echo shar: will not over-write existing file "'call.1L'"
- else
- cat << \SHAR_EOF > 'call.1L'
- .TH CALL 1L local
- .SH NAME
- call \- make a connection to an available machine via cu or kermit
- .SH SYNOPSIS
- .B call "[ -d ]" "[ -ck ]" "system"
- .P
- .B call "[ -d ]" -l "[ system ]"
- .P
- .B call "[ -d ]" "-s"
- .SH DESCRIPTION
- .I Call
- provides a means to connect to another UNIX system, a terminal, or possibly
- a non-UNIX system. It restricts access to the actual calling programs,
- .I cu
- and
- .IR kermit ,
- in an effort to limit access to expensive resources (ie. phone lines).
- .I Call
- maintains a log of all activity on the available lines. It will only allow
- access to
- .I cu
- with a valid system name, thus preventing direct dialing.
- .P
- .I Call
- allows for the peaceful co-existence of
- .I kermit
- with
- .I cu
- and
- .IR uucp ,
- because it will not execute
- .I kermit
- unless the specified line is currently available. It respects HoneyDANBER
- lockfiles with the pid of the active process, and the older lockfiles which
- simply indicate that the line is used.
- .TP
- .B call
- accepts the following options and arguments.
- .TP
- -c
- Invokes
- .B call
- with
- .I cu
- as the calling program. This is the default calling program, if neither
- .B "-c"
- or
- .B "-k"
- is present.
- .TP
- -k
- Invokes
- .B call
- with
- .I kermit
- as the calling program. It will supply
- .I kermit
- with the device name and baud rate. Calling with
- .I kermit
- is not premitted over a dialed line. Only "direct" connections are
- supported with this option.
- .TP
- system
- A valid system name obtained from the
- .B /usr/lib/uucp/Call-sys
- file. To list the currently available system names, see the
- .B -s
- option below.
- .TP
- -d
- Turn on the debugging mode for the calling program. This is useful
- when connecting over an unreliable line since the progression of the
- connection may be monitored.
- .I Cu
- will display the debugging information on the screen whereas
- .I kermit
- will send all debugging information to the file
- .B debug.log
- in the current directory.
- .TP
- -s
- Display a list of available systems.
- .TP
- -l
- List the log file for the specified system name. If no system is
- specified, the entire log is displayed, sorted by machine and then
- by time.
- .SH FILES
- .P
- /usr/lib/uucp/Call-sys
- .P
- /usr/lib/uucp/Call-log
- /usr/spool/uucp/LCK..(tty-device)
- .SH SEE ALSO
- .P
- cu(1C), uucp(1C), kermit(1L)
- .SH DIAGNOSTICS
- .P
- Exit code is zero for normal exit, non-zero (various values) otherwise.
- .SH BUGS
- As yet, none have been reported.
- .SH AUTHORS
- .P
- Bennett Smith
- .br
- Jim Garlick
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'Call-sys'
- then
- echo shar: will not over-write existing file "'Call-sys'"
- else
- cat << \SHAR_EOF > 'Call-sys'
- # Connections contains a list of all valid connections for the call
- # program.
- #
- # Line syntax:
- # system \t device \t baud \t modemtype \t telno
- #
- # If an argument does not apply, use a dash '-' as a place holder for it.
- # There must be 5 arguments per line, and comments are NOT allowed to
- # follow the arguments. Comments are OK on other lines, and start with
- # a hatch '#' character.
- #
- # The system and device fields are always necessary, but the baud, modemtype,
- # and telno fields are only used by kermit.
- #
- # examples -
- # bugs tty106 9600 - -
- # bunky tty021 9600 - -
- #
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
- --
- Cascade Research | uucp: ihnp4!csun!csuchico!bsmith
- Bennett Smith, Software Engineer | voice: (916) 343-5731
-
-