home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / UUCPBB21 / uucpbb21.lzh / UUCPBB21 / uucico.c < prev    next >
Text File  |  1994-09-25  |  21KB  |  716 lines

  1. /*  uucico.c   This is the main UUCP communications program.
  2.     Copyright (C) 1990, 1993  Rick Adams and Bob Billson
  3.  
  4.     This file is part of the OS-9 UUCP package, UUCPbb.
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     The author of UUCPbb, Bob Billson, can be contacted at:
  21.     bob@kc2wz.bubble.org  or  uunet!kc2wz!bob  or  by snail mail:
  22.     21 Bates Way, Westfield, NJ 07090
  23. */
  24.  
  25. /*  usage: uucico [opts] -r | sys [sys...]  [opts]
  26.  
  27.          sys       -remote system to call as MASTER, e.g.
  28.                       uucico sys1 sys2   calls sys1 then sys2
  29.  
  30.     opts: -r       -run as SLAVE
  31.           -u       -do not run UUXQT at all
  32.           -a       -run UUXQT after each call, default is after all
  33.                       calls are completed
  34.           -iN      -wait N minutes between call retries
  35.           -tN      -try to call remote up to N times
  36.           -wN      -use window size of N
  37.           -xN      -set debug level to N (0-9), default is 0 (off)
  38.           -o       -orphan UUXQT
  39.           -pN      -run UUXQT at a priority of N
  40.           -q       -send no output to standard out
  41.           -l       -use RAM disk for temporary uulog
  42.           -z       -send debug output to screen if debug level is 1 to 5
  43.                       overrides -l
  44. */
  45.  
  46. #define MAIN
  47.  
  48. #include "uucp.h"
  49. #include "uucico.h"
  50. #ifdef _OSK
  51. #include <procid.h>
  52. #endif
  53. #include "getopt.h"
  54.  
  55. #define MAXTRIES    1        /* default number of attempts to call a system */
  56. #define LOGSIZE     80       /* size of uulog pathname */
  57.  
  58. extern QQ unsigned myuid;
  59.  
  60. int interrupt();
  61.  
  62.  
  63. main (argc, argv)
  64. int argc; 
  65. char *argv[];
  66. {
  67.      int option, priority, naptime, numsys, maxtries;
  68.      char **syslist;
  69.      register char **sysptr;
  70.      flag runuuxqt, aftercall, gotmail, orphan;
  71.  
  72.      /* defaults */
  73.      logopen   = FALSE;                         /* log file open flag       */
  74.      debuglvl  = 0;                             /* debug off                */
  75.      role      = MASTER;                        /* default role is master   */
  76.      ramdisk   = FALSE;                         /* don't use RAM disk yet   */
  77.      quiet     = FALSE;                         /* print to stdout --BGP    */
  78.      logflag   = TRUE;                          /* write /DD/LOG/uulog --TK */
  79.      maxtries  = MAXTRIES;                      /* max call attempts        */
  80.      aftercall = TRUE;                     /* run UUXQT when calls are done */
  81.      naptime   = NAPTIME;                       /* sleep between retries    */
  82.      runuuxqt  = TRUE;                          /* run UUXQT                */
  83.      gotmail   = FALSE;                         /* no mail received         */
  84.      orphan    = FALSE;                         /* run UUXQT as an orphan   */
  85.      priority  = 128;                           /* normal priority          */
  86.  
  87. #ifndef _OSK
  88.      pflinit();                                    /* longs will be printed */
  89. #endif
  90.  
  91.      intercept (interrupt);                      /* deal with interruptions */
  92.      asetuid (0);
  93.  
  94.      if (getparam() == FALSE)
  95.           exit (0);
  96.  
  97.      if ((logdir = getenv ("LOGDIR")) != NULL)
  98.           logdir = strdup (logdir);
  99.      else
  100.           logdir = LOGDIR;
  101.  
  102.      if ((spooldir = getdirs ("spooldir")) == NULL)
  103.           fatal ("spooldir not in Parameters");
  104.  
  105.      if ((pubdir = getdirs ("pubdir")) == NULL)
  106.           fatal ("pubdir not in Parameters");
  107.  
  108.      syslist = sysptr = (char **) malloc (argc * sizeof (char));
  109.  
  110.      if (syslist == NULL)
  111.           fatal ("can't malloc() syslist");
  112.  
  113.      /* no system to call yet */
  114.      *syslist = NULL;
  115.      numsys = 0;
  116.  
  117.      while (((option = getopt (argc, argv, "arqx:uw:lop:i:t:zS:s:m:?"))
  118.              != NONOPT)  ||  optarg != NULL)
  119.        {
  120.           int scnt = 0;
  121.  
  122.           switch (option)
  123.             {
  124.                case 'S':                 /* DEBUG--run under different name */
  125. #ifdef DEBUG
  126.                     strcpy (nodename, optarg);
  127. #endif
  128.                     break;
  129.  
  130.                case 'a':                      /* run UUXQT after each call */
  131.                     aftercall = FALSE;
  132.                     break;
  133.  
  134.                case 'r':                             /* run as slave */
  135.                     role = SLAVE; 
  136.                     break;
  137.  
  138.                case 'x':                              /* debug level */
  139.                     debuglvl = atoi (optarg);
  140.  
  141.                     if (debuglvl > 5)
  142.                          ramdisk = TRUE;
  143.                     break;
  144.  
  145.                case 'u':                               /* do not run UUXQT */
  146.                     runuuxqt = FALSE;
  147.                     break;
  148.  
  149.                case 'w':               /* override 'parameters' window size */
  150.                     rec_window = atoi (optarg);
  151.  
  152.                     if (rec_window > 7)
  153.                          rec_window = 7;
  154.                     else if (rec_window <= 0)
  155.                          rec_window = 1;
  156.                     break;
  157.  
  158.                case 'm':               /* segment size */
  159.                     while (ssiz[scnt][0] != '\0')
  160.                       {
  161.                          if (strcmp (optarg, ssiz[scnt]) == 0)
  162.                            {
  163.                               rec_segment = scnt;
  164.                               break;
  165.                            }
  166.                          scnt++;
  167.                       }
  168.  
  169.                     if (ssiz[scnt][0] == '\0')
  170.                          fprintf (stderr, "Don't understand '%s'\n", optarg);
  171.                     break;
  172.  
  173.                case 'l':             /* use RAM disk for temporary log file */
  174.                     ramdisk = TRUE;
  175.                     break;
  176.  
  177.                case 'o':                    /* orphan UUXQT when it is run */
  178.                     orphan = TRUE;
  179.                     break;
  180.  
  181.                case 'p':                 /* run UUXQT at different priority */
  182.                     priority = atoi (optarg);
  183.  
  184.                     if (priority < 1)
  185.                          priority = 0;                       /* no change */
  186.                     else if (priority > MAXPRIORITY)
  187.                          priority = MAXPRIORITY;
  188.  
  189.                     break;
  190.  
  191.                case 'i':            /* minutes to wait between call retries */
  192.                     naptime = atoi (optarg);
  193.                     break;
  194.  
  195.                case 'q':                         /* no output to the screen */
  196.                     quiet = TRUE;
  197.                     break;
  198.  
  199.                case 't':                /* max call retries for each remote */
  200.                     maxtries = atoi (optarg);
  201.                     break;
  202.  
  203.                case 'z':           /* log to screen if debug level >0 && <6 */
  204.                     logflag = FALSE;
  205.                     break;
  206.  
  207.                case 's':                            /* remote's name */
  208.                case NONOPT:
  209.                     *sysptr++ = optarg;
  210.                     *sysptr = NULL;
  211.                     ++numsys;
  212.                     break;
  213.  
  214.                case '?':                        /* help/bad option */
  215.                     usage();
  216.             }
  217.        }
  218.  
  219.      if (!logflag  &&  debuglvl > 5)
  220.           logflag = ramdisk = TRUE;
  221.  
  222.      /* can't orphan UUXQT unless it is run after all calls are completed */
  223.      if (aftercall == FALSE)
  224.           orphan = FALSE;
  225.  
  226.      asetuid (0);                            /* we run as the superuser */
  227.  
  228.      if (role == MASTER)
  229.        {
  230.           if (*syslist == NULL)
  231.                fatal ("no remote to call!");
  232.  
  233.           if (numsys == 1)
  234.                aftercall = TRUE;
  235.  
  236.           if (!quiet)
  237.                putchar ('\n');
  238.  
  239.           /* poll each system we were given */
  240.           for (sysptr = syslist; *sysptr; sysptr++)
  241.              {
  242.                int call;
  243.                flag done;
  244.  
  245.                normal_end = done = uuxflag = offhook = FALSE;
  246.                call = 1;
  247.                openlog();
  248.  
  249.                /* get remote's info */
  250.                strncpy (sysname, *sysptr, sizeof (sysname));
  251.                sysname[sizeof (sysname) - 1] = '\0';
  252.  
  253.                /* initial sender is 'uucp' */
  254.                strcpy (sender, "uucp");
  255.  
  256.                /* skip bad system */
  257.                if (SystemIsOK (TRUE) == FALSE)
  258.                     continue;
  259.  
  260.                if (!quiet)
  261.                     printf ("polling '%s' ... %d attempt%s will be made\n",
  262.                                  sysname, maxtries, maxtries > 1 ? "s" : "");
  263.  
  264.                /* loop until success or we retry out */
  265.                while (!normal_end  &&  !done)
  266.                  {
  267.                     if (!quiet)
  268.                       {
  269.                          fputs ("      calling...  ", stdout);
  270.  
  271.                          if (!logflag)
  272.                               putchar ('\n');
  273.  
  274.                          fflush (stdout);
  275.                       }
  276.  
  277.                     role = MASTER;    /* make sure we are running as master */
  278.                     pollremote();
  279.                     closelog();
  280.  
  281.                     if (normal_end)
  282.                       {
  283.                          if (!quiet)
  284.                            {
  285.                               backspace (12);
  286.                               printf ("call successful after %2d %s\n",
  287.                                        call, call > 1 ? "tries": "try");
  288.                            }
  289.  
  290.                          if (uuxflag)
  291.                               gotmail = TRUE;
  292.                       }
  293.                     else
  294.                       {
  295.                          if (!quiet)
  296.                            {
  297.                               backspace (12);
  298.                               printf ("call %d failed -- ", call);
  299.                            }
  300.  
  301.                          if (call < maxtries)
  302.                            {
  303.                               if (!quiet)
  304.                                 {
  305.                                    printf ("will try again in %d minute%s...",
  306.                                            naptime, naptime > 1 ? "s" : "");
  307.  
  308.                                    fflush (stdout);
  309.                                 }
  310.                               ++call;
  311.                               sleep (naptime * 60);
  312.  
  313.                               if (!quiet)
  314.                                    backspace (52);
  315.                            }
  316.                          else
  317.                            {
  318.                               if (!quiet)
  319.                                    printf ("'%s' is unavailable\n", sysname);
  320.  
  321.                               done = TRUE;
  322.                            }
  323.                       }
  324.                  }
  325.  
  326.                /* run UUXQT after each call? */
  327.                if (!aftercall)
  328.                     if (runuuxqt &&  uuxflag)
  329.                          do_uuxqt (priority, FALSE, sysname, orphan);
  330.  
  331.                if (!quiet)
  332.                     putchar ('\n');
  333.             } 
  334.           free (syslist);
  335.  
  336.           if (!quiet)
  337.                printf ("call%s completed\n\n", numsys > 1 ? "s" : "");
  338.  
  339.           /* all calls are made, run UUXQT on every remote? */
  340.           if (aftercall)
  341.                if (runuuxqt && gotmail)
  342.                     if (numsys > 1)
  343.                          do_uuxqt (priority, TRUE, "ALL", orphan);
  344.                     else
  345.                          do_uuxqt (priority, TRUE, sysname, orphan);
  346.        }
  347.  
  348.      /* running as slave, take the call */
  349.      else
  350.        {
  351.           /* initial sender is 'uucp' */
  352.           strcpy (sender, "uucp");
  353.           normal_end = uuxflag = offhook = FALSE;
  354.           openlog();
  355.           pollremote();
  356.           closelog();                                           /* TK */
  357.  
  358.           /* run UUXQT? */
  359.           if (runuuxqt  &&  uuxflag)
  360.                do_uuxqt (priority, TRUE, sysname, orphan);
  361.        }
  362. }
  363.  
  364.  
  365.  
  366. int pollremote()
  367. {
  368.      register flag state;
  369.  
  370.      *device = '\0';                             /* no port yet */
  371.  
  372.      /* set up for longjmp() abort from a low level function --REB */
  373.      state = setjmp (env);
  374.  
  375.      /* run this loop "forever" */
  376.      for (;;)
  377.       {
  378.           switch (state)
  379.             {
  380.                case INITIAL:
  381.                     state = role == MASTER ? callup() : openport();
  382.                     break;
  383.  
  384.                case MOPEN:
  385.                     state = mopenuucp();
  386.                     break;
  387.  
  388.                case SOPEN:
  389.                     endflag = TRUE;
  390.                     time (&start_time);
  391.                     state = sopenuucp();
  392.                     break;
  393.  
  394.                case MS_SNDRCV:
  395.                     sprintf (fname, "%s/%s", spooldir, sysname);
  396.  
  397.                     /* can't open spool directory? */
  398.                     if (chdir (fname) == ERROR)
  399.                       {
  400.                          char tmp[128];
  401.  
  402.                          sprintf (tmp,
  403.                                   "pollremote: can't change to spool directory: %s",
  404.                                   fname);
  405.                          logerror (tmp);
  406.                          state = ABORT;
  407.                       }
  408.                     else
  409.                          state = gproto();
  410.                     break;
  411.  
  412.                case _END:
  413.                     state = role == MASTER ? mcloseuucp() : scloseuucp();
  414.                     break;
  415.             }
  416.  
  417.           if (state == ABORT  ||  state == FATAL)
  418.                break;
  419.        }
  420.      endcall();
  421. }
  422.  
  423.  
  424.  
  425. /* Try to connect for each applicable System file entry findmach() updates
  426.    the index.  Changed --REB */
  427.  
  428. int callup()
  429. {
  430.      int index = 0;
  431.      register flag state = INITIAL; 
  432.  
  433.      for (;;)
  434.           switch (state)
  435.             {
  436.                case INITIAL:
  437.                     state = findmach (&index);
  438.                     break;
  439.  
  440.                case OPENPORT:
  441.                     endflag = TRUE;
  442.                     state = openport();
  443.                     break;
  444.  
  445.                case PORTBUSY:
  446.                     if (!quiet)
  447.                          printf ("  %s is in use...aborting\n", device);
  448.  
  449.                     exit (NONSHARE);
  450.  
  451.                case MAKECALL:
  452.                     time (&start_time);
  453.                     state = connect (index);
  454.                     break;
  455.  
  456.                case OK:
  457.                     if (!quiet)
  458.                       {
  459.                          backspace (12);
  460.                          fputs ("connected...", stdout);
  461.                          fflush (stdout);
  462.                       }
  463.                     return (MOPEN);
  464.  
  465.                case BUSY:
  466.                case NOCARRIER:
  467.                     endcall();
  468.                     state = INITIAL;
  469.                     break;
  470.  
  471.                case NODIALTONE:
  472.                case NOANSWER:
  473.                case CHATERROR:
  474.                case ABORT:
  475.                     return (ABORT);
  476.  
  477.                case FATAL:
  478.                     state = INITIAL;
  479.                     break;
  480.             }
  481. }
  482.  
  483.  
  484.  
  485. int endcall()
  486. {
  487.      closeport();
  488.      time (&endtime);
  489.      *device = '\0';
  490.  
  491.      if (endflag)
  492.        {
  493.           if (offhook)
  494.                call_length = endtime - start_time;
  495.           else
  496.                call_length = 0L;
  497.  
  498.           fprintf (log, "%s %s %s Call complete (%ld seconds)%s\n",
  499.                         sender, sysname, gtime(), call_length,
  500.                         normal_end ? "" : " --FAILED");
  501.  
  502.           offhook = endflag = FALSE;
  503.        }
  504. }
  505.  
  506.  
  507.  
  508. /* Open the log file.  It should be unbuffered.  If we don't want the RAM
  509.    RAM disk or can't open the log file on it use the directory logdir --REB
  510.  
  511.    Altered logging for UUCP.  If ramdisk is TRUE then /R0 logging.  If logflag
  512.    is TRUE then HD logging else log to screen. */
  513.  
  514. void openlog()
  515. {
  516.      static flag firstpass = TRUE;
  517.      static char lname[LOGSIZE];
  518.  
  519.      if (logopen)
  520.           return;
  521.  
  522.      if (firstpass)
  523.        {
  524.           if (ramdisk)
  525.                strcat (strcpy (lname, RAMDISK), "/uulog");
  526.           else
  527.                if (logflag)
  528.                     strcat (strcpy (lname, logdir), "/uulog");
  529.           firstpass = FALSE;
  530.        }
  531.  
  532.      /* if log file RAM or HD logging...
  533.         otherwise, use screen logging-- standard error path */
  534.  
  535.      if (logflag)
  536.        {
  537.           if ((log = fopen (lname, "a")) != NULL)
  538.             {
  539.                setbuf (log, NULL);
  540.                logopen = TRUE;
  541.                return;
  542.             }
  543.           else
  544.                quiet = TRUE;
  545.        }
  546.  
  547.      /* send everything to bit bucket if quiet or can't open log file */
  548.      if (quiet)
  549.           log = fopen (NIL, "w");
  550.      else
  551.           log = stderr;
  552.  
  553.      logopen = TRUE;
  554.      return;
  555. }
  556.  
  557.  
  558.  
  559. /* Close log file, if we used RAM disk, move the temporary to the permanent
  560.    uulog file --REB
  561.    modified for "new" logging procedure! -TK */
  562.  
  563. void closelog()
  564. {
  565.      if (logopen)
  566.        {
  567.           fclose (log);
  568.           logopen = FALSE;
  569.  
  570.           if (ramdisk)
  571.             {
  572.  
  573.                strcat (strcpy (temp, RAMDISK), "/uulog");
  574.                strcat (strcpy (fname, logdir), "/uulog");
  575.                fileapnd (temp, fname, TRUE);
  576.                unlink (temp);
  577.             }
  578.        }
  579. }
  580.  
  581.  
  582.  
  583. /* If the orphan flag is set, UUXQT will be forked without a parent.  This
  584.    should prevent the modem kill switch from killing off UUXQT on some
  585.    systems. */
  586.  
  587. int do_uuxqt (priority, chain, remotef, orphan)
  588. int priority;
  589. flag chain;
  590. char *remotef;
  591. flag orphan;
  592. {
  593.      sprintf (temp, "%suuxqt -%sx%d %s%s%s",
  594.                     orphan ? "shell (" : "",
  595.                     (orphan || quiet) ? "q" : "",
  596.                     debuglvl, remotef,
  597.                     orphan ? "&) >>" : "",
  598.                     orphan ? NIL : "");
  599.  
  600.      if (debuglvl > 0)
  601.           puts (temp);
  602.  
  603.      if (chain)
  604.        {
  605.           /* do we want to run at a different priority? */
  606.           if (priority)
  607.                setpr (getpid(), priority);
  608.           dochcmd (temp);
  609.        }
  610.      else
  611.           docmd (temp);
  612. }
  613.  
  614.  
  615.  
  616. /* remove line by backspace-space-backspace over it */
  617.  
  618. int backspace (howmany)
  619. int howmany;
  620. {
  621.      register int i;
  622.  
  623.      for (i = 0; i < howmany; ++i)
  624.           fputs ("\b \b", stdout);
  625. }
  626.  
  627.  
  628.  
  629. /* log errors to file */
  630.  
  631. int logerror (msg)
  632. char *msg;
  633. {
  634.      fprintf (log, "%s %s %s ERROR--%s\n", sender, sysname, gtime(), msg);
  635. }
  636.  
  637.  
  638.  
  639. /* log normal events */
  640.  
  641. int lognorm (msg)
  642. char *msg;
  643. {
  644.      fprintf (log, "%s %s %s %s\n", sender, sysname, gtime(), msg);
  645. }
  646.  
  647.  
  648.  
  649. int fatal (msg)
  650. char *msg;
  651. {
  652.      fprintf (stderr, "\nuucico: %s", msg);
  653.  
  654.      if (errno != 0)
  655.           fprintf (stderr, "...error %d", errno);
  656.      putc ('\n', stderr);
  657.      exit (0);
  658. }
  659.  
  660.  
  661.  
  662. /* clean up before we exit on keyboard abort -- REB */
  663.  
  664. int interrupt (sig)
  665. int sig;
  666. {
  667.      fprintf (log, "\n%s %s %s OPERATOR ABORTED\n", sender,sysname,gtime() );
  668.      endcall();
  669.      exit (sig);
  670. }
  671.  
  672.  
  673.  
  674. int usage()
  675. {
  676.      char *strdetab();
  677.      static char *help1[] = {
  678.           "usage: uucico [opts] -r | sys [sys...]  [opts]",
  679.           " ",
  680.           "\tsys      -remote system to call as MASTER (default)",
  681.           " ",
  682.           "opts: -r\t -run as SLAVE",
  683.           "\t-u\t -do not run UUXQT at all",
  684.           "\t-a\t -run UUXQT after each call, default is after all calls",
  685.           "\t\t\tare completed",
  686.           "\t-l\t -use RAM disk for temporary \"uulog\"",
  687.           "\t-o\t -orphan UUXQT",
  688.           "\t-pN\t-fork UUXQT with a priority of N",
  689.           "\t-q\t -run quietly",
  690.           "\t-wN\t-use window size of N",
  691.           "\t-xN\t-set debug level to N (0-9), default is 0 (off), if N > 5",
  692.           "\t\t\tadditional info sent to 'uulog'",
  693.           "\t-z\t -send log info to screen if debug level is 1 to 5,",
  694.           "\t\t\toverrides -l",
  695. #ifdef DEBUG
  696.           "\t-S<node> -run as <node> instead of using Parameters file nodename",
  697. #endif
  698.           NULL
  699.         };
  700.      static char *help2 =
  701.         "\t-iN\t-wait N minutes between call retries, default is "; 
  702.      static char *help3 = 
  703.         "\t-tN\t-try to call remote up to N times, default is ";
  704.      register char **hlp;
  705.  
  706.      for (hlp = help1;  *hlp != NULL;  ++hlp)
  707.           fprintf (stderr, "%s\n", strdetab (strcpy (temp, *hlp), 6));
  708.  
  709.      fprintf (stderr, "%s%d\n", strdetab (strcpy (temp, help2), 6), NAPTIME);
  710.      fprintf (stderr, "%s%d\n", strdetab (strcpy (temp, help3), 6), MAXTRIES);
  711.      fprintf (stderr, "\nv%s (%s) This is free software released under the GNU General Public\n",
  712.                       version, VERDATE);
  713.      fputs ("License.  Please send suggestions/bug reports to:  bob@kc2wz.bubble.org\n", stderr);
  714.      exit (0);
  715. }
  716.