1993-08-05 18:28:27 +00:00
|
|
|
|
/* uux.c
|
|
|
|
|
Prepare to execute a command on a remote system.
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
Copyright (C) 1991, 1992, 1993, 1994, 1995 Ian Lance Taylor
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
This file is part of the Taylor UUCP package.
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
1995-08-19 21:30:30 +00:00
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
The author of the program may be contacted at ian@airs.com or
|
1995-08-19 21:30:30 +00:00
|
|
|
|
c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
|
1993-08-05 18:28:27 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "uucp.h"
|
|
|
|
|
|
|
|
|
|
#if USE_RCS_ID
|
1997-02-22 15:28:58 +00:00
|
|
|
|
const char uux_rcsid[] = "$Id$";
|
1993-08-05 18:28:27 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "uudefs.h"
|
|
|
|
|
#include "uuconf.h"
|
|
|
|
|
#include "system.h"
|
|
|
|
|
#include "sysdep.h"
|
|
|
|
|
#include "getopt.h"
|
|
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
/* These character lists should, perhaps, be in sysdep.h. */
|
|
|
|
|
|
|
|
|
|
/* This is the list of shell metacharacters that we check for. If one
|
|
|
|
|
of these is present, we request uuxqt to execute the command with
|
|
|
|
|
/bin/sh. Otherwise we let it execute using execve. */
|
|
|
|
|
|
|
|
|
|
#define ZSHELLCHARS "\"'`*?[;&()|<>\\$"
|
|
|
|
|
|
|
|
|
|
/* This is the list of word separators. We break filename arguments
|
|
|
|
|
at these characters. */
|
|
|
|
|
#define ZSHELLSEPS ";&*|<> \t"
|
|
|
|
|
|
|
|
|
|
/* This is the list of word separators without the redirection
|
|
|
|
|
operators. */
|
|
|
|
|
#define ZSHELLNONREDIRSEPS ";&*| \t"
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
/* Whether this execution is occurring on the local system. */
|
|
|
|
|
static boolean fXxqtlocal;
|
|
|
|
|
|
|
|
|
|
/* The execution system. */
|
|
|
|
|
static struct uuconf_system sXxqtsys;
|
|
|
|
|
|
|
|
|
|
/* The name of local system from the point of view of the execution
|
|
|
|
|
system. */
|
|
|
|
|
static const char *zXxqtloc;
|
|
|
|
|
|
|
|
|
|
/* The job grade to use. */
|
|
|
|
|
static char bXgrade = BDEFAULT_UUX_GRADE;
|
|
|
|
|
|
|
|
|
|
/* The temporary file name of the execute file. */
|
|
|
|
|
static char abXxqt_tname[CFILE_NAME_LEN];
|
|
|
|
|
|
|
|
|
|
/* The name of the execute file on the remote system. */
|
|
|
|
|
static char abXxqt_xname[CFILE_NAME_LEN];
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* The execute file we are creating. */
|
|
|
|
|
static FILE *eXxqt_file;
|
|
|
|
|
|
|
|
|
|
/* A list of commands to be spooled. */
|
|
|
|
|
static struct scmd *pasXcmds;
|
|
|
|
|
static int cXcmds;
|
|
|
|
|
|
|
|
|
|
/* A file to close if we're forced to exit. */
|
|
|
|
|
static FILE *eXclose;
|
1994-05-07 18:14:43 +00:00
|
|
|
|
|
|
|
|
|
/* A list of file names which will match the file names which appear
|
|
|
|
|
in the uucico logs. */
|
|
|
|
|
static char *zXnames;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* Local functions. */
|
|
|
|
|
static void uxusage P((void));
|
1994-05-07 18:14:43 +00:00
|
|
|
|
static void uxhelp P((void));
|
1993-08-05 18:28:27 +00:00
|
|
|
|
static void uxadd_xqt_line P((int bchar, const char *z1, const char *z2));
|
|
|
|
|
static void uxadd_send_file P((const char *zfrom, const char *zto,
|
|
|
|
|
const char *zoptions, const char *ztemp,
|
1995-08-19 21:30:30 +00:00
|
|
|
|
const char *zforward));
|
1993-08-05 18:28:27 +00:00
|
|
|
|
static void uxcopy_stdin P((FILE *e));
|
|
|
|
|
static void uxrecord_file P((const char *zfile));
|
|
|
|
|
static void uxabort P((void));
|
1994-05-07 18:14:43 +00:00
|
|
|
|
static void uxadd_name P((const char *));
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* Long getopt options. */
|
1994-05-07 18:14:43 +00:00
|
|
|
|
static const struct option asXlongopts[] =
|
|
|
|
|
{
|
|
|
|
|
{ "requestor", required_argument, NULL, 'a' },
|
|
|
|
|
{ "return-stdin", no_argument, NULL, 'b' },
|
|
|
|
|
{ "nocopy", no_argument, NULL, 'c' },
|
|
|
|
|
{ "copy", no_argument, NULL, 'C' },
|
|
|
|
|
{ "grade", required_argument, NULL, 'g' },
|
|
|
|
|
{ "jobid", no_argument, NULL, 'j' },
|
|
|
|
|
{ "link", no_argument, NULL, 'l' },
|
|
|
|
|
{ "notification", required_argument, NULL, 2 },
|
|
|
|
|
{ "stdin", no_argument, NULL, 'p' },
|
|
|
|
|
{ "nouucico", no_argument, NULL, 'r' },
|
|
|
|
|
{ "status", required_argument, NULL, 's' },
|
|
|
|
|
{ "noexpand", no_argument, NULL, 'W' },
|
|
|
|
|
{ "config", required_argument, NULL, 'I' },
|
|
|
|
|
{ "debug", required_argument, NULL, 'x' },
|
|
|
|
|
{ "version", no_argument, NULL, 'v' },
|
|
|
|
|
{ "help", no_argument, NULL, 1 },
|
|
|
|
|
{ NULL, 0, NULL, 0 }
|
|
|
|
|
};
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* The main routine. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main (argc, argv)
|
|
|
|
|
int argc;
|
|
|
|
|
char **argv;
|
|
|
|
|
{
|
|
|
|
|
/* -a: requestor address for status reports. */
|
|
|
|
|
const char *zrequestor = NULL;
|
|
|
|
|
/* -b: if true, return standard input on error. */
|
|
|
|
|
boolean fretstdin = FALSE;
|
|
|
|
|
/* -c,-C: if true, copy to spool directory. */
|
|
|
|
|
boolean fcopy = FALSE;
|
|
|
|
|
/* -c: set if -c appears explicitly; if it and -l appear, then if the
|
|
|
|
|
link fails we don't copy the file. */
|
|
|
|
|
boolean fdontcopy = FALSE;
|
|
|
|
|
/* -I: configuration file name. */
|
|
|
|
|
const char *zconfig = NULL;
|
|
|
|
|
/* -j: output job id. */
|
|
|
|
|
boolean fjobid = FALSE;
|
|
|
|
|
/* -l: link file to spool directory. */
|
|
|
|
|
boolean flink = FALSE;
|
|
|
|
|
/* -n: do not notify upon command completion. */
|
|
|
|
|
boolean fno_ack = FALSE;
|
|
|
|
|
/* -p: read standard input for command standard input. */
|
|
|
|
|
boolean fread_stdin = FALSE;
|
|
|
|
|
/* -r: do not start uucico when finished. */
|
|
|
|
|
boolean fuucico = TRUE;
|
|
|
|
|
/* -s: report status to named file. */
|
|
|
|
|
const char *zstatus_file = NULL;
|
|
|
|
|
/* -W: only expand local file names. */
|
|
|
|
|
boolean fexpand = TRUE;
|
|
|
|
|
/* -z: report status only on error. */
|
|
|
|
|
boolean ferror_ack = FALSE;
|
|
|
|
|
int iopt;
|
|
|
|
|
pointer puuconf;
|
|
|
|
|
int iuuconf;
|
|
|
|
|
const char *zlocalname;
|
|
|
|
|
int i;
|
|
|
|
|
size_t clen;
|
|
|
|
|
char *zargs;
|
|
|
|
|
char *zarg;
|
|
|
|
|
char *zcmd;
|
|
|
|
|
const char *zsys;
|
|
|
|
|
char *zexclam;
|
|
|
|
|
boolean fgetcwd;
|
|
|
|
|
const char *zuser;
|
|
|
|
|
char *zforward;
|
|
|
|
|
char **pzargs;
|
|
|
|
|
int calloc_args;
|
|
|
|
|
int cargs;
|
|
|
|
|
const char *zinput_from;
|
|
|
|
|
const char *zinput_to;
|
|
|
|
|
const char *zinput_temp;
|
|
|
|
|
boolean finputcopied;
|
|
|
|
|
char *zcall_system;
|
|
|
|
|
boolean fcall_any;
|
|
|
|
|
struct uuconf_system slocalsys;
|
|
|
|
|
boolean fneedshell;
|
|
|
|
|
char *zfullcmd;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
boolean fpoll;
|
1994-05-07 18:14:43 +00:00
|
|
|
|
char aboptions[10];
|
1993-08-05 18:28:27 +00:00
|
|
|
|
boolean fexit;
|
|
|
|
|
|
1994-05-07 18:14:43 +00:00
|
|
|
|
zProgram = argv[0];
|
|
|
|
|
|
1993-08-05 18:28:27 +00:00
|
|
|
|
/* We need to be able to read a single - as an option, which getopt
|
1994-05-07 18:14:43 +00:00
|
|
|
|
won't do. We handle this by using getopt to scan the argument
|
|
|
|
|
list multiple times, replacing any single "-" with "-p". */
|
|
|
|
|
opterr = 0;
|
|
|
|
|
while (1)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
1995-08-19 21:30:30 +00:00
|
|
|
|
while (getopt_long (argc, argv, "+a:bcCg:I:jlnprs:Wvx:z",
|
1994-05-07 18:14:43 +00:00
|
|
|
|
asXlongopts, (int *) NULL) != EOF)
|
|
|
|
|
;
|
|
|
|
|
if (optind >= argc || strcmp (argv[optind], "-") != 0)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
break;
|
1994-05-07 18:14:43 +00:00
|
|
|
|
argv[optind] = zbufcpy ("-p");
|
|
|
|
|
optind = 0;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
1994-05-07 18:14:43 +00:00
|
|
|
|
opterr = 1;
|
|
|
|
|
optind = 0;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* The leading + in the getopt string means to stop processing
|
|
|
|
|
options as soon as a non-option argument is seen. */
|
1994-05-07 18:14:43 +00:00
|
|
|
|
while ((iopt = getopt_long (argc, argv, "+a:bcCg:I:jlnprs:Wvx:z",
|
1993-08-05 18:28:27 +00:00
|
|
|
|
asXlongopts, (int *) NULL)) != EOF)
|
|
|
|
|
{
|
|
|
|
|
switch (iopt)
|
|
|
|
|
{
|
|
|
|
|
case 'a':
|
|
|
|
|
/* Set requestor name: mail address to which status reports
|
|
|
|
|
should be sent. */
|
|
|
|
|
zrequestor = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
|
/* Return standard input on error. */
|
|
|
|
|
fretstdin = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
|
/* Do not copy local files to spool directory. */
|
|
|
|
|
fcopy = FALSE;
|
|
|
|
|
fdontcopy = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'C':
|
|
|
|
|
/* Copy local files to spool directory. */
|
|
|
|
|
fcopy = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'I':
|
1995-08-19 21:30:30 +00:00
|
|
|
|
/* Configuration file name. */
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (fsysdep_other_config (optarg))
|
|
|
|
|
zconfig = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'j':
|
|
|
|
|
/* Output jobid. */
|
|
|
|
|
fjobid = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
|
/* Set job grade. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
bXgrade = optarg[0];
|
1993-08-05 18:28:27 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'l':
|
|
|
|
|
/* Link file to spool directory. */
|
|
|
|
|
flink = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
/* Do not notify upon command completion. */
|
|
|
|
|
fno_ack = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
|
/* Read standard input for command standard input. */
|
|
|
|
|
fread_stdin = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
|
/* Do not start uucico when finished. */
|
|
|
|
|
fuucico = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
/* Report status to named file. */
|
|
|
|
|
zstatus_file = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'W':
|
|
|
|
|
/* Only expand local file names. */
|
|
|
|
|
fexpand = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'x':
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
/* Set debugging level. */
|
|
|
|
|
iDebug |= idebug_parse (optarg);
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'z':
|
|
|
|
|
/* Report status only on error. */
|
|
|
|
|
ferror_ack = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
1994-05-07 18:14:43 +00:00
|
|
|
|
case 2:
|
|
|
|
|
/* --notify={true,false,error}. */
|
|
|
|
|
if (*optarg == 't'
|
|
|
|
|
|| *optarg == 'T'
|
|
|
|
|
|| *optarg == 'y'
|
|
|
|
|
|| *optarg == 'Y'
|
|
|
|
|
|| *optarg == 'e'
|
|
|
|
|
|| *optarg == 'E')
|
|
|
|
|
{
|
|
|
|
|
ferror_ack = TRUE;
|
|
|
|
|
fno_ack = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (*optarg == 'f'
|
|
|
|
|
|| *optarg == 'F'
|
|
|
|
|
|| *optarg == 'n'
|
|
|
|
|
|| *optarg == 'N')
|
|
|
|
|
{
|
|
|
|
|
ferror_ack = FALSE;
|
|
|
|
|
fno_ack = TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
|
/* Print version and exit. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
printf ("%s: Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995 Ian Lance Taylor\n",
|
1994-05-07 18:14:43 +00:00
|
|
|
|
zProgram, VERSION);
|
|
|
|
|
exit (EXIT_SUCCESS);
|
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
/* --help. */
|
|
|
|
|
uxhelp ();
|
|
|
|
|
exit (EXIT_SUCCESS);
|
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
|
1993-08-05 18:28:27 +00:00
|
|
|
|
case 0:
|
|
|
|
|
/* Long option found and flag set. */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
uxusage ();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-21 11:28:26 +00:00
|
|
|
|
if (! UUCONF_GRADE_LEGAL (bXgrade)
|
|
|
|
|
|| ((bXgrade < '0' || bXgrade > '9')
|
|
|
|
|
&& (bXgrade < 'a' || bXgrade > 'z')
|
|
|
|
|
&& (bXgrade < 'A' || bXgrade > 'Z')))
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "Ignoring illegal grade");
|
1995-08-19 21:30:30 +00:00
|
|
|
|
bXgrade = BDEFAULT_UUX_GRADE;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (optind == argc)
|
|
|
|
|
uxusage ();
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
|
|
|
|
|
if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
|
|
|
|
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
{
|
|
|
|
|
const char *zdebug;
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_debuglevel (puuconf, &zdebug);
|
|
|
|
|
if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
|
|
|
|
if (zdebug != NULL)
|
|
|
|
|
iDebug |= idebug_parse (zdebug);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* The command and files arguments could be quoted in any number of
|
|
|
|
|
ways, so we split them apart ourselves. We do this before
|
|
|
|
|
calling usysdep_initialize because we want to set fgetcwd
|
|
|
|
|
correctly. */
|
|
|
|
|
clen = 1;
|
|
|
|
|
for (i = optind; i < argc; i++)
|
|
|
|
|
clen += strlen (argv[i]) + 1;
|
|
|
|
|
|
|
|
|
|
zargs = zbufalc (clen);
|
|
|
|
|
*zargs = '\0';
|
|
|
|
|
for (i = optind; i < argc; i++)
|
|
|
|
|
{
|
|
|
|
|
strcat (zargs, argv[i]);
|
|
|
|
|
strcat (zargs, " ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The first argument is the command to execute. */
|
|
|
|
|
clen = strcspn (zargs, ZSHELLSEPS);
|
|
|
|
|
zcmd = zbufalc (clen + 1);
|
|
|
|
|
strncpy (zcmd, zargs, clen);
|
|
|
|
|
zcmd[clen] = '\0';
|
|
|
|
|
zargs += clen;
|
|
|
|
|
|
|
|
|
|
/* Split the arguments out into an array. We break the arguments
|
|
|
|
|
into alternating sequences of characters not in ZSHELLSEPS
|
|
|
|
|
and characters in ZSHELLSEPS. We remove whitespace. We
|
|
|
|
|
separate the redirection characters '>' and '<' into their
|
|
|
|
|
own arguments to make them easier to process below. */
|
|
|
|
|
calloc_args = 10;
|
|
|
|
|
pzargs = (char **) xmalloc (calloc_args * sizeof (char *));
|
|
|
|
|
cargs = 0;
|
|
|
|
|
|
|
|
|
|
for (zarg = strtok (zargs, " \t");
|
|
|
|
|
zarg != NULL;
|
|
|
|
|
zarg = strtok ((char *) NULL, " \t"))
|
|
|
|
|
{
|
|
|
|
|
while (*zarg != '\0')
|
|
|
|
|
{
|
|
|
|
|
if (cargs + 1 >= calloc_args)
|
|
|
|
|
{
|
|
|
|
|
calloc_args += 10;
|
|
|
|
|
pzargs = (char **) xrealloc ((pointer) pzargs,
|
|
|
|
|
calloc_args * sizeof (char *));
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (*zarg == '(')
|
|
|
|
|
clen = strlen (zarg);
|
|
|
|
|
else
|
|
|
|
|
clen = strcspn (zarg, ZSHELLSEPS);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (clen > 0)
|
|
|
|
|
{
|
|
|
|
|
pzargs[cargs] = zbufalc (clen + 1);
|
|
|
|
|
memcpy (pzargs[cargs], zarg, clen);
|
|
|
|
|
pzargs[cargs][clen] = '\0';
|
|
|
|
|
++cargs;
|
|
|
|
|
zarg += clen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We deliberately separate '>' and '<' out. */
|
|
|
|
|
if (*zarg != '\0')
|
|
|
|
|
{
|
|
|
|
|
clen = strspn (zarg, ZSHELLNONREDIRSEPS);
|
|
|
|
|
if (clen == 0)
|
|
|
|
|
clen = 1;
|
|
|
|
|
pzargs[cargs] = zbufalc (clen + 1);
|
|
|
|
|
memcpy (pzargs[cargs], zarg, clen);
|
|
|
|
|
pzargs[cargs][clen] = '\0';
|
|
|
|
|
++cargs;
|
|
|
|
|
zarg += clen;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now look through the arguments to see if we are going to need the
|
|
|
|
|
current working directory. We don't try to make a precise
|
|
|
|
|
determination, just a conservative one. The basic idea is that
|
|
|
|
|
we don't want to get the cwd for 'foo!rmail - user' (note that we
|
|
|
|
|
don't examine the command itself). */
|
|
|
|
|
fgetcwd = FALSE;
|
|
|
|
|
for (i = 0; i < cargs; i++)
|
|
|
|
|
{
|
|
|
|
|
if (pzargs[i][0] == '(')
|
|
|
|
|
continue;
|
|
|
|
|
zexclam = strrchr (pzargs[i], '!');
|
|
|
|
|
if (zexclam != NULL && fsysdep_needs_cwd (zexclam + 1))
|
|
|
|
|
{
|
|
|
|
|
fgetcwd = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((pzargs[i][0] == '<' || pzargs[i][0] == '>')
|
|
|
|
|
&& i + 1 < cargs
|
|
|
|
|
&& strchr (pzargs[i + 1], '!') == NULL
|
|
|
|
|
&& fsysdep_needs_cwd (pzargs[i + 1]))
|
|
|
|
|
{
|
|
|
|
|
fgetcwd = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SIGINT
|
|
|
|
|
usysdep_signal (SIGINT);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SIGHUP
|
|
|
|
|
usysdep_signal (SIGHUP);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SIGQUIT
|
|
|
|
|
usysdep_signal (SIGQUIT);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SIGTERM
|
|
|
|
|
usysdep_signal (SIGTERM);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SIGPIPE
|
|
|
|
|
usysdep_signal (SIGPIPE);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
usysdep_initialize (puuconf, INIT_SUID | (fgetcwd ? INIT_GETCWD : 0));
|
|
|
|
|
|
|
|
|
|
ulog_fatal_fn (uxabort);
|
|
|
|
|
|
|
|
|
|
zuser = zsysdep_login_name ();
|
|
|
|
|
|
|
|
|
|
/* Get the local system name. */
|
|
|
|
|
iuuconf = uuconf_localname (puuconf, &zlocalname);
|
|
|
|
|
if (iuuconf == UUCONF_NOT_FOUND)
|
|
|
|
|
{
|
|
|
|
|
zlocalname = zsysdep_localname ();
|
|
|
|
|
if (zlocalname == NULL)
|
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
else if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
|
|
|
|
|
|
|
|
|
/* Get the local system information. */
|
|
|
|
|
iuuconf = uuconf_system_info (puuconf, zlocalname, &slocalsys);
|
|
|
|
|
if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
if (iuuconf != UUCONF_NOT_FOUND)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
|
|
|
|
iuuconf = uuconf_system_local (puuconf, &slocalsys);
|
|
|
|
|
if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
1994-05-07 18:14:43 +00:00
|
|
|
|
slocalsys.uuconf_zname = (char *) zlocalname;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
1994-05-07 18:14:43 +00:00
|
|
|
|
/* Figure out which system the command is to be executed on. */
|
|
|
|
|
zcmd = zremove_local_sys (&slocalsys, zcmd);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
zexclam = strchr (zcmd, '!');
|
|
|
|
|
if (zexclam == NULL)
|
|
|
|
|
{
|
|
|
|
|
zsys = zlocalname;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
fXxqtlocal = TRUE;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
zforward = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1994-05-07 18:14:43 +00:00
|
|
|
|
*zexclam = '\0';
|
1993-08-05 18:28:27 +00:00
|
|
|
|
zsys = zcmd;
|
|
|
|
|
zcmd = zexclam + 1;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
fXxqtlocal = FALSE;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* See if we must forward this command through other systems
|
|
|
|
|
(e.g. uux a!b!cmd). */
|
|
|
|
|
zexclam = strrchr (zcmd, '!');
|
|
|
|
|
if (zexclam == NULL)
|
|
|
|
|
zforward = NULL;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
clen = zexclam - zcmd;
|
|
|
|
|
zforward = zbufalc (clen);
|
|
|
|
|
memcpy (zforward, zcmd, clen);
|
|
|
|
|
zforward[clen] = '\0';
|
|
|
|
|
zcmd = zexclam + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (fXxqtlocal)
|
|
|
|
|
sXxqtsys = slocalsys;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
1995-08-19 21:30:30 +00:00
|
|
|
|
iuuconf = uuconf_system_info (puuconf, zsys, &sXxqtsys);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
if (iuuconf != UUCONF_NOT_FOUND)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! funknown_system (puuconf, zsys, &sXxqtsys))
|
1993-08-05 18:28:27 +00:00
|
|
|
|
ulog (LOG_FATAL, "%s: System not found", zsys);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the local name the remote system know us as. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zXxqtloc = sXxqtsys.uuconf_zlocalname;
|
|
|
|
|
if (zXxqtloc == NULL)
|
|
|
|
|
zXxqtloc = zlocalname;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
/* Look through the arguments. Any argument containing an
|
|
|
|
|
exclamation point character is interpreted as a file name, and is
|
|
|
|
|
sent to the appropriate system. */
|
|
|
|
|
zinput_from = NULL;
|
|
|
|
|
zinput_to = NULL;
|
|
|
|
|
zinput_temp = NULL;
|
|
|
|
|
finputcopied = FALSE;
|
|
|
|
|
zcall_system = NULL;
|
|
|
|
|
fcall_any = FALSE;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cargs; i++)
|
|
|
|
|
{
|
|
|
|
|
const char *zsystem;
|
|
|
|
|
char *zfile;
|
|
|
|
|
char *zforw;
|
|
|
|
|
boolean finput, foutput;
|
|
|
|
|
boolean flocal, fonxqt;
|
|
|
|
|
|
|
|
|
|
/* Check for a parenthesized argument; remove the parentheses
|
|
|
|
|
and otherwise ignore it (this is how an exclamation point is
|
|
|
|
|
quoted). */
|
|
|
|
|
if (pzargs[i][0] == '(')
|
|
|
|
|
{
|
|
|
|
|
clen = strlen (pzargs[i]);
|
|
|
|
|
if (pzargs[i][clen - 1] != ')')
|
|
|
|
|
ulog (LOG_ERROR, "Mismatched parentheses");
|
|
|
|
|
else
|
|
|
|
|
pzargs[i][clen - 1] = '\0';
|
|
|
|
|
++pzargs[i];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check whether we are doing a redirection. */
|
|
|
|
|
finput = FALSE;
|
|
|
|
|
foutput = FALSE;
|
|
|
|
|
if (i + 1 < cargs)
|
|
|
|
|
{
|
|
|
|
|
if (pzargs[i][0] == '<')
|
|
|
|
|
finput = TRUE;
|
|
|
|
|
else if (pzargs[i][0] == '>')
|
|
|
|
|
foutput = TRUE;
|
|
|
|
|
if (finput || foutput)
|
|
|
|
|
{
|
|
|
|
|
pzargs[i] = NULL;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zexclam = strchr (pzargs[i], '!');
|
|
|
|
|
|
|
|
|
|
/* If there is no exclamation point and no redirection, this
|
|
|
|
|
argument is left untouched. */
|
|
|
|
|
if (zexclam == NULL && ! finput && ! foutput)
|
|
|
|
|
continue;
|
|
|
|
|
|
1994-05-07 18:14:43 +00:00
|
|
|
|
if (zexclam != NULL)
|
|
|
|
|
{
|
|
|
|
|
pzargs[i] = zremove_local_sys (&slocalsys, pzargs[i]);
|
|
|
|
|
zexclam = strchr (pzargs[i], '!');
|
|
|
|
|
}
|
|
|
|
|
|
1993-08-05 18:28:27 +00:00
|
|
|
|
/* Get the system name and file name for this file. */
|
|
|
|
|
if (zexclam == NULL)
|
|
|
|
|
{
|
|
|
|
|
zsystem = zlocalname;
|
|
|
|
|
zfile = pzargs[i];
|
|
|
|
|
flocal = TRUE;
|
|
|
|
|
zforw = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*zexclam = '\0';
|
|
|
|
|
zsystem = pzargs[i];
|
|
|
|
|
zfile = zexclam + 1;
|
1994-05-07 18:14:43 +00:00
|
|
|
|
flocal = FALSE;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
zexclam = strrchr (zfile, '!');
|
|
|
|
|
if (zexclam == NULL)
|
|
|
|
|
zforw = NULL;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*zexclam = '\0';
|
|
|
|
|
zforw = zfile;
|
|
|
|
|
zfile = zexclam + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if the file is already on the execution system. */
|
|
|
|
|
if (flocal)
|
1995-08-19 21:30:30 +00:00
|
|
|
|
fonxqt = fXxqtlocal;
|
|
|
|
|
else if (fXxqtlocal)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
fonxqt = FALSE;
|
|
|
|
|
else if (zforward == NULL ? zforw != NULL : zforw == NULL)
|
|
|
|
|
fonxqt = FALSE;
|
|
|
|
|
else if (zforward != NULL
|
|
|
|
|
&& zforw != NULL
|
|
|
|
|
&& strcmp (zforward, zforw) != 0)
|
|
|
|
|
fonxqt = FALSE;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
else if (strcmp (zsystem, sXxqtsys.uuconf_zname) == 0)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
fonxqt = TRUE;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
else if (sXxqtsys.uuconf_pzalias == NULL)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
fonxqt = FALSE;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char **pzal;
|
|
|
|
|
|
|
|
|
|
fonxqt = FALSE;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
for (pzal = sXxqtsys.uuconf_pzalias; *pzal != NULL; pzal++)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
|
|
|
|
if (strcmp (zsystem, *pzal) == 0)
|
|
|
|
|
{
|
|
|
|
|
fonxqt = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Turn the file into an absolute path. */
|
|
|
|
|
if (flocal)
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zfile = zsysdep_local_file_cwd (zfile, sXxqtsys.uuconf_zpubdir,
|
1994-05-07 18:14:43 +00:00
|
|
|
|
(boolean *) NULL);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
else if (fexpand)
|
|
|
|
|
zfile = zsysdep_add_cwd (zfile);
|
|
|
|
|
if (zfile == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
/* Check for output redirection. */
|
|
|
|
|
if (foutput)
|
|
|
|
|
{
|
|
|
|
|
if (flocal)
|
|
|
|
|
{
|
|
|
|
|
if (! fin_directory_list (zfile,
|
1995-08-19 21:30:30 +00:00
|
|
|
|
sXxqtsys.uuconf_pzremote_receive,
|
|
|
|
|
sXxqtsys.uuconf_zpubdir, TRUE,
|
1993-08-05 18:28:27 +00:00
|
|
|
|
FALSE, (const char *) NULL))
|
|
|
|
|
ulog (LOG_FATAL, "Not permitted to create %s", zfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* There are various cases of output redirection.
|
|
|
|
|
|
|
|
|
|
uux cmd >out: The command is executed on the local
|
|
|
|
|
system, and the output file is placed on the local
|
|
|
|
|
system (fonxqt is TRUE).
|
|
|
|
|
|
|
|
|
|
uux cmd >a!out: The command is executed on the local
|
|
|
|
|
system, and the output file is sent to a.
|
|
|
|
|
|
|
|
|
|
uux a!cmd >out: The command is executed on a, and the
|
|
|
|
|
output file is returned to the local system (flocal
|
|
|
|
|
is TRUE).
|
|
|
|
|
|
|
|
|
|
uux a!cmd >a!out: The command is executed on a, and the
|
|
|
|
|
output file is left on a (fonxqt is TRUE).
|
|
|
|
|
|
|
|
|
|
uux a!cmd >b!out: The command is executed on a, and the
|
|
|
|
|
output file is sent to b; traditionally, I believe
|
|
|
|
|
that b is relative to a, rather than to the local
|
|
|
|
|
system. However, this essentially contradicts the
|
|
|
|
|
previous two cases, in which the output file is
|
|
|
|
|
relative to the local system.
|
|
|
|
|
|
|
|
|
|
Now, the cases that we don't handle.
|
|
|
|
|
|
|
|
|
|
uux cmd >a!b!out: The command is executed on the local
|
|
|
|
|
system, and the output file is sent to b via a. This
|
|
|
|
|
requires the local uuxqt to support forwarding of the
|
|
|
|
|
output file.
|
|
|
|
|
|
|
|
|
|
uux a!b!cmd >out: The command is executed on b, which is
|
|
|
|
|
reached via a. Probably the output file is intended
|
|
|
|
|
for the local system, in which case the uuxqt on b
|
|
|
|
|
must support forwarding of the output file.
|
|
|
|
|
|
|
|
|
|
uux a!b!cmd >c!out: Is c relative to b or to the local
|
|
|
|
|
system? If it's relative to b this is easy to
|
|
|
|
|
handle. Otherwise, we must arrange for the file to
|
|
|
|
|
be sent back to the local system and for the local
|
|
|
|
|
system to send it on to c.
|
|
|
|
|
|
|
|
|
|
There are many variations of the last case. It's not at
|
|
|
|
|
all clear to me how they should be handled. */
|
|
|
|
|
if (zforward != NULL || zforw != NULL)
|
|
|
|
|
ulog (LOG_FATAL, "May not forward standard output");
|
|
|
|
|
|
|
|
|
|
if (fonxqt)
|
|
|
|
|
uxadd_xqt_line ('O', zfile, (const char *) NULL);
|
|
|
|
|
else if (flocal)
|
1995-08-19 21:30:30 +00:00
|
|
|
|
uxadd_xqt_line ('O', zfile, zXxqtloc);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
else
|
|
|
|
|
uxadd_xqt_line ('O', zfile, zsystem);
|
|
|
|
|
pzargs[i] = NULL;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (finput)
|
|
|
|
|
{
|
|
|
|
|
if (fread_stdin)
|
|
|
|
|
ulog (LOG_FATAL, "Standard input specified twice");
|
|
|
|
|
pzargs[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flocal)
|
|
|
|
|
{
|
|
|
|
|
char *zuse;
|
|
|
|
|
char *zdata;
|
|
|
|
|
char abtname[CFILE_NAME_LEN];
|
|
|
|
|
char abdname[CFILE_NAME_LEN];
|
|
|
|
|
|
|
|
|
|
/* It's a local file. If requested by -C, copy the file to
|
|
|
|
|
the spool directory. If requested by -l, link the file
|
|
|
|
|
to the spool directory; if the link fails, we copy the
|
|
|
|
|
file, unless -c was explictly used. If the execution is
|
|
|
|
|
occurring on the local system, we force the copy as well,
|
|
|
|
|
because otherwise we would have to have some way to tell
|
|
|
|
|
uuxqt not to move the file. If the file is being shipped
|
|
|
|
|
to another system, we must set up a transfer request.
|
|
|
|
|
First make sure the user has legitimate access, since we
|
|
|
|
|
are running setuid. */
|
|
|
|
|
if (! fsysdep_access (zfile))
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zdata = zsysdep_data_file_name (&sXxqtsys, zXxqtloc, bXgrade, FALSE,
|
1993-08-05 18:28:27 +00:00
|
|
|
|
abtname, abdname, (char *) NULL);
|
|
|
|
|
if (zdata == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (fcopy || flink || fXxqtlocal)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
|
|
|
|
boolean fdid;
|
|
|
|
|
|
|
|
|
|
uxrecord_file (zdata);
|
|
|
|
|
|
|
|
|
|
fdid = FALSE;
|
|
|
|
|
if (flink)
|
|
|
|
|
{
|
|
|
|
|
boolean fworked;
|
|
|
|
|
|
|
|
|
|
if (! fsysdep_link (zfile, zdata, &fworked))
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
if (fworked)
|
|
|
|
|
fdid = TRUE;
|
|
|
|
|
else if (fdontcopy)
|
|
|
|
|
ulog (LOG_FATAL, "%s: Can't link to spool directory",
|
|
|
|
|
zfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! fdid)
|
|
|
|
|
{
|
|
|
|
|
openfile_t efile;
|
|
|
|
|
|
|
|
|
|
efile = esysdep_user_fopen (zfile, TRUE, TRUE);
|
|
|
|
|
if (! ffileisopen (efile))
|
|
|
|
|
uxabort ();
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fcopy_open_file (efile, zdata, FALSE, TRUE, TRUE))
|
1993-08-05 18:28:27 +00:00
|
|
|
|
uxabort ();
|
|
|
|
|
(void) ffileclose (efile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zuse = abtname;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We don't actually use the spool file name, but we
|
|
|
|
|
need a name to use as the destination. */
|
|
|
|
|
ubuffree (zdata);
|
|
|
|
|
/* Make sure the daemon can access the file. */
|
|
|
|
|
if (! fsysdep_daemon_access (zfile))
|
|
|
|
|
uxabort ();
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fin_directory_list (zfile, sXxqtsys.uuconf_pzlocal_send,
|
|
|
|
|
sXxqtsys.uuconf_zpubdir, TRUE,
|
1993-08-05 18:28:27 +00:00
|
|
|
|
TRUE, zuser))
|
|
|
|
|
ulog (LOG_FATAL, "Not permitted to send from %s",
|
|
|
|
|
zfile);
|
|
|
|
|
|
|
|
|
|
zuse = zfile;
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (fXxqtlocal)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
|
|
|
|
if (finput)
|
|
|
|
|
uxadd_xqt_line ('I', zuse, (char *) NULL);
|
|
|
|
|
else
|
|
|
|
|
pzargs[i] = zuse;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
finputcopied = fcopy || flink;
|
|
|
|
|
|
|
|
|
|
if (finput)
|
|
|
|
|
{
|
|
|
|
|
zinput_from = zuse;
|
|
|
|
|
zinput_to = zbufcpy (abdname);
|
|
|
|
|
zinput_temp = zbufcpy (abtname);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *zbase;
|
|
|
|
|
|
|
|
|
|
uxadd_send_file (zuse, abdname,
|
|
|
|
|
finputcopied ? "C" : "c",
|
1995-08-19 21:30:30 +00:00
|
|
|
|
abtname, zforward);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
zbase = zsysdep_base_name (zfile);
|
|
|
|
|
if (zbase == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
uxadd_xqt_line ('F', abdname, zbase);
|
|
|
|
|
pzargs[i] = zbase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (fonxqt)
|
|
|
|
|
{
|
|
|
|
|
/* The file is already on the system where the command is to
|
|
|
|
|
be executed. */
|
|
|
|
|
if (finput)
|
|
|
|
|
uxadd_xqt_line ('I', zfile, (const char *) NULL);
|
|
|
|
|
else
|
|
|
|
|
pzargs[i] = zfile;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
struct uuconf_system sfromsys;
|
|
|
|
|
char abtname[CFILE_NAME_LEN];
|
|
|
|
|
struct scmd s;
|
|
|
|
|
char *zjobid;
|
|
|
|
|
|
|
|
|
|
/* We need to request a remote file. */
|
|
|
|
|
iuuconf = uuconf_system_info (puuconf, zsystem, &sfromsys);
|
|
|
|
|
if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
if (iuuconf != UUCONF_NOT_FOUND)
|
|
|
|
|
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
|
1994-04-02 17:10:19 +00:00
|
|
|
|
if (! funknown_system (puuconf, zsystem, &sfromsys))
|
1993-08-05 18:28:27 +00:00
|
|
|
|
ulog (LOG_FATAL, "%s: System not found", zsystem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fonxqt)
|
|
|
|
|
{
|
|
|
|
|
/* The file is already on the system where the command is to
|
|
|
|
|
be executed. */
|
|
|
|
|
if (finput)
|
|
|
|
|
uxadd_xqt_line ('I', zfile, (const char *) NULL);
|
|
|
|
|
else
|
|
|
|
|
pzargs[i] = zfile;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *zdata;
|
|
|
|
|
|
|
|
|
|
if (! sfromsys.uuconf_fcall_transfer
|
|
|
|
|
&& ! sfromsys.uuconf_fcalled_transfer)
|
|
|
|
|
ulog (LOG_FATAL,
|
|
|
|
|
"Not permitted to transfer files to or from %s",
|
|
|
|
|
sfromsys.uuconf_zname);
|
|
|
|
|
|
|
|
|
|
if (zforw != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* This is ``uux cmd a!b!file''. To make this work,
|
|
|
|
|
we would have to be able to set up a request to a
|
|
|
|
|
to fetch file from b and send it to us. But it
|
|
|
|
|
turns out that that will not work, because when a
|
|
|
|
|
sends us the file we will put it in a's spool
|
|
|
|
|
directory, not the local system spool directory.
|
|
|
|
|
So we won't have any way to find it. This is not
|
|
|
|
|
a conceptual problem, and it could doubtless be
|
|
|
|
|
solved. Please feel free to solve it and send me
|
|
|
|
|
the solution. */
|
|
|
|
|
ulog (LOG_FATAL, "File forwarding not supported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We must request the file from the remote system to
|
|
|
|
|
this one. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zdata = zsysdep_data_file_name (&slocalsys, zXxqtloc, bXgrade,
|
1993-08-05 18:28:27 +00:00
|
|
|
|
FALSE, abtname, (char *) NULL,
|
|
|
|
|
(char *) NULL);
|
|
|
|
|
if (zdata == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
ubuffree (zdata);
|
|
|
|
|
|
|
|
|
|
/* Request the file. The special option '9' is a signal
|
|
|
|
|
to uucico that it's OK to receive a file into the
|
|
|
|
|
spool directory; normally such requests are rejected.
|
|
|
|
|
This privilege is easy to abuse. */
|
|
|
|
|
s.bcmd = 'R';
|
1995-08-19 21:30:30 +00:00
|
|
|
|
s.bgrade = bXgrade;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
s.pseq = NULL;
|
|
|
|
|
s.zfrom = zfile;
|
|
|
|
|
s.zto = zbufcpy (abtname);
|
|
|
|
|
s.zuser = zuser;
|
|
|
|
|
s.zoptions = "9";
|
|
|
|
|
s.ztemp = "";
|
|
|
|
|
s.imode = 0600;
|
|
|
|
|
s.znotify = "";
|
|
|
|
|
s.cbytes = -1;
|
|
|
|
|
s.zcmd = NULL;
|
|
|
|
|
s.ipos = 0;
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zjobid = zsysdep_spool_commands (&sfromsys, bXgrade, 1, &s);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (zjobid == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
if (fjobid)
|
|
|
|
|
printf ("%s\n", zjobid);
|
|
|
|
|
|
|
|
|
|
ubuffree (zjobid);
|
|
|
|
|
|
|
|
|
|
if (fcall_any)
|
|
|
|
|
{
|
|
|
|
|
ubuffree (zcall_system);
|
|
|
|
|
zcall_system = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fcall_any = TRUE;
|
|
|
|
|
zcall_system = zbufcpy (sfromsys.uuconf_zname);
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (fXxqtlocal)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
|
|
|
|
/* Tell the command execution to wait until the file
|
|
|
|
|
has been received, and tell it the real file
|
|
|
|
|
name. */
|
|
|
|
|
if (finput)
|
|
|
|
|
{
|
|
|
|
|
uxadd_xqt_line ('F', abtname, (char *) NULL);
|
|
|
|
|
uxadd_xqt_line ('I', abtname, (char *) NULL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *zbase;
|
|
|
|
|
|
|
|
|
|
zbase = zsysdep_base_name (zfile);
|
|
|
|
|
if (zbase == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
uxadd_xqt_line ('F', abtname, zbase);
|
|
|
|
|
pzargs[i] = zbase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char abxtname[CFILE_NAME_LEN];
|
|
|
|
|
char *zbase;
|
|
|
|
|
char *zxqt;
|
|
|
|
|
FILE *e;
|
|
|
|
|
|
|
|
|
|
/* Now we must arrange to forward the file on to the
|
|
|
|
|
execution system. We need to get a name to give
|
|
|
|
|
the file on the execution system (abxtname). */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zdata = zsysdep_data_file_name (&sXxqtsys, zXxqtloc,
|
|
|
|
|
bXgrade, TRUE, abxtname,
|
1993-08-05 18:28:27 +00:00
|
|
|
|
(char *) NULL,
|
|
|
|
|
(char *) NULL);
|
|
|
|
|
if (zdata == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
ubuffree (zdata);
|
|
|
|
|
|
|
|
|
|
zbase = zsysdep_base_name (zfile);
|
|
|
|
|
if (zbase == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
zxqt = zsysdep_xqt_file_name ();
|
|
|
|
|
if (zxqt == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
e = esysdep_fopen (zxqt, FALSE, FALSE, TRUE);
|
|
|
|
|
if (e == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
uxrecord_file (zxqt);
|
|
|
|
|
|
|
|
|
|
fprintf (e, "U %s %s\n", zsysdep_login_name (),
|
|
|
|
|
zlocalname);
|
|
|
|
|
fprintf (e, "F %s %s\n", abtname, zbase);
|
1995-08-19 21:30:30 +00:00
|
|
|
|
fprintf (e, "C uucp -C -W -d -g %c %s %s!", bXgrade,
|
|
|
|
|
zbase, sXxqtsys.uuconf_zname);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (zforward != NULL)
|
|
|
|
|
fprintf (e, "%s!", zforward);
|
|
|
|
|
fprintf (e, "%s\n", abxtname);
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fstdiosync (e, zxqt))
|
|
|
|
|
ulog (LOG_FATAL, "fsync failed");
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (fclose (e) != 0)
|
|
|
|
|
ulog (LOG_FATAL, "fclose: %s", strerror (errno));
|
|
|
|
|
|
|
|
|
|
if (finput)
|
|
|
|
|
{
|
|
|
|
|
uxadd_xqt_line ('F', abxtname, (char *) NULL);
|
|
|
|
|
uxadd_xqt_line ('I', abxtname, (char *) NULL);
|
|
|
|
|
ubuffree (zbase);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uxadd_xqt_line ('F', abxtname, zbase);
|
|
|
|
|
pzargs[i] = zbase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(void) uuconf_system_free (puuconf, &sfromsys);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If standard input is to be read from the stdin of uux, we read it
|
|
|
|
|
here into a temporary file and send it to the execute system. */
|
|
|
|
|
if (fread_stdin)
|
|
|
|
|
{
|
|
|
|
|
char *zdata;
|
|
|
|
|
char abtname[CFILE_NAME_LEN];
|
|
|
|
|
char abdname[CFILE_NAME_LEN];
|
|
|
|
|
FILE *e;
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zdata = zsysdep_data_file_name (&sXxqtsys, zXxqtloc, bXgrade, FALSE,
|
1993-08-05 18:28:27 +00:00
|
|
|
|
abtname, abdname, (char *) NULL);
|
|
|
|
|
if (zdata == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
e = esysdep_fopen (zdata, FALSE, FALSE, TRUE);
|
|
|
|
|
if (e == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
eXclose = e;
|
|
|
|
|
uxrecord_file (zdata);
|
|
|
|
|
|
|
|
|
|
uxcopy_stdin (e);
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fstdiosync (e, zdata))
|
|
|
|
|
ulog (LOG_FATAL, "fsync failed");
|
1993-08-05 18:28:27 +00:00
|
|
|
|
eXclose = NULL;
|
|
|
|
|
if (fclose (e) != 0)
|
|
|
|
|
ulog (LOG_FATAL, "fclose: %s", strerror (errno));
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (fXxqtlocal)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
uxadd_xqt_line ('I', abtname, (const char *) NULL);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
zinput_from = zbufcpy (abtname);
|
|
|
|
|
zinput_to = zbufcpy (abdname);
|
|
|
|
|
zinput_temp = zinput_from;
|
|
|
|
|
finputcopied = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we are returning standard input, or we're putting the status
|
|
|
|
|
in a file, we can't use an E command. */
|
|
|
|
|
if (fretstdin)
|
|
|
|
|
uxadd_xqt_line ('B', (const char *) NULL, (const char *) NULL);
|
|
|
|
|
|
|
|
|
|
if (zstatus_file != NULL)
|
|
|
|
|
uxadd_xqt_line ('M', zstatus_file, (const char *) NULL);
|
|
|
|
|
|
|
|
|
|
/* Get the complete command line, and decide whether the command
|
|
|
|
|
needs to be executed by the shell. */
|
|
|
|
|
fneedshell = FALSE;
|
|
|
|
|
|
|
|
|
|
if (zcmd[strcspn (zcmd, ZSHELLCHARS)] != '\0')
|
|
|
|
|
fneedshell = TRUE;
|
|
|
|
|
|
|
|
|
|
clen = strlen (zcmd) + 1;
|
|
|
|
|
for (i = 0; i < cargs; i++)
|
|
|
|
|
{
|
|
|
|
|
if (pzargs[i] != NULL)
|
|
|
|
|
{
|
|
|
|
|
clen += strlen (pzargs[i]) + 1;
|
|
|
|
|
if (pzargs[i][strcspn (pzargs[i], ZSHELLCHARS)] != '\0')
|
|
|
|
|
fneedshell = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zfullcmd = zbufalc (clen);
|
|
|
|
|
|
|
|
|
|
strcpy (zfullcmd, zcmd);
|
|
|
|
|
for (i = 0; i < cargs; i++)
|
|
|
|
|
{
|
|
|
|
|
if (pzargs[i] != NULL)
|
|
|
|
|
{
|
|
|
|
|
strcat (zfullcmd, " ");
|
|
|
|
|
strcat (zfullcmd, pzargs[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
fpoll = FALSE;
|
|
|
|
|
|
1993-08-05 18:28:27 +00:00
|
|
|
|
/* If we haven't written anything to the execution file yet, and we
|
|
|
|
|
have a standard input file, and we're not forwarding, then every
|
|
|
|
|
other option can be handled in an E command. */
|
|
|
|
|
if (eXxqt_file == NULL && zinput_from != NULL && zforward == NULL)
|
|
|
|
|
{
|
|
|
|
|
struct scmd s;
|
|
|
|
|
char *zoptions;
|
|
|
|
|
|
|
|
|
|
/* Set up an E command. */
|
|
|
|
|
s.bcmd = 'E';
|
1995-08-19 21:30:30 +00:00
|
|
|
|
s.bgrade = bXgrade;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
s.pseq = NULL;
|
|
|
|
|
s.zuser = zuser;
|
|
|
|
|
s.zfrom = zinput_from;
|
|
|
|
|
s.zto = zinput_to;
|
|
|
|
|
s.zoptions = aboptions;
|
|
|
|
|
zoptions = aboptions;
|
|
|
|
|
*zoptions++ = finputcopied ? 'C' : 'c';
|
|
|
|
|
if (fno_ack)
|
|
|
|
|
*zoptions++ = 'N';
|
|
|
|
|
if (ferror_ack)
|
|
|
|
|
*zoptions++ = 'Z';
|
|
|
|
|
if (zrequestor != NULL)
|
|
|
|
|
*zoptions++ = 'R';
|
|
|
|
|
if (fneedshell)
|
|
|
|
|
*zoptions++ = 'e';
|
|
|
|
|
*zoptions = '\0';
|
|
|
|
|
s.ztemp = zinput_temp;
|
|
|
|
|
s.imode = 0666;
|
|
|
|
|
if (zrequestor == NULL)
|
|
|
|
|
zrequestor = "\"\"";
|
|
|
|
|
s.znotify = zrequestor;
|
|
|
|
|
s.cbytes = -1;
|
|
|
|
|
s.zcmd = zfullcmd;
|
|
|
|
|
s.ipos = 0;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
|
1993-08-05 18:28:27 +00:00
|
|
|
|
++cXcmds;
|
|
|
|
|
pasXcmds = (struct scmd *) xrealloc ((pointer) pasXcmds,
|
|
|
|
|
cXcmds * sizeof (struct scmd));
|
|
|
|
|
pasXcmds[cXcmds - 1] = s;
|
1994-05-07 18:14:43 +00:00
|
|
|
|
|
|
|
|
|
uxadd_name (zinput_from);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
1995-08-19 21:30:30 +00:00
|
|
|
|
else if (*zfullcmd == '\0'
|
|
|
|
|
&& eXxqt_file == NULL
|
|
|
|
|
&& zinput_from == NULL
|
|
|
|
|
&& cXcmds == 0)
|
|
|
|
|
{
|
|
|
|
|
/* As a special case, if we are asked to execute an empty
|
|
|
|
|
command, we create a poll file instead. */
|
|
|
|
|
fpoll = TRUE;
|
|
|
|
|
}
|
1993-08-05 18:28:27 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Finish up the execute file. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
uxadd_xqt_line ('U', zuser, zXxqtloc);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (zinput_from != NULL)
|
|
|
|
|
{
|
|
|
|
|
uxadd_xqt_line ('F', zinput_to, (char *) NULL);
|
|
|
|
|
uxadd_xqt_line ('I', zinput_to, (char *) NULL);
|
|
|
|
|
uxadd_send_file (zinput_from, zinput_to,
|
|
|
|
|
finputcopied ? "C" : "c",
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zinput_temp, zforward);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
if (fno_ack)
|
|
|
|
|
uxadd_xqt_line ('N', (const char *) NULL, (const char *) NULL);
|
|
|
|
|
if (ferror_ack)
|
|
|
|
|
uxadd_xqt_line ('Z', (const char *) NULL, (const char *) NULL);
|
|
|
|
|
if (zrequestor != NULL)
|
|
|
|
|
uxadd_xqt_line ('R', zrequestor, (const char *) NULL);
|
|
|
|
|
if (fneedshell)
|
|
|
|
|
uxadd_xqt_line ('e', (const char *) NULL, (const char *) NULL);
|
|
|
|
|
uxadd_xqt_line ('C', zfullcmd, (const char *) NULL);
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fstdiosync (eXxqt_file, "execution file"))
|
|
|
|
|
ulog (LOG_FATAL, "fsync failed");
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (fclose (eXxqt_file) != 0)
|
|
|
|
|
ulog (LOG_FATAL, "fclose: %s", strerror (errno));
|
|
|
|
|
eXxqt_file = NULL;
|
|
|
|
|
|
|
|
|
|
/* If the execution is to occur on another system, we must now
|
|
|
|
|
arrange to copy the execute file to this system. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fXxqtlocal)
|
|
|
|
|
uxadd_send_file (abXxqt_tname, abXxqt_xname, "C", abXxqt_tname,
|
|
|
|
|
zforward);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we got a signal, get out before spooling anything. */
|
|
|
|
|
if (FGOT_SIGNAL ())
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
/* From here on in, it's too late. We don't call uxabort. */
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (cXcmds > 0 || fpoll)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
|
|
|
|
char *zjobid;
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fpoll
|
|
|
|
|
&& ! sXxqtsys.uuconf_fcall_transfer
|
|
|
|
|
&& ! sXxqtsys.uuconf_fcalled_transfer)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
ulog (LOG_FATAL, "Not permitted to transfer files to or from %s",
|
1995-08-19 21:30:30 +00:00
|
|
|
|
sXxqtsys.uuconf_zname);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zjobid = zsysdep_spool_commands (&sXxqtsys, bXgrade, cXcmds, pasXcmds);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (zjobid == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog_close ();
|
|
|
|
|
usysdep_exit (FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fjobid)
|
|
|
|
|
printf ("%s\n", zjobid);
|
|
|
|
|
|
|
|
|
|
ubuffree (zjobid);
|
|
|
|
|
|
|
|
|
|
if (fcall_any)
|
|
|
|
|
{
|
|
|
|
|
ubuffree (zcall_system);
|
|
|
|
|
zcall_system = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fcall_any = TRUE;
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zcall_system = zbufcpy (sXxqtsys.uuconf_zname);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fpoll)
|
|
|
|
|
{
|
|
|
|
|
/* If all that worked, make a log file entry. All log file
|
|
|
|
|
reports up to this point went to stderr. */
|
|
|
|
|
ulog_to_file (puuconf, TRUE);
|
|
|
|
|
ulog_system (sXxqtsys.uuconf_zname);
|
|
|
|
|
ulog_user (zuser);
|
|
|
|
|
|
|
|
|
|
if (zXnames == NULL)
|
|
|
|
|
ulog (LOG_NORMAL, "Queuing %s", zfullcmd);
|
|
|
|
|
else
|
|
|
|
|
ulog (LOG_NORMAL, "Queuing %s (%s)", zfullcmd, zXnames);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
ulog_close ();
|
|
|
|
|
}
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
1994-05-07 18:14:43 +00:00
|
|
|
|
if (! fuucico
|
|
|
|
|
|| (zcall_system == NULL && ! fcall_any))
|
1995-08-19 21:30:30 +00:00
|
|
|
|
{
|
|
|
|
|
if (! fXxqtlocal || ! fuucico)
|
|
|
|
|
fexit = TRUE;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *zconfigarg;
|
|
|
|
|
|
|
|
|
|
if (zconfig == NULL)
|
|
|
|
|
zconfigarg = NULL;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
zconfigarg = zbufalc (sizeof "-I" + strlen (zconfig));
|
|
|
|
|
sprintf (zconfigarg, "-I%s", zconfig);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fexit = fsysdep_run (FALSE, "uuxqt", zconfigarg,
|
|
|
|
|
(const char *) NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
1993-08-05 18:28:27 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
1994-05-07 18:14:43 +00:00
|
|
|
|
const char *zcicoarg;
|
|
|
|
|
char *zconfigarg;
|
|
|
|
|
|
|
|
|
|
if (zcall_system == NULL)
|
|
|
|
|
zcicoarg = "-r1";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *z;
|
|
|
|
|
|
|
|
|
|
z = zbufalc (sizeof "-Cs" + strlen (zcall_system));
|
|
|
|
|
sprintf (z, "-Cs%s", zcall_system);
|
|
|
|
|
zcicoarg = z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (zconfig == NULL)
|
|
|
|
|
zconfigarg = NULL;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
else
|
1994-05-07 18:14:43 +00:00
|
|
|
|
{
|
|
|
|
|
zconfigarg = zbufalc (sizeof "-I" + strlen (zconfig));
|
|
|
|
|
sprintf (zconfigarg, "-I%s", zconfig);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fexit = fsysdep_run (FALSE, "uucico", zcicoarg, zconfigarg);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usysdep_exit (fexit);
|
|
|
|
|
|
|
|
|
|
/* Avoid error about not returning a value. */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Report command usage. */
|
|
|
|
|
|
|
|
|
|
static void
|
1994-05-07 18:14:43 +00:00
|
|
|
|
uxhelp ()
|
1993-08-05 18:28:27 +00:00
|
|
|
|
{
|
1995-08-19 21:30:30 +00:00
|
|
|
|
printf ("Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995 Ian Lance Taylor\n",
|
1994-05-07 18:14:43 +00:00
|
|
|
|
VERSION);
|
|
|
|
|
printf ("Usage: %s [options] [-] command\n", zProgram);
|
|
|
|
|
printf (" -,-p,--stdin: Read standard input for standard input of command\n");
|
|
|
|
|
printf (" -c,--nocopy: Do not copy local files to spool directory (default)\n");
|
|
|
|
|
printf (" -C,--copy: Copy local files to spool directory\n");
|
|
|
|
|
printf (" -l,--link: link local files to spool directory\n");
|
|
|
|
|
printf (" -g,--grade grade: Set job grade (must be alphabetic)\n");
|
|
|
|
|
printf (" -n,--notification=no: Do not report completion status\n");
|
|
|
|
|
printf (" -z,--notification=error: Report completion status only on error\n");
|
|
|
|
|
printf (" -r,--nouucico: Do not start uucico daemon\n");
|
|
|
|
|
printf (" -a,--requestor address: Address to mail status report to\n");
|
|
|
|
|
printf (" -b,--return-stdin: Return standard input with status report\n");
|
|
|
|
|
printf (" -s,--status file: Report completion status to file\n");
|
|
|
|
|
printf (" -j,--jobid: Report job id\n");
|
|
|
|
|
printf (" -x,--debug debug: Set debugging level\n");
|
1993-08-05 18:28:27 +00:00
|
|
|
|
#if HAVE_TAYLOR_CONFIG
|
1994-05-07 18:14:43 +00:00
|
|
|
|
printf (" -I,--config file: Set configuration file to use\n");
|
1993-08-05 18:28:27 +00:00
|
|
|
|
#endif /* HAVE_TAYLOR_CONFIG */
|
1994-05-07 18:14:43 +00:00
|
|
|
|
printf (" -v,--version: Print version and exit\n");
|
|
|
|
|
printf (" --help: Print help and exit\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
uxusage ()
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr,
|
|
|
|
|
"Usage: %s [options] [-] command\n", zProgram);
|
|
|
|
|
fprintf (stderr, "Use %s --help for help\n", zProgram);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add a line to the execute file. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
uxadd_xqt_line (bchar, z1, z2)
|
|
|
|
|
int bchar;
|
|
|
|
|
const char *z1;
|
|
|
|
|
const char *z2;
|
|
|
|
|
{
|
|
|
|
|
if (eXxqt_file == NULL)
|
|
|
|
|
{
|
1995-08-19 21:30:30 +00:00
|
|
|
|
const char *zxqt_name;
|
|
|
|
|
|
|
|
|
|
if (fXxqtlocal)
|
|
|
|
|
zxqt_name = zsysdep_xqt_file_name ();
|
|
|
|
|
else
|
|
|
|
|
zxqt_name = zsysdep_data_file_name (&sXxqtsys, zXxqtloc, bXgrade, TRUE,
|
|
|
|
|
abXxqt_tname, (char *) NULL,
|
|
|
|
|
abXxqt_xname);
|
|
|
|
|
if (zxqt_name == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
uxrecord_file (zxqt_name);
|
|
|
|
|
|
|
|
|
|
eXxqt_file = esysdep_fopen (zxqt_name, FALSE, FALSE, TRUE);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (eXxqt_file == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (z1 == NULL)
|
|
|
|
|
fprintf (eXxqt_file, "%c\n", bchar);
|
|
|
|
|
else if (z2 == NULL)
|
|
|
|
|
fprintf (eXxqt_file, "%c %s\n", bchar, z1);
|
|
|
|
|
else
|
|
|
|
|
fprintf (eXxqt_file, "%c %s %s\n", bchar, z1, z2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add a file to be sent to the execute system. */
|
|
|
|
|
|
|
|
|
|
static void
|
1995-08-19 21:30:30 +00:00
|
|
|
|
uxadd_send_file (zfrom, zto, zoptions, ztemp, zforward)
|
1993-08-05 18:28:27 +00:00
|
|
|
|
const char *zfrom;
|
|
|
|
|
const char *zto;
|
|
|
|
|
const char *zoptions;
|
|
|
|
|
const char *ztemp;
|
|
|
|
|
const char *zforward;
|
|
|
|
|
{
|
|
|
|
|
struct scmd s;
|
|
|
|
|
|
|
|
|
|
if (zforward != NULL)
|
|
|
|
|
{
|
|
|
|
|
char *zbase;
|
|
|
|
|
char *zxqt;
|
|
|
|
|
char abtname[CFILE_NAME_LEN];
|
|
|
|
|
char abdname[CFILE_NAME_LEN];
|
|
|
|
|
char abxname[CFILE_NAME_LEN];
|
|
|
|
|
FILE *e;
|
|
|
|
|
|
|
|
|
|
/* We want to forward this file through the first execution
|
|
|
|
|
system to other systems. We set up a remote execution of
|
|
|
|
|
uucp to forward the file. */
|
|
|
|
|
zbase = zsysdep_base_name (zfrom);
|
|
|
|
|
if (zbase == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
zxqt = zsysdep_data_file_name (&sXxqtsys, zXxqtloc, bXgrade, TRUE,
|
|
|
|
|
abtname, abdname, abxname);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (zxqt == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
e = esysdep_fopen (zxqt, FALSE, FALSE, TRUE);
|
|
|
|
|
if (e == NULL)
|
|
|
|
|
uxabort ();
|
|
|
|
|
uxrecord_file (zxqt);
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
fprintf (e, "U %s %s\n", zsysdep_login_name (), zXxqtloc);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
fprintf (e, "F %s %s\n", abdname, zbase);
|
|
|
|
|
fprintf (e, "C uucp -C -W -d -g %c %s %s!%s\n",
|
1995-08-19 21:30:30 +00:00
|
|
|
|
bXgrade, zbase, zforward, zto);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
|
|
|
|
|
ubuffree (zbase);
|
|
|
|
|
|
1995-08-19 21:30:30 +00:00
|
|
|
|
if (! fstdiosync (e, zxqt))
|
|
|
|
|
ulog (LOG_FATAL, "fsync failed");
|
1993-08-05 18:28:27 +00:00
|
|
|
|
if (fclose (e) != 0)
|
|
|
|
|
ulog (LOG_FATAL, "fclose: %s", strerror (errno));
|
|
|
|
|
|
|
|
|
|
/* Send the execution file. */
|
|
|
|
|
s.bcmd = 'S';
|
1995-08-19 21:30:30 +00:00
|
|
|
|
s.bgrade = bXgrade;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
s.pseq = NULL;
|
|
|
|
|
s.zfrom = zbufcpy (abtname);
|
|
|
|
|
s.zto = zbufcpy (abxname);
|
|
|
|
|
s.zuser = zsysdep_login_name ();
|
|
|
|
|
s.zoptions = "C";
|
|
|
|
|
s.ztemp = s.zfrom;
|
|
|
|
|
s.imode = 0666;
|
|
|
|
|
s.znotify = NULL;
|
|
|
|
|
s.cbytes = -1;
|
|
|
|
|
s.zcmd = NULL;
|
|
|
|
|
s.ipos = 0;
|
|
|
|
|
|
|
|
|
|
++cXcmds;
|
|
|
|
|
pasXcmds = (struct scmd *) xrealloc ((pointer) pasXcmds,
|
|
|
|
|
cXcmds * sizeof (struct scmd));
|
|
|
|
|
pasXcmds[cXcmds - 1] = s;
|
|
|
|
|
|
1994-05-07 18:14:43 +00:00
|
|
|
|
uxadd_name (abtname);
|
|
|
|
|
|
1993-08-05 18:28:27 +00:00
|
|
|
|
/* Send the data file to abdname where the execution file will
|
|
|
|
|
expect it. */
|
|
|
|
|
zto = abdname;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.bcmd = 'S';
|
1995-08-19 21:30:30 +00:00
|
|
|
|
s.bgrade = bXgrade;
|
1993-08-05 18:28:27 +00:00
|
|
|
|
s.pseq = NULL;
|
|
|
|
|
s.zfrom = zbufcpy (zfrom);
|
|
|
|
|
s.zto = zbufcpy (zto);
|
|
|
|
|
s.zuser = zsysdep_login_name ();
|
|
|
|
|
s.zoptions = zbufcpy (zoptions);
|
|
|
|
|
s.ztemp = zbufcpy (ztemp);
|
|
|
|
|
s.imode = 0666;
|
|
|
|
|
s.znotify = "";
|
|
|
|
|
s.cbytes = -1;
|
|
|
|
|
s.zcmd = NULL;
|
|
|
|
|
s.ipos = 0;
|
|
|
|
|
|
|
|
|
|
++cXcmds;
|
|
|
|
|
pasXcmds = (struct scmd *) xrealloc ((pointer) pasXcmds,
|
|
|
|
|
cXcmds * sizeof (struct scmd));
|
|
|
|
|
pasXcmds[cXcmds - 1] = s;
|
1994-05-07 18:14:43 +00:00
|
|
|
|
|
|
|
|
|
uxadd_name (zfrom);
|
1993-08-05 18:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy stdin to a file. This is a separate function because it may
|
|
|
|
|
call setjmp. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
uxcopy_stdin (e)
|
|
|
|
|
FILE *e;
|
|
|
|
|
{
|
|
|
|
|
CATCH_PROTECT size_t cread;
|
|
|
|
|
char ab[1024];
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
size_t cwrite;
|
|
|
|
|
|
|
|
|
|
/* I want to use fread here, but there is a bug in some versions
|
|
|
|
|
of SVR4 which causes fread to return less than a complete
|
|
|
|
|
buffer even if EOF has not been reached. This is not online
|
|
|
|
|
time, so speed is not critical, but it's still quite annoying
|
|
|
|
|
to have to use an inefficient algorithm. */
|
|
|
|
|
cread = 0;
|
|
|
|
|
if (fsysdep_catch ())
|
|
|
|
|
{
|
|
|
|
|
usysdep_start_catch ();
|
|
|
|
|
|
|
|
|
|
while (cread < sizeof (ab))
|
|
|
|
|
{
|
|
|
|
|
int b;
|
|
|
|
|
|
|
|
|
|
if (FGOT_SIGNAL ())
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
/* There's an unimportant race here. If the user hits
|
|
|
|
|
^C between the FGOT_SIGNAL we just did and the time
|
|
|
|
|
we enter getchar, we won't know about the signal
|
|
|
|
|
(unless we're doing a longjmp, but we normally
|
|
|
|
|
aren't). It's not a big problem, because the user
|
|
|
|
|
can just hit ^C again. */
|
|
|
|
|
b = getchar ();
|
|
|
|
|
if (b == EOF)
|
|
|
|
|
break;
|
|
|
|
|
ab[cread] = b;
|
|
|
|
|
++cread;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usysdep_end_catch ();
|
|
|
|
|
|
|
|
|
|
if (FGOT_SIGNAL ())
|
|
|
|
|
uxabort ();
|
|
|
|
|
|
|
|
|
|
if (cread > 0)
|
|
|
|
|
{
|
|
|
|
|
cwrite = fwrite (ab, sizeof (char), cread, e);
|
|
|
|
|
if (cwrite != cread)
|
|
|
|
|
ulog (LOG_FATAL, "fwrite: Wrote %d when attempted %d",
|
|
|
|
|
(int) cwrite, (int) cread);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (cread == sizeof ab);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Keep track of all files we have created so that we can delete them
|
|
|
|
|
if we get a signal. The argument will be on the heap. */
|
|
|
|
|
|
|
|
|
|
static int cXfiles;
|
|
|
|
|
static const char **pXaz;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
uxrecord_file (zfile)
|
|
|
|
|
const char *zfile;
|
|
|
|
|
{
|
|
|
|
|
pXaz = (const char **) xrealloc ((pointer) pXaz,
|
|
|
|
|
(cXfiles + 1) * sizeof (const char *));
|
|
|
|
|
pXaz[cXfiles] = zfile;
|
|
|
|
|
++cXfiles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Delete all the files we have recorded and exit. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
uxabort ()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (eXxqt_file != NULL)
|
|
|
|
|
(void) fclose (eXxqt_file);
|
|
|
|
|
if (eXclose != NULL)
|
|
|
|
|
(void) fclose (eXclose);
|
|
|
|
|
for (i = 0; i < cXfiles; i++)
|
|
|
|
|
(void) remove (pXaz[i]);
|
|
|
|
|
ulog_close ();
|
|
|
|
|
usysdep_exit (FALSE);
|
|
|
|
|
}
|
1994-05-07 18:14:43 +00:00
|
|
|
|
|
|
|
|
|
/* Add a name to the list of file names we are going to log. We log
|
|
|
|
|
all the file names which will appear in the uucico log file. This
|
|
|
|
|
permits people to associate the file send in the uucico log with
|
|
|
|
|
the uux entry which created the file. Normally only one file name
|
|
|
|
|
will appear. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
uxadd_name (z)
|
|
|
|
|
const char *z;
|
|
|
|
|
{
|
|
|
|
|
if (zXnames == NULL)
|
|
|
|
|
zXnames = zbufcpy (z);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
size_t cold, cadd;
|
|
|
|
|
char *znew;
|
|
|
|
|
|
|
|
|
|
cold = strlen (zXnames);
|
|
|
|
|
cadd = strlen (z);
|
|
|
|
|
znew = zbufalc (cold + 2 + cadd);
|
|
|
|
|
memcpy (znew, zXnames, cold);
|
|
|
|
|
znew[cold] = ' ';
|
|
|
|
|
memcpy (znew + cold + 1, z, cadd + 1);
|
|
|
|
|
ubuffree (zXnames);
|
|
|
|
|
zXnames = znew;
|
|
|
|
|
}
|
|
|
|
|
}
|