home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume15 / cu-shell < prev    next >
Text File  |  1988-07-06  |  16KB  |  627 lines

  1. Subject:  v15i083:  A "shell" for CU, Kermit, etc.
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: bsmith@csuchico.EDU (Bennett Smith)
  7. Posting-number: Volume 15, Issue 83
  8. Archive-name: cu-shell
  9.  
  10. This program attempts to solve some of the problems with having kermit
  11. cu, and uucp sharing the same lines.  It also keeps a log of all connections
  12. that are made.  Access to costly resources such as phone lines may be
  13. restricted by way of a Call-sys file.  It will not allow the use of cu or
  14. kermit directly, thus a user cannot specify a phone number.
  15.  
  16. Hope this helps.  Chico State University has been using it for about one
  17. month, and it seems to solve most of their problems.  Have Fun.
  18.  
  19.                 Bennett (bsmith@csuchico.EDU)
  20.  
  21. # This is a shell archive, meaning:
  22. # 1. Remove everything above the #! /bin/sh line.
  23. # 2. Save the resulting text in a file.
  24. # 3. Execute the file with /bin/sh (not csh) to create the files:
  25. #    Makefile
  26. #    call.c
  27. #    call.1L
  28. #    Call-sys
  29. export PATH; PATH=/bin:$PATH
  30. if test -f 'Makefile'
  31. then
  32.     echo shar: will not over-write existing file "'Makefile'"
  33. else
  34. cat << \SHAR_EOF > 'Makefile'
  35. #      Copyright (c) 1988 Cascade Research
  36. #       All Rights Reserved              
  37. #      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF CASCADE RESEARCH
  38. #     The copyright notice above does not evidence any actual or     
  39. #     intended publication of such source code                       
  40. #     @(#)Makefile    1.2 */
  41. #  WHO    MODIFICATION                DATE DONE
  42. #  ---  -------------------------------------   ---------
  43. #  cbs    Creation of Makefile for call.c        12-Apr-88
  44.  
  45. # Comment out if you don't have HonneyDANBER lockfiles.
  46. HDB        = 1
  47.  
  48. # Full path to file containing list of valid systems for call.
  49. CALLFILE    = /usr/lib/uucp/Call-sys
  50.  
  51. # Full path to call log file.
  52. LOGFILE        = /usr/lib/uucp/Call-log
  53.  
  54. # Sprintf string for pathname of lockfile.
  55. LOCKFILE    = /usr/spool/locks/LCK..%s
  56.  
  57. # Full path to kermit executable.
  58. KERMIT        = /usr/local/bin/kermit
  59.  
  60. # Full path to cu executable.
  61. CU        = /usr/bin/cu
  62.  
  63. # User and group id for uucp (used to chown the device back after call).
  64. UIDUUCP        = 5
  65. GIDUUCP        = 5
  66.  
  67. # Mode of device for kermit and uucp/cu (used to chmod the device during call). 
  68. MODKER        = 00600
  69. MODUUCP        = 00622
  70.  
  71. DEFS        = -DHDB=\"$(HDB)\" -DCALLFILE=\"$(CALLFILE)\" \
  72.           -DLOGFILE=\"$(LOGFILE)\" -DLOCKFILE=\"$(LOCKFILE)\" \
  73.           -DKERMIT=\"$(KERMIT)\" -DCU=\"$(CU)\" \
  74.           -DUIDUUCP=\"$(UIDUUCP)\" -DGIDUUCP=\"$(GIDUUCP)\" \
  75.           -DMODKER=\"$(MODKER)\" -DMODUUCP=\"$(MODUUCP)\"
  76.  
  77. # Directory for call executable
  78. BINDIR        = /usr/local/bin
  79.  
  80. # Directory for call manual page ([nt]roff form)
  81. MANDIR        = /usr/man/l_man/man1
  82.  
  83. ############################################################################
  84.  
  85. SRC        = call.c
  86. OBJ        = call.o
  87. MAN        = call.1L
  88. CFLAGS        = -O ${DEFS}
  89. LFLAGS        =
  90. LINTFLAGS    = ${DEFS}
  91. ROFF        = psroff -man
  92. LP        = remsh bugs rlp pluto
  93.  
  94. call:        $(OBJ)
  95.         cc $(LFLAGS) $(OBJ) -o call
  96.  
  97. man:
  98.         $(ROFF) $(MAN)
  99. print:
  100.         pr Makefile call.c | $(LP)
  101.         $(ROFF) $(MAN) | $(LP)
  102. clean:    
  103.         -rm -f $(OBJ) call
  104.  
  105. install:
  106.         -cp call $(BINDIR)
  107.         -cp Call-sys $(CALLFILE)
  108.         -cp call.1 $(MANDIR)
  109.         -chmod 4555 $(BINDIR)/call
  110.         -chown root $(BINDIR)/call
  111.         -chgrp bin $(BINDIR)/call
  112.         -chmod 600 $(CALLFILE)
  113.         -chown root $(CALLFILE)
  114.         -chgrp bin $(CALLFILE)
  115.         -chmod 444 $(MANDIR)/call.1
  116. SHAR_EOF
  117. fi # end of overwriting check
  118. if test -f 'call.c'
  119. then
  120.     echo shar: will not over-write existing file "'call.c'"
  121. else
  122. cat << \SHAR_EOF > 'call.c'
  123.  
  124. /*     Copyright (c) 1988 Cascade Research */
  125. /*      All Rights Reserved               */
  126.  
  127. /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF CASCADE RESEARCH */
  128. /*    The copyright notice above does not evidence any actual or      */
  129. /*    intended publication of such source code                        */
  130.  
  131. /*    @(#)call.c    1.2 */
  132.  
  133. /* WHO    MODIFICATION                DATE DONE */
  134. /* ---  -------------------------------------   --------- */
  135. /* cbs    Initial creation of call.c program.    05-Apr-88 */
  136. /* cbs    Added code for the -d option.        07-Apr-88 */
  137. /* cbs    Added -l with no machine name to show    07-Apr-88 */
  138. /*    entire contents of log file.              */
  139. /* cbs    Added code to set the HUPCL value for    12-Apr-88 */
  140. /*    the device to be connected to.              */
  141.  
  142. /* Call allows the invocation of cu or kermit in a more   */
  143. /* restrictive environment.  It allows for the monitoring */
  144. /* of callers, and the duration of their connections to   */
  145. /* various machines.  Call gets a list of available       */
  146. /* machines from the Call-devices file which is located   */
  147. /* in the /usr/lib/uucp directory.  The log file of all   */
  148. /* actions is in /usr/adm/Call-log.                       */
  149.  
  150. /* Call must run setuid(root).  It respects the HDB type  */
  151. /* lock files as well as the v7 ones.  It will set the    */
  152. /* permissions and ownerships of the appropriate device   */
  153. /* for the duration of the call.                          */
  154.  
  155. #include <fcntl.h>
  156. #include <termio.h>
  157. #include <stdio.h>
  158. #include <ctype.h>
  159. #include <string.h>
  160. #include <time.h>
  161.  
  162. /* The following are the defaults.  If you wish to make changes, do so */
  163. /* in the Makefile, not here.                           */
  164.  
  165. #ifndef CALLFILE
  166. #define    CALLFILE    "/usr/lib/uucp/Call-sys"
  167. #endif
  168. #ifndef LOGFILE
  169. #define LOGFILE        "/usr/lib/uucp/Call-log"
  170. #endif
  171. #ifndef LOCKFILE
  172. #define LOCKFILE    "/usr/spool/locks/LCK..%s"
  173. #endif
  174. #ifndef KERMIT
  175. #define KERMIT        "/usr/local/bin/kermit"
  176. #endif
  177. #ifndef CU
  178. #define CU        "/usr/bin/cu"
  179. #endif
  180. #ifndef UIDUUCP
  181. #define UIDUUCP    5
  182. #endif
  183. #ifndef GIDUUCP
  184. #define GIDUUCP    5
  185. #endif
  186. #ifndef MODKER
  187. #define MODKER    00600
  188. #endif
  189. #ifndef MODUUCP
  190. #define MODUUCP 00622
  191. #endif
  192.  
  193. struct calldev {
  194.     char *name;        /* name of system */
  195.     char *dev;        /* device attached to */
  196.     char *baud;        /* baud rate to connect at */
  197.     char *mdmtype;        /* modem type */
  198.     char *telno;        /* telephone number */
  199.     struct calldev *next;    /* pointer to next available device */
  200. };
  201.  
  202. struct calldev *callhead, *callcur, *match, *getcall();
  203. char *pname, *getlogin(), typecall[50], whocall[50];
  204.  
  205. struct termio *devparam;
  206. int fd;
  207.  
  208. int errflg,kflg,cflg,lflg,sflg,dflg;
  209.  
  210. main(argc,argv)
  211. int argc;
  212. char *argv[];
  213. {
  214.     extern char *optarg;
  215.     extern int optind,opterr;
  216.     int c;
  217.     char *callsys, cmd[100];
  218.     FILE *cf, *fopen();
  219.  
  220.     devparam = (struct termio *)malloc(sizeof(struct termio));
  221.  
  222.     pname=(char *)malloc(sizeof(argv[0])+1);
  223.     strcpy(pname,argv[0]);
  224.     strcpy(typecall,"?????");
  225.     strcpy(whocall,"?????");
  226.     dflg=sflg=errflg=kflg=lflg=0;
  227.     cflg=1;
  228.  
  229.     while ((c=getopt(argc,argv,"dckls"))!=EOF)
  230.         switch (c) {
  231.             case 'd':    dflg++;
  232.                     break;    
  233.             case 'c':    cflg++;
  234.                     if (kflg) kflg=0;
  235.                     break;
  236.             case 'k':    kflg++;
  237.                     if (cflg) cflg=0;
  238.                     break;
  239.             case 'l':    lflg++;
  240.                     break;
  241.             case 's':    sflg++;
  242.                     break;
  243.             case '?':    errflg++;
  244.         }
  245.  
  246.     if (errflg || argc < 2) {
  247.         fprintf(stderr,"usage: %s [-d] [-c|-k|-l] system | [-s]\n",pname);
  248.         exit (2);
  249.     }
  250.  
  251.     callsys = argv[optind];
  252.         
  253.     if ((cf=fopen(CALLFILE,"r"))==(FILE *)NULL) {
  254.         fprintf(stderr,"%s: cannot open %s\n",pname,CALLFILE);
  255.         exit (2);
  256.     }
  257.     callhead = getcall(cf);    /* load the call structure from the CALLFILE */
  258.  
  259.     if (sflg) {
  260.         strcpy(typecall,"SYSTEM LIST");
  261.         for (callcur=callhead; callcur!=(struct calldev *)NULL; callcur=callcur->next)
  262.             printf("%s\n",callcur->name);  
  263.         exit(0);
  264.     }
  265.  
  266.     if (lflg && (optind==argc)) {
  267.         sprintf(cmd,"/bin/cat %s 2>/dev/null",LOGFILE);
  268.         system(cmd);
  269.         exit(0);
  270.     }
  271.  
  272.     match=(struct calldev *)NULL;
  273.     for (callcur=callhead; callcur!=(struct calldev *)NULL; callcur=callcur->next)
  274.         if (strcmp(callsys,callcur->name)==0) match=callcur;
  275.     if (match==(struct calldev *)NULL) {
  276.         if (!lflg) 
  277.             fprintf(stderr,"%s: %s is not a valid system\n",pname,callsys);
  278.         else
  279.             fprintf(stderr,"%s: must specify system for log viewing\n",pname);
  280.         exit (2);
  281.     }
  282.     strcpy(whocall,match->name);
  283.     if (!lflg) {
  284.         exit (kflg?dokermit(match):docu(match));
  285.     } else if (lflg)
  286.         exit (showlog(match));
  287.     exit(0);
  288. }
  289.  
  290. /* showlog() - display the log for the specified match to CALLFILE */
  291.  
  292. int showlog(where)
  293. struct calldev *where;
  294. {
  295.     char cmd[100];
  296.     sprintf(cmd,"/bin/grep %s %s 2>/dev/null",where->name,LOGFILE);
  297.     system(cmd);
  298.     return (0);
  299. }
  300.  
  301. /* dokermit() - invoke KERMIT for the specified match to CALLFILE */
  302.  
  303. int dokermit(where)
  304. struct calldev *where;
  305. {
  306.     char line[35],rmlck[70];
  307.  
  308.     strcpy(typecall,"KERMIT");
  309.     fprintf(stderr,"Calling with kermit\n");
  310.     if(checklock(where->dev)==0) {
  311.         sprintf(rmlck,"rm -f ");
  312.         sprintf(line,LOCKFILE,where->dev);
  313.         strcat(rmlck,line);
  314.         strcat(rmlck," 2>&1 1>/dev/null");
  315.         if (dflg)
  316.             fprintf(stderr,"%s: removing invalid lock file [%s]\n",pname,line);
  317.         system(rmlck);
  318.         sprintf(line,"/dev/%s",where->dev);
  319.         if (chown(line,getuid(),getgid())<0) {
  320.             fprintf(stderr,"%s: cannot chown %s for kermit\n",pname,line);
  321.             writelog("CHOWN FAILED");
  322.             exit(2);
  323.         }
  324.         if (chmod(line,MODKER)<0) {
  325.             fprintf(stderr,"%s: cannot chmod %s for kermit\n",pname,line);
  326.             writelog("CHMOD FAILED");
  327.             exit(2);
  328.         }
  329.         ioctl((fd=open(line,O_RDONLY)),devparam,TCGETA);
  330.         devparam->c_cflag=devparam->c_cflag||HUPCL;
  331.         ioctl(fd,devparam,TCSETA);
  332.         close(fd);
  333.         writelog("CONNECT");
  334.         if (fork() == 0) {
  335.             setuid(getuid());
  336.             if (dflg)
  337.                 execlp(KERMIT,"kermit","-d","-l",line,"-b",where->baud,(char *)0);
  338.             else
  339.                 execlp(KERMIT,"kermit","-l",line,"-b",where->baud,(char *)0);
  340.             fprintf(stderr,"%s: cannot execute kermit\n",pname);
  341.             exit(2);
  342.         }
  343.         wait((int *)0);
  344.         writelog("DISCONNECT");
  345.         if (chown(line,UIDUUCP,GIDUUCP)<0) {
  346.             fprintf(stderr,"%s: cannot reset %s\n",pname,line);
  347.             writelog("CHOWN FAILED");
  348.             exit(2);
  349.         }
  350.         if (chmod(line,MODUUCP)<0) {
  351.             fprintf(stderr,"%s: cannot reset %s\n",pname,line);
  352.             writelog("CHMOD FAILED");
  353.             exit(2);
  354.         }
  355.         return (0);
  356.     } else {
  357.         fprintf(stderr,"%s: line busy - try later\n",pname);
  358.         return (1);
  359.     }
  360. }
  361.  
  362. /* docu() - invoke CU for the specified match to CALLFILE */
  363.  
  364. int docu(where)
  365. struct calldev *where;
  366. {
  367.     char line[35];
  368.  
  369.     strcpy(typecall,"CU");
  370.     fprintf(stderr,"Calling with cu\n");
  371.     if(checklock(where->dev)==0) {
  372.         sprintf(line,LOCKFILE,where->dev);
  373.         ioctl((fd=open(line,O_RDONLY)),devparam,TCGETA);
  374.         devparam->c_cflag=devparam->c_cflag||HUPCL;
  375.         ioctl(fd,devparam,TCSETA);
  376.         close(fd);
  377.         writelog("CONNECT");
  378.         if (fork() == 0) {
  379.             if (dflg)
  380.                 execlp(CU,"cu","-d",where->name,(char *)0); /* run cu */
  381.             else
  382.                 execlp(CU,"cu",where->name,(char *)0); /* run cu */
  383.             fprintf(stderr,"%s: cannot execute cu\n",pname);
  384.             exit(2);
  385.         }
  386.         wait((int *)0); /* wait for cu to disconnect */
  387.         writelog("DISCONNECT");
  388.         return (0);
  389.     } else {
  390.         fprintf(stderr,"%s: line busy - try later\n",pname);
  391.         return (1);
  392.     }
  393. }
  394.  
  395. /* writelog() - write a line into the call logfile */
  396.  
  397. int writelog(desc)
  398. char *desc;
  399. {
  400.     FILE *fopen(), *log;
  401.     long clock;
  402.     
  403.     if ((log=fopen(LOGFILE,"a"))==(FILE *)NULL) {
  404.         fprintf(stderr,"%s: could not open log file\n",pname);
  405.         exit(2);
  406.     }
  407.     clock=time((long *)0);
  408.     if (dflg)
  409.         fprintf(stderr,"%-10s %-10s %-10s %-20s %s",whocall,getlogin(),typecall,desc,asctime(localtime(&clock)));
  410.     fprintf(log,"%-10s %-10s %-10s %-20s %s",whocall,getlogin(),typecall,desc,asctime(localtime(&clock)));
  411.     fclose(log);
  412.     return (0);
  413. }
  414.  
  415. /* checklock() - check that the device which we want is available */
  416. /*               return: 0=ok 1=device in use                     */
  417.  
  418. int checklock(dev)
  419. char *dev;
  420. {
  421.     char lckfile[100];
  422.     int lkpid;
  423.     FILE *lf;
  424.  
  425.     sprintf(lckfile,LOCKFILE,dev);
  426.     if (access(lckfile,0)==0) { /* check if lockfile exists */
  427. #ifdef HDB
  428.         if ((lf=fopen(lckfile,"r"))!=(FILE *)NULL) {
  429.             fscanf(lf,"%d",&lkpid);
  430.             if (kill(lkpid,0)==(-1))  /* check if line avail */
  431.                 return(0); /* pid is invalid, line avail */
  432.             else return (1); /* valid pid, line busy */
  433.         }
  434. #endif
  435.         return(1);    
  436.     }
  437.     return(0);
  438. }
  439.  
  440. /* getcall() - read and parse the CALLFILE and setup the linked list */
  441. /*             of allowed connections                                */
  442.  
  443. struct calldev *getcall(cf)
  444. FILE *cf;
  445. {
  446.     struct calldev *head, *cur;
  447.     int c; 
  448.     char tname[25], tdev[25], tbaud[25], tmdmtype[25], ttelno[25];
  449.  
  450.     cur=head=(struct calldev *)NULL;
  451.     while ((c=fgetc(cf))!=EOF)
  452.         if (c=='#' || c==' ' || c=='\t' || c=='\n')
  453.             while ((c=fgetc(cf))!='\n');
  454.         else {
  455.             ungetc(c,cf);
  456.             fscanf(cf,"%s %s %s %s %s\n",tname,tdev,tbaud,tmdmtype,ttelno);
  457.             if (cur==(struct calldev *)NULL) {
  458.                 head=(struct calldev *)malloc(sizeof(struct calldev));
  459.                 cur=head;
  460.             } else {
  461.                 cur->next=(struct calldev *)malloc(sizeof(struct calldev));
  462.                 cur=cur->next;
  463.             }
  464.             cur->name=(char *)malloc(strlen(tname)+1);
  465.             strcpy(cur->name,tname);
  466.             cur->dev=(char *)malloc(strlen(tdev)+1);
  467.             strcpy(cur->dev,tdev);
  468.             cur->baud=(char *)malloc(strlen(tbaud)+1);
  469.             strcpy(cur->baud,tbaud);
  470.             cur->mdmtype=(char *)malloc(strlen(tmdmtype)+1);
  471.             strcpy(cur->mdmtype,tmdmtype);
  472.             cur->telno=(char *)malloc(strlen(ttelno)+1);
  473.             strcpy(cur->telno,ttelno);
  474.         }
  475.     fclose(cf);
  476.     return (head);
  477. }
  478. SHAR_EOF
  479. fi # end of overwriting check
  480. if test -f 'call.1L'
  481. then
  482.     echo shar: will not over-write existing file "'call.1L'"
  483. else
  484. cat << \SHAR_EOF > 'call.1L'
  485. .TH CALL 1L local
  486. .SH NAME
  487. call \- make a connection to an available machine via cu or kermit
  488. .SH SYNOPSIS
  489. .B call "[ -d ]" "[ -ck ]" "system"
  490. .P
  491. .B call "[ -d ]" -l "[ system ]"
  492. .P
  493. .B call "[ -d ]" "-s"
  494. .SH DESCRIPTION
  495. .I Call
  496. provides a means to connect to another UNIX system, a terminal, or possibly
  497. a non-UNIX system.  It restricts access to the actual calling programs,
  498. .I cu
  499. and
  500. .IR kermit ,
  501. in an effort to limit access to expensive resources (ie. phone lines).
  502. .I Call
  503. maintains a log of all activity on the available lines.  It will only allow
  504. access to
  505. .I cu
  506. with a valid system name, thus preventing direct dialing.
  507. .P
  508. .I Call
  509. allows for the peaceful co-existence of
  510. .I kermit
  511. with 
  512. .I cu
  513. and
  514. .IR uucp ,
  515. because it will not execute
  516. .I kermit
  517. unless the specified line is currently available.  It respects HoneyDANBER
  518. lockfiles with the pid of the active process, and the older lockfiles which
  519. simply indicate that the line is used.
  520. .TP
  521. .B call
  522. accepts the following options and arguments.
  523. .TP
  524. -c
  525. Invokes
  526. .B call
  527. with
  528. .I cu
  529. as the calling program.  This is the default calling program, if neither
  530. .B "-c"
  531. or
  532. .B "-k"
  533. is present.
  534. .TP
  535. -k
  536. Invokes
  537. .B call
  538. with 
  539. .I kermit
  540. as the calling program.  It will supply
  541. .I kermit
  542. with the device name and baud rate.  Calling with
  543. .I kermit
  544. is not premitted over a dialed line.  Only "direct" connections are
  545. supported with this option.
  546. .TP
  547. system
  548. A valid system name obtained from the
  549. .B /usr/lib/uucp/Call-sys
  550. file.  To list the currently available system names, see the
  551. .B -s
  552. option below.
  553. .TP
  554. -d
  555. Turn on the debugging mode for the calling program.  This is useful
  556. when connecting over an unreliable line since the progression of the
  557. connection may be monitored.  
  558. .I Cu
  559. will display the debugging information on the screen whereas
  560. .I kermit
  561. will send all debugging information to the file
  562. .B debug.log
  563. in the current directory.
  564. .TP
  565. -s
  566. Display a list of available systems. 
  567. .TP
  568. -l
  569. List the log file for the specified system name.  If no system is
  570. specified, the entire log is displayed, sorted by machine and then
  571. by time.
  572. .SH FILES
  573. .P
  574. /usr/lib/uucp/Call-sys
  575. .P
  576. /usr/lib/uucp/Call-log
  577. /usr/spool/uucp/LCK..(tty-device)
  578. .SH SEE ALSO
  579. .P
  580. cu(1C), uucp(1C), kermit(1L)
  581. .SH DIAGNOSTICS
  582. .P
  583. Exit code is zero for normal exit, non-zero (various values) otherwise.
  584. .SH BUGS
  585. As yet, none have been reported.
  586. .SH AUTHORS
  587. .P
  588. Bennett Smith
  589. .br
  590. Jim Garlick
  591. SHAR_EOF
  592. fi # end of overwriting check
  593. if test -f 'Call-sys'
  594. then
  595.     echo shar: will not over-write existing file "'Call-sys'"
  596. else
  597. cat << \SHAR_EOF > 'Call-sys'
  598. # Connections contains a list of all valid connections for the call
  599. # program.
  600. #
  601. # Line syntax:
  602. #    system \t device \t baud \t modemtype \t telno
  603. #
  604. # If an argument does not apply, use a dash '-' as a place holder for it.
  605. # There must be 5 arguments per line, and comments are NOT allowed to
  606. # follow the arguments.  Comments are OK on other lines, and start with
  607. # a hatch '#' character.
  608. #
  609. # The system and device fields are always necessary, but the baud, modemtype,
  610. # and telno fields are only used by kermit.
  611. #
  612. # examples -
  613. #    bugs tty106 9600 - -
  614. #    bunky tty021 9600 - -
  615. #
  616. SHAR_EOF
  617. fi # end of overwriting check
  618. #    End of shell archive
  619. exit 0
  620. -- 
  621. Cascade Research                        | uucp:     ihnp4!csun!csuchico!bsmith
  622. Bennett Smith, Software Engineer        | voice:    (916) 343-5731
  623.  
  624.