Annotation of coherent/g/usr/lib/uucp/tay104/uux.c, revision 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.