home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / UUPC11XS.ZIP / UUCP / UUXQT.C < prev   
C/C++ Source or Header  |  1992-11-25  |  50KB  |  1,422 lines

  1. /*
  2.       Program:    uuxqt.c              23 September 1991
  3.       Author:     Mitch Mitchell
  4.       Email:      mitch@harlie.lonestar.org
  5.  
  6.       This is a re-write of the (much cleaner) UUXQT.C originally
  7.       distributed with UUPC/Extended.  The modifications are
  8.       intended primarily to lay a foundation for support for the
  9.       more advanced features of UUX.
  10.  
  11.       Usage:      uuxqt -xDEBUG -sSYSTEM
  12.  
  13.       Last Revised: 26-Jan-1992
  14. */
  15.  
  16. /*--------------------------------------------------------------------*/
  17. /*                          RCS Information                           */
  18. /*--------------------------------------------------------------------*/
  19.  
  20. /*
  21.  *    $Header: E:\src\uupc\UUCP\RCS\UUXQT.C 1.5 1992/11/25 12:59:17 ahd Exp $
  22.  *
  23.  *    Revision history:
  24.  *    $Log: UUXQT.C $
  25.  * Revision 1.5  1992/11/25  12:59:17  ahd
  26.  * Change NUL to /dev/nul to prevent ImportPath() mangling.
  27.  *
  28.  * Revision 1.4  1992/11/23  03:56:06  ahd
  29.  * Selected fixes for use of generlized uux commands
  30.  *
  31.  * Revision 1.3  1992/11/19  03:03:33  ahd
  32.  * drop rcsid
  33.  *
  34.  * Revision 1.2  1992/11/19  03:03:09  ahd
  35.  * Revision 1.1  1992/11/15  20:16:50  ahd
  36.  * Initial revision
  37.  *
  38.  * Revision 1.1  1992/04/27  02:46:02  ahd
  39.  * Initial revision
  40.  *
  41.  */
  42.  
  43.  
  44. /*--------------------------------------------------------------------*/
  45. /*                        System include files                        */
  46. /*--------------------------------------------------------------------*/
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <ctype.h>
  52. #include <errno.h>
  53. #include <time.h>
  54. #include <fcntl.h>
  55. #include <process.h>
  56. #include <sys/types.h>
  57. #include <sys/stat.h>
  58. #include <io.h>
  59.  
  60. /*--------------------------------------------------------------------*/
  61. /*                    UUPC/extended include files                     */
  62. /*--------------------------------------------------------------------*/
  63.  
  64. #include "lib.h"
  65. #include "arpadate.h"
  66. #include "dater.h"
  67. #include "expath.h"
  68. #include "getopt.h"
  69. #include "getseq.h"
  70. #include "hlib.h"
  71. #include "hostable.h"
  72. #include "import.h"
  73. #include "lock.h"
  74. #include "logger.h"
  75. #include "pushpop.h"
  76. #include "readnext.h"
  77. #include "security.h"
  78. #include "timestmp.h"
  79. #include "usertabl.h"
  80.  
  81. currentfile();
  82.  
  83. /*--------------------------------------------------------------------*/
  84. /*                      Execution flag defines                        */
  85. /*--------------------------------------------------------------------*/
  86.  
  87. typedef enum {
  88.         X_OUTPUT,     /* 'O' return output to "outnode"       */
  89.         X_FAILED,     /* 'Z' send status if command failed    */
  90.         X_SUCCESS,    /* 'n' send status if command succeeded */
  91.         X_INPUT,      /* 'B' return command input on error    */
  92.         X_USEEXEC,    /* 'E' process command using exec(2)    */
  93.         X_STATFIL,    /* 'M' return status to file on remote  */
  94.  
  95.         S_CORRUPT,
  96.         S_EMPTY,
  97.         S_NOREAD,
  98.         S_NOWRITE,
  99.         S_STDIN,
  100.  
  101.         E_NORMAL,
  102.         E_NOACC,
  103.         E_SIGNAL,
  104.         E_STATUS,
  105.         E_NOEXE,
  106.         E_FAILED,
  107.  
  108.         UU_LAST,
  109.  
  110.         } UU_FLAGS;
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*                          Global Variables                          */
  114. /*--------------------------------------------------------------------*/
  115.  
  116. static char *spool_fmt = SPOOLFMT;
  117. static char *dataf_fmt = DATAFFMT;
  118. static char *send_cmd  = "S %s %s %s -%s %s 0666 %s\n";
  119.  
  120. /*--------------------------------------------------------------------*/
  121. /*                        Internal prototypes                         */
  122. /*--------------------------------------------------------------------*/
  123.  
  124. static void usage( void );
  125.  
  126. static boolean copylocal(const char *from, const char *to);
  127.  
  128. static boolean do_uuxqt( const char *sysname );
  129.  
  130. static void process( const char *fname, const char *remote );
  131.  
  132. char **create_environment(const char *logname,
  133.                           const char *requestor);
  134.  
  135. static void delete_environment( char **envp);
  136.  
  137. static boolean AppendData( const char *input, FILE* dataout);
  138.  
  139. static boolean do_copy( char *localfile,
  140.                        const char *rmtsystem,
  141.                        const char *remotefile,
  142.                        const char *requestor,
  143.                        const boolean success );
  144.  
  145. static void ReportResults(const int   status,
  146.                           const char *input,
  147.                                 char *output,
  148.                           const char *command,
  149.                           const char *job_id,
  150.                           const time_t jtime,
  151.                           const char *requestor,
  152.                           const char *outnode,
  153.                           const char *outname,
  154.                           const boolean xflag[],
  155.                           const char *statfil,
  156.                           const char *machine,
  157.                           const char *user);
  158.  
  159. static int shell(char *command,
  160.                  const char *inname,
  161.                  const char *outname,
  162.                  const char *remotename,
  163.                  boolean xflag[]);
  164.  
  165. static boolean MailStatus(char *tempfile,
  166.                           char *address,
  167.                           char *subject);
  168.  
  169. static boolean internal( char *command );
  170.  
  171. /*--------------------------------------------------------------------*/
  172. /*    m a i n                                                         */
  173. /*                                                                    */
  174. /*    Main program                                                    */
  175. /*--------------------------------------------------------------------*/
  176.  
  177. void main( int argc, char **argv)
  178. {
  179.    int c;
  180.    extern char *optarg;
  181.    extern int   optind;
  182.    char *sysname = "all";
  183.  
  184. /*--------------------------------------------------------------------*/
  185. /*     Report our version number and date/time compiled               */
  186. /*--------------------------------------------------------------------*/
  187.  
  188.    debuglevel = 1;
  189.    banner( argv );
  190.  
  191. #if defined(__CORE__)
  192.    copywrong = strdup(copyright);
  193.    checkref(copywrong);
  194. #endif
  195.  
  196. /*--------------------------------------------------------------------*/
  197. /*        Process our arguments                                       */
  198. /*--------------------------------------------------------------------*/
  199.  
  200.    while ((c = getopt(argc, argv, "s:x:")) !=  EOF)
  201.       switch(c) {
  202.  
  203.       case 's':
  204.          sysname = optarg;
  205.          break;
  206.  
  207.       case 'x':
  208.          debuglevel = atoi( optarg );
  209.          break;
  210.  
  211.       case '?':
  212.          usage();
  213.          exit(1);
  214.          break;
  215.  
  216.       default:
  217.          printmsg(0, "uuxqt - invalid option -%c", c);
  218.          usage();
  219.          exit(2);
  220.          break;
  221.    }
  222.  
  223.    if (optind != argc) {
  224.       fputs("Extra parameter(s) at end.\n", stderr);
  225.       usage();
  226.       exit(2);
  227.    }
  228.  
  229. /*--------------------------------------------------------------------*/
  230. /*                             Initialize                             */
  231. /*--------------------------------------------------------------------*/
  232.  
  233.    tzset();                      /* Set up time zone information  */
  234.  
  235.    if (!configure( B_UUXQT ))
  236.       exit(1);   /* system configuration failed */
  237.  
  238. /*--------------------------------------------------------------------*/
  239. /*                  Switch to the spooling directory                  */
  240. /*--------------------------------------------------------------------*/
  241.  
  242.    PushDir( E_spooldir );
  243.    atexit( PopDir );
  244.  
  245. /*--------------------------------------------------------------------*/
  246. /*                     Initialize logging file                        */
  247. /*--------------------------------------------------------------------*/
  248.  
  249.    openlog( NULL );
  250.  
  251.    checkuser( E_mailbox  );   /* Force User Table to initialize      */
  252.    checkreal( E_mailserv );   /* Force Host Table to initialize      */
  253.  
  254.    if (!LoadSecurity())
  255.    {
  256.       printmsg(0,"Unable to initialize security, see previous message");
  257.       exit(2);
  258.    } /* if (!LoadSecurity()) */
  259.  
  260. /*--------------------------------------------------------------------*/
  261. /*                Set up search path for our programs                 */
  262. /*--------------------------------------------------------------------*/
  263.  
  264.    if ( E_uuxqtpath != NULL )
  265.    {
  266.       char *p = malloc( 6 + strlen( E_uuxqtpath ));
  267.       checkref( p );
  268.              /*  ....+        5 characters plus \0 and length of path */
  269.       sprintf(p,"PATH=%s", E_uuxqtpath);
  270.  
  271.       if (putenv( p ))
  272.       {
  273.          printmsg(0,"Unable to set path \"%s\"", p);
  274.          panic();
  275.       } /* if (putenv( p )) */
  276.    } /* if ( E_uuxqtpath != NULL ) */
  277.  
  278. /*--------------------------------------------------------------------*/
  279. /*              Disable OS/2 undelete support if desired              */
  280. /*--------------------------------------------------------------------*/
  281.  
  282.    if ( !bflag[ F_UNDELETE ] )
  283.       putenv( "DELDIR=");
  284.  
  285. /*--------------------------------------------------------------------*/
  286. /*    Actually invoke the processing routine for the eXecute files    */
  287. /*--------------------------------------------------------------------*/
  288.  
  289.    do_uuxqt( sysname );
  290.    if( equal( sysname , "all" ) )
  291.        do_uuxqt( E_nodename );
  292.  
  293.    exit(0);
  294.  
  295. } /* main */
  296.  
  297. /*--------------------------------------------------------------------*/
  298. /*    d o _ u u x q t                                                 */
  299. /*                                                                    */
  300. /*    Processing incoming eXecute (X.*) files for a remote system     */
  301. /*--------------------------------------------------------------------*/
  302.  
  303. static boolean do_uuxqt( const char *sysname )
  304. {
  305.    struct HostTable *hostp;
  306.    static char uu_machine[] = UU_MACHINE "=";
  307.    char hostenv[sizeof uu_machine + 25 + 2];
  308.  
  309. /*--------------------------------------------------------------------*/
  310. /*                 Determine if we have a valid host                  */
  311. /*--------------------------------------------------------------------*/
  312.  
  313.    if( !equal( sysname , "all" ) ) {
  314.       if (equal( sysname , E_nodename ))
  315.           hostp = checkname( sysname );
  316.       else
  317.           hostp = checkreal( sysname );
  318.  
  319.       if (hostp  ==  BADHOST) {
  320.          printmsg(0, "Unknown host \"%s\".", sysname );
  321.          exit(1);
  322.       }
  323.  
  324.    } else
  325.         hostp = nexthost( TRUE );
  326.  
  327. /*--------------------------------------------------------------------*/
  328. /*             Outer loop for processing different hosts              */
  329. /*--------------------------------------------------------------------*/
  330.  
  331.    while  (hostp != BADHOST)
  332.    {
  333.       char fname[FILENAME_MAX];
  334.       boolean locked = FALSE;
  335.  
  336. /*--------------------------------------------------------------------*/
  337. /*                Initialize security for this remote                 */
  338. /*--------------------------------------------------------------------*/
  339.  
  340.       if ( !equal(sysname, E_nodename) &&
  341.            (securep = GetSecurity( hostp )) == NULL )
  342.          printmsg(0,"No security defined for \"%s\","
  343.                   " cannot process X.* files",
  344.                   hostp->hostname );
  345.       else {
  346.  
  347. /*--------------------------------------------------------------------*/
  348. /*              Set up environment for the machine name               */
  349. /*--------------------------------------------------------------------*/
  350.  
  351.       sprintf(hostenv,"%s%.25s", uu_machine, hostp->hostname);
  352.  
  353.       if (putenv( hostenv ))
  354.       {
  355.          printmsg(0,"Unable to set environment \"%s\"",hostenv);
  356.          panic();
  357.       }
  358.  
  359. /*--------------------------------------------------------------------*/
  360. /*           Inner loop for processing files from one host            */
  361. /*--------------------------------------------------------------------*/
  362.  
  363.          while (readnext(fname, hostp->hostname, "X", NULL) )
  364.             if ( locked || LockSystem( hostp->hostname , B_UUXQT ))
  365.             {
  366.                process( fname , hostp->hostname );
  367.                locked = TRUE;
  368.             }
  369.             else
  370.                break;               /* We didn't get the lock        */
  371.  
  372.          if ( locked )
  373.             UnlockSystem();
  374.  
  375.       } /* else if */
  376.  
  377. /*--------------------------------------------------------------------*/
  378. /*                        Restore environment                         */
  379. /*--------------------------------------------------------------------*/
  380.  
  381.       putenv( uu_machine );   /* Reset to empty string               */
  382.  
  383. /*--------------------------------------------------------------------*/
  384. /*    If processing all hosts, step to the next host in the queue     */
  385. /*--------------------------------------------------------------------*/
  386.  
  387.       if( equal(sysname,"all") )
  388.          hostp = nexthost( FALSE );
  389.       else
  390.          hostp = BADHOST;
  391.  
  392.    } /*while nexthost*/
  393.  
  394.    return FALSE;
  395.  
  396. } /* do_uuxqt */
  397.  
  398. /*--------------------------------------------------------------------*/
  399. /*    p r o c e s s                                                   */
  400. /*                                                                    */
  401. /*    Process a single execute file                                   */
  402. /*--------------------------------------------------------------------*/
  403.  
  404. static void process( const char *fname, const char *remote )
  405. {
  406.    char *command = NULL,
  407.         *input = NULL,
  408.         *output = NULL,
  409.         *job_id = NULL,
  410.         *token = NULL,
  411.         line[BUFSIZ];
  412.    char hostfile[FILENAME_MAX];
  413.    boolean skip = FALSE;
  414.    boolean reject = FALSE;
  415.    FILE *fxqt;
  416.    int   status;
  417.  
  418.    char *outnode = NULL;
  419.    char *outname = NULL;
  420.    char *user = NULL;
  421.    char *requestor = NULL;
  422.    char *statfil = NULL;
  423.    char *machine = NULL;
  424.    char   **envp;
  425.  
  426.    boolean xflag[UU_LAST - 1] = { 0 };
  427.    time_t jtime = time(NULL);
  428.  
  429. /*--------------------------------------------------------------------*/
  430. /*                         Open the X.* file                          */
  431. /*--------------------------------------------------------------------*/
  432.  
  433.    if ( (fxqt = FOPEN(fname, "r", BINARY)) == NULL) {  /* inbound X.* file */
  434.       printerr(fname);
  435.       return;
  436.    }
  437.    else
  438.       printmsg(2, "processing %s", fname);
  439.  
  440. /*--------------------------------------------------------------------*/
  441. /*                  Begin loop to read the X.* file                   */
  442. /*--------------------------------------------------------------------*/
  443.  
  444.    while (!skip & (fgets(line, BUFSIZ, fxqt) != NULL)) {
  445.       char *cp;
  446.  
  447.       if ( (cp = strchr(line, '\n')) != NULL )
  448.          *cp = '\0';
  449.  
  450.       printmsg(8, "input read: %s", line);
  451.  
  452. /*--------------------------------------------------------------------*/
  453. /*            Process the input line according to its type            */
  454. /*--------------------------------------------------------------------*/
  455.  
  456.       switch (line[0])
  457.       {
  458.  
  459.       case '#':
  460.          break;
  461.  
  462. /*--------------------------------------------------------------------*/
  463. /*                  User which submitted the command                  */
  464. /*--------------------------------------------------------------------*/
  465.  
  466.       case 'U':
  467.          strtok(line," \t\n");      /* Trim off leading "U"       */
  468.                                     /* Get the user name          */
  469.          if ( (cp = strtok(NULL," \t\n")) == NULL ) {
  470.             printmsg(0,"No user on U line in file \"%s\"", fname );
  471.          } else {
  472.              user = strdup(cp);
  473.              checkref(user);
  474.          };
  475.                                     /* Get the system name        */
  476.          if ( (cp = strtok(NULL," \t\n")) == NULL)
  477.          {                          /* Did we get a string?       */
  478.             printmsg(2,"No node on U line in file \"%s\"", fname );
  479.             cp = (char *) remote;
  480.          } else if (!equal(cp,remote)) {
  481.             printmsg(2,"Node on U line in file \"%s\" doesn't match remote",
  482.                      fname );
  483.             cp = (char * ) remote;
  484.          };
  485.          machine = newstr(cp);
  486.          break;
  487.  
  488. /*--------------------------------------------------------------------*/
  489. /*                       Input file for command                       */
  490. /*--------------------------------------------------------------------*/
  491.  
  492.       case 'I':
  493.          input = strdup( &line[2] );                     /* ahd   */
  494.          checkref(input);
  495.          if (!equal(remote, E_nodename))
  496.             if (!(equaln(input,"D.",2) || ValidateFile( input, ALLOW_READ)))
  497.             {
  498.                 reject = TRUE;
  499.                 xflag[S_NOREAD] = TRUE;
  500.             }
  501.          break;
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*                      Output file for command                       */
  505. /*--------------------------------------------------------------------*/
  506.  
  507.       case 'O':
  508.          strtok(line," \t\n");      /* Trim off leading "U"       */
  509.                                     /* Get the user name          */
  510.          if ( (cp = strtok(NULL," \t\n")) != NULL )
  511.          {
  512.              outname = strdup(cp);
  513.              checkref(outname);
  514.              xflag[X_OUTPUT] = TRUE;  /* return output to "outnode" */
  515.              if ( (cp = strtok(NULL," \t\n")) != NULL)
  516.              {                /* Did we get a string?                */
  517.                    outnode = strdup(cp);
  518.                    checkref(outnode);
  519.                    checkreal(outnode);
  520.              }
  521.              else if (!equal(remote, E_nodename))
  522.              {
  523.                 if (!(equaln(outname,"D.",2) || ValidateFile( outname, ALLOW_WRITE)))
  524.                 {
  525.                     reject = TRUE;
  526.                     xflag[S_NOWRITE] = TRUE;
  527.                 } /* if */
  528.              } /* else if (!equal(remote, E_nodename)) */
  529.          } /* if ( (cp = strtok(NULL," \t\n")) != NULL ) */
  530.          break;
  531.  
  532. /*--------------------------------------------------------------------*/
  533. /*                         Command to execute                         */
  534. /*--------------------------------------------------------------------*/
  535.  
  536.       case 'C':
  537.          command = strdup( &line[2] );                   /* ahd   */
  538.          checkref(command);                              /* ahd   */
  539.          break;
  540.  
  541. /*--------------------------------------------------------------------*/
  542. /*                      Job Id for status reporting                   */
  543. /*--------------------------------------------------------------------*/
  544.  
  545.       case 'J':
  546.          strtok(line," \t\n");      /* Trim off leading "J"       */
  547.                                     /* Get the job id             */
  548.          if ( (cp = strtok(NULL," \t\n")) == NULL )
  549.          {
  550.             printmsg(0,"No job id on J line in file \"%s\"", fname );
  551.             reject = TRUE;
  552.          }
  553.          else {
  554.             job_id = strdup( cp );
  555.             checkref( job_id );
  556.          } /* else */
  557.          break;
  558.  
  559. /*--------------------------------------------------------------------*/
  560. /*                 Check that a required file exists                  */
  561. /*--------------------------------------------------------------------*/
  562.  
  563.       case 'F':
  564.          token = strtok(&line[1]," ");
  565.          importpath(hostfile, token, remote);
  566.  
  567.          if ( access( hostfile, 0 ))   /* Does the host file exist?  */
  568.          {                             /* No --> Skip the file       */
  569.             printmsg(0,"Missing file %s (%s) for %s, command skipped",
  570.                      token, hostfile, fname);
  571.             skip = TRUE;
  572.          }
  573.  
  574.          break;
  575.  
  576. /*--------------------------------------------------------------------*/
  577. /*             Requestor name (overrides user name, above)            */
  578. /*--------------------------------------------------------------------*/
  579.  
  580.       case 'R':
  581.          strtok(line," \t\n");      /* Trim off leading "R"       */
  582.                                     /* Get the user name          */
  583.          if ( (cp = strtok(NULL," \t\n")) == NULL )
  584.             printmsg(0,"No requestor on R line in file \"%s\"", fname );
  585.          else {
  586.             requestor = strdup(cp);
  587.             checkref(requestor);
  588.          }
  589.          break;
  590.  
  591. /*--------------------------------------------------------------------*/
  592. /*        Status file name to return info to on remote node           */
  593. /*--------------------------------------------------------------------*/
  594.  
  595.       case 'M':
  596.          strtok(line," \t\n");      /* Trim off leading "M"           */
  597.                                     /* Get the file name              */
  598.          if ( (cp = strtok(NULL," \t\n")) != NULL ) {
  599.             statfil = strdup(cp);
  600.             checkref(statfil);
  601.             xflag[X_STATFIL] = TRUE;     /* return status to remote file   */
  602.          } else {
  603.             printmsg(0,"No file name on M line in file \"%s\"", fname);
  604.          }
  605.          break;
  606.  
  607. /*--------------------------------------------------------------------*/
  608. /*                            Flag fields                             */
  609. /*--------------------------------------------------------------------*/
  610.  
  611.       case 'Z': xflag[X_FAILED] = TRUE;   /* send status if command failed */
  612.          break;
  613.  
  614.       case 'N': xflag[X_FAILED] = FALSE;  /* send NO status if command failed */
  615.          break;
  616.  
  617.       case 'n': xflag[X_SUCCESS] = TRUE;  /* send status if command succeeded */
  618.          break;
  619.  
  620.       case 'z': xflag[X_SUCCESS] = FALSE; /* NO status if command succeeded */
  621.          break;
  622.  
  623.       case 'B': xflag[X_INPUT] = TRUE;    /* return command input on error */
  624.          break;
  625.  
  626.       case 'e': xflag[X_USEEXEC] = FALSE; /* process command using sh(1) */
  627.          break;
  628.  
  629.       case 'E': xflag[X_USEEXEC] = TRUE;  /* process command using exec(2) */
  630.          break;
  631.  
  632. /*--------------------------------------------------------------------*/
  633. /*                    Quietly ignore unknown fields                   */
  634. /*--------------------------------------------------------------------*/
  635.  
  636.       default :
  637.          break;
  638.  
  639.       } /* switch */
  640.    } /* while (!skip & (fgets(line, BUFSIZ, fxqt) != NULL)) */
  641.  
  642.    if ( fxqt != NULL )
  643.       fclose(fxqt);
  644.  
  645.  
  646.    if ((command == NULL) && !skip)
  647.    {
  648.       printmsg(0,"No command supplied for X.* file %s, skipped", fname);
  649.       reject = TRUE;
  650.    }
  651.  
  652. /*--------------------------------------------------------------------*/
  653. /*           We have the data for this command; process it            */
  654. /*--------------------------------------------------------------------*/
  655.  
  656.    if ( ! (skip || reject ))
  657.    {
  658.       if ( user == NULL )
  659.       {
  660.          user = strdup("uucp");    /* User if none given         */
  661.          checkref(user);
  662.       }
  663.  
  664.       if (requestor == NULL)
  665.       {
  666.          requestor = strdup(user);
  667.          checkref(requestor);
  668.       }
  669.  
  670.       if (input == NULL)
  671.          input = strdup("/dev/nul");
  672.  
  673.       if (output == NULL)
  674.          output = mktempname(NULL, "OUT");
  675.  
  676.       printmsg(equaln(command,RMAIL,5) ? 2 : 0,
  677.                "uuxqt: executing \"%s\" for user \"%s\" at  \"%s\"",
  678.                    command, user, machine);
  679.  
  680. /*--------------------------------------------------------------------*/
  681. /*             Create the environment and run the command             */
  682. /*--------------------------------------------------------------------*/
  683.  
  684.       envp = create_environment("uucp", requestor);
  685.       status = shell(command, input, output, remote, xflag );
  686.       delete_environment(envp);
  687.  
  688.       ReportResults( status, input, output, command, job_id,
  689.                      jtime, requestor, outnode, outname, xflag,
  690.                      statfil, machine, user);
  691.  
  692. /*--------------------------------------------------------------------*/
  693. /*                  Clean up files after the command                  */
  694. /*--------------------------------------------------------------------*/
  695.  
  696.       unlink(fname);       /* Already a local file name            */
  697.  
  698.       if (equaln(input,"D.",2))
  699.       {
  700.           importpath(hostfile, input, remote);
  701.           unlink(hostfile);
  702.       }
  703.  
  704.       if (xflag[X_OUTPUT])
  705.       {
  706.           importpath(hostfile, output, remote);
  707.           unlink(hostfile);
  708.       }
  709.  
  710.    }
  711.    else if (reject && !skip)
  712.         unlink(fname);       /* Already a local file name            */
  713.  
  714. /*--------------------------------------------------------------------*/
  715. /*              Free various temporary character strings              */
  716. /*--------------------------------------------------------------------*/
  717.  
  718.    if (command    != NULL) free(command);
  719.    if (input      != NULL) free(input);
  720.    if (job_id     != NULL) free(job_id);
  721.    if (outnode    != NULL) free(outnode);
  722.    if (output     != NULL) free(output);
  723.    if (requestor  != NULL) free(requestor);
  724.    if (statfil    != NULL) free(statfil);
  725.    if (user       != NULL) free(user);
  726.  
  727. } /* process */
  728.  
  729. /*--------------------------------------------------------------------*/
  730. /*    s h e l l                                                       */
  731. /*                                                                    */
  732. /*    Simulate a Unix command                                         */
  733. /*--------------------------------------------------------------------*/
  734.  
  735. static int shell(char *command,
  736.                  const char *inname,
  737.                  const char *outname,
  738.                  const char *remotename,
  739.                  boolean xflag[])
  740. {
  741.    char  *argv[50];
  742.    int    argc;
  743.    int    result = 0;
  744.    char   inlocal[FILENAME_MAX];
  745.    char   outlocal[FILENAME_MAX];
  746.    char   savecmd[BUFSIZ];
  747.  
  748.    if (xflag[X_USEEXEC])
  749.       printmsg(2, "exec(2) not supported, executing using spawn");
  750.  
  751.    strcpy( savecmd, command );
  752.    argc = getargs(command, argv);
  753.  
  754.    printmsg(2,"uux: command arg count = %d", argc);
  755.    if (debuglevel >= 2) {
  756.       char **argvp = argv;
  757.       int i = 0;
  758.       while (i < argc)
  759.          printmsg(2, "shell: argv[%d]=\"%s\"", i++, *argvp++);
  760.    }
  761.  
  762. /*--------------------------------------------------------------------*/
  763. /*    Verify we support the command, and get it's real name, if so    */
  764. /*--------------------------------------------------------------------*/
  765.  
  766.    if ( (!equal(remotename, E_nodename)) && (!ValidateCommand( argv[0] )) )
  767.    {
  768.       printmsg(0,"Command \"%s\" not allowed at this site", argv[0]);
  769.       xflag[E_NOEXE] = TRUE;
  770.       return 99;
  771.    }
  772.  
  773. /*--------------------------------------------------------------------*/
  774. /*                     Open files for processing                      */
  775. /*--------------------------------------------------------------------*/
  776.  
  777.    if (inname != NULL)
  778.    {
  779.       importpath(inlocal, inname, remotename);
  780.       printmsg(2, "shell: opening %s for input", inlocal);
  781.       if (freopen(inlocal, "rb", stdin) == NULL)
  782.       {
  783.          printmsg(0, "shell: couldn't open %s (%s), errno=%d.",
  784.             inname, inlocal, errno);
  785.          printerr(inlocal);
  786.          xflag[S_CORRUPT] = TRUE;
  787.          return -2;
  788.       }
  789.    }
  790.  
  791.    if (outname != NULL)
  792.    {
  793.       importpath(outlocal, outname, remotename);
  794.       printmsg(2, "shell: opening %s for output", outlocal);
  795.       if (freopen(outlocal, "wt", stdout) == NULL) {
  796.          printmsg(0, "shell: couldn't open %s (%s), errno=%d.",
  797.             outname, outlocal, errno);
  798.          printerr(outlocal);
  799.          if ( inname != NULL)
  800.             freopen("con", "rt", stdin);
  801.          xflag[S_NOWRITE] = TRUE;
  802.          return -2;
  803.       }
  804.    }
  805.  
  806. /*--------------------------------------------------------------------*/
  807. /*               We support the command; execute it                   */
  808. /*--------------------------------------------------------------------*/
  809.  
  810.    argv[argc] = NULL;
  811.    fflush(logfile);
  812.  
  813.    if (equal(argv[0],RMAIL) && ( inname != NULL )) /* Rmail w/input? */
  814.    {
  815.       int addr = 1;
  816.  
  817.       while (( addr < argc )  && (result != -1 ))
  818.       {
  819. #ifdef __TURBOC__
  820.          size_t rlen =  126 ;
  821. #else
  822.          size_t rlen = (_osmode == DOS_MODE) ? 126 :  254;
  823. #endif
  824.          char buf[255];
  825.          rlen -= strlen( argv[0] );
  826.                               /* Compute space left on command line  */
  827.          *buf = '\0';         /* Terminate the buffer string         */
  828.  
  829. /*--------------------------------------------------------------------*/
  830. /*                   Copy addresses into the buffer                   */
  831. /*--------------------------------------------------------------------*/
  832.  
  833.          while (( addr < argc ) && (rlen >= strlen( argv[addr] )))
  834.          {
  835.             if ( *argv[addr] == '-')   /* Option flag for mail?      */
  836.             {
  837.                printmsg(0,"Disallowed option %s ignored",argv[addr]);
  838.                continue;
  839.             }
  840.  
  841.             strcat( buf, argv[addr] );
  842.             rlen -= strlen( argv[addr++] ) + 1;
  843.             if (rlen > 0)     /* Room for another address?           */
  844.                strcat( buf, " ");   /* Yes --> Add space after addr  */
  845.          } /* while (( addr < argc ) && (rlen >= strlen( argv[addr] ) */
  846.  
  847.          if (*buf == '\0')    /* Did we process at least one addr?   */
  848.          {                    /* No --> Serious problem!             */
  849.             printmsg(0,"shell: address \"%s\" too long to process!",
  850.                   argv[addr] );
  851.             panic();
  852.          } /* if (*buf = '\0') */
  853.  
  854. /*--------------------------------------------------------------------*/
  855. /*               Execute one command line of addresses                */
  856. /*--------------------------------------------------------------------*/
  857.  
  858.          printmsg(2, "shell: %s %s", argv[0], buf );
  859.  
  860.          result = spawnlp( P_WAIT, argv[0], argv[0], buf , NULL);
  861.  
  862.          if (freopen(inlocal, "rb", stdin) == NULL)
  863.          {
  864.             printmsg(0, "shell: couldn't reopen %s (%s), errno=%d.",
  865.                inname, inlocal, errno);
  866.             printerr(inlocal);
  867.             panic();
  868.          } /* if */
  869.  
  870.          if ( result != 0 )
  871.          {
  872.             if (result == -1)       /* Did spawn fail?               */
  873.                printerr(argv[0]);   /* Yes --> Report error          */
  874.             printmsg(0,"shell: command \"%s %s\" returned error code %d",
  875.                      argv[0], buf, result);
  876.             panic();
  877.          }
  878.       } /* while (( addr < argc )  && (result != -1 )) */
  879.  
  880.    } /* if (equal(argv[0],RMAIL) && ( inname != NULL )) */
  881.    else if (internal(argv[0]))  /* Internal command?             */
  882.    {
  883.       result = system( savecmd );
  884.                               /* Use COMMAND.COM to run command   */
  885.    } /* else  if (internal(argv[0])) */
  886.    else  {                    /* No --> Invoke normally           */
  887.       result = spawnvp( P_WAIT, argv[0], argv );
  888.  
  889.    } /* else */
  890.  
  891. /*--------------------------------------------------------------------*/
  892. /*                    Determine result of command                     */
  893. /*--------------------------------------------------------------------*/
  894.  
  895.    if ( result == 0 )
  896.       xflag[E_NORMAL] = TRUE;
  897.    else if ( result > 0 )
  898.       xflag[E_STATUS] = TRUE;
  899.  
  900.    if (result == -1)       /* Did spawn fail?                     */
  901.       printerr(argv[0]);   /* Yes --> Report error                */
  902.  
  903. /*--------------------------------------------------------------------*/
  904. /*                  Re-open our standard i/o streams                  */
  905. /*--------------------------------------------------------------------*/
  906.  
  907.    errno = 0;
  908.  
  909.    if ( outname != NULL )
  910.       freopen("con", "wt", stdout);
  911.  
  912.    errno = 0;
  913.  
  914.    if ( inname != NULL )
  915.    {
  916.       FILE *temp = freopen("con", "rt", stdin);
  917.       if ( (temp == NULL) && (errno != 0) )
  918.       {
  919.          printerr("stdin");
  920.          panic();
  921.       }
  922.    } /* if ( inname != NULL ) */
  923.  
  924. /*--------------------------------------------------------------------*/
  925. /*                     Report results of command                      */
  926. /*--------------------------------------------------------------------*/
  927.  
  928.    printmsg( (result == 0 ) ? 8 : 1,"Result of spawn %s is ... %d",
  929.                                  argv[0], result);
  930.    fflush(logfile);
  931.  
  932.    return result;
  933.  
  934. } /*shell*/
  935.  
  936. /*--------------------------------------------------------------------*/
  937. /*    u s a g e                                                       */
  938. /*                                                                    */
  939. /*    Report how to run this program                                  */
  940. /*--------------------------------------------------------------------*/
  941.  
  942. static void usage( void )
  943. {
  944.    fputs("Usage:\tuuxqt\t[-xDEBUG] [-sSYSTEM]", stderr);
  945.    exit(1);
  946. } /* usage */
  947.  
  948. /*--------------------------------------------------------------------*/
  949. /*    c o p y l o c a l                                               */
  950. /*                                                                    */
  951. /*    Copy Local Files                                                */
  952. /*--------------------------------------------------------------------*/
  953.  
  954. static boolean copylocal(const char *from, const char *to)
  955. {
  956.       int  fd_from, fd_to;
  957.       int  nr;
  958.       int  nw = -1;
  959.       char buf[BUFSIZ];            /* faster if we alloc a big buffer */
  960.  
  961.       /* This would be even faster if we determined that both files
  962.          were on the same device, dos >= 3.0, and used the dos move
  963.          function */
  964.  
  965.       if ((fd_from = open(from, O_RDONLY | O_BINARY)) == -1)
  966.          return FALSE;        /* failed */
  967.  
  968.       /* what if the to is a directory? */
  969.       /* possible with local source & dest uucp */
  970.  
  971.       if ((fd_to = open(to, O_CREAT | O_BINARY | O_WRONLY, S_IWRITE | S_IREAD)) == -1) {
  972.          close(fd_from);
  973.          return FALSE;        /* failed */
  974.          /* NOTE - this assumes all the required directories exist!  */
  975.       }
  976.  
  977.       while  ((nr = read(fd_from, buf, sizeof buf)) > 0 &&
  978.          (nw = write(fd_to, buf, nr)) == nr)
  979.          ;
  980.  
  981.       close(fd_to);
  982.       close(fd_from);
  983.  
  984.       if (nr != 0 || nw == -1)
  985.          return FALSE;        /* failed in copy */
  986.       return TRUE;
  987. } /* copylocal */
  988.  
  989. /*--------------------------------------------------------------------*/
  990. /*    c r e a t e _ e n v i r o n m e n t                             */
  991. /*                                                                    */
  992. /*    Create the environment array for subprocesses                   */
  993. /*--------------------------------------------------------------------*/
  994.  
  995. char **create_environment(const char *logname,
  996.                           const char *requestor)
  997. {
  998.    char buffer[MAXADDR + 20];
  999.    int subscript = 0;
  1000.    char **envp = (char **) malloc(sizeof(char *) * 3);
  1001.  
  1002.    checkref(envp);
  1003.  
  1004. /*--------------------------------------------------------------------*/
  1005. /*              "Current" user id processing the request              */
  1006. /*--------------------------------------------------------------------*/
  1007.  
  1008.    if ( logname != NULL )
  1009.    {
  1010.      sprintf(buffer,"%s=%s", LOGNAME, logname);
  1011.      envp[subscript] = strdup(buffer);
  1012.      checkref(envp[subscript++]);
  1013.    }
  1014.  
  1015. /*--------------------------------------------------------------------*/
  1016. /*               user id/nodename of original requestor               */
  1017. /*--------------------------------------------------------------------*/
  1018.  
  1019.    if ( requestor != NULL )
  1020.    {
  1021.       sprintf(buffer,"%s=%s",UU_USER, requestor);
  1022.       envp[subscript] =  strdup(buffer);
  1023.       checkref(envp[subscript++]);
  1024.    }
  1025.  
  1026.    envp[subscript] =  NULL;   /* Terminate the list                  */
  1027.  
  1028. /*--------------------------------------------------------------------*/
  1029. /*               Now put the data into our environment                */
  1030. /*--------------------------------------------------------------------*/
  1031.  
  1032.    while( subscript-- > 0)
  1033.    {
  1034.       if (putenv( envp[subscript] ))
  1035.       {
  1036.          printmsg(0,"Unable to set environment \"%s\"",envp[subscript]);
  1037.          panic();
  1038.       }
  1039.    } /* while */
  1040.  
  1041.    return envp;
  1042. } /* create_environment */
  1043.  
  1044. /*--------------------------------------------------------------------*/
  1045. /*    d e l e t e  _ e n v i r o n m e n t                            */
  1046. /*                                                                    */
  1047. /*    Delete variables inserted by create_enviroment                  */
  1048. /*                                                                    */
  1049. /*    Our environment goes away when we are done executing we; just   */
  1050. /*    clean up the environment because we are freeing the storage     */
  1051. /*--------------------------------------------------------------------*/
  1052.  
  1053. static void delete_environment( char **envp )
  1054. {
  1055.    int subscript = 0;
  1056.  
  1057.    while ( envp[subscript] != NULL )
  1058.    {
  1059.       char *equal = strchr(envp[subscript]  , '=' );
  1060.       *++equal = '\0';        /* Terminate the string             */
  1061.       if (putenv( envp[subscript] ))
  1062.       {
  1063.          printmsg(0,"Unable to reset environment \"%s\"",envp[subscript]);
  1064.          panic();
  1065.       }
  1066.       free( envp[subscript++] );
  1067.    }
  1068.  
  1069.    free( envp );
  1070. } /* delete_environment */
  1071.  
  1072.  
  1073. /*--------------------------------------------------------------------*/
  1074. /*    d o _ c o p y                                                   */
  1075. /*                                                                    */
  1076. /*    Send a file to remote node via uucp                             */
  1077. /*--------------------------------------------------------------------*/
  1078.  
  1079. static boolean do_copy(char *localfile,
  1080.                        const char *rmtsystem,
  1081.                        const char *remotefile,
  1082.                        const char *requestor,
  1083.                        const boolean success )
  1084. {
  1085.       if (rmtsystem == NULL) {
  1086.           copylocal(localfile, remotefile);
  1087.       } else {
  1088.           char    tmfile[FILENAME_MAX];  /* Unix style name for c file */
  1089.           char    idfile[FILENAME_MAX];  /* Unix style name for data file copy */
  1090.           char    work[FILENAME_MAX]; /* temp area for filename hacking */
  1091.           char    icfilename[FILENAME_MAX];  /* our hacked c file path */
  1092.           char    idfilename[FILENAME_MAX];  /* our hacked d file path */
  1093.  
  1094.           struct  stat    statbuf;
  1095.  
  1096.           long    int     sequence;
  1097.           static  char    subseq = 'A';
  1098.           char   *sequence_s;
  1099.           FILE   *cfile;
  1100.  
  1101.  
  1102.           sequence = getseq();
  1103.           sequence_s = JobNumber( sequence );
  1104.  
  1105.           sprintf(tmfile, spool_fmt, 'C', rmtsystem, 'Z', sequence_s);
  1106.           importpath(work, tmfile, rmtsystem);
  1107.           mkfilename(icfilename, E_spooldir, work);
  1108.  
  1109.           if (stat((char *) localfile, &statbuf) != 0)  {
  1110.               printerr( localfile );
  1111.               return FALSE;
  1112.           }
  1113.  
  1114.           sprintf(idfile , dataf_fmt, 'D', E_nodename, sequence_s,
  1115.                   (char) subseq++ );
  1116.           importpath(work, idfile, rmtsystem);
  1117.           mkfilename(idfilename, E_spooldir, work);
  1118.  
  1119.           if (!copylocal(localfile, idfilename))  {
  1120.              printmsg(0, "Copy \"%s\" to \"%s\" failed", localfile, idfilename);
  1121.              return FALSE;
  1122.           }
  1123.  
  1124.           if ((cfile = FOPEN(icfilename, "a", TEXT)) == NULL)  {
  1125.              printerr( icfilename );
  1126.              printf("cannot append to %s\n", icfilename);
  1127.              return FALSE;
  1128.           }
  1129.  
  1130.           fprintf(cfile, send_cmd, localfile, remotefile,
  1131.                    "uucp" , success ? "n" : " ", idfile,
  1132.                     success ? requestor : " ");
  1133.  
  1134.           fclose(cfile);
  1135.     };
  1136.  
  1137.     return TRUE;
  1138. } /* do_copy */
  1139.  
  1140. /*--------------------------------------------------------------------*/
  1141. /*    R e p o r t R e s u l t s                                       */
  1142. /*                                                                    */
  1143. /*    report results of command execution as specified by flags in    */
  1144. /*    X.* file.                                                       */
  1145. /*--------------------------------------------------------------------*/
  1146.  
  1147. static void ReportResults(const int status,
  1148.                           const char *input,
  1149.                                 char *output,
  1150.                           const char *command,
  1151.                           const char *job_id,
  1152.                           const time_t jtime,
  1153.                           const char *requestor,
  1154.                           const char *outnode,
  1155.                           const char *outname,
  1156.                           const boolean xflag[],
  1157.                           const char *statfil,
  1158.                           const char *machine,
  1159.                           const char *user)
  1160. {
  1161.      char address[MAXADDR];
  1162.      char subject[80];
  1163.      FILE *mailtmp = NULL;
  1164.      char *tempmail = mktempname(NULL, "TMP");
  1165.  
  1166.  
  1167.      if (!(xflag[X_FAILED] | xflag[X_SUCCESS] |
  1168.            xflag[X_INPUT]  | xflag[X_STATFIL]))
  1169.      {  /* default actions */
  1170.          unlink(output);
  1171.          return;
  1172.      }
  1173.  
  1174.      if ((mailtmp = FOPEN(tempmail, "w+", BINARY)) == NULL) {
  1175.          printerr(tempmail);
  1176.          return;
  1177.      }
  1178.  
  1179.      sprintf(subject, "\"[uucp job %s (%s)]\"", job_id, dater(jtime, NULL) );
  1180.  
  1181.      fprintf(mailtmp,"remote execution\n");
  1182.      fprintf(mailtmp,"%s\n", command);
  1183.  
  1184. #ifdef BETA_TEST
  1185.      strcpy(address,"postmaster");
  1186. #else
  1187.      if (equal(machine, E_nodename))
  1188.         strcpy(address, requestor);
  1189.      else
  1190.         sprintf(address,"%s!%s", machine, requestor);
  1191. #endif
  1192.  
  1193.      if (xflag[E_NORMAL])
  1194.      {                        /* command succeded, process appropriate flags */
  1195.  
  1196.        fprintf(mailtmp,"exited normally\n");
  1197.  
  1198.        if (xflag[X_OUTPUT])
  1199.            do_copy(output, outnode, outname, requestor, xflag[X_SUCCESS]);
  1200.        else
  1201.            unlink(output);
  1202.  
  1203.        fclose(mailtmp);
  1204.  
  1205.        if (xflag[X_SUCCESS]) {
  1206.           if (xflag[X_STATFIL]) {
  1207.               do_copy(tempmail, outnode, statfil, requestor, xflag[X_SUCCESS]);
  1208.           } else {
  1209.               MailStatus(tempmail, address, subject);
  1210.           }
  1211.        };
  1212.  
  1213.    } else {            /* command failed, process appropriate flags   */
  1214.      if (xflag[E_NOACC])
  1215.          fprintf(mailtmp,"file access denied to %s!%s", machine, user);
  1216.      else if (xflag[E_NOEXE])
  1217.         fprintf(mailtmp,"execution permission denied to %s!%s\n",
  1218.                 machine, requestor);
  1219.      else if (xflag[E_SIGNAL])
  1220.         fprintf(mailtmp,"terminated by signal\n");
  1221.      else if (xflag[E_STATUS])
  1222.         fprintf(mailtmp,"exited with status %d\n", status);
  1223.      else /* xflag->e & E_FAILED */
  1224.         fprintf(mailtmp,"failed completely\n");
  1225.  
  1226.  
  1227.      if (xflag[E_STATUS]) {
  1228.        if ((xflag[X_FAILED]) && !(xflag[X_INPUT])) {
  1229.            fprintf(mailtmp,"===== error output not available =====\n");
  1230.        } else if ((xflag[X_FAILED]) && (xflag[X_INPUT])) {
  1231.            fprintf(mailtmp,"===== stdin was ");
  1232.  
  1233.            if (xflag[S_CORRUPT])
  1234.                fprintf(mailtmp,"unreadable =====\n");
  1235.            else if (xflag[S_EMPTY])
  1236.                fprintf(mailtmp,"empty =====\n");
  1237.            else if (xflag[S_NOREAD])
  1238.                fprintf(mailtmp,"denied read permission =====\n");
  1239.            else {
  1240.                fprintf(mailtmp,"=====\n");
  1241.                AppendData( input, mailtmp);
  1242.            };
  1243.            unlink(input);
  1244.  
  1245.            fprintf(mailtmp,"===== stderr is unavailable =====\n");
  1246.        }
  1247.      }
  1248.  
  1249.      fclose(mailtmp);
  1250.  
  1251.      if (xflag[X_STATFIL]) {
  1252.          do_copy(tempmail, outnode, statfil, requestor, xflag[X_SUCCESS]);
  1253.      } else {
  1254.          MailStatus(tempmail, address, subject);
  1255.      }
  1256.  
  1257.    }
  1258.  
  1259.    if (xflag[X_OUTPUT])
  1260.        unlink(output);
  1261.  
  1262.    unlink(tempmail);
  1263.    return;
  1264. } /* ReportResults */
  1265.  
  1266. /*--------------------------------------------------------------------*/
  1267. /* A p p e n d D a t a                                                */
  1268. /*                                                                    */
  1269. /* Append data to output file                                         */
  1270. /*--------------------------------------------------------------------*/
  1271.  
  1272. static boolean AppendData( const char *input, FILE* dataout)
  1273. {
  1274.    FILE    *datain;
  1275.    char     buf[BUFSIZ];
  1276.    boolean  status = TRUE;
  1277.  
  1278. /*--------------------------------------------------------------------*/
  1279. /*                      Verify the input opened                       */
  1280. /*--------------------------------------------------------------------*/
  1281.  
  1282.    if (input == NULL)
  1283.       return FALSE;
  1284.    else
  1285.       datain = FOPEN(input, "r", TEXT);
  1286.  
  1287.    if (datain == NULL) {
  1288.       printerr(input);
  1289.       printmsg(0,"Unable to open input file \"%s\"", input);
  1290.       return FALSE;
  1291.    } /* datain */
  1292.  
  1293. /*--------------------------------------------------------------------*/
  1294. /*                       Loop to copy the data                        */
  1295. /*--------------------------------------------------------------------*/
  1296.  
  1297.    while (fgets(buf, BUFSIZ, datain) != 0)
  1298.    {
  1299.       if (fputs(buf, dataout) == EOF)     /* I/O error?               */
  1300.       {
  1301.          printmsg(0,"AppendData: I/O error on output file");
  1302.          printerr("dataout");
  1303.          fclose(datain);
  1304.          return FALSE;
  1305.       } /* if */
  1306.    } /* while */
  1307.  
  1308. /*--------------------------------------------------------------------*/
  1309. /*                      Close up shop and return                      */
  1310. /*--------------------------------------------------------------------*/
  1311.  
  1312.    if (ferror(datain))        /* Clean end of file on input?          */
  1313.    {
  1314.       printerr(input);
  1315.       clearerr(datain);
  1316.       status = FALSE;
  1317.    }
  1318.  
  1319.    fclose(datain);
  1320.    return status;
  1321.  
  1322. } /* AppendData */
  1323.  
  1324. /*--------------------------------------------------------------------*/
  1325. /*    M a i l S t a t u s                                             */
  1326. /*                                                                    */
  1327. /*    Send text in a mailbag file to address(es) specified by line.   */
  1328. /*--------------------------------------------------------------------*/
  1329.  
  1330. static boolean MailStatus(char *tempfile,
  1331.                           char *address,
  1332.                           char *subject)
  1333. {
  1334.    boolean status;
  1335.    char **envp;
  1336.  
  1337. /*--------------------------------------------------------------------*/
  1338. /*                            Invoke RMAIL                            */
  1339. /*--------------------------------------------------------------------*/
  1340.  
  1341.    envp = create_environment( "uucp", NULL );
  1342.  
  1343.    if ( subject == NULL )
  1344.       status = spawnlp( P_WAIT, RMAIL, RMAIL,
  1345.                         "-f", tempfile, "-w", address, NULL);
  1346.    else
  1347.       status = spawnlp( P_WAIT, RMAIL, RMAIL,
  1348.                         "-f", tempfile, "-w", "-s", subject, address, NULL);
  1349.  
  1350.    delete_environment( envp );
  1351.  
  1352. /*--------------------------------------------------------------------*/
  1353. /*                       Report errors, if any                        */
  1354. /*--------------------------------------------------------------------*/
  1355.  
  1356.    if ( status < 0 )
  1357.    {
  1358.       printerr( RMAIL );
  1359.       printmsg(0,"Unable to execute rmail; status not delivered.");
  1360.    }
  1361.    else if ( status > 0 )
  1362.       printmsg(0, "Rmail returned error;\
  1363.  status delivery may be incomplete.");
  1364.  
  1365. /*--------------------------------------------------------------------*/
  1366. /*                          Return to caller                          */
  1367. /*--------------------------------------------------------------------*/
  1368.  
  1369.    return (status == 0 );
  1370.  
  1371. } /*MailStatus*/
  1372.  
  1373. /*--------------------------------------------------------------------*/
  1374. /*    i n t e r n a l                                                 */
  1375. /*                                                                    */
  1376. /*    Determine if command is internal DOS command                    */
  1377. /*--------------------------------------------------------------------*/
  1378.  
  1379. static boolean internal( char *command )
  1380. {
  1381.    static char *commands[] = { "break",   "cd",    "chdir",    "copy",
  1382.                                "ctty",    "date",  "del",      "dir",
  1383.                                "echo",    "erase", "for",      "md",
  1384.                                "mkdir",   "rd",    "rem",      "ren",
  1385.                                "rename",  "rmdir", "time",     "ver",
  1386.                                "verify",  "vol",
  1387.                                NULL };
  1388.    char **list;
  1389.  
  1390. /*--------------------------------------------------------------------*/
  1391. /*                   Determine command list to use                    */
  1392. /*--------------------------------------------------------------------*/
  1393.  
  1394.    if (E_internal == NULL )
  1395.       list = commands;
  1396.    else
  1397.       list = E_internal;
  1398.  
  1399. /*--------------------------------------------------------------------*/
  1400. /*                   Scan the list for the command                    */
  1401. /*--------------------------------------------------------------------*/
  1402.  
  1403.    while( *list != NULL )
  1404.    {
  1405.       printmsg(5,"Searching for \"%s\", comparing to \"%s\"",
  1406.                   *list, command);
  1407.       if (equali(*list++,command))
  1408.       {
  1409.          printmsg(4,"\"%s\" is an internal command",command);
  1410.          return TRUE;
  1411.       } /* if */
  1412.    } /* while( *list != NULL ) */
  1413.  
  1414. /*--------------------------------------------------------------------*/
  1415. /*  The command is not in the list; return FALSE (external command)   */
  1416. /*--------------------------------------------------------------------*/
  1417.  
  1418.    printmsg(4,"\"%s\" is an external command",command);
  1419.    return FALSE;
  1420.  
  1421. } /* internal */
  1422.