Annotation of coherent/g/usr/lib/uucp/tay104/uux.c, revision 1.1.1.1

1.1       root        1: /* uux.c
                      2:    Prepare to execute a command on a remote system.
                      3: 
                      4:    Copyright (C) 1991, 1992 Ian Lance Taylor
                      5: 
                      6:    This file is part of the Taylor UUCP package.
                      7: 
                      8:    This program is free software; you can redistribute it and/or
                      9:    modify it under the terms of the GNU General Public License as
                     10:    published by the Free Software Foundation; either version 2 of the
                     11:    License, or (at your option) any later version.
                     12: 
                     13:    This program is distributed in the hope that it will be useful, but
                     14:    WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     16:    General Public License for more details.
                     17: 
                     18:    You should have received a copy of the GNU General Public License
                     19:    along with this program; if not, write to the Free Software
                     20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     21: 
                     22:    The author of the program may be contacted at [email protected] or
                     23:    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
                     24:    */
                     25: 
                     26: #include "uucp.h"
                     27: 
                     28: #if USE_RCS_ID
                     29: const char uux_rcsid[] = "$Id: uux.c,v 1.1 93/07/30 08:00:09 bin Exp Locker: bin $";
                     30: #endif
                     31: 
                     32: #include "uudefs.h"
                     33: #include "uuconf.h"
                     34: #include "system.h"
                     35: #include "sysdep.h"
                     36: #include "getopt.h"
                     37: 
                     38: #include <ctype.h>
                     39: #include <errno.h>
                     40: 
                     41: /* These character lists should, perhaps, be in sysdep.h.  */
                     42: 
                     43: /* This is the list of shell metacharacters that we check for.  If one
                     44:    of these is present, we request uuxqt to execute the command with
                     45:    /bin/sh.  Otherwise we let it execute using execve.  */
                     46: 
                     47: #define ZSHELLCHARS "\"'`*?[;&()|<>\\$"
                     48: 
                     49: /* This is the list of word separators.  We break filename arguments
                     50:    at these characters.  */
                     51: #define ZSHELLSEPS ";&*|<> \t"
                     52: 
                     53: /* This is the list of word separators without the redirection
                     54:    operators.  */
                     55: #define ZSHELLNONREDIRSEPS ";&*| \t"
                     56: 
                     57: /* The program name.  */
                     58: char abProgram[] = "uux";
                     59: 
                     60: /* The name of the execute file.  */
                     61: const char *zXxqt_name;
                     62: 
                     63: /* The execute file we are creating.  */
                     64: static FILE *eXxqt_file;
                     65: 
                     66: /* A list of commands to be spooled.  */
                     67: static struct scmd *pasXcmds;
                     68: static int cXcmds;
                     69: 
                     70: /* A file to close if we're forced to exit.  */
                     71: static FILE *eXclose;
                     72: 
                     73: /* Local functions.  */
                     74: static void uxusage P((void));
                     75: static void uxadd_xqt_line P((int bchar, const char *z1, const char *z2));
                     76: static void uxadd_send_file P((const char *zfrom, const char *zto,
                     77:                               const char *zoptions, const char *ztemp,
                     78:                               const char *zforward,
                     79:                               const struct uuconf_system *qxqtsys,
                     80:                               const char *zxqtloc,
                     81:                               int bgrade));
                     82: static void uxcopy_stdin P((FILE *e));
                     83: static void uxrecord_file P((const char *zfile));
                     84: static void uxabort P((void));
                     85: 
                     86: /* Long getopt options.  */
                     87: static const struct option asXlongopts[] = { { NULL, 0, NULL, 0 } };
                     88: 
                     89: /* The main routine.  */
                     90: 
                     91: int
                     92: main (argc, argv)
                     93:      int argc;
                     94:      char **argv;
                     95: {
                     96:   /* -a: requestor address for status reports.  */
                     97:   const char *zrequestor = NULL;
                     98:   /* -b: if true, return standard input on error.  */
                     99:   boolean fretstdin = FALSE;
                    100:   /* -c,-C: if true, copy to spool directory.  */
                    101:   boolean fcopy = FALSE;
                    102:   /* -c: set if -c appears explicitly; if it and -l appear, then if the
                    103:      link fails we don't copy the file.  */
                    104:   boolean fdontcopy = FALSE;
                    105:   /* -I: configuration file name.  */
                    106:   const char *zconfig = NULL;
                    107:   /* -j: output job id.  */
                    108:   boolean fjobid = FALSE;
                    109:   /* -g: job grade.  */
                    110:   char bgrade = BDEFAULT_UUX_GRADE;
                    111:   /* -l: link file to spool directory.  */
                    112:   boolean flink = FALSE;
                    113:   /* -n: do not notify upon command completion.  */
                    114:   boolean fno_ack = FALSE;
                    115:   /* -p: read standard input for command standard input.  */
                    116:   boolean fread_stdin = FALSE;
                    117:   /* -r: do not start uucico when finished.  */
                    118:   boolean fuucico = TRUE;
                    119:   /* -s: report status to named file.  */
                    120:   const char *zstatus_file = NULL;
                    121:   /* -W: only expand local file names.  */
                    122:   boolean fexpand = TRUE;
                    123:   /* -z: report status only on error.  */
                    124:   boolean ferror_ack = FALSE;
                    125:   int iopt;
                    126:   pointer puuconf;
                    127:   int iuuconf;
                    128:   const char *zlocalname;
                    129:   const char *zxqtloc;
                    130:   int i;
                    131:   size_t clen;
                    132:   char *zargs;
                    133:   char *zarg;
                    134:   char *zcmd;
                    135:   const char *zsys;
                    136:   char *zexclam;
                    137:   boolean fgetcwd;
                    138:   const char *zuser;
                    139:   struct uuconf_system sxqtsys;
                    140:   boolean fxqtlocal;
                    141:   char *zforward;
                    142:   char **pzargs;
                    143:   int calloc_args;
                    144:   int cargs;
                    145:   char abxqt_tname[CFILE_NAME_LEN];
                    146:   char abxqt_xname[CFILE_NAME_LEN];
                    147:   const char *zinput_from;
                    148:   const char *zinput_to;
                    149:   const char *zinput_temp;
                    150:   boolean finputcopied;
                    151:   char *zcall_system;
                    152:   boolean fcall_any;
                    153:   struct uuconf_system slocalsys;
                    154:   boolean fneedshell;
                    155:   char *zfullcmd;
                    156:   boolean fexit;
                    157: 
                    158:   /* We need to be able to read a single - as an option, which getopt
                    159:      won't do.  So that we can still use getopt, we run through the
                    160:      options looking for an option "-"; if we find one we change it to
                    161:      "-p", which is equivalent to "-".  */
                    162:   for (i = 1; i < argc; i++)
                    163:     {
                    164:       if (argv[i][0] != '-')
                    165:        break;
                    166:       if (argv[i][1] == '\0')
                    167:        argv[i] = zbufcpy ("-p");
                    168:       else
                    169:        {
                    170:          const char *z;
                    171: 
                    172:          for (z = argv[i] + 1; *z != '\0'; z++)
                    173:            {
                    174:              /* If the option takes an argument, and the argument is
                    175:                 not appended, then skip the next argument.  */
                    176:              if (*z == 'a' || *z == 'g' || *z == 'I'
                    177:                  || *z == 's' || *z == 'x')
                    178:                {
                    179:                  if (z[1] == '\0')
                    180:                    i++;
                    181:                  break;
                    182:                }
                    183:            }
                    184:        }
                    185:     }
                    186: 
                    187:   /* The leading + in the getopt string means to stop processing
                    188:      options as soon as a non-option argument is seen.  */
                    189:   while ((iopt = getopt_long (argc, argv, "+a:bcCg:I:jlnprs:Wx:z",
                    190:                              asXlongopts, (int *) NULL)) != EOF)
                    191:     {
                    192:       switch (iopt)
                    193:        {
                    194:        case 'a':
                    195:          /* Set requestor name: mail address to which status reports
                    196:             should be sent.  */
                    197:          zrequestor = optarg;
                    198:          break;
                    199: 
                    200:        case 'b':
                    201:          /* Return standard input on error.  */
                    202:          fretstdin = TRUE;
                    203:          break;
                    204: 
                    205:        case 'c':
                    206:          /* Do not copy local files to spool directory.  */
                    207:          fcopy = FALSE;
                    208:          fdontcopy = TRUE;
                    209:          break;
                    210: 
                    211:        case 'C':
                    212:          /* Copy local files to spool directory.  */
                    213:          fcopy = TRUE;
                    214:          break;
                    215: 
                    216:        case 'I':
                    217:          /* Configuration file name.  */ 
                    218:          if (fsysdep_other_config (optarg))
                    219:            zconfig = optarg;
                    220:          break;
                    221: 
                    222:        case 'j':
                    223:          /* Output jobid.  */
                    224:          fjobid = TRUE;
                    225:          break;
                    226: 
                    227:        case 'g':
                    228:          /* Set job grade.  */
                    229:          bgrade = optarg[0];
                    230:          break;
                    231: 
                    232:        case 'l':
                    233:          /* Link file to spool directory.  */
                    234:          flink = TRUE;
                    235:          break;
                    236: 
                    237:        case 'n':
                    238:          /* Do not notify upon command completion.  */
                    239:          fno_ack = TRUE;
                    240:          break;
                    241: 
                    242:        case 'p':
                    243:          /* Read standard input for command standard input.  */
                    244:          fread_stdin = TRUE;
                    245:          break;
                    246: 
                    247:        case 'r':
                    248:          /* Do not start uucico when finished.  */
                    249:          fuucico = FALSE;
                    250:          break;
                    251: 
                    252:        case 's':
                    253:          /* Report status to named file.  */
                    254:          zstatus_file = optarg;
                    255:          break;
                    256: 
                    257:        case 'W':
                    258:          /* Only expand local file names.  */
                    259:          fexpand = FALSE;
                    260:          break;
                    261: 
                    262:        case 'x':
                    263: #if DEBUG > 1
                    264:          /* Set debugging level.  */
                    265:          iDebug |= idebug_parse (optarg);
                    266: #endif
                    267:          break;
                    268: 
                    269:        case 'z':
                    270:          /* Report status only on error.  */
                    271:          ferror_ack = TRUE;
                    272:          break;
                    273: 
                    274:        case 0:
                    275:          /* Long option found and flag set.  */
                    276:          break;
                    277: 
                    278:        default:
                    279:          uxusage ();
                    280:          break;
                    281:        }
                    282:     }
                    283: 
                    284:   if (! UUCONF_GRADE_LEGAL (bgrade))
                    285:     {
                    286:       ulog (LOG_ERROR, "Ignoring illegal grade");
                    287:       bgrade = BDEFAULT_UUX_GRADE;
                    288:     }
                    289: 
                    290:   if (optind == argc)
                    291:     uxusage ();
                    292: 
                    293:   iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
                    294:   if (iuuconf != UUCONF_SUCCESS)
                    295:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    296: 
                    297: #if DEBUG > 1
                    298:   {
                    299:     const char *zdebug;
                    300: 
                    301:     iuuconf = uuconf_debuglevel (puuconf, &zdebug);
                    302:     if (iuuconf != UUCONF_SUCCESS)
                    303:       ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    304:     if (zdebug != NULL)
                    305:       iDebug |= idebug_parse (zdebug);
                    306:   }
                    307: #endif
                    308: 
                    309:   /* The command and files arguments could be quoted in any number of
                    310:      ways, so we split them apart ourselves.  We do this before
                    311:      calling usysdep_initialize because we want to set fgetcwd
                    312:      correctly.  */
                    313:   clen = 1;
                    314:   for (i = optind; i < argc; i++)
                    315:     clen += strlen (argv[i]) + 1;
                    316: 
                    317:   zargs = zbufalc (clen);
                    318:   *zargs = '\0';
                    319:   for (i = optind; i < argc; i++)
                    320:     {
                    321:       strcat (zargs, argv[i]);
                    322:       strcat (zargs, " ");
                    323:     }
                    324: 
                    325:   /* The first argument is the command to execute.  */
                    326:   clen = strcspn (zargs, ZSHELLSEPS);
                    327:   zcmd = zbufalc (clen + 1);
                    328:   strncpy (zcmd, zargs, clen);
                    329:   zcmd[clen] = '\0';
                    330:   zargs += clen;
                    331: 
                    332:   /* Split the arguments out into an array.  We break the arguments
                    333:      into alternating sequences of characters not in ZSHELLSEPS
                    334:      and characters in ZSHELLSEPS.  We remove whitespace.  We
                    335:      separate the redirection characters '>' and '<' into their
                    336:      own arguments to make them easier to process below.  */
                    337:   calloc_args = 10;
                    338:   pzargs = (char **) xmalloc (calloc_args * sizeof (char *));
                    339:   cargs = 0;
                    340: 
                    341:   for (zarg = strtok (zargs, " \t");
                    342:        zarg != NULL;
                    343:        zarg = strtok ((char *) NULL, " \t"))
                    344:     {
                    345:       while (*zarg != '\0')
                    346:        {
                    347:          if (cargs + 1 >= calloc_args)
                    348:            {
                    349:              calloc_args += 10;
                    350:              pzargs = (char **) xrealloc ((pointer) pzargs,
                    351:                                           calloc_args * sizeof (char *));
                    352:            }
                    353: 
                    354:          clen = strcspn (zarg, ZSHELLSEPS);
                    355:          if (clen > 0)
                    356:            {
                    357:              pzargs[cargs] = zbufalc (clen + 1);
                    358:              memcpy (pzargs[cargs], zarg, clen);
                    359:              pzargs[cargs][clen] = '\0';
                    360:              ++cargs;
                    361:              zarg += clen;
                    362:            }
                    363: 
                    364:          /* We deliberately separate '>' and '<' out.  */
                    365:          if (*zarg != '\0')
                    366:            {
                    367:              clen = strspn (zarg, ZSHELLNONREDIRSEPS);
                    368:              if (clen == 0)
                    369:                clen = 1;
                    370:              pzargs[cargs] = zbufalc (clen + 1);
                    371:              memcpy (pzargs[cargs], zarg, clen);
                    372:              pzargs[cargs][clen] = '\0';
                    373:              ++cargs;
                    374:              zarg += clen;
                    375:            }
                    376:        }
                    377:     }
                    378: 
                    379:   /* Now look through the arguments to see if we are going to need the
                    380:      current working directory.  We don't try to make a precise
                    381:      determination, just a conservative one.  The basic idea is that
                    382:      we don't want to get the cwd for 'foo!rmail - user' (note that we
                    383:      don't examine the command itself).  */
                    384:   fgetcwd = FALSE;
                    385:   for (i = 0; i < cargs; i++)
                    386:     {
                    387:       if (pzargs[i][0] == '(')
                    388:        continue;
                    389:       zexclam = strrchr (pzargs[i], '!');
                    390:       if (zexclam != NULL && fsysdep_needs_cwd (zexclam + 1))
                    391:        {
                    392:          fgetcwd = TRUE;
                    393:          break;
                    394:        }
                    395:       if ((pzargs[i][0] == '<' || pzargs[i][0] == '>')
                    396:          && i + 1 < cargs
                    397:          && strchr (pzargs[i + 1], '!') == NULL
                    398:          && fsysdep_needs_cwd (pzargs[i + 1]))
                    399:        {
                    400:          fgetcwd = TRUE;
                    401:          break;
                    402:        }
                    403:     }
                    404: 
                    405: #ifdef SIGINT
                    406:   usysdep_signal (SIGINT);
                    407: #endif
                    408: #ifdef SIGHUP
                    409:   usysdep_signal (SIGHUP);
                    410: #endif
                    411: #ifdef SIGQUIT
                    412:   usysdep_signal (SIGQUIT);
                    413: #endif
                    414: #ifdef SIGTERM
                    415:   usysdep_signal (SIGTERM);
                    416: #endif
                    417: #ifdef SIGPIPE
                    418:   usysdep_signal (SIGPIPE);
                    419: #endif
                    420: 
                    421:   usysdep_initialize (puuconf, INIT_SUID | (fgetcwd ? INIT_GETCWD : 0));
                    422: 
                    423:   ulog_fatal_fn (uxabort);
                    424: 
                    425:   zuser = zsysdep_login_name ();
                    426: 
                    427:   /* Get the local system name.  */
                    428:   iuuconf = uuconf_localname (puuconf, &zlocalname);
                    429:   if (iuuconf == UUCONF_NOT_FOUND)
                    430:     {
                    431:       zlocalname = zsysdep_localname ();
                    432:       if (zlocalname == NULL)
                    433:        exit (EXIT_FAILURE);
                    434:     }
                    435:   else if (iuuconf != UUCONF_SUCCESS)
                    436:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    437: 
                    438:   /* Get the local system information.  */
                    439:   iuuconf = uuconf_system_info (puuconf, zlocalname, &slocalsys);
                    440:   if (iuuconf != UUCONF_SUCCESS)
                    441:     {
                    442:       if (iuuconf != UUCONF_NOT_FOUND)
                    443:        ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    444:       iuuconf = uuconf_system_local (puuconf, &slocalsys);
                    445:       if (iuuconf != UUCONF_SUCCESS)
                    446:        ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    447:     }
                    448: 
                    449:   /* Figure out which system the command is to be executed on.  Some
                    450:      mailers apparently pass local!rmail, so we must explicitly check
                    451:      for that.  */
                    452:   zexclam = strchr (zcmd, '!');
                    453:   while (zexclam != NULL)
                    454:     {
                    455:       *zexclam = '\0';
                    456:       if (strcmp (zcmd, zlocalname) == 0)
                    457:        ;
                    458:       else if (slocalsys.uuconf_pzalias == NULL)
                    459:        break;
                    460:       else
                    461:        {
                    462:          char **pzal;
                    463: 
                    464:          for (pzal = slocalsys.uuconf_pzalias; *pzal != NULL; pzal++)
                    465:            if (strcmp (zcmd, *pzal) == 0)
                    466:              break;
                    467:          if (*pzal == NULL)
                    468:            break;
                    469:        }
                    470:       zcmd = zexclam + 1;
                    471:       zexclam = strchr (zcmd, '!');
                    472:     }
                    473:   if (zexclam == NULL)
                    474:     {
                    475:       zsys = zlocalname;
                    476:       fxqtlocal = TRUE;
                    477:       zforward = NULL;
                    478:     }
                    479:   else
                    480:     {
                    481:       zsys = zcmd;
                    482:       zcmd = zexclam + 1;
                    483:       fxqtlocal = FALSE;
                    484: 
                    485:       /* See if we must forward this command through other systems
                    486:         (e.g. uux a!b!cmd).  */
                    487:       zexclam = strrchr (zcmd, '!');
                    488:       if (zexclam == NULL)
                    489:        zforward = NULL;
                    490:       else
                    491:        {
                    492:          clen = zexclam - zcmd;
                    493:          zforward = zbufalc (clen);
                    494:          memcpy (zforward, zcmd, clen);
                    495:          zforward[clen] = '\0';
                    496:          zcmd = zexclam + 1;
                    497:        }
                    498:     }
                    499: 
                    500:   if (fxqtlocal)
                    501:     sxqtsys = slocalsys;
                    502:   else
                    503:     {
                    504:       iuuconf = uuconf_system_info (puuconf, zsys, &sxqtsys);
                    505:       if (iuuconf != UUCONF_SUCCESS)
                    506:        {
                    507:          if (iuuconf != UUCONF_NOT_FOUND)
                    508:            ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    509:          if (! funknown_system (puuconf, zsys, &sxqtsys))
                    510:            ulog (LOG_FATAL, "%s: System not found", zsys);
                    511:        }
                    512:     }
                    513: 
                    514:   /* Get the local name the remote system know us as.  */
                    515:   zxqtloc = sxqtsys.uuconf_zlocalname;
                    516:   if (zxqtloc == NULL)
                    517:     zxqtloc = zlocalname;
                    518: 
                    519:   /* We can send this as an E command if the execution is on a
                    520:      different, directly connected, system and the only file used is
                    521:      the standard input and comes from this system.  This is true of
                    522:      the common cases of rmail and rnews.  We get an execute file name
                    523:      here in case we need it.  */
                    524:   if (fxqtlocal)
                    525:     zXxqt_name = zsysdep_xqt_file_name ();
                    526:   else
                    527:     zXxqt_name = zsysdep_data_file_name (&sxqtsys, zxqtloc, bgrade, TRUE,
                    528:                                         abxqt_tname, (char *) NULL,
                    529:                                         abxqt_xname);
                    530:   if (zXxqt_name == NULL)
                    531:     uxabort ();
                    532: 
                    533:   uxrecord_file (zXxqt_name);
                    534: 
                    535:   /* Look through the arguments.  Any argument containing an
                    536:      exclamation point character is interpreted as a file name, and is
                    537:      sent to the appropriate system.  */
                    538:   zinput_from = NULL;
                    539:   zinput_to = NULL;
                    540:   zinput_temp = NULL;
                    541:   finputcopied = FALSE;
                    542:   zcall_system = NULL;
                    543:   fcall_any = FALSE;
                    544: 
                    545:   for (i = 0; i < cargs; i++)
                    546:     {
                    547:       const char *zsystem;
                    548:       char *zfile;
                    549:       char *zforw;
                    550:       boolean finput, foutput;
                    551:       boolean flocal, fonxqt;
                    552: 
                    553:       /* Check for a parenthesized argument; remove the parentheses
                    554:         and otherwise ignore it (this is how an exclamation point is
                    555:         quoted).  */
                    556:       if (pzargs[i][0] == '(')
                    557:        {
                    558:          clen = strlen (pzargs[i]);
                    559:          if (pzargs[i][clen - 1] != ')')
                    560:            ulog (LOG_ERROR, "Mismatched parentheses");
                    561:          else
                    562:            pzargs[i][clen - 1] = '\0';
                    563:          ++pzargs[i];
                    564:          continue;
                    565:        }
                    566: 
                    567:       /* Check whether we are doing a redirection.  */
                    568:       finput = FALSE;
                    569:       foutput = FALSE;
                    570:       if (i + 1 < cargs)
                    571:        {
                    572:          if (pzargs[i][0] == '<')
                    573:            finput = TRUE;
                    574:          else if (pzargs[i][0] == '>')
                    575:            foutput = TRUE;
                    576:          if (finput || foutput)
                    577:            {
                    578:              pzargs[i] = NULL;
                    579:              i++;
                    580:            }
                    581:        }
                    582: 
                    583:       zexclam = strchr (pzargs[i], '!');
                    584: 
                    585:       /* If there is no exclamation point and no redirection, this
                    586:         argument is left untouched.  */
                    587:       if (zexclam == NULL && ! finput && ! foutput)
                    588:        continue;
                    589: 
                    590:       /* Get the system name and file name for this file.  */
                    591:       if (zexclam == NULL)
                    592:        {
                    593:          zsystem = zlocalname;
                    594:          zfile = pzargs[i];
                    595:          flocal = TRUE;
                    596:          zforw = NULL;
                    597:        }
                    598:       else
                    599:        {
                    600:          *zexclam = '\0';
                    601:          zsystem = pzargs[i];
                    602:          if (*zsystem != '\0')
                    603:            flocal = FALSE;
                    604:          else
                    605:            {
                    606:              zsystem = zlocalname;
                    607:              flocal = TRUE;
                    608:            }
                    609:          zfile = zexclam + 1;
                    610:          zexclam = strrchr (zfile, '!');
                    611:          if (zexclam == NULL)
                    612:            zforw = NULL;
                    613:          else
                    614:            {
                    615:              if (flocal)
                    616:                ulog (LOG_FATAL, "!%s: Can't figure out where to get file",
                    617:                      zfile);
                    618:              *zexclam = '\0';
                    619:              zforw = zfile;
                    620:              zfile = zexclam + 1;
                    621:            }
                    622:        }
                    623: 
                    624:       /* Check if the file is already on the execution system.  */
                    625:       if (flocal)
                    626:        fonxqt = fxqtlocal;
                    627:       else if (fxqtlocal)
                    628:        fonxqt = FALSE;
                    629:       else if (zforward == NULL ? zforw != NULL : zforw == NULL)
                    630:        fonxqt = FALSE;
                    631:       else if (zforward != NULL
                    632:               && zforw != NULL
                    633:               && strcmp (zforward, zforw) != 0)
                    634:        fonxqt = FALSE;
                    635:       else if (strcmp (zsystem, sxqtsys.uuconf_zname) == 0)
                    636:        fonxqt = TRUE;
                    637:       else if (sxqtsys.uuconf_pzalias == NULL)
                    638:        fonxqt = FALSE;
                    639:       else
                    640:        {
                    641:          char **pzal;
                    642: 
                    643:          fonxqt = FALSE;
                    644:          for (pzal = sxqtsys.uuconf_pzalias; *pzal != NULL; pzal++)
                    645:            {
                    646:              if (strcmp (zsystem, *pzal) == 0)
                    647:                {
                    648:                  fonxqt = TRUE;
                    649:                  break;
                    650:                }
                    651:            }
                    652:        }
                    653: 
                    654:       /* Turn the file into an absolute path.  */
                    655:       if (flocal)
                    656:        zfile = zsysdep_local_file_cwd (zfile, sxqtsys.uuconf_zpubdir);
                    657:       else if (fexpand)
                    658:        zfile = zsysdep_add_cwd (zfile);
                    659:       if (zfile == NULL)
                    660:        uxabort ();
                    661: 
                    662:       /* Check for output redirection.  */
                    663:       if (foutput)
                    664:        {
                    665:          if (flocal)
                    666:            {
                    667:              if (! fin_directory_list (zfile,
                    668:                                        sxqtsys.uuconf_pzremote_receive,
                    669:                                        sxqtsys.uuconf_zpubdir, TRUE,
                    670:                                        FALSE, (const char *) NULL))
                    671:                ulog (LOG_FATAL, "Not permitted to create %s", zfile);
                    672:            }
                    673: 
                    674:          /* There are various cases of output redirection.
                    675: 
                    676:             uux cmd >out: The command is executed on the local
                    677:                 system, and the output file is placed on the local
                    678:                 system (fonxqt is TRUE).
                    679: 
                    680:             uux cmd >a!out: The command is executed on the local
                    681:                 system, and the output file is sent to a.
                    682: 
                    683:             uux a!cmd >out: The command is executed on a, and the
                    684:                 output file is returned to the local system (flocal
                    685:                 is TRUE).
                    686: 
                    687:             uux a!cmd >a!out: The command is executed on a, and the
                    688:                 output file is left on a (fonxqt is TRUE).
                    689: 
                    690:             uux a!cmd >b!out: The command is executed on a, and the
                    691:                 output file is sent to b; traditionally, I believe
                    692:                 that b is relative to a, rather than to the local
                    693:                 system.  However, this essentially contradicts the
                    694:                 previous two cases, in which the output file is
                    695:                 relative to the local system.
                    696: 
                    697:             Now, the cases that we don't handle.
                    698: 
                    699:             uux cmd >a!b!out: The command is executed on the local
                    700:                 system, and the output file is sent to b via a.  This
                    701:                 requires the local uuxqt to support forwarding of the
                    702:                 output file.
                    703: 
                    704:             uux a!b!cmd >out: The command is executed on b, which is
                    705:                 reached via a.  Probably the output file is intended
                    706:                 for the local system, in which case the uuxqt on b
                    707:                 must support forwarding of the output file.
                    708: 
                    709:             uux a!b!cmd >c!out: Is c relative to b or to the local
                    710:                 system?  If it's relative to b this is easy to
                    711:                 handle.  Otherwise, we must arrange for the file to
                    712:                 be sent back to the local system and for the local
                    713:                 system to send it on to c.
                    714: 
                    715:             There are many variations of the last case.  It's not at
                    716:             all clear to me how they should be handled.  */
                    717:          if (zforward != NULL || zforw != NULL)
                    718:            ulog (LOG_FATAL, "May not forward standard output");
                    719: 
                    720:          if (fonxqt)
                    721:            uxadd_xqt_line ('O', zfile, (const char *) NULL);
                    722:          else if (flocal)
                    723:            uxadd_xqt_line ('O', zfile, zxqtloc);
                    724:          else
                    725:            uxadd_xqt_line ('O', zfile, zsystem);
                    726:          pzargs[i] = NULL;
                    727:          continue;
                    728:        }
                    729: 
                    730:       if (finput)
                    731:        {
                    732:          if (fread_stdin)
                    733:            ulog (LOG_FATAL, "Standard input specified twice");
                    734:          pzargs[i] = NULL;
                    735:        }
                    736: 
                    737:       if (flocal)
                    738:        {
                    739:          char *zuse;
                    740:          char *zdata;
                    741:          char abtname[CFILE_NAME_LEN];
                    742:          char abdname[CFILE_NAME_LEN];
                    743: 
                    744:          /* It's a local file.  If requested by -C, copy the file to
                    745:             the spool directory.  If requested by -l, link the file
                    746:             to the spool directory; if the link fails, we copy the
                    747:             file, unless -c was explictly used.  If the execution is
                    748:             occurring on the local system, we force the copy as well,
                    749:             because otherwise we would have to have some way to tell
                    750:             uuxqt not to move the file.  If the file is being shipped
                    751:             to another system, we must set up a transfer request.
                    752:             First make sure the user has legitimate access, since we
                    753:             are running setuid.  */
                    754:          if (! fsysdep_access (zfile))
                    755:            uxabort ();
                    756: 
                    757:          zdata = zsysdep_data_file_name (&sxqtsys, zxqtloc, bgrade, FALSE,
                    758:                                          abtname, abdname, (char *) NULL);
                    759:          if (zdata == NULL)
                    760:            uxabort ();
                    761: 
                    762:          if (fcopy || flink || fxqtlocal)
                    763:            {
                    764:              boolean fdid;
                    765: 
                    766:              uxrecord_file (zdata);
                    767: 
                    768:              fdid = FALSE;
                    769:              if (flink)
                    770:                {
                    771:                  boolean fworked;
                    772: 
                    773:                  if (! fsysdep_link (zfile, zdata, &fworked))
                    774:                    uxabort ();
                    775: 
                    776:                  if (fworked)
                    777:                    fdid = TRUE;
                    778:                  else if (fdontcopy)
                    779:                    ulog (LOG_FATAL, "%s: Can't link to spool directory",
                    780:                          zfile);
                    781:                }
                    782: 
                    783:              if (! fdid)
                    784:                {
                    785:                  openfile_t efile;
                    786: 
                    787:                  efile = esysdep_user_fopen (zfile, TRUE, TRUE);
                    788:                  if (! ffileisopen (efile))
                    789:                    uxabort ();
                    790:                  if (! fcopy_open_file (efile, zdata, FALSE, TRUE))
                    791:                    uxabort ();
                    792:                  (void) ffileclose (efile);
                    793:                }
                    794: 
                    795:              zuse = abtname;
                    796:            }
                    797:          else
                    798:            {
                    799:              /* We don't actually use the spool file name, but we
                    800:                 need a name to use as the destination.  */
                    801:              ubuffree (zdata);
                    802:              /* Make sure the daemon can access the file.  */
                    803:              if (! fsysdep_daemon_access (zfile))
                    804:                uxabort ();
                    805:              if (! fin_directory_list (zfile, sxqtsys.uuconf_pzlocal_send,
                    806:                                        sxqtsys.uuconf_zpubdir, TRUE,
                    807:                                        TRUE, zuser))
                    808:                ulog (LOG_FATAL, "Not permitted to send from %s",
                    809:                      zfile);
                    810: 
                    811:              zuse = zfile;
                    812:            }
                    813: 
                    814:          if (fxqtlocal)
                    815:            {
                    816:              if (finput)
                    817:                uxadd_xqt_line ('I', zuse, (char *) NULL);
                    818:              else
                    819:                pzargs[i] = zuse;
                    820:            }
                    821:          else
                    822:            {
                    823:              finputcopied = fcopy || flink;
                    824: 
                    825:              if (finput)
                    826:                {
                    827:                  zinput_from = zuse;
                    828:                  zinput_to = zbufcpy (abdname);
                    829:                  zinput_temp = zbufcpy (abtname);
                    830:                }
                    831:              else
                    832:                {
                    833:                  char *zbase;
                    834: 
                    835:                  uxadd_send_file (zuse, abdname,
                    836:                                   finputcopied ? "C" : "c",
                    837:                                   abtname, zforward, &sxqtsys,
                    838:                                   zxqtloc, bgrade);
                    839:                  zbase = zsysdep_base_name (zfile);
                    840:                  if (zbase == NULL)
                    841:                    uxabort ();
                    842:                  uxadd_xqt_line ('F', abdname, zbase);
                    843:                  pzargs[i] = zbase;
                    844:                }
                    845:            }
                    846:        }
                    847:       else if (fonxqt)
                    848:        {
                    849:          /* The file is already on the system where the command is to
                    850:             be executed.  */
                    851:          if (finput)
                    852:            uxadd_xqt_line ('I', zfile, (const char *) NULL);
                    853:          else
                    854:            pzargs[i] = zfile;
                    855:        }
                    856:       else
                    857:        {
                    858:          struct uuconf_system sfromsys;
                    859:          char abtname[CFILE_NAME_LEN];
                    860:          struct scmd s;
                    861:          char *zjobid;
                    862: 
                    863:          /* We need to request a remote file.  */
                    864:          iuuconf = uuconf_system_info (puuconf, zsystem, &sfromsys);
                    865:          if (iuuconf != UUCONF_SUCCESS)
                    866:            {
                    867:              if (iuuconf != UUCONF_NOT_FOUND)
                    868:                ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    869:              if (! funknown_system (puuconf, zsystem, &sfromsys))
                    870:                ulog (LOG_FATAL, "%s: System not found", zsystem);
                    871:            }
                    872: 
                    873:          if (fonxqt)
                    874:            {
                    875:              /* The file is already on the system where the command is to
                    876:                 be executed.  */
                    877:              if (finput)
                    878:                uxadd_xqt_line ('I', zfile, (const char *) NULL);
                    879:              else
                    880:                pzargs[i] = zfile;
                    881:            }
                    882:          else
                    883:            {
                    884:              char *zdata;
                    885: 
                    886:              if (! sfromsys.uuconf_fcall_transfer
                    887:                  && ! sfromsys.uuconf_fcalled_transfer)
                    888:                ulog (LOG_FATAL,
                    889:                      "Not permitted to transfer files to or from %s",
                    890:                      sfromsys.uuconf_zname);
                    891: 
                    892:              if (zforw != NULL)
                    893:                {
                    894:                  /* This is ``uux cmd a!b!file''.  To make this work,
                    895:                     we would have to be able to set up a request to a
                    896:                     to fetch file from b and send it to us.  But it
                    897:                     turns out that that will not work, because when a
                    898:                     sends us the file we will put it in a's spool
                    899:                     directory, not the local system spool directory.
                    900:                     So we won't have any way to find it.  This is not
                    901:                     a conceptual problem, and it could doubtless be
                    902:                     solved.  Please feel free to solve it and send me
                    903:                     the solution.  */
                    904:                  ulog (LOG_FATAL, "File forwarding not supported");
                    905:                }
                    906: 
                    907:              /* We must request the file from the remote system to
                    908:                 this one.  */
                    909:              zdata = zsysdep_data_file_name (&slocalsys, zxqtloc, bgrade,
                    910:                                              FALSE, abtname, (char *) NULL,
                    911:                                              (char *) NULL);
                    912:              if (zdata == NULL)
                    913:                uxabort ();
                    914:              ubuffree (zdata);
                    915: 
                    916:              /* Request the file.  The special option '9' is a signal
                    917:                 to uucico that it's OK to receive a file into the
                    918:                 spool directory; normally such requests are rejected.
                    919:                 This privilege is easy to abuse.  */
                    920:              s.bcmd = 'R';
                    921:              s.pseq = NULL;
                    922:              s.zfrom = zfile;
                    923:              s.zto = zbufcpy (abtname);
                    924:              s.zuser = zuser;
                    925:              s.zoptions = "9";
                    926:              s.ztemp = "";
                    927:              s.imode = 0600;
                    928:              s.znotify = "";
                    929:              s.cbytes = -1;
                    930:              s.zcmd = NULL;
                    931:              s.ipos = 0;
                    932: 
                    933:              zjobid = zsysdep_spool_commands (&sfromsys, bgrade, 1, &s);
                    934:              if (zjobid == NULL)
                    935:                uxabort ();
                    936: 
                    937:              if (fjobid)
                    938:                printf ("%s\n", zjobid);
                    939: 
                    940:              ubuffree (zjobid);
                    941: 
                    942:              if (fcall_any)
                    943:                {
                    944:                  ubuffree (zcall_system);
                    945:                  zcall_system = NULL;
                    946:                }
                    947:              else
                    948:                {
                    949:                  fcall_any = TRUE;
                    950:                  zcall_system = zbufcpy (sfromsys.uuconf_zname);
                    951:                }
                    952: 
                    953:              if (fxqtlocal)
                    954:                {
                    955:                  /* Tell the command execution to wait until the file
                    956:                     has been received, and tell it the real file
                    957:                     name.  */
                    958:                  if (finput)
                    959:                    {
                    960:                      uxadd_xqt_line ('F', abtname, (char *) NULL);
                    961:                      uxadd_xqt_line ('I', abtname, (char *) NULL);
                    962:                    }
                    963:                  else
                    964:                    {
                    965:                      char *zbase;
                    966: 
                    967:                      zbase = zsysdep_base_name (zfile);
                    968:                      if (zbase == NULL)
                    969:                        uxabort ();
                    970:                      uxadd_xqt_line ('F', abtname, zbase);
                    971:                      pzargs[i] = zbase;
                    972:                    }
                    973:                }
                    974:              else
                    975:                {
                    976:                  char abxtname[CFILE_NAME_LEN];
                    977:                  char *zbase;
                    978:                  char *zxqt;
                    979:                  FILE *e;
                    980: 
                    981:                  /* Now we must arrange to forward the file on to the
                    982:                     execution system.  We need to get a name to give
                    983:                     the file on the execution system (abxtname).  */
                    984:                  zdata = zsysdep_data_file_name (&sxqtsys, zxqtloc,
                    985:                                                  bgrade, TRUE, abxtname,
                    986:                                                  (char *) NULL,
                    987:                                                  (char *) NULL);
                    988:                  if (zdata == NULL)
                    989:                    uxabort ();
                    990:                  ubuffree (zdata);
                    991: 
                    992:                  zbase = zsysdep_base_name (zfile);
                    993:                  if (zbase == NULL)
                    994:                    uxabort ();
                    995: 
                    996:                  zxqt = zsysdep_xqt_file_name ();
                    997:                  if (zxqt == NULL)
                    998:                    uxabort ();
                    999:                  e = esysdep_fopen (zxqt, FALSE, FALSE, TRUE);
                   1000:                  if (e == NULL)
                   1001:                    uxabort ();
                   1002:                  uxrecord_file (zxqt);
                   1003: 
                   1004:                  fprintf (e, "U %s %s\n", zsysdep_login_name (),
                   1005:                           zlocalname);
                   1006:                  fprintf (e, "F %s %s\n", abtname, zbase);
                   1007:                  fprintf (e, "C uucp -C -W -d -g %c %s %s!", bgrade,
                   1008:                           zbase, sxqtsys.uuconf_zname);
                   1009:                  if (zforward != NULL)
                   1010:                    fprintf (e, "%s!", zforward);
                   1011:                  fprintf (e, "%s\n", abxtname);
                   1012: 
                   1013:                  if (fclose (e) != 0)
                   1014:                    ulog (LOG_FATAL, "fclose: %s", strerror (errno));
                   1015: 
                   1016:                  if (finput)
                   1017:                    {
                   1018:                      uxadd_xqt_line ('F', abxtname, (char *) NULL);
                   1019:                      uxadd_xqt_line ('I', abxtname, (char *) NULL);
                   1020:                      ubuffree (zbase);
                   1021:                    }
                   1022:                  else
                   1023:                    {
                   1024:                      uxadd_xqt_line ('F', abxtname, zbase);
                   1025:                      pzargs[i] = zbase;
                   1026:                    }
                   1027:                }
                   1028:            }
                   1029: 
                   1030:          (void) uuconf_system_free (puuconf, &sfromsys);
                   1031:        }
                   1032:     }
                   1033: 
                   1034:   /* If standard input is to be read from the stdin of uux, we read it
                   1035:      here into a temporary file and send it to the execute system.  */
                   1036:   if (fread_stdin)
                   1037:     {
                   1038:       char *zdata;
                   1039:       char abtname[CFILE_NAME_LEN];
                   1040:       char abdname[CFILE_NAME_LEN];
                   1041:       FILE *e;
                   1042: 
                   1043:       zdata = zsysdep_data_file_name (&sxqtsys, zxqtloc, bgrade, FALSE,
                   1044:                                      abtname, abdname, (char *) NULL);
                   1045:       if (zdata == NULL)
                   1046:        uxabort ();
                   1047: 
                   1048:       e = esysdep_fopen (zdata, FALSE, FALSE, TRUE);
                   1049:       if (e == NULL)
                   1050:        uxabort ();
                   1051: 
                   1052:       eXclose = e;
                   1053:       uxrecord_file (zdata);
                   1054: 
                   1055:       uxcopy_stdin (e);
                   1056: 
                   1057:       eXclose = NULL;
                   1058:       if (fclose (e) != 0)
                   1059:        ulog (LOG_FATAL, "fclose: %s", strerror (errno));
                   1060: 
                   1061:       if (fxqtlocal)
                   1062:        uxadd_xqt_line ('I', abtname, (const char *) NULL);
                   1063:       else
                   1064:        {
                   1065:          zinput_from = zbufcpy (abtname);
                   1066:          zinput_to = zbufcpy (abdname);
                   1067:          zinput_temp = zinput_from;
                   1068:          finputcopied = TRUE;
                   1069:        }
                   1070:     }
                   1071: 
                   1072:   /* If we are returning standard input, or we're putting the status
                   1073:      in a file, we can't use an E command.  */
                   1074:   if (fretstdin)
                   1075:     uxadd_xqt_line ('B', (const char *) NULL, (const char *) NULL);
                   1076: 
                   1077:   if (zstatus_file != NULL)
                   1078:     uxadd_xqt_line ('M', zstatus_file, (const char *) NULL);
                   1079: 
                   1080:   /* Get the complete command line, and decide whether the command
                   1081:      needs to be executed by the shell.  */
                   1082:   fneedshell = FALSE;
                   1083: 
                   1084:   if (zcmd[strcspn (zcmd, ZSHELLCHARS)] != '\0')
                   1085:     fneedshell = TRUE;
                   1086: 
                   1087:   clen = strlen (zcmd) + 1;
                   1088:   for (i = 0; i < cargs; i++)
                   1089:     {
                   1090:       if (pzargs[i] != NULL)
                   1091:        {
                   1092:          clen += strlen (pzargs[i]) + 1;
                   1093:          if (pzargs[i][strcspn (pzargs[i], ZSHELLCHARS)] != '\0')
                   1094:            fneedshell = TRUE;
                   1095:        }
                   1096:     }
                   1097: 
                   1098:   zfullcmd = zbufalc (clen);
                   1099: 
                   1100:   strcpy (zfullcmd, zcmd);
                   1101:   for (i = 0; i < cargs; i++)
                   1102:     {
                   1103:       if (pzargs[i] != NULL)
                   1104:        {
                   1105:          strcat (zfullcmd, " ");
                   1106:          strcat (zfullcmd, pzargs[i]);
                   1107:        }
                   1108:     }
                   1109: 
                   1110:   /* If we haven't written anything to the execution file yet, and we
                   1111:      have a standard input file, and we're not forwarding, then every
                   1112:      other option can be handled in an E command.  */
                   1113:   if (eXxqt_file == NULL && zinput_from != NULL && zforward == NULL)
                   1114:     {
                   1115:       struct scmd s;
                   1116:       char aboptions[10];
                   1117:       char *zoptions;
                   1118: 
                   1119:       /* Set up an E command.  */
                   1120:       s.bcmd = 'E';
                   1121:       s.pseq = NULL;
                   1122:       s.zuser = zuser;
                   1123:       s.zfrom = zinput_from;
                   1124:       s.zto = zinput_to;
                   1125:       s.zoptions = aboptions;
                   1126:       zoptions = aboptions;
                   1127:       *zoptions++ = finputcopied ? 'C' : 'c';
                   1128:       if (fno_ack)
                   1129:        *zoptions++ = 'N';
                   1130:       if (ferror_ack)
                   1131:        *zoptions++ = 'Z';
                   1132:       if (zrequestor != NULL)
                   1133:        *zoptions++ = 'R';
                   1134:       if (fneedshell)
                   1135:        *zoptions++ = 'e';
                   1136:       *zoptions = '\0';
                   1137:       s.ztemp = zinput_temp;
                   1138:       s.imode = 0666;
                   1139:       if (zrequestor == NULL)
                   1140:        zrequestor = "\"\"";
                   1141:       s.znotify = zrequestor;
                   1142:       s.cbytes = -1;
                   1143:       s.zcmd = zfullcmd;
                   1144:       s.ipos = 0;
                   1145:       
                   1146:       ++cXcmds;
                   1147:       pasXcmds = (struct scmd *) xrealloc ((pointer) pasXcmds,
                   1148:                                           cXcmds * sizeof (struct scmd));
                   1149:       pasXcmds[cXcmds - 1] = s;
                   1150:     }
                   1151:   else
                   1152:     {
                   1153:       /* Finish up the execute file.  */
                   1154:       uxadd_xqt_line ('U', zuser, zxqtloc);
                   1155:       if (zinput_from != NULL)
                   1156:        {
                   1157:          uxadd_xqt_line ('F', zinput_to, (char *) NULL);
                   1158:          uxadd_xqt_line ('I', zinput_to, (char *) NULL);
                   1159:          uxadd_send_file (zinput_from, zinput_to,
                   1160:                           finputcopied ? "C" : "c",
                   1161:                           zinput_temp, zforward, &sxqtsys, zxqtloc,
                   1162:                           bgrade);
                   1163:        }
                   1164:       if (fno_ack)
                   1165:        uxadd_xqt_line ('N', (const char *) NULL, (const char *) NULL);
                   1166:       if (ferror_ack)
                   1167:        uxadd_xqt_line ('Z', (const char *) NULL, (const char *) NULL);
                   1168:       if (zrequestor != NULL)
                   1169:        uxadd_xqt_line ('R', zrequestor, (const char *) NULL);
                   1170:       if (fneedshell)
                   1171:        uxadd_xqt_line ('e', (const char *) NULL, (const char *) NULL);
                   1172:       uxadd_xqt_line ('C', zfullcmd, (const char *) NULL);
                   1173:       if (fclose (eXxqt_file) != 0)
                   1174:        ulog (LOG_FATAL, "fclose: %s", strerror (errno));
                   1175:       eXxqt_file = NULL;
                   1176: 
                   1177:       /* If the execution is to occur on another system, we must now
                   1178:         arrange to copy the execute file to this system.  */
                   1179:       if (! fxqtlocal)
                   1180:        uxadd_send_file (abxqt_tname, abxqt_xname, "C", abxqt_tname,
                   1181:                         zforward, &sxqtsys, zxqtloc, bgrade);
                   1182:     }
                   1183: 
                   1184:   /* If we got a signal, get out before spooling anything.  */
                   1185:   if (FGOT_SIGNAL ())
                   1186:     uxabort ();
                   1187: 
                   1188:   /* From here on in, it's too late.  We don't call uxabort.  */
                   1189:   if (cXcmds > 0)
                   1190:     {
                   1191:       char *zjobid;
                   1192: 
                   1193:       if (! sxqtsys.uuconf_fcall_transfer
                   1194:          && ! sxqtsys.uuconf_fcalled_transfer)
                   1195:        ulog (LOG_FATAL, "Not permitted to transfer files to or from %s",
                   1196:              sxqtsys.uuconf_zname);
                   1197: 
                   1198:       zjobid = zsysdep_spool_commands (&sxqtsys, bgrade, cXcmds, pasXcmds);
                   1199:       if (zjobid == NULL)
                   1200:        {
                   1201:          ulog_close ();
                   1202:          usysdep_exit (FALSE);
                   1203:        }
                   1204: 
                   1205:       if (fjobid)
                   1206:        printf ("%s\n", zjobid);
                   1207: 
                   1208:       ubuffree (zjobid);
                   1209: 
                   1210:       if (fcall_any)
                   1211:        {
                   1212:          ubuffree (zcall_system);
                   1213:          zcall_system = NULL;
                   1214:        }
                   1215:       else
                   1216:        {
                   1217:          fcall_any = TRUE;
                   1218:          zcall_system = zbufcpy (sxqtsys.uuconf_zname);
                   1219:        }
                   1220:     }
                   1221: 
                   1222:   /* If all that worked, make a log file entry.  All log file reports
                   1223:      up to this point went to stderr.  */
                   1224:   ulog_to_file (puuconf, TRUE);
                   1225:   ulog_system (sxqtsys.uuconf_zname);
                   1226:   ulog_user (zuser);
                   1227: 
                   1228:   ulog (LOG_NORMAL, "Queuing %s", zfullcmd);
                   1229: 
                   1230:   ulog_close ();
                   1231: 
                   1232:   if (! fuucico)
                   1233:     fexit = TRUE;
                   1234:   else
                   1235:     {
                   1236:       if (zcall_system != NULL)
                   1237:        fexit = fsysdep_run ("uucico", "-s", zcall_system);
                   1238:       else if (fcall_any)
                   1239:        fexit = fsysdep_run ("uucico", "-r1", (const char *) NULL);
                   1240:       else
                   1241:        fexit = TRUE;
                   1242:     }
                   1243: 
                   1244:   usysdep_exit (fexit);
                   1245: 
                   1246:   /* Avoid error about not returning a value.  */
                   1247:   return 0;
                   1248: }
                   1249: 
                   1250: /* Report command usage.  */
                   1251: 
                   1252: static void
                   1253: uxusage ()
                   1254: {
                   1255:   fprintf (stderr,
                   1256:           "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
                   1257:           VERSION);
                   1258:   fprintf (stderr,
                   1259:           "Usage: uux [options] [-] command\n");
                   1260:   fprintf (stderr,
                   1261:           " -,-p: Read standard input for standard input of command\n");
                   1262:   fprintf (stderr,
                   1263:           " -c: Do not copy local files to spool directory (default)\n");
                   1264:   fprintf (stderr,
                   1265:           " -C: Copy local files to spool directory\n");
                   1266:   fprintf (stderr,
                   1267:           " -l: link local files to spool directory\n");
                   1268:   fprintf (stderr,
                   1269:           " -g grade: Set job grade (must be alphabetic)\n");
                   1270:   fprintf (stderr,
                   1271:           " -n: Do not report completion status\n");
                   1272:   fprintf (stderr,
                   1273:           " -z: Report completion status only on error\n");
                   1274:   fprintf (stderr,
                   1275:           " -r: Do not start uucico daemon\n");
                   1276:   fprintf (stderr,
                   1277:           " -a address: Address to mail status report to\n");
                   1278:   fprintf (stderr,
                   1279:           " -b: Return standard input with status report\n");
                   1280:   fprintf (stderr,
                   1281:           " -s file: Report completion status to file\n");
                   1282:   fprintf (stderr,
                   1283:           " -j: Report job id\n");
                   1284:   fprintf (stderr,
                   1285:           " -x debug: Set debugging level\n");
                   1286: #if HAVE_TAYLOR_CONFIG
                   1287:   fprintf (stderr,
                   1288:           " -I file: Set configuration file to use\n");
                   1289: #endif /* HAVE_TAYLOR_CONFIG */
                   1290:   exit (EXIT_FAILURE);
                   1291: }
                   1292: 
                   1293: /* Add a line to the execute file.  */
                   1294: 
                   1295: static void
                   1296: uxadd_xqt_line (bchar, z1, z2)
                   1297:      int bchar;
                   1298:      const char *z1;
                   1299:      const char *z2;
                   1300: {
                   1301:   if (eXxqt_file == NULL)
                   1302:     {
                   1303:       eXxqt_file = esysdep_fopen (zXxqt_name, FALSE, FALSE, TRUE);
                   1304:       if (eXxqt_file == NULL)
                   1305:        uxabort ();
                   1306:     }
                   1307: 
                   1308:   if (z1 == NULL)
                   1309:     fprintf (eXxqt_file, "%c\n", bchar);
                   1310:   else if (z2 == NULL)
                   1311:     fprintf (eXxqt_file, "%c %s\n", bchar, z1);
                   1312:   else
                   1313:     fprintf (eXxqt_file, "%c %s %s\n", bchar, z1, z2);
                   1314: }
                   1315: 
                   1316: /* Add a file to be sent to the execute system.  */
                   1317: 
                   1318: static void
                   1319: uxadd_send_file (zfrom, zto, zoptions, ztemp, zforward, qxqtsys, zxqtloc,
                   1320:                 bgrade)
                   1321:      const char *zfrom;
                   1322:      const char *zto;
                   1323:      const char *zoptions;
                   1324:      const char *ztemp;
                   1325:      const char *zforward;
                   1326:      const struct uuconf_system *qxqtsys;
                   1327:      const char *zxqtloc;
                   1328:      int bgrade;
                   1329: {
                   1330:   struct scmd s;
                   1331: 
                   1332:   if (zforward != NULL)
                   1333:     {
                   1334:       char *zbase;
                   1335:       char *zxqt;
                   1336:       char abtname[CFILE_NAME_LEN];
                   1337:       char abdname[CFILE_NAME_LEN];
                   1338:       char abxname[CFILE_NAME_LEN];
                   1339:       FILE *e;
                   1340: 
                   1341:       /* We want to forward this file through the first execution
                   1342:         system to other systems.  We set up a remote execution of
                   1343:         uucp to forward the file.  */
                   1344:       zbase = zsysdep_base_name (zfrom);
                   1345:       if (zbase == NULL)
                   1346:        uxabort ();
                   1347: 
                   1348:       zxqt = zsysdep_data_file_name (qxqtsys, zxqtloc, bgrade, TRUE, abtname,
                   1349:                                     abdname, abxname);
                   1350:       if (zxqt == NULL)
                   1351:        uxabort ();
                   1352:       e = esysdep_fopen (zxqt, FALSE, FALSE, TRUE);
                   1353:       if (e == NULL)
                   1354:        uxabort ();
                   1355:       uxrecord_file (zxqt);
                   1356: 
                   1357:       fprintf (e, "U %s %s\n", zsysdep_login_name (), zxqtloc);
                   1358:       fprintf (e, "F %s %s\n", abdname, zbase);
                   1359:       fprintf (e, "C uucp -C -W -d -g %c %s %s!%s\n",
                   1360:               bgrade, zbase, zforward, zto);
                   1361: 
                   1362:       ubuffree (zbase);
                   1363: 
                   1364:       if (fclose (e) != 0)
                   1365:        ulog (LOG_FATAL, "fclose: %s", strerror (errno));
                   1366: 
                   1367:       /* Send the execution file.  */
                   1368:       s.bcmd = 'S';
                   1369:       s.pseq = NULL;
                   1370:       s.zfrom = zbufcpy (abtname);
                   1371:       s.zto = zbufcpy (abxname);
                   1372:       s.zuser = zsysdep_login_name ();
                   1373:       s.zoptions = "C";
                   1374:       s.ztemp = s.zfrom;
                   1375:       s.imode = 0666;
                   1376:       s.znotify = NULL;
                   1377:       s.cbytes = -1;
                   1378:       s.zcmd = NULL;
                   1379:       s.ipos = 0;
                   1380: 
                   1381:       ++cXcmds;
                   1382:       pasXcmds = (struct scmd *) xrealloc ((pointer) pasXcmds,
                   1383:                                           cXcmds * sizeof (struct scmd));
                   1384:       pasXcmds[cXcmds - 1] = s;
                   1385: 
                   1386:       /* Send the data file to abdname where the execution file will
                   1387:         expect it.  */
                   1388:       zto = abdname;
                   1389:     }
                   1390: 
                   1391:   s.bcmd = 'S';
                   1392:   s.pseq = NULL;
                   1393:   s.zfrom = zbufcpy (zfrom);
                   1394:   s.zto = zbufcpy (zto);
                   1395:   s.zuser = zsysdep_login_name ();
                   1396:   s.zoptions = zbufcpy (zoptions);
                   1397:   s.ztemp = zbufcpy (ztemp);
                   1398:   s.imode = 0666;
                   1399:   s.znotify = "";
                   1400:   s.cbytes = -1;
                   1401:   s.zcmd = NULL;
                   1402:   s.ipos = 0;
                   1403: 
                   1404:   ++cXcmds;
                   1405:   pasXcmds = (struct scmd *) xrealloc ((pointer) pasXcmds,
                   1406:                                       cXcmds * sizeof (struct scmd));
                   1407:   pasXcmds[cXcmds - 1] = s;
                   1408: }
                   1409: 
                   1410: /* Copy stdin to a file.  This is a separate function because it may
                   1411:    call setjmp.  */
                   1412: 
                   1413: static void
                   1414: uxcopy_stdin (e)
                   1415:      FILE *e;
                   1416: {
                   1417:   CATCH_PROTECT size_t cread;
                   1418:   char ab[1024];
                   1419: 
                   1420:   do
                   1421:     {
                   1422:       size_t cwrite;
                   1423: 
                   1424:       /* I want to use fread here, but there is a bug in some versions
                   1425:         of SVR4 which causes fread to return less than a complete
                   1426:         buffer even if EOF has not been reached.  This is not online
                   1427:         time, so speed is not critical, but it's still quite annoying
                   1428:         to have to use an inefficient algorithm.  */
                   1429:       cread = 0;
                   1430:       if (fsysdep_catch ())
                   1431:        {
                   1432:          usysdep_start_catch ();
                   1433: 
                   1434:          while (cread < sizeof (ab))
                   1435:            {
                   1436:              int b;
                   1437: 
                   1438:              if (FGOT_SIGNAL ())
                   1439:                uxabort ();
                   1440: 
                   1441:              /* There's an unimportant race here.  If the user hits
                   1442:                 ^C between the FGOT_SIGNAL we just did and the time
                   1443:                 we enter getchar, we won't know about the signal
                   1444:                 (unless we're doing a longjmp, but we normally
                   1445:                 aren't).  It's not a big problem, because the user
                   1446:                 can just hit ^C again.  */
                   1447:              b = getchar ();
                   1448:              if (b == EOF)
                   1449:                break;
                   1450:              ab[cread] = b;
                   1451:              ++cread;
                   1452:            }
                   1453:        }
                   1454: 
                   1455:       usysdep_end_catch ();
                   1456: 
                   1457:       if (FGOT_SIGNAL ())
                   1458:        uxabort ();
                   1459: 
                   1460:       if (cread > 0)
                   1461:        {
                   1462:          cwrite = fwrite (ab, sizeof (char), cread, e);
                   1463:          if (cwrite != cread)
                   1464:            ulog (LOG_FATAL, "fwrite: Wrote %d when attempted %d",
                   1465:                  (int) cwrite, (int) cread);
                   1466:        }
                   1467:     }
                   1468:   while (cread == sizeof ab);
                   1469: }
                   1470: 
                   1471: /* Keep track of all files we have created so that we can delete them
                   1472:    if we get a signal.  The argument will be on the heap.  */
                   1473: 
                   1474: static int cXfiles;
                   1475: static const char **pXaz;
                   1476: 
                   1477: static void
                   1478: uxrecord_file (zfile)
                   1479:      const char *zfile;
                   1480: {
                   1481:   pXaz = (const char **) xrealloc ((pointer) pXaz,
                   1482:                                   (cXfiles + 1) * sizeof (const char *));
                   1483:   pXaz[cXfiles] = zfile;
                   1484:   ++cXfiles;
                   1485: }
                   1486: 
                   1487: /* Delete all the files we have recorded and exit.  */
                   1488: 
                   1489: static void
                   1490: uxabort ()
                   1491: {
                   1492:   int i;
                   1493: 
                   1494:   if (eXxqt_file != NULL)
                   1495:     (void) fclose (eXxqt_file);
                   1496:   if (eXclose != NULL)
                   1497:     (void) fclose (eXclose);
                   1498:   for (i = 0; i < cXfiles; i++)
                   1499:     (void) remove (pXaz[i]);
                   1500:   ulog_close ();
                   1501:   usysdep_exit (FALSE);
                   1502: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.