|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.