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

1.1       root        1: /* uuxqt.c
                      2:    Run uux commands.
                      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 uuxqt_rcsid[] = "$Id: uuxqt.c,v 1.1 93/07/30 08:00:15 bin Exp Locker: bin $";
                     30: #endif
                     31: 
                     32: #include <errno.h>
                     33: #include <ctype.h>
                     34: 
                     35: #include "getopt.h"
                     36: 
                     37: #include "uudefs.h"
                     38: #include "uuconf.h"
                     39: #include "system.h"
                     40: 
                     41: /* The program name.  */
                     42: char abProgram[] = "uuxqt";
                     43: 
                     44: /* Static variables used to unlock things if we get a fatal error.  */
                     45: static int iQlock_seq = -1;
                     46: static const char *zQunlock_cmd;
                     47: static const char *zQunlock_file;
                     48: static boolean fQunlock_directory;
                     49: int cQmaxuuxqts;
                     50: 
                     51: /* Static variables to free in uqcleanup.  */
                     52: static char *zQoutput;
                     53: static char *zQmail;
                     54: 
                     55: /* Local functions.  */
                     56: static void uqusage P((void));
                     57: static void uqabort P((void));
                     58: static void uqdo_xqt_file P((pointer puuconf, const char *zfile,
                     59:                             const char *zbase,
                     60:                             const struct uuconf_system *qsys,
                     61:                             const char *zlocalname,
                     62:                             const char *zcmd, boolean *pfprocessed));
                     63: static void uqcleanup P((const char *zfile, int iflags));
                     64: static boolean fqforward P((const char *zfile, char **pzallowed,
                     65:                            const char *zlog, const char *zmail));
                     66: 
                     67: /* Long getopt options.  */
                     68: static const struct option asQlongopts[] = { { NULL, 0, NULL, 0 } };
                     69: 
                     70: int
                     71: main (argc, argv)
                     72:      int argc;
                     73:      char **argv;
                     74: {
                     75:   /* The type of command to execute (NULL for any type).  */
                     76:   const char *zcmd = NULL;
                     77:   /* The configuration file name.  */
                     78:   const char *zconfig = NULL;
                     79:   /* The system to execute commands for.  */
                     80:   const char *zdosys = NULL;
                     81:   int iopt;
                     82:   pointer puuconf;
                     83:   int iuuconf;
                     84:   const char *zlocalname;
                     85:   boolean fany;
                     86:   char *z, *zgetsys;
                     87:   boolean ferr;
                     88:   boolean fsys;
                     89:   struct uuconf_system ssys;
                     90: 
                     91:   while ((iopt = getopt_long (argc, argv, "c:I:s:x:", asQlongopts,
                     92:                              (int *) NULL)) != EOF)
                     93:     {
                     94:       switch (iopt)
                     95:        {
                     96:        case 'c':
                     97:          /* Set the type of command to execute.  */
                     98:          zcmd = optarg;
                     99:          break;
                    100: 
                    101:        case 'I':
                    102:          /* Set the configuration file name.  */
                    103:          if (fsysdep_other_config (optarg))
                    104:            zconfig = optarg;
                    105:          break;
                    106: 
                    107:        case 's':
                    108:          zdosys = optarg;
                    109:          break;
                    110: 
                    111:        case 'x':
                    112: #if DEBUG > 1
                    113:          /* Set the debugging level.  */
                    114:          iDebug |= idebug_parse (optarg);
                    115: #endif
                    116:          break;
                    117: 
                    118:        case 0:
                    119:          /* Long option found and flag set.  */
                    120:          break;
                    121: 
                    122:        default:
                    123:          uqusage ();
                    124:          break;
                    125:        }
                    126:     }
                    127: 
                    128:   if (optind != argc)
                    129:     uqusage ();
                    130: 
                    131:   iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
                    132:   if (iuuconf != UUCONF_SUCCESS)
                    133:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    134: 
                    135: #if DEBUG > 1
                    136:   {
                    137:     const char *zdebug;
                    138: 
                    139:     iuuconf = uuconf_debuglevel (puuconf, &zdebug);
                    140:     if (iuuconf != UUCONF_SUCCESS)
                    141:       ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    142:     if (zdebug != NULL)
                    143:       iDebug |= idebug_parse (zdebug);
                    144:   }
                    145: #endif
                    146: 
                    147:   iuuconf = uuconf_maxuuxqts (puuconf, &cQmaxuuxqts);
                    148:   if (iuuconf != UUCONF_SUCCESS)
                    149:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    150: 
                    151: #ifdef SIGINT
                    152:   usysdep_signal (SIGINT);
                    153: #endif
                    154: #ifdef SIGHUP
                    155:   usysdep_signal (SIGHUP);
                    156: #endif
                    157: #ifdef SIGQUIT
                    158:   usysdep_signal (SIGQUIT);
                    159: #endif
                    160: #ifdef SIGTERM
                    161:   usysdep_signal (SIGTERM);
                    162: #endif
                    163: #ifdef SIGPIPE
                    164:   usysdep_signal (SIGPIPE);
                    165: #endif
                    166: 
                    167:   usysdep_initialize (puuconf, INIT_SUID);
                    168: 
                    169:   ulog_to_file (puuconf, TRUE);
                    170:   ulog_fatal_fn (uqabort);
                    171: 
                    172:   iuuconf = uuconf_localname (puuconf, &zlocalname);
                    173:   if (iuuconf == UUCONF_NOT_FOUND)
                    174:     {
                    175:       zlocalname = zsysdep_localname ();
                    176:       if (zlocalname == NULL)
                    177:        exit (EXIT_FAILURE);
                    178:     }
                    179:   else if (iuuconf != UUCONF_SUCCESS)
                    180:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    181: 
                    182:   fsys = FALSE;
                    183: 
                    184:   /* If we were given a system name, canonicalize it, since the system
                    185:      dependent layer will not be returning aliases.  */
                    186:   if (zdosys != NULL)
                    187:     {
                    188:       iuuconf = uuconf_system_info (puuconf, zdosys, &ssys);
                    189:       if (iuuconf == UUCONF_NOT_FOUND)
                    190:        ulog (LOG_FATAL, "%s: System not found", zdosys);
                    191:       else if (iuuconf != UUCONF_SUCCESS)
                    192:        ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
                    193: 
                    194:       zdosys = zbufcpy (ssys.uuconf_zname);
                    195:       fsys = TRUE;
                    196:     }
                    197: 
                    198:   /* Limit the number of uuxqt processes, and make sure we're the only
                    199:      uuxqt daemon running for this command.  */
                    200:   iQlock_seq = ixsysdep_lock_uuxqt (zcmd, cQmaxuuxqts);
                    201:   if (iQlock_seq < 0)
                    202:     {
                    203:       ulog_close ();
                    204:       usysdep_exit (TRUE);
                    205:     }
                    206:   zQunlock_cmd = zcmd;
                    207: 
                    208:   /* Keep scanning the execute files until we don't process any of
                    209:      them.  */
                    210:   do
                    211:     {
                    212:       fany = FALSE;
                    213: 
                    214:       /* Look for each execute file, and run it.  */
                    215: 
                    216:       if (! fsysdep_get_xqt_init ())
                    217:        {
                    218:          ulog_close ();
                    219:          usysdep_exit (FALSE);
                    220:        }
                    221: 
                    222:       while ((z = zsysdep_get_xqt (&zgetsys, &ferr)) != NULL)
                    223:        {
                    224:          const char *zloc;
                    225:          boolean fprocessed;
                    226:          char *zbase;
                    227: 
                    228:          /* It would be more efficient to pass zdosys down to the
                    229:             routines which retrieve execute files.  */
                    230:          if (zdosys != NULL && strcmp (zdosys, zgetsys) != 0)
                    231:            {
                    232:              ubuffree (z);
                    233:              ubuffree (zgetsys);
                    234:              continue;
                    235:            }
                    236: 
                    237:          if (! fsys || strcmp (ssys.uuconf_zname, zgetsys) != 0)
                    238:            {
                    239:              if (fsys)
                    240:                (void) uuconf_system_free (puuconf, &ssys);
                    241: 
                    242:              iuuconf = uuconf_system_info (puuconf, zgetsys,
                    243:                                            &ssys);
                    244:              if (iuuconf != UUCONF_SUCCESS)
                    245:                {
                    246:                  if (iuuconf != UUCONF_NOT_FOUND)
                    247:                    {
                    248:                      ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                    249:                      ubuffree (z);
                    250:                      ubuffree (zgetsys);
                    251:                      continue;
                    252:                    }
                    253:                  else if (strcmp (zgetsys, zlocalname) == 0)
                    254:                    {
                    255:                      iuuconf = uuconf_system_local (puuconf, &ssys);
                    256:                      if (iuuconf != UUCONF_SUCCESS)
                    257:                        {
                    258:                          ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                    259:                          ubuffree (z);
                    260:                          ubuffree (zgetsys);
                    261:                          continue;
                    262:                        }
                    263:                    }
                    264:                  else
                    265:                    {
                    266:                      if (! funknown_system (puuconf, zgetsys, &ssys))
                    267:                        {
                    268:                          ulog (LOG_ERROR,
                    269:                                "%s: Execute file for unknown system %s",
                    270:                                z, zgetsys);
                    271:                          (void) remove (z);
                    272:                          ubuffree (z);
                    273:                          ubuffree (zgetsys);
                    274:                          continue;
                    275:                        }
                    276:                    }
                    277:                }
                    278: 
                    279:              fsys = TRUE;
                    280:            }
                    281: 
                    282:          /* If we've received a signal, get out of the loop.  */
                    283:          if (FGOT_SIGNAL ())
                    284:            {
                    285:              ubuffree (z);
                    286:              ubuffree (zgetsys);
                    287:              break;
                    288:            }
                    289: 
                    290:          zloc = ssys.uuconf_zlocalname;
                    291:          if (zloc == NULL)
                    292:            zloc = zlocalname;
                    293: 
                    294:          ulog_system (ssys.uuconf_zname);
                    295:          zbase = zsysdep_base_name (z);
                    296:          uqdo_xqt_file (puuconf, z, zbase, &ssys, zloc, zcmd, &fprocessed);
                    297:          ubuffree (zbase);
                    298:          ulog_system ((const char *) NULL);
                    299:          ulog_user ((const char *) NULL);
                    300: 
                    301:          if (fprocessed)
                    302:            fany = TRUE;
                    303:          ubuffree (z);
                    304:          ubuffree (zgetsys);
                    305:        }
                    306: 
                    307:       usysdep_get_xqt_free ();
                    308:     }
                    309:   while (fany && ! FGOT_SIGNAL ());
                    310: 
                    311:   (void) fsysdep_unlock_uuxqt (iQlock_seq, zcmd, cQmaxuuxqts);
                    312:   iQlock_seq = -1;
                    313: 
                    314:   ulog_close ();
                    315: 
                    316:   if (FGOT_SIGNAL ())
                    317:     ferr = TRUE;
                    318: 
                    319:   usysdep_exit (! ferr);
                    320: 
                    321:   /* Avoid errors about not returning a value.  */
                    322:   return 0;
                    323: }
                    324: 
                    325: static void
                    326: uqusage ()
                    327: {
                    328:   fprintf (stderr,
                    329:           "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
                    330:           VERSION);
                    331:   fprintf (stderr,
                    332:           "Usage: uuxqt [-c cmd] [-I file] [-s system] [-x debug]\n");
                    333:   fprintf (stderr,
                    334:           " -c cmd: Set type of command to execute\n");
                    335:   fprintf (stderr,
                    336:           " -s system: Execute commands only for named system\n");
                    337:   fprintf (stderr,
                    338:           " -x debug: Set debugging level (0 for none, 9 is max)\n");
                    339: #if HAVE_TAYLOR_CONFIG
                    340:   fprintf (stderr,
                    341:           " -I file: Set configuration file to use\n");
                    342: #endif /* HAVE_TAYLOR_CONFIG */
                    343:   exit (EXIT_FAILURE);
                    344: }
                    345: 
                    346: /* This is the abort function called when we get a fatal error.  */
                    347: 
                    348: static void
                    349: uqabort ()
                    350: {
                    351: #if ! HAVE_HDB_LOGGING
                    352:   /* When using HDB logging, it's a pain to have no system name.  */
                    353:   ulog_system ((const char *) NULL);
                    354: #endif
                    355: 
                    356:   ulog_user ((const char *) NULL);
                    357: 
                    358:   if (fQunlock_directory)
                    359:     (void) fsysdep_unlock_uuxqt_dir (iQlock_seq);
                    360: 
                    361:   if (zQunlock_file != NULL)
                    362:     (void) fsysdep_unlock_uuxqt_file (zQunlock_file);
                    363: 
                    364:   if (iQlock_seq >= 0)
                    365:     (void) fsysdep_unlock_uuxqt (iQlock_seq, zQunlock_cmd, cQmaxuuxqts);
                    366: 
                    367:   ulog_close ();
                    368: 
                    369:   usysdep_exit (FALSE);
                    370: }
                    371: 
                    372: /* An execute file is a series of lines.  The first character of each
                    373:    line is a command.  The following commands are defined:
                    374: 
                    375:    C command-line
                    376:    I standard-input
                    377:    O standard-output [ system ]
                    378:    F required-file filename-to-use
                    379:    R requestor-address
                    380:    U user system
                    381:    Z (acknowledge if command failed; default)
                    382:    N (no acknowledgement on failure)
                    383:    n (acknowledge if command succeeded)
                    384:    B (return command input on error)
                    385:    e (process with sh)
                    386:    E (process with exec)
                    387:    M status-file
                    388:    # comment
                    389: 
                    390:    Unrecognized commands are ignored.  We actually do not recognize
                    391:    the Z command, since it requests default behaviour.  We always send
                    392:    mail on failure, unless the N command appears.  We never send mail
                    393:    on success, unless the n command appears.
                    394: 
                    395:    This code does not currently support the B or M commands.  */
                    396: 
                    397: /* Command arguments.  */
                    398: static char **azQargs;
                    399: /* Command as a complete string.  */
                    400: static char *zQcmd;
                    401: /* Standard input file name.  */
                    402: static char *zQinput;
                    403: /* Standard output file name.  */
                    404: static char *zQoutfile;
                    405: /* Standard output system.  */
                    406: static char *zQoutsys;
                    407: /* Number of required files.  */
                    408: static int cQfiles;
                    409: /* Names of required files.  */
                    410: static char **azQfiles;
                    411: /* Names required files should be renamed to (NULL if original is OK).  */
                    412: static char **azQfiles_to;
                    413: /* Requestor address (this is where mail should be sent).  */
                    414: static char *zQrequestor;
                    415: /* User name.  */
                    416: static const char *zQuser;
                    417: /* System name.  */
                    418: static const char *zQsystem;
                    419: /* This is set by the N flag, meaning that no acknowledgement should
                    420:    be mailed on failure.  */
                    421: static boolean fQno_ack;
                    422: /* This is set by the n flag, meaning that acknowledgement should be
                    423:    mailed if the command succeeded.  */
                    424: static boolean fQsuccess_ack;
                    425: /* This is set by the B flag, meaning that command input should be
                    426:    mailed to the requestor if an error occurred.  */
                    427: static boolean fQsend_input;
                    428: /* This is set by the E flag, meaning that exec should be used to
                    429:    execute the command.  */
                    430: static boolean fQuse_exec;
                    431: /* The status should be copied to this file on the requesting host.  */
                    432: static const char *zQstatus_file;
                    433: #if ALLOW_SH_EXECUTION
                    434: /* This is set by the e flag, meaning that sh should be used to
                    435:    execute the command.  */
                    436: static boolean fQuse_sh;
                    437: #endif /* ALLOW_SH_EXECUTION */
                    438: 
                    439: static int iqcmd P((pointer puuconf, int argc, char **argv, pointer pvar,
                    440:                    pointer pinfo));
                    441: static int iqout P((pointer puuconf, int argc, char **argv, pointer pvar,
                    442:                    pointer pinfo));
                    443: static int iqfile P((pointer puuconf, int argc, char **argv, pointer pvar,
                    444:                     pointer pinfo));
                    445: static int iqrequestor P((pointer puuconf, int argc, char **argv,
                    446:                          pointer pvar, pointer pinfo));
                    447: static int iquser P((pointer puuconf, int argc, char **argv, pointer pvar,
                    448:                     pointer pinfo));
                    449: static int iqset P((pointer puuconf, int argc, char **argv, pointer pvar,
                    450:                    pointer pinfo));
                    451: 
                    452: static const struct uuconf_cmdtab asQcmds[] =
                    453: {
                    454:   { "C", UUCONF_CMDTABTYPE_FN | 0, NULL, iqcmd },
                    455:   { "I", UUCONF_CMDTABTYPE_STRING, (pointer) &zQinput, NULL },
                    456:   { "O", UUCONF_CMDTABTYPE_FN | 0, NULL, iqout },
                    457:   { "F", UUCONF_CMDTABTYPE_FN | 0, NULL, iqfile },
                    458:   { "R", UUCONF_CMDTABTYPE_FN, NULL, iqrequestor },
                    459:   { "U", UUCONF_CMDTABTYPE_FN | 3, NULL, iquser },
                    460:   { "N", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQno_ack, iqset },
                    461:   { "n", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQsuccess_ack, iqset },
                    462:   /* Some systems create execution files in which B takes an argument;
                    463:      I don't know what it means, so I just ignore it.  */
                    464:   { "B", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQsend_input, iqset },
                    465: #if ALLOW_SH_EXECUTION
                    466:   { "e", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQuse_sh, iqset },
                    467: #endif
                    468:   { "E", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQuse_exec, iqset },
                    469:   { "M", UUCONF_CMDTABTYPE_STRING, (pointer) &zQstatus_file, NULL },
                    470:   { NULL, 0, NULL, NULL }
                    471: };
                    472: 
                    473: /* Handle the C command: store off the arguments.  */
                    474: 
                    475: /*ARGSUSED*/
                    476: static int
                    477: iqcmd (puuconf, argc, argv, pvar, pinfo)
                    478:      pointer puuconf;
                    479:      int argc;
                    480:      char **argv;
                    481:      pointer pvar;
                    482:      pointer pinfo;
                    483: {
                    484:   int i;
                    485:   size_t clen;
                    486: 
                    487:   if (argc <= 1)
                    488:     return UUCONF_CMDTABRET_CONTINUE;
                    489: 
                    490:   azQargs = (char **) xmalloc (argc * sizeof (char *));
                    491:   clen = 0;
                    492:   for (i = 1; i < argc; i++)
                    493:     {
                    494:       azQargs[i - 1] = zbufcpy (argv[i]);
                    495:       clen += strlen (argv[i]) + 1;
                    496:     }
                    497:   azQargs[i - 1] = NULL;
                    498: 
                    499:   zQcmd = (char *) xmalloc (clen);
                    500:   zQcmd[0] = '\0';
                    501:   for (i = 1; i < argc - 1; i++)
                    502:     {
                    503:       strcat (zQcmd, argv[i]);
                    504:       strcat (zQcmd, " ");
                    505:     }
                    506:   strcat (zQcmd, argv[i]);
                    507: 
                    508:   return UUCONF_CMDTABRET_CONTINUE;
                    509: }
                    510: 
                    511: /* Handle the O command, which may have one or two arguments.  */
                    512: 
                    513: /*ARGSUSED*/
                    514: static int
                    515: iqout (puuconf, argc, argv, pvar, pinfo)
                    516:      pointer puuconf;
                    517:      int argc;
                    518:      char **argv;
                    519:      pointer pvar;
                    520:      pointer pinfo;
                    521: {
                    522:   const char *zbase = (const char *) pinfo;
                    523: 
                    524:   if (argc != 2 && argc != 3)
                    525:     {
                    526:       ulog (LOG_ERROR, "%s: %s: Wrong number of arguments",
                    527:            zbase, argv[0]);
                    528:       return UUCONF_CMDTABRET_CONTINUE;
                    529:     }
                    530: 
                    531:   zQoutfile = zbufcpy (argv[1]);
                    532:   if (argc == 3)
                    533:     zQoutsys = zbufcpy (argv[2]);
                    534: 
                    535:   return UUCONF_CMDTABRET_CONTINUE;
                    536: }
                    537: 
                    538: /* Handle the F command, which may have one or two arguments.  */
                    539: 
                    540: /*ARGSUSED*/
                    541: static int
                    542: iqfile (puuconf, argc, argv, pvar, pinfo)
                    543:      pointer puuconf;
                    544:      int argc;
                    545:      char **argv;
                    546:      pointer pvar;
                    547:      pointer pinfo;
                    548: {
                    549:   const char *zbase = (const char *) pinfo;
                    550: 
                    551:   if (argc != 2 && argc != 3)
                    552:     {
                    553:       ulog (LOG_ERROR, "%s: %s: Wrong number of arguments",
                    554:            zbase, argv[0]);
                    555:       return UUCONF_CMDTABRET_CONTINUE;
                    556:     }
                    557: 
                    558:   /* If this file is not in the spool directory, just ignore it.  */
                    559:   if (! fspool_file (argv[1]))
                    560:     return UUCONF_CMDTABRET_CONTINUE;
                    561: 
                    562:   ++cQfiles;
                    563:   azQfiles = (char **) xrealloc ((pointer) azQfiles,
                    564:                                 cQfiles * sizeof (char *));
                    565:   azQfiles_to = (char **) xrealloc ((pointer) azQfiles_to,
                    566:                                    cQfiles * sizeof (char *));
                    567: 
                    568:   azQfiles[cQfiles - 1] = zbufcpy (argv[1]);
                    569:   if (argc == 3)
                    570:     azQfiles_to[cQfiles - 1] = zbufcpy (argv[2]);
                    571:   else
                    572:     azQfiles_to[cQfiles - 1] = NULL;
                    573: 
                    574:   return UUCONF_CMDTABRET_CONTINUE;
                    575: }
                    576: 
                    577: /* Handle the R command, which may have one or two arguments.  */
                    578: 
                    579: /*ARGSUSED*/
                    580: static int
                    581: iqrequestor (puuconf, argc, argv, pvar, pinfo)
                    582:      pointer puuconf;
                    583:      int argc;
                    584:      char **argv;
                    585:      pointer pvar;
                    586:      pointer pinfo;
                    587: {
                    588:   const char *zbase = (const char *) pinfo;
                    589: 
                    590:   if (argc != 2 && argc != 3)
                    591:     {
                    592:       ulog (LOG_ERROR, "%s: %s: Wrong number of arguments",
                    593:            zbase, argv[0]);
                    594:       return UUCONF_CMDTABRET_CONTINUE;
                    595:     }
                    596: 
                    597:   /* We normally have a single argument, which is the ``requestor''
                    598:      address, to which we should send any success or error messages.
                    599:      Apparently the DOS program UUPC sends two arguments, which are
                    600:      the username and the host.  */
                    601:   if (argc == 2)
                    602:     zQrequestor = zbufcpy (argv[1]);
                    603:   else
                    604:     {
                    605:       zQrequestor = zbufalc (strlen (argv[1]) + strlen (argv[2])
                    606:                             + sizeof "!");
                    607:       sprintf (zQrequestor, "%s!%s", argv[2], argv[1]);
                    608:     }
                    609: 
                    610:   return UUCONF_CMDTABRET_CONTINUE;
                    611: }
                    612: 
                    613: /* Handle the U command, which takes two arguments.  */
                    614: 
                    615: /*ARGSUSED*/
                    616: static int
                    617: iquser (puuconf, argc, argv, pvar, pinfo)
                    618:      pointer puuconf;
                    619:      int argc;
                    620:      char **argv;
                    621:      pointer pvar;
                    622:      pointer pinfo;
                    623: {
                    624:   zQuser = argv[1];
                    625:   zQsystem = argv[2];
                    626:   return UUCONF_CMDTABRET_KEEP;
                    627: }
                    628: 
                    629: /* Handle various commands which just set boolean variables.  */
                    630: 
                    631: /*ARGSUSED*/
                    632: static int
                    633: iqset (puuconf, argc, argv, pvar, pinfo)
                    634:      pointer puuconf;
                    635:      int argc;
                    636:      char **argv;
                    637:      pointer pvar;
                    638:      pointer pinfo;     
                    639: {
                    640:   boolean *pf = (boolean *) pvar;
                    641: 
                    642:   *pf = TRUE;
                    643:   return UUCONF_CMDTABRET_CONTINUE;
                    644: }
                    645: 
                    646: /* The execution processing does a lot of things that have to be
                    647:    cleaned up.  Rather than try to add the appropriate statements
                    648:    to each return point, we keep a set of flags indicating what
                    649:    has to be cleaned up.  The actual clean up is done by the
                    650:    function uqcleanup.  */
                    651: #define REMOVE_FILE (01)
                    652: #define REMOVE_NEEDED (02)
                    653: #define FREE_QINPUT (04)
                    654: #define FREE_OUTPUT (010)
                    655: #define FREE_MAIL (020)
                    656: 
                    657: /* Process an execute file.  The zfile argument is the name of the
                    658:    execute file.  The zbase argument is the base name of zfile.  The
                    659:    qsys argument describes the system it came from.  The zcmd argument
                    660:    is the name of the command we are executing (from the -c option) or
                    661:    NULL if any command is OK.  This sets *pfprocessed to TRUE if the
                    662:    file is ready to be executed.  */
                    663: 
                    664: static void
                    665: uqdo_xqt_file (puuconf, zfile, zbase, qsys, zlocalname, zcmd, pfprocessed)
                    666:      pointer puuconf;
                    667:      const char *zfile;
                    668:      const char *zbase;
                    669:      const struct uuconf_system *qsys;
                    670:      const char *zlocalname;
                    671:      const char *zcmd;
                    672:      boolean *pfprocessed;
                    673: {
                    674:   char *zabsolute;
                    675:   boolean ferr;
                    676:   FILE *e;
                    677:   int iuuconf;
                    678:   int i;
                    679:   int iclean;
                    680:   const char *zmail;
                    681:   char *zoutput;
                    682:   char *zinput;
                    683:   char abtemp[CFILE_NAME_LEN];
                    684:   char abdata[CFILE_NAME_LEN];
                    685:   char *zerror;
                    686:   struct uuconf_system soutsys;
                    687:   const struct uuconf_system *qoutsys;
                    688:   boolean fshell;
                    689:   size_t clen;
                    690:   char *zfullcmd;
                    691:   boolean ftemp;
                    692: 
                    693:   *pfprocessed = FALSE;
                    694: 
                    695:   e = fopen (zfile, "r");
                    696:   if (e == NULL)
                    697:     return;
                    698: 
                    699:   azQargs = NULL;
                    700:   zQcmd = NULL;
                    701:   zQinput = NULL;
                    702:   zQoutfile = NULL;
                    703:   zQoutsys = NULL;
                    704:   cQfiles = 0;
                    705:   azQfiles = NULL;
                    706:   azQfiles_to = NULL;
                    707:   zQrequestor = NULL;
                    708:   zQuser = NULL;
                    709:   zQsystem = NULL;
                    710:   fQno_ack = FALSE;
                    711:   fQsuccess_ack = FALSE;
                    712:   fQsend_input = FALSE;
                    713:   fQuse_exec = FALSE;
                    714:   zQstatus_file = NULL;
                    715: #if ALLOW_SH_EXECUTION
                    716:   fQuse_sh = FALSE;
                    717: #endif
                    718: 
                    719:   iuuconf = uuconf_cmd_file (puuconf, e, asQcmds, (pointer) zbase,
                    720:                             (uuconf_cmdtabfn) NULL,
                    721:                             UUCONF_CMDTABFLAG_CASE, (pointer) NULL);
                    722:   (void) fclose (e);
                    723: 
                    724:   if (iuuconf != UUCONF_SUCCESS)
                    725:     {
                    726:       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                    727:       return;
                    728:     }
                    729: 
                    730:   iclean = 0;
                    731: 
                    732:   if (azQargs == NULL)
                    733:     {
                    734:       ulog (LOG_ERROR, "%s: No command given", zbase);
                    735:       uqcleanup (zfile, iclean | REMOVE_FILE);
                    736:       return;
                    737:     }
                    738: 
                    739:   if (zcmd != NULL)
                    740:     {
                    741:       if (strcmp (zcmd, azQargs[0]) != 0)
                    742:        {
                    743:          uqcleanup (zfile, iclean);
                    744:          return;
                    745:        }
                    746:     }
                    747:   else
                    748:     {
                    749:       /* If there is a lock file for this particular command already,
                    750:         it means that some other uuxqt is supposed to handle it.  */
                    751:       if (fsysdep_uuxqt_locked (azQargs[0]))
                    752:        {
                    753:          uqcleanup (zfile, iclean);
                    754:          return;
                    755:        }
                    756:     }
                    757: 
                    758:   /* Lock this particular file.  */
                    759:   if (! fsysdep_lock_uuxqt_file (zfile))
                    760:     {
                    761:       uqcleanup (zfile, iclean);
                    762:       return;
                    763:     }
                    764: 
                    765:   zQunlock_file = zfile;
                    766: 
                    767:   /* Now that we have the file locked, make sure it still exists.
                    768:      Otherwise another uuxqt could have just finished processing it
                    769:      and removed the lock file.  */
                    770:   if (! fsysdep_file_exists (zfile))
                    771:     {
                    772:       uqcleanup (zfile, iclean);
                    773:       return;
                    774:     }
                    775: 
                    776:   if (zQuser != NULL)
                    777:     ulog_user (zQuser);
                    778:   else if (zQrequestor != NULL)
                    779:     ulog_user (zQrequestor);
                    780:   else
                    781:     ulog_user ("unknown");
                    782: 
                    783:   /* Make sure that all the required files exist, and get their
                    784:      full names in the spool directory.  */
                    785:   for (i = 0; i < cQfiles; i++)
                    786:     {
                    787:       char *zreal;
                    788: 
                    789:       zreal = zsysdep_spool_file_name (qsys, azQfiles[i], (pointer) NULL);
                    790:       if (zreal == NULL)
                    791:        {
                    792:          uqcleanup (zfile, iclean);
                    793:          return;
                    794:        }
                    795:       if (! fsysdep_file_exists (zreal))
                    796:        {
                    797:          uqcleanup (zfile, iclean);
                    798:          return;
                    799:        }
                    800:       ubuffree (azQfiles[i]);
                    801:       azQfiles[i] = zbufcpy (zreal);
                    802:       ubuffree (zreal);
                    803:     }
                    804: 
                    805:   /* Lock the execution directory.  */
                    806:   if (! fsysdep_lock_uuxqt_dir (iQlock_seq))
                    807:     {
                    808:       ulog (LOG_ERROR, "Could not lock execute directory");
                    809:       uqcleanup (zfile, iclean);
                    810:       return;
                    811:     }
                    812:   fQunlock_directory = TRUE;
                    813: 
                    814:   iclean |= REMOVE_FILE | REMOVE_NEEDED;
                    815:   *pfprocessed = TRUE;
                    816: 
                    817:   /* Get the address to mail results to.  Prepend the system from
                    818:      which the execute file originated, since mail addresses are
                    819:      relative to it.  */
                    820:   zmail = NULL;
                    821:   if (zQrequestor != NULL)
                    822:     zmail = zQrequestor;
                    823:   else if (zQuser != NULL)
                    824:     zmail = zQuser;
                    825:   if (zmail != NULL
                    826:       && zQsystem != NULL
                    827: #if HAVE_INTERNET_MAIL
                    828:       && strchr (zmail, '@') == NULL
                    829: #endif
                    830:       && strcmp (zQsystem, zlocalname) != 0)
                    831:     {
                    832:       char *zset;
                    833: 
                    834:       zset = zbufalc (strlen (zQsystem) + strlen (zmail) + 2);
                    835:       sprintf (zset, "%s!%s", zQsystem, zmail);
                    836:       zmail = zset;
                    837:       zQmail = zset;
                    838:       iclean |= FREE_MAIL;
                    839:     }
                    840: 
                    841:   /* The command "uucp" is handled specially.  We make sure that the
                    842:      appropriate forwarding is permitted, and we add a -u argument to
                    843:      specify the user.  */
                    844:   if (strcmp (azQargs[0], "uucp") == 0)
                    845:     {
                    846:       char *zfrom, *zto;
                    847:       boolean fmany;
                    848:       char **azargs;
                    849:       const char *zuser, *zsystem;
                    850: 
                    851:       zfrom = NULL;
                    852:       zto = NULL;
                    853:       fmany = FALSE;
                    854: 
                    855:       /* Skip all the options, and get the from and to specs.  We
                    856:         don't permit multiple arguments.  */
                    857:       for (i = 1; azQargs[i] != NULL; i++)
                    858:        {
                    859:          if (azQargs[i][0] == '-')
                    860:            {
                    861:              char *zopts;
                    862: 
                    863:              for (zopts = azQargs[i] + 1; *zopts != '\0'; zopts++)
                    864:                {
                    865:                  /* The -g, -n, and -s options take an argument.  */
                    866:                  if (*zopts == 'g' || *zopts == 'n' || *zopts == 's')
                    867:                    {
                    868:                      if (zopts[1] == '\0')
                    869:                        ++i;
                    870:                      break;
                    871:                    }
                    872:                  /* The -I, -u and -x options are not permitted.  */
                    873:                  if (*zopts == 'I' || *zopts == 'u' || *zopts == 'x')
                    874:                    {
                    875:                      *zopts = 'r';
                    876:                      if (zopts[1] != '\0')
                    877:                        zopts[1] = '\0';
                    878:                      else
                    879:                        {
                    880:                          ++i;
                    881:                          azQargs[i] = zbufcpy ("-r");
                    882:                        }
                    883:                      break;
                    884:                    }
                    885:                }
                    886:            }
                    887:          else if (zfrom == NULL)
                    888:            zfrom = azQargs[i];
                    889:          else if (zto == NULL)
                    890:            zto = azQargs[i];
                    891:          else
                    892:            {
                    893:              fmany = TRUE;
                    894:              break;
                    895:            }
                    896:        }
                    897: 
                    898:       /* Add the -u argument.  This is required to let uucp do the
                    899:         correct permissions checking on the file transfer.  */
                    900:       for (i = 0; azQargs[i] != NULL; i++)
                    901:        ;
                    902:       azargs = (char **) xmalloc ((i + 2) * sizeof (char *));
                    903:       azargs[0] = azQargs[0];
                    904:       zuser = zQuser;
                    905:       if (zuser == NULL)
                    906:        zuser = "uucp";
                    907:       zsystem = zQsystem;
                    908:       if (zsystem == NULL)
                    909:        zsystem = qsys->uuconf_zname;
                    910:       azargs[1] = zbufalc (strlen (zsystem) + strlen (zuser)
                    911:                           + sizeof "-u!");
                    912:       sprintf (azargs[1], "-u%s!%s", zsystem, zuser);
                    913:       memcpy (azargs + 2, azQargs + 1, i * sizeof (char *));
                    914:       xfree ((pointer) azQargs);
                    915:       azQargs = azargs;
                    916: 
                    917:       /* Find the uucp binary.  */
                    918:       zabsolute = zsysdep_find_command ("uucp", qsys->uuconf_pzcmds,
                    919:                                        qsys->uuconf_pzpath, &ferr);
                    920:       if (zabsolute == NULL && ! ferr)
                    921:        {
                    922:          const char *azcmds[2];
                    923: 
                    924:          /* If "uucp" is not a permitted command, then the forwarding
                    925:             entries must be set.  */
                    926:          if (! fqforward (zfrom, qsys->uuconf_pzforward_from, "from", zmail)
                    927:              || ! fqforward (zto, qsys->uuconf_pzforward_to, "to", zmail))
                    928:            {
                    929:              uqcleanup (zfile, iclean);
                    930:              return;
                    931:            }
                    932: 
                    933:          /* If "uucp" is not a permitted command, then only uucp
                    934:             requests with a single source are permitted, since that
                    935:             is all that will be generated by uucp or uux.  */
                    936:          if (fmany)
                    937:            {
                    938:              ulog (LOG_ERROR, "Bad uucp request %s", zQcmd);
                    939: 
                    940:              if (zmail != NULL && ! fQno_ack)
                    941:                {
                    942:                  const char *az[20];
                    943: 
                    944:                  i = 0;
                    945:                  az[i++] = "Your execution request failed because it was an";
                    946:                  az[i++] = " unsupported uucp request.\n";
                    947:                  az[i++] = "Execution requested was:\n\t";
                    948:                  az[i++] = zQcmd;
                    949:                  az[i++] = "\n";
                    950: 
                    951:                  (void) fsysdep_mail (zmail, "Execution failed", i, az);
                    952:                }
                    953: 
                    954:              uqcleanup (zfile, iclean);
                    955:              return;
                    956:            }
                    957: 
                    958:          azcmds[0] = "uucp";
                    959:          azcmds[1] = NULL;
                    960:          zabsolute = zsysdep_find_command ("uucp", (char **) azcmds,
                    961:                                            qsys->uuconf_pzpath, &ferr);
                    962:        }
                    963:       if (zabsolute == NULL)
                    964:        {
                    965:          if (! ferr)
                    966:            ulog (LOG_ERROR, "Can't find uucp executable");
                    967: 
                    968:          uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                    969:          *pfprocessed = FALSE;
                    970:          return;
                    971:        }
                    972:     }
                    973:   else
                    974:     {
                    975:       /* Get the pathname to execute.  */
                    976:       zabsolute = zsysdep_find_command (azQargs[0], qsys->uuconf_pzcmds,
                    977:                                        qsys->uuconf_pzpath,
                    978:                                        &ferr);
                    979:       if (zabsolute == NULL)
                    980:        {
                    981:          if (ferr)
                    982:            {
                    983:              /* If we get an error, try again later.  */
                    984:              uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                    985:              *pfprocessed = FALSE;
                    986:              return;
                    987:            }
                    988: 
                    989:          /* Not permitted.  Send mail to requestor.  */
                    990:          ulog (LOG_ERROR, "Not permitted to execute %s",
                    991:                azQargs[0]);
                    992: 
                    993:          if (zmail != NULL && ! fQno_ack)
                    994:            {
                    995:              const char *az[20];
                    996: 
                    997:              i = 0;
                    998:              az[i++] = "Your execution request failed because you are not";
                    999:              az[i++] = " permitted to execute\n\t";
                   1000:              az[i++] = azQargs[0];
                   1001:              az[i++] = "\non this system.\n";
                   1002:              az[i++] = "Execution requested was:\n\t";
                   1003:              az[i++] = zQcmd;
                   1004:              az[i++] = "\n";
                   1005: 
                   1006:              (void) fsysdep_mail (zmail, "Execution failed", i, az);
                   1007:            }
                   1008: 
                   1009:          uqcleanup (zfile, iclean);
                   1010:          return;
                   1011:        }
                   1012:     }
                   1013: 
                   1014:   ubuffree (azQargs[0]);
                   1015:   azQargs[0] = zabsolute;
                   1016: 
                   1017:   for (i = 1; azQargs[i] != NULL; i++)
                   1018:     {
                   1019:       char *zlocal;
                   1020: 
                   1021:       zlocal = zsysdep_xqt_local_file (qsys, azQargs[i]);
                   1022:       if (zlocal != NULL)
                   1023:        {
                   1024:          ubuffree (azQargs[i]);
                   1025:          azQargs[i] = zlocal;
                   1026:        }
                   1027:     }
                   1028: 
                   1029: #if ! ALLOW_FILENAME_ARGUMENTS
                   1030: 
                   1031:   /* Check all the arguments to make sure they don't try to specify
                   1032:      files they are not permitted to access.  */
                   1033:   for (i = 1; azQargs[i] != NULL; i++)
                   1034:     {
                   1035:       if (! fsysdep_xqt_check_file (qsys, azQargs[i]))
                   1036:        {
                   1037:          if (zmail != NULL && ! fQno_ack)
                   1038:            {
                   1039:              const char *az[20];
                   1040:              const char *zfailed;
                   1041: 
                   1042:              zfailed = azQargs[i];
                   1043:              i = 0;
                   1044:              az[i++] = "Your execution request failed because you are not";
                   1045:              az[i++] = " permitted to refer to file\n\t";
                   1046:              az[i++] = zfailed;
                   1047:              az[i++] = "\non this system.\n";
                   1048:              az[i++] = "Execution requested was:\n\t";
                   1049:              az[i++] = zQcmd;
                   1050:              az[i++] = "\n";
                   1051: 
                   1052:              (void) fsysdep_mail (zmail, "Execution failed", i, az);
                   1053:            }
                   1054: 
                   1055:          uqcleanup (zfile, iclean);
                   1056:          return;
                   1057:        }
                   1058:     }
                   1059: 
                   1060: #endif /* ! ALLOW_FILENAME_ARGUMENTS */
                   1061: 
                   1062:   ulog (LOG_NORMAL, "Executing %s (%s)", zbase, zQcmd);
                   1063: 
                   1064:   if (zQinput != NULL)
                   1065:     {
                   1066:       boolean fspool;
                   1067:       char *zreal;
                   1068: 
                   1069:       fspool = fspool_file (zQinput);
                   1070:       if (fspool)
                   1071:        zreal = zsysdep_spool_file_name (qsys, zQinput, (pointer) NULL);
                   1072:       else
                   1073:        zreal = zsysdep_local_file (zQinput, qsys->uuconf_zpubdir);
                   1074:       if (zreal == NULL)
                   1075:        {
                   1076:          /* If we get an error, try again later.  */
                   1077:          uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                   1078:          *pfprocessed = FALSE;
                   1079:          return;
                   1080:        }
                   1081: 
                   1082:       zQinput = zreal;
                   1083:       iclean |= FREE_QINPUT;
                   1084: 
                   1085:       if (! fspool
                   1086:          && ! fin_directory_list (zQinput, qsys->uuconf_pzremote_send,
                   1087:                                   qsys->uuconf_zpubdir, TRUE, TRUE,
                   1088:                                   (const char *) NULL))
                   1089:        {
                   1090:          ulog (LOG_ERROR, "Not permitted to read %s", zQinput);
                   1091:              
                   1092:          if (zmail != NULL && ! fQno_ack)
                   1093:            {
                   1094:              const char *az[20];
                   1095: 
                   1096:              i = 0;
                   1097:              az[i++] = "Your execution request failed because you are";
                   1098:              az[i++] = " not permitted to read\n\t";
                   1099:              az[i++] = zQinput;
                   1100:              az[i++] = "\non this system.\n";
                   1101:              az[i++] = "Execution requested was:\n\t";
                   1102:              az[i++] = zQcmd;
                   1103:              az[i++] = "\n";
                   1104: 
                   1105:              (void) fsysdep_mail (zmail, "Execution failed", i, az);
                   1106:            }
                   1107: 
                   1108:          uqcleanup (zfile, iclean);
                   1109:          return;
                   1110:        }
                   1111:     }
                   1112: 
                   1113:   zoutput = NULL;
                   1114:   if (zQoutfile == NULL)
                   1115:     qoutsys = NULL;
                   1116:   else if (zQoutsys != NULL
                   1117:           && strcmp (zQoutsys, zlocalname) != 0)
                   1118:     {
                   1119:       char *zdata;
                   1120:         
                   1121:       /* The output file is destined for some other system, so we must
                   1122:         use a temporary file to catch standard output.  */
                   1123:       if (strcmp (zQoutsys, qsys->uuconf_zname) == 0)
                   1124:        qoutsys = qsys;
                   1125:       else
                   1126:        {
                   1127:          iuuconf = uuconf_system_info (puuconf, zQoutsys, &soutsys);
                   1128:          if (iuuconf != UUCONF_SUCCESS)
                   1129:            {
                   1130:              if (iuuconf != UUCONF_NOT_FOUND)
                   1131:                {
                   1132:                  ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                   1133:                  uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                   1134:                  *pfprocessed = FALSE;
                   1135:                  return;
                   1136:                }
                   1137: 
                   1138:              if (! funknown_system (puuconf, zQoutsys, &soutsys))
                   1139:                {
                   1140:                  ulog (LOG_ERROR,
                   1141:                        "Can't send standard output to unknown system %s",
                   1142:                        zQoutsys);
                   1143:                  /* We don't send mail to unknown systems, either.
                   1144:                     Maybe we should.  */
                   1145:                  uqcleanup (zfile, iclean);
                   1146:                  return;
                   1147:                }
                   1148:            }
                   1149: 
                   1150:          qoutsys = &soutsys;
                   1151:        }
                   1152: 
                   1153:       zdata = zsysdep_data_file_name (qoutsys, zlocalname,
                   1154:                                      BDEFAULT_UUX_GRADE, FALSE, abtemp,
                   1155:                                      abdata, (char *) NULL);
                   1156:       if (zdata == NULL)
                   1157:        {
                   1158:          /* If we get an error, try again later.  */
                   1159:          uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                   1160:          *pfprocessed = FALSE;
                   1161:          return;
                   1162:        }
                   1163:       zoutput = zdata;
                   1164:       zQoutput = zoutput;
                   1165:       iclean |= FREE_OUTPUT;
                   1166:     }
                   1167:   else
                   1168:     {
                   1169:       boolean fok;
                   1170:         
                   1171:       qoutsys = NULL;
                   1172: 
                   1173:       /* If we permitted the standard output to be redirected into
                   1174:         the spool directory, people could set up phony commands.  */
                   1175:       if (fspool_file (zQoutfile))
                   1176:        fok = FALSE;
                   1177:       else
                   1178:        {
                   1179:          zoutput = zsysdep_local_file (zQoutfile, qsys->uuconf_zpubdir);
                   1180:          if (zoutput == NULL)
                   1181:            {
                   1182:              /* If we get an error, try again later.  */
                   1183:              uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                   1184:              *pfprocessed = FALSE;
                   1185:              return;
                   1186:            }
                   1187:          ubuffree (zQoutfile);
                   1188:          zQoutfile = zoutput;
                   1189: 
                   1190:          /* Make sure it's OK to receive this file.  */
                   1191:          fok = fin_directory_list (zQoutfile,
                   1192:                                    qsys->uuconf_pzremote_receive,
                   1193:                                    qsys->uuconf_zpubdir, TRUE, FALSE,
                   1194:                                    (const char *) NULL);
                   1195:        }
                   1196: 
                   1197:       if (! fok)
                   1198:        {
                   1199:          ulog (LOG_ERROR, "Not permitted to write to %s", zQoutfile);
                   1200:              
                   1201:          if (zmail != NULL && ! fQno_ack)
                   1202:            {
                   1203:              const char *az[20];
                   1204: 
                   1205:              i = 0;
                   1206:              az[i++] = "Your execution request failed because you are";
                   1207:              az[i++] = " not permitted to write to\n\t";
                   1208:              az[i++] = zQoutfile;
                   1209:              az[i++] = "\non this system.\n";
                   1210:              az[i++] = "Execution requested was:\n\t";
                   1211:              az[i++] = zQcmd;
                   1212:              az[i++] = "\n";
                   1213: 
                   1214:              (void) fsysdep_mail (zmail, "Execution failed", i, az);
                   1215:            }
                   1216: 
                   1217:          uqcleanup (zfile, iclean);
                   1218:          return;
                   1219:        }
                   1220:     }
                   1221: 
                   1222:   /* Move the required files to the execution directory if necessary.  */
                   1223:   zinput = zQinput;
                   1224:   if (! fsysdep_move_uuxqt_files (cQfiles, (const char **) azQfiles,
                   1225:                                  (const char **) azQfiles_to,
                   1226:                                  TRUE, iQlock_seq, &zinput))
                   1227:     {
                   1228:       /* If we get an error, try again later.  */
                   1229:       uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                   1230:       *pfprocessed = FALSE;
                   1231:       return;
                   1232:     }
                   1233:   if (zQinput != NULL && strcmp (zQinput, zinput) != 0)
                   1234:     {
                   1235:       if ((iclean & FREE_QINPUT) != 0)
                   1236:        ubuffree (zQinput);
                   1237:       zQinput = zinput;
                   1238:       iclean |= FREE_QINPUT;
                   1239:     }
                   1240: 
                   1241: #if ALLOW_SH_EXECUTION
                   1242:   fshell = fQuse_sh;
                   1243: #else
                   1244:   fshell = FALSE;
                   1245: #endif
                   1246: 
                   1247:   /* Get a shell command which uses the full path of the command to
                   1248:      execute.  */
                   1249:   clen = 0;
                   1250:   for (i = 0; azQargs[i] != NULL; i++)
                   1251:     clen += strlen (azQargs[i]) + 1;
                   1252:   zfullcmd = zbufalc (clen);
                   1253:   strcpy (zfullcmd, azQargs[0]);
                   1254:   for (i = 1; azQargs[i] != NULL; i++)
                   1255:     {
                   1256:       strcat (zfullcmd, " ");
                   1257:       strcat (zfullcmd, azQargs[i]);
                   1258:     }
                   1259: 
                   1260:   if (! fsysdep_execute (qsys,
                   1261:                         zQuser == NULL ? (const char *) "uucp" : zQuser,
                   1262:                         (const char **) azQargs, zfullcmd, zQinput,
                   1263:                         zoutput, fshell, iQlock_seq, &zerror, &ftemp))
                   1264:     {
                   1265:       ubuffree (zfullcmd);
                   1266: 
                   1267:       if (ftemp)
                   1268:        {
                   1269:          ulog (LOG_NORMAL, "Will retry later (%s)", zbase);
                   1270:          if (zoutput != NULL)
                   1271:            (void) remove (zoutput);
                   1272:          if (zerror != NULL)
                   1273:            {
                   1274:              (void) remove (zerror);
                   1275:              ubuffree (zerror);
                   1276:            }
                   1277:          (void) fsysdep_move_uuxqt_files (cQfiles, (const char **) azQfiles,
                   1278:                                           (const char **) azQfiles_to,
                   1279:                                           FALSE, iQlock_seq,
                   1280:                                           (char **) NULL);
                   1281:          uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
                   1282:          *pfprocessed = FALSE;
                   1283:          return;
                   1284:        }
                   1285: 
                   1286:       ulog (LOG_NORMAL, "Execution failed (%s)", zbase);
                   1287: 
                   1288:       if (zmail != NULL && ! fQno_ack)
                   1289:        {
                   1290:          const char **pz;
                   1291:          int cgot;
                   1292:          FILE *eerr;
                   1293:          int istart;
                   1294: 
                   1295:          cgot = 20;
                   1296:          pz = (const char **) xmalloc (cgot * sizeof (const char *));
                   1297:          i = 0;
                   1298:          pz[i++] = "Execution request failed:\n\t";
                   1299:          pz[i++] = zQcmd;
                   1300:          pz[i++] = "\n";
                   1301: 
                   1302:          if (zerror == NULL)
                   1303:            eerr = NULL;
                   1304:          else
                   1305:            eerr = fopen (zerror, "r");
                   1306:          if (eerr == NULL)
                   1307:            {
                   1308:              pz[i++] = "There was no output on standard error\n";
                   1309:              istart = i;
                   1310:            }
                   1311:          else
                   1312:            {
                   1313:              char *zline;
                   1314:              size_t cline;
                   1315: 
                   1316:              pz[i++] = "Standard error output was:\n";
                   1317:              istart = i;
                   1318: 
                   1319:              zline = NULL;
                   1320:              cline = 0;
                   1321:              while (getline (&zline, &cline, eerr) > 0)
                   1322:                {
                   1323:                  if (i >= cgot)
                   1324:                    {
                   1325:                      cgot += 20;
                   1326:                      pz = ((const char **)
                   1327:                            xrealloc ((pointer) pz,
                   1328:                                      cgot * sizeof (const char *)));
                   1329:                    }
                   1330:                  pz[i++] = zbufcpy (zline);
                   1331:                }
                   1332: 
                   1333:              (void) fclose (eerr);
                   1334:              xfree ((pointer) zline);
                   1335:            }
                   1336: 
                   1337:          (void) fsysdep_mail (zmail, "Execution failed", i, pz);
                   1338: 
                   1339:          for (; istart < i; istart++)
                   1340:            ubuffree ((char *) pz[istart]);
                   1341:          xfree ((pointer) pz);
                   1342:        }
                   1343: 
                   1344:       if (qoutsys != NULL)
                   1345:        (void) remove (zoutput);
                   1346:     }
                   1347:   else
                   1348:     {
                   1349:       ubuffree (zfullcmd);
                   1350: 
                   1351:       if (zmail != NULL && fQsuccess_ack)
                   1352:        {
                   1353:          const char *az[20];
                   1354: 
                   1355:          i = 0;
                   1356:          az[i++] = "\nExecution request succeeded:\n\t";
                   1357:          az[i++] = zQcmd;
                   1358:          az[i++] = "\n";
                   1359: 
                   1360:          (void) fsysdep_mail (zmail, "Execution succeded", i, az);
                   1361:        }
                   1362: 
                   1363:       /* Now we may have to uucp the output to some other machine.  */
                   1364: 
                   1365:       if (qoutsys != NULL)
                   1366:        {
                   1367:          struct scmd s;
                   1368: 
                   1369:          /* Fill in the command structure.  */
                   1370: 
                   1371:          s.bcmd = 'S';
                   1372:          s.pseq = NULL;
                   1373:          s.zfrom = abtemp;
                   1374:          s.zto = zQoutfile;
                   1375:          if (zQuser != NULL)
                   1376:            s.zuser = zQuser;
                   1377:          else
                   1378:            s.zuser = "uucp";
                   1379:          if (zmail != NULL && fQsuccess_ack)
                   1380:            s.zoptions = "Cn";
                   1381:          else
                   1382:            s.zoptions = "C";
                   1383:          s.ztemp = abtemp;
                   1384:          s.imode = 0666;
                   1385:          if (zmail != NULL && fQsuccess_ack)
                   1386:            s.znotify = zmail;
                   1387:          else
                   1388:            s.znotify = "";
                   1389:          s.cbytes = -1;
                   1390:          s.zcmd = NULL;
                   1391:          s.ipos = 0;
                   1392: 
                   1393:          ubuffree (zsysdep_spool_commands (qoutsys, BDEFAULT_UUX_GRADE,
                   1394:                                            1, &s));
                   1395:        }
                   1396:     }
                   1397: 
                   1398:   if (zerror != NULL)
                   1399:     {
                   1400:       (void) remove (zerror);
                   1401:       ubuffree (zerror);
                   1402:     }
                   1403: 
                   1404:   uqcleanup (zfile, iclean);
                   1405: }
                   1406: 
                   1407: /* Clean up the results of uqdo_xqt_file.  */
                   1408: 
                   1409: static void
                   1410: uqcleanup (zfile, iflags)
                   1411:      const char *zfile;
                   1412:      int iflags;
                   1413: {
                   1414:   int i;
                   1415: 
                   1416:   DEBUG_MESSAGE2 (DEBUG_SPOOLDIR,
                   1417:                  "uqcleanup: %s, %d", zfile, iflags);
                   1418: 
                   1419:   if (zQunlock_file != NULL)
                   1420:     {
                   1421:       (void) fsysdep_unlock_uuxqt_file (zQunlock_file);
                   1422:       zQunlock_file = NULL;
                   1423:     }
                   1424: 
                   1425:   if ((iflags & REMOVE_FILE) != 0)
                   1426:     (void) remove (zfile);
                   1427: 
                   1428:   if ((iflags & REMOVE_NEEDED) != 0)
                   1429:     {
                   1430:       for (i = 0; i < cQfiles; i++)
                   1431:        {
                   1432:          if (azQfiles[i] != NULL)
                   1433:            (void) remove (azQfiles[i]);
                   1434:        }
                   1435:     }
                   1436: 
                   1437:   if ((iflags & FREE_QINPUT) != 0)
                   1438:     ubuffree (zQinput);
                   1439: 
                   1440:   if ((iflags & FREE_OUTPUT) != 0)
                   1441:     ubuffree (zQoutput);
                   1442:   if ((iflags & FREE_MAIL) != 0)
                   1443:     ubuffree (zQmail);
                   1444: 
                   1445:   if (fQunlock_directory)
                   1446:     {
                   1447:       (void) fsysdep_unlock_uuxqt_dir (iQlock_seq);
                   1448:       fQunlock_directory = FALSE;
                   1449:     }
                   1450: 
                   1451:   for (i = 0; i < cQfiles; i++)
                   1452:     {
                   1453:       ubuffree (azQfiles[i]);
                   1454:       ubuffree (azQfiles_to[i]);
                   1455:     }
                   1456: 
                   1457:   ubuffree (zQoutfile);
                   1458:   ubuffree (zQoutsys);
                   1459:   ubuffree (zQrequestor);
                   1460: 
                   1461:   if (azQargs != NULL)
                   1462:     {
                   1463:       for (i = 0; azQargs[i] != NULL; i++)
                   1464:        ubuffree (azQargs[i]);
                   1465:       xfree ((pointer) azQargs);
                   1466:       azQargs = NULL;
                   1467:     }
                   1468: 
                   1469:   xfree ((pointer) zQcmd);
                   1470:   zQcmd = NULL;
                   1471: 
                   1472:   xfree ((pointer) azQfiles);
                   1473:   azQfiles = NULL;
                   1474: 
                   1475:   xfree ((pointer) azQfiles_to);
                   1476:   azQfiles_to = NULL;
                   1477: }
                   1478: 
                   1479: /* Check whether forwarding is permitted.  */
                   1480: 
                   1481: static boolean
                   1482: fqforward (zfile, pzallowed, zlog, zmail)
                   1483:      const char *zfile;
                   1484:      char **pzallowed;
                   1485:      const char *zlog;
                   1486:      const char *zmail;
                   1487: {
                   1488:   const char *zexclam;
                   1489: 
                   1490:   zexclam = strchr (zfile, '!');
                   1491:   if (zexclam != NULL)
                   1492:     {
                   1493:       size_t clen;
                   1494:       char *zsys;
                   1495:       boolean fret;
                   1496: 
                   1497:       clen = zexclam - zfile;
                   1498:       zsys = zbufalc (clen + 1);
                   1499:       memcpy (zsys, zfile, clen);
                   1500:       zsys[clen] = '\0';
                   1501: 
                   1502:       fret = FALSE;
                   1503:       if (pzallowed != NULL)
                   1504:        {
                   1505:          char **pz;
                   1506: 
                   1507:          for (pz = pzallowed; *pz != NULL; pz++)
                   1508:            {
                   1509:              if (strcmp (*pz, "ANY") == 0
                   1510:                  || strcmp (*pz, zsys) == 0)
                   1511:                {
                   1512:                  fret = TRUE;
                   1513:                  break;
                   1514:                }
                   1515:            }
                   1516:        }
                   1517: 
                   1518:       if (! fret)
                   1519:        {
                   1520:          ulog (LOG_ERROR, "Not permitted to forward %s %s (%s)",
                   1521:                zlog, zsys, zQcmd);
                   1522: 
                   1523:          if (zmail != NULL && ! fQno_ack)
                   1524:            {
                   1525:              int i;
                   1526:              const char *az[20];
                   1527: 
                   1528:              i = 0;
                   1529:              az[i++] = "Your execution request failed because you are";
                   1530:              az[i++] = " not permitted to forward files\n";
                   1531:              az[i++] = zlog;
                   1532:              az[i++] = " the system\n\t";
                   1533:              az[i++] = zsys;
                   1534:              az[i++] = "\n";
                   1535:              az[i++] = "Execution requested was:\n\t";
                   1536:              az[i++] = zQcmd;
                   1537:              az[i++] = "\n";
                   1538: 
                   1539:              (void) fsysdep_mail (zmail, "Execution failed", i, az);
                   1540:            }
                   1541:        }
                   1542: 
                   1543:       ubuffree (zsys);
                   1544: 
                   1545:       return fret;
                   1546:     }
                   1547: 
                   1548:   return TRUE;
                   1549: }

unix.superglobalmegacorp.com

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