#include "uucp.h"
#if USE_RCS_ID
const char uuxqt_rcsid[] = "$Id: uuxqt.c,v 1.92 2002/03/05 19:10:42 ian Rel $";
#endif
#include <errno.h>
#include <ctype.h>
#include "getopt.h"
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
static int iQlock_seq = -1;
static const char *zQunlock_cmd;
static const char *zQunlock_file;
static boolean fQunlock_directory;
int cQmaxuuxqts;
static char *zQoutput;
static char *zQmail;
static void uqusage P((void));
static void uqhelp P((void));
static void uqabort P((void));
static void uqdo_xqt_file P((pointer puuconf, const char *zfile,
const char *zbase,
const struct uuconf_system *qsys,
const char *zlocalname,
const char *zcmd, boolean *pfprocessed));
static void uqcleanup P((const char *zfile, int iflags));
static int isave_files P((const struct uuconf_system *, const char *zmail,
const char *zfile, int iclean));
static boolean fqforward P((const char *zfile, char **pzallowed,
const char *zlog, const char *zmail));
static const struct option asQlongopts[] =
{
{ "command", required_argument, 0, 'c' },
{ "system", required_argument, 0, 's' },
{ "config", required_argument, NULL, 'I' },
{ "debug", required_argument, NULL, 'x' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 1 },
{ NULL, 0, NULL, 0 }
};
int
main (argc, argv)
int argc;
char **argv;
{
const char *zcmd = NULL;
const char *zconfig = NULL;
const char *zdosys = NULL;
int iopt;
pointer puuconf;
int iuuconf;
const char *zlocalname;
boolean fany;
char *z, *zgetsys;
boolean ferr;
boolean fsys;
struct uuconf_system ssys;
if (argc < 1)
{
zProgram = "uuxqt";
uqusage ();
}
zProgram = argv[0];
while ((iopt = getopt_long (argc, argv, "c:I:s:vx:", asQlongopts,
(int *) NULL)) != EOF)
{
switch (iopt)
{
case 'c':
zcmd = optarg;
break;
case 'I':
if (fsysdep_other_config (optarg))
zconfig = optarg;
break;
case 's':
zdosys = optarg;
break;
case 'x':
#if DEBUG > 1
iDebug |= idebug_parse (optarg);
#endif
break;
case 'v':
printf ("uuxqt (Taylor UUCP) %s\n", VERSION);
printf ("Copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n");
printf ("This program is free software; you may redistribute it under the terms of\n");
printf ("the GNU General Public LIcense. This program has ABSOLUTELY NO WARRANTY.\n");
exit (EXIT_SUCCESS);
case 1:
uqhelp ();
exit (EXIT_SUCCESS);
case 0:
break;
default:
uqusage ();
break;
}
}
if (optind != argc)
uqusage ();
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
iuuconf = uuconf_maxuuxqts (puuconf, &cQmaxuuxqts);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
#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);
ulog_to_file (puuconf, TRUE);
ulog_fatal_fn (uqabort);
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);
fsys = FALSE;
if (zdosys != NULL)
{
iuuconf = uuconf_system_info (puuconf, zdosys, &ssys);
if (iuuconf != UUCONF_SUCCESS)
{
if (iuuconf != UUCONF_NOT_FOUND)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
if (strcmp (zdosys, zlocalname) == 0)
{
iuuconf = uuconf_system_local (puuconf, &ssys);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
ssys.uuconf_zname = (char *) zlocalname;
}
else
{
if (! funknown_system (puuconf, zdosys, &ssys))
ulog (LOG_FATAL, "%s: system not found", zdosys);
}
}
zdosys = zbufcpy (ssys.uuconf_zname);
fsys = TRUE;
}
iQlock_seq = ixsysdep_lock_uuxqt (zcmd, cQmaxuuxqts);
if (iQlock_seq < 0)
{
ulog_close ();
usysdep_exit (TRUE);
}
zQunlock_cmd = zcmd;
do
{
fany = FALSE;
if (! fsysdep_get_xqt_init (zdosys))
{
ulog_close ();
usysdep_exit (FALSE);
}
while ((z = zsysdep_get_xqt (zdosys, &zgetsys, &ferr)) != NULL)
{
const char *zloc;
boolean fprocessed;
char *zbase;
if (! fsys || strcmp (ssys.uuconf_zname, zgetsys) != 0)
{
if (fsys)
(void) uuconf_system_free (puuconf, &ssys);
iuuconf = uuconf_system_info (puuconf, zgetsys,
&ssys);
if (iuuconf != UUCONF_SUCCESS)
{
if (iuuconf != UUCONF_NOT_FOUND)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
ubuffree (z);
ubuffree (zgetsys);
continue;
}
else if (strcmp (zgetsys, zlocalname) == 0)
{
iuuconf = uuconf_system_local (puuconf, &ssys);
if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
ubuffree (z);
ubuffree (zgetsys);
continue;
}
ssys.uuconf_zname = (char *) zlocalname;
}
else
{
if (! funknown_system (puuconf, zgetsys, &ssys))
{
ulog (LOG_ERROR,
"%s: Execute file for unknown system %s",
z, zgetsys);
(void) remove (z);
ubuffree (z);
ubuffree (zgetsys);
continue;
}
}
}
fsys = TRUE;
}
if (FGOT_SIGNAL ())
{
ubuffree (z);
ubuffree (zgetsys);
break;
}
if (zdosys != NULL && strcmp (zdosys, ssys.uuconf_zname) != 0)
{
ubuffree (z);
ubuffree (zgetsys);
continue;
}
zloc = ssys.uuconf_zlocalname;
if (zloc == NULL)
zloc = zlocalname;
ulog_system (ssys.uuconf_zname);
zbase = zsysdep_base_name (z);
uqdo_xqt_file (puuconf, z, zbase, &ssys, zloc, zcmd, &fprocessed);
ubuffree (zbase);
ulog_system ((const char *) NULL);
ulog_user ((const char *) NULL);
if (fprocessed)
fany = TRUE;
ubuffree (z);
ubuffree (zgetsys);
}
usysdep_get_xqt_free (zdosys);
}
while (fany && ! FGOT_SIGNAL ());
(void) fsysdep_unlock_uuxqt (iQlock_seq, zcmd, cQmaxuuxqts);
iQlock_seq = -1;
ulog_close ();
if (FGOT_SIGNAL ())
ferr = TRUE;
usysdep_exit (! ferr);
return 0;
}
static void
uqhelp ()
{
printf ("Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n",
VERSION);
printf ("Usage: %s [-c,--command cmd] [-s,--system system]\n", zProgram);
printf (" -c,--command cmd: Set type of command to execute\n");
printf (" -s,--system system: Execute commands only for named system\n");
printf (" -x,--debug debug: Set debugging level\n");
#if HAVE_TAYLOR_CONFIG
printf (" -I,--config file: Set configuration file to use\n");
#endif
printf (" -v,--version: Print version and exit\n");
printf (" --help: Print help and exit\n");
printf ("Report bugs to taylor-uucp@gnu.org\n");
}
static void
uqusage ()
{
fprintf (stderr,
"Usage: %s [-c,--command cmd] [-s,--system system]\n", zProgram);
fprintf (stderr, "Use %s --help for help\n", zProgram);
exit (EXIT_FAILURE);
}
static void
uqabort ()
{
#if ! HAVE_HDB_LOGGING
ulog_system ((const char *) NULL);
#endif
ulog_user ((const char *) NULL);
if (fQunlock_directory)
(void) fsysdep_unlock_uuxqt_dir (iQlock_seq);
if (zQunlock_file != NULL)
(void) fsysdep_unlock_uuxqt_file (zQunlock_file);
if (iQlock_seq >= 0)
(void) fsysdep_unlock_uuxqt (iQlock_seq, zQunlock_cmd, cQmaxuuxqts);
ulog_close ();
usysdep_exit (FALSE);
}
static char **azQargs;
static char *zQcmd;
static char *zQwd;
static char *zQinput;
static char *zQoutfile;
static char *zQoutsys;
static int cQfiles;
static char **azQfiles;
static char **azQfiles_to;
static char *zQrequestor;
static const char *zQuser;
static const char *zQsystem;
static boolean fQno_ack;
static boolean fQsuccess_ack;
static boolean fQsend_input;
static boolean fQuse_exec;
static const char *zQstatus_file;
static boolean fQquoted;
#if ALLOW_SH_EXECUTION
static boolean fQuse_sh;
#endif
static int iqcmd P((pointer puuconf, int argc, char **argv, pointer pvar,
pointer pinfo));
static int iqout P((pointer puuconf, int argc, char **argv, pointer pvar,
pointer pinfo));
static int iqfile P((pointer puuconf, int argc, char **argv, pointer pvar,
pointer pinfo));
static int iqrequestor P((pointer puuconf, int argc, char **argv,
pointer pvar, pointer pinfo));
static int iquser P((pointer puuconf, int argc, char **argv, pointer pvar,
pointer pinfo));
static int iqset P((pointer puuconf, int argc, char **argv, pointer pvar,
pointer pinfo));
static const struct uuconf_cmdtab asQcmds[] =
{
{ "C", UUCONF_CMDTABTYPE_FN | 0, NULL, iqcmd },
{ "I", UUCONF_CMDTABTYPE_STRING, (pointer) &zQinput, NULL },
{ "O", UUCONF_CMDTABTYPE_FN | 0, NULL, iqout },
{ "F", UUCONF_CMDTABTYPE_FN | 0, NULL, iqfile },
{ "R", UUCONF_CMDTABTYPE_FN | 0, NULL, iqrequestor },
{ "U", UUCONF_CMDTABTYPE_FN | 0, NULL, iquser },
{ "N", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQno_ack, iqset },
{ "n", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQsuccess_ack, iqset },
{ "B", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQsend_input, iqset },
#if ALLOW_SH_EXECUTION
{ "e", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQuse_sh, iqset },
#endif
{ "E", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQuse_exec, iqset },
{ "M", UUCONF_CMDTABTYPE_STRING, (pointer) &zQstatus_file, NULL },
{ "Q", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQquoted, iqset },
{ "W", UUCONF_CMDTABTYPE_STRING | 0, (pointer) &zQwd, NULL },
{ NULL, 0, NULL, NULL }
};
static int
iqcmd (puuconf, argc, argv, pvar, pinfo)
pointer puuconf ATTRIBUTE_UNUSED;
int argc;
char **argv;
pointer pvar ATTRIBUTE_UNUSED;
pointer pinfo ATTRIBUTE_UNUSED;
{
int i;
size_t clen;
if (argc <= 1)
return UUCONF_CMDTABRET_CONTINUE;
azQargs = (char **) xmalloc (argc * sizeof (char *));
clen = 0;
for (i = 1; i < argc; i++)
{
azQargs[i - 1] = zbufcpy (argv[i]);
clen += strlen (argv[i]) + 1;
}
azQargs[i - 1] = NULL;
zQcmd = (char *) xmalloc (clen);
zQcmd[0] = '\0';
for (i = 1; i < argc - 1; i++)
{
strcat (zQcmd, argv[i]);
strcat (zQcmd, " ");
}
strcat (zQcmd, argv[i]);
return UUCONF_CMDTABRET_CONTINUE;
}
static int
iqout (puuconf, argc, argv, pvar, pinfo)
pointer puuconf ATTRIBUTE_UNUSED;
int argc;
char **argv;
pointer pvar ATTRIBUTE_UNUSED;
pointer pinfo ATTRIBUTE_UNUSED;
{
if (argc > 1)
zQoutfile = zbufcpy (argv[1]);
if (argc > 2)
zQoutsys = zbufcpy (argv[2]);
return UUCONF_CMDTABRET_CONTINUE;
}
static int
iqfile (puuconf, argc, argv, pvar, pinfo)
pointer puuconf ATTRIBUTE_UNUSED;
int argc;
char **argv;
pointer pvar ATTRIBUTE_UNUSED;
pointer pinfo ATTRIBUTE_UNUSED;
{
if (argc < 2)
return UUCONF_CMDTABRET_CONTINUE;
if (! fspool_file (argv[1]))
return UUCONF_CMDTABRET_CONTINUE;
++cQfiles;
azQfiles = (char **) xrealloc ((pointer) azQfiles,
cQfiles * sizeof (char *));
azQfiles_to = (char **) xrealloc ((pointer) azQfiles_to,
cQfiles * sizeof (char *));
azQfiles[cQfiles - 1] = zbufcpy (argv[1]);
if (argc > 2)
azQfiles_to[cQfiles - 1] = zbufcpy (argv[2]);
else
azQfiles_to[cQfiles - 1] = NULL;
return UUCONF_CMDTABRET_CONTINUE;
}
static int
iqrequestor (puuconf, argc, argv, pvar, pinfo)
pointer puuconf ATTRIBUTE_UNUSED;
int argc;
char **argv;
pointer pvar ATTRIBUTE_UNUSED;
pointer pinfo ATTRIBUTE_UNUSED;
{
if (argc == 2)
zQrequestor = zbufcpy (argv[1]);
else if (argc > 2)
{
zQrequestor = zbufalc (strlen (argv[1]) + strlen (argv[2])
+ sizeof "!");
sprintf (zQrequestor, "%s!%s", argv[2], argv[1]);
}
return UUCONF_CMDTABRET_CONTINUE;
}
static int
iquser (puuconf, argc, argv, pvar, pinfo)
pointer puuconf ATTRIBUTE_UNUSED;
int argc;
char **argv;
pointer pvar ATTRIBUTE_UNUSED;
pointer pinfo ATTRIBUTE_UNUSED;
{
if (argc > 1)
zQuser = argv[1];
if (argc > 2)
zQsystem = argv[2];
return UUCONF_CMDTABRET_KEEP;
}
static int
iqset (puuconf, argc, argv, pvar, pinfo)
pointer puuconf ATTRIBUTE_UNUSED;
int argc ATTRIBUTE_UNUSED;
char **argv ATTRIBUTE_UNUSED;
pointer pvar;
pointer pinfo ATTRIBUTE_UNUSED;
{
boolean *pf = (boolean *) pvar;
*pf = TRUE;
return UUCONF_CMDTABRET_CONTINUE;
}
#define REMOVE_FILE (01)
#define REMOVE_NEEDED (02)
#define FREE_QINPUT (04)
#define REMOVE_QINPUT (010)
#define FREE_OUTPUT (020)
#define FREE_MAIL (040)
static void ulog_azQargs(char *msg) {
char *buf = NULL;
int i;
for(i = 0; azQargs[i]; i++) {
char *tmp = NULL;
asprintf(&tmp, "%s [%d] '%s'", buf ? buf : "", i, azQargs[i]);
free(buf);
buf = tmp;
}
ulog(LOG_ERROR, "%s %s", msg, buf);
free(buf);
}
char *strbufdup(char *src) {
char *ret = zbufalc(strlen(src));
strcpy(ret, src);
return ret;
}
static void
uqdo_xqt_file (puuconf, zfile, zbase, qsys, zlocalname, zcmd, pfprocessed)
pointer puuconf;
const char *zfile;
const char *zbase;
const struct uuconf_system *qsys;
const char *zlocalname;
const char *zcmd;
boolean *pfprocessed;
{
char *zabsolute;
boolean ferr;
FILE *e;
int iuuconf;
int i;
int iclean;
const char *zmail;
char *zoutput;
char *zinput;
boolean fbadname;
char abtemp[CFILE_NAME_LEN];
char abdata[CFILE_NAME_LEN];
char *zerror;
struct uuconf_system soutsys;
const struct uuconf_system *qoutsys;
boolean fshell;
size_t clen;
char *zfullcmd;
boolean ftemp;
*pfprocessed = FALSE;
e = fopen (zfile, "r");
if (e == NULL)
return;
azQargs = NULL;
zQcmd = NULL;
zQwd = NULL;
zQinput = NULL;
zQoutfile = NULL;
zQoutsys = NULL;
cQfiles = 0;
azQfiles = NULL;
azQfiles_to = NULL;
zQrequestor = NULL;
zQuser = NULL;
zQsystem = NULL;
fQno_ack = FALSE;
fQsuccess_ack = FALSE;
fQsend_input = FALSE;
fQuse_exec = FALSE;
zQstatus_file = NULL;
fQquoted = FALSE;
#if ALLOW_SH_EXECUTION
fQuse_sh = FALSE;
#endif
iuuconf = uuconf_cmd_file (puuconf, e, asQcmds, (pointer) zbase,
(uuconf_cmdtabfn) NULL,
(UUCONF_CMDTABFLAG_CASE
| UUCONF_CMDTABFLAG_NOCOMMENTS),
(pointer) NULL);
(void) fclose (e);
if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
if (UUCONF_ERROR_VALUE (iuuconf) == UUCONF_SYNTAX_ERROR
|| UUCONF_ERROR_VALUE (iuuconf) == UUCONF_UNKNOWN_COMMAND)
{
const char *az[20];
char *znew;
i = 0;
az[i++] = "The execution file\n\t";
az[i++] = zfile;
az[i++] = "\nfor system\n\t";
az[i++] = qsys->uuconf_zname;
az[i++] = "\nwas corrupt. ";
znew = zsysdep_save_corrupt_file (zfile);
if (znew == NULL)
{
az[i++] = "The file could not be preserved.\n";
(void) remove (zfile);
}
else
{
az[i++] = "It has been moved to\n\t";
az[i++] = znew;
az[i++] = "\n";
}
(void) fsysdep_mail (OWNER, "Corrupt execution file", i, az);
ubuffree (znew);
}
return;
}
if (fQquoted)
{
if (azQargs != NULL)
{
for (i = 0; azQargs[i] != NULL; ++i)
(void) cescape (azQargs[i]);
}
if (zQcmd != NULL)
(void) cescape (zQcmd);
if (zQinput != NULL)
(void) cescape (zQinput);
if (zQoutfile != NULL)
(void) cescape (zQoutfile);
if (zQoutsys != NULL)
(void) cescape (zQoutsys);
for (i = 0; i < cQfiles; ++i)
{
(void) cescape (azQfiles[i]);
if (azQfiles_to[i] != NULL)
(void) cescape (azQfiles_to[i]);
}
if (zQrequestor != NULL)
(void) cescape (zQrequestor);
if (zQuser != NULL)
(void) cescape ((char *) zQuser);
if (zQsystem != NULL)
(void) cescape ((char *) zQsystem);
if (zQstatus_file != NULL)
(void) cescape ((char *) zQstatus_file);
}
iclean = 0;
if (azQargs == NULL)
{
ulog (LOG_ERROR, "%s: No command given", zbase);
uqcleanup (zfile, iclean | REMOVE_FILE);
return;
}
if (zcmd != NULL)
{
if (strcmp (zcmd, azQargs[0]) != 0)
{
uqcleanup (zfile, iclean);
return;
}
}
else
{
if (fsysdep_uuxqt_locked (azQargs[0]))
{
uqcleanup (zfile, iclean);
return;
}
}
if (! fsysdep_lock_uuxqt_file (zfile))
{
uqcleanup (zfile, iclean);
return;
}
zQunlock_file = zfile;
if (! fsysdep_file_exists (zfile))
{
uqcleanup (zfile, iclean);
return;
}
if (zQuser != NULL)
ulog_user (zQuser);
else if (zQrequestor != NULL)
ulog_user (zQrequestor);
else
ulog_user ("unknown");
if (zQsystem == NULL
|| strncmp (zQsystem, qsys->uuconf_zname,
strlen (qsys->uuconf_zname)) != 0)
zQsystem = qsys->uuconf_zname;
for (i = 0; i < cQfiles; i++)
{
char *zreal;
zreal = zsysdep_spool_file_name (qsys, azQfiles[i], (pointer) NULL);
if (zreal == NULL)
{
uqcleanup (zfile, iclean);
return;
}
if (! fsysdep_file_exists (zreal))
{
uqcleanup (zfile, iclean);
return;
}
ubuffree (azQfiles[i]);
azQfiles[i] = zbufcpy (zreal);
ubuffree (zreal);
}
if (! fsysdep_lock_uuxqt_dir (iQlock_seq))
{
ulog (LOG_ERROR, "Could not lock execute directory");
uqcleanup (zfile, iclean);
return;
}
fQunlock_directory = TRUE;
iclean |= REMOVE_FILE | REMOVE_NEEDED;
*pfprocessed = TRUE;
zmail = NULL;
if (zQrequestor != NULL)
zmail = zQrequestor;
else if (zQuser != NULL)
zmail = zQuser;
if (zmail != NULL
#if HAVE_INTERNET_MAIL
&& strchr (zmail, '@') == NULL
#endif
&& strcmp (zQsystem, zlocalname) != 0)
{
char *zset;
zset = zbufalc (strlen (zQsystem) + strlen (zmail) + 2);
sprintf (zset, "%s!%s", zQsystem, zmail);
zmail = zset;
zQmail = zset;
iclean |= FREE_MAIL;
}
if (strcmp (azQargs[0], "uucp") == 0)
{
char *zfrom, *zto;
boolean fmany;
boolean finoptions;
char **azargs;
const char *zuser;
zfrom = NULL;
zto = NULL;
fmany = FALSE;
finoptions = TRUE;
for (i = 1; azQargs[i] != NULL; i++)
{
if (azQargs[i][0] == '-' && finoptions)
{
if (azQargs[i][1] == '-')
{
if (azQargs[i][2] == '\0')
finoptions = FALSE;
else if (strncmp (azQargs[i] + 2, "g", 1) == 0
|| strncmp (azQargs[i] + 2, "not", 3) == 0
|| strncmp (azQargs[i] + 2, "s", 1) == 0)
{
if (strchr (azQargs[i] + 2, '=') == NULL)
++i;
}
else if (strncmp (azQargs[i] + 2, "con", 3) == 0
|| strncmp (azQargs[i] + 2, "us", 2) == 0
|| strncmp (azQargs[i] + 2, "de", 2) == 0)
{
azQargs[i][1] = 'r';
azQargs[i][2] = '\0';
if (strchr (azQargs[i] + 3, '=') == NULL)
{
++i;
azQargs[i] = zbufcpy ("-r");
}
}
}
else
{
char *zopts;
for (zopts = azQargs[i] + 1; *zopts != '\0'; zopts++)
{
if (*zopts == 'g' || *zopts == 'n' || *zopts == 's' || *zopts == 'x')
{
if (zopts[1] == '\0')
++i;
break;
}
if (*zopts == 'I' || *zopts == 'u' || *zopts == 'x')
{
*zopts = 'r';
if (zopts[1] != '\0')
zopts[1] = '\0';
else
{
++i;
azQargs[i] = zbufcpy ("-r");
}
break;
}
}
}
}
else if (zfrom == NULL)
zfrom = azQargs[i];
else if (zto == NULL)
zto = azQargs[i];
else
{
fmany = TRUE;
break;
}
}
#define USE_KTRACE 0
for (i = 0; azQargs[i] != NULL; i++)
;
azargs = (char **) xmalloc ((i + 2 + USE_KTRACE) * sizeof (char *));
ulog(LOG_ERROR, "USE_KTRACE %d azargs %p azQargs %p", USE_KTRACE, azargs, azQargs);
azargs[0] = azQargs[0];
zuser = zQuser;
if (zuser == NULL)
zuser = "uucp";
azargs[1 + USE_KTRACE] = zbufalc (strlen (zQsystem) + strlen (zuser)
+ sizeof "-u!");
sprintf (azargs[1 + USE_KTRACE], "-u%s!%s", zQsystem, zuser);
memcpy (azargs + 2 + USE_KTRACE, azQargs + 1 + USE_KTRACE, i * sizeof (char *));
xfree ((pointer) azQargs);
azQargs = azargs;
#if USE_KTRACE
ulog(LOG_ERROR, "KTRACE");
azQargs[0] = strbufdup("ktrace");
azQargs[1] = strbufdup("-f");
azQargs[2] = strbufdup("/tmp/uu.kt");
azQargs[3] = zsysdep_find_command ("uucp", qsys->uuconf_pzcmds, qsys->uuconf_pzpath, &ferr);
ulog_azQargs("USE_KTRACE ");
#endif
zabsolute = zsysdep_find_command (USE_KTRACE ? "ktrace" : "uucp",
qsys->uuconf_pzcmds, qsys->uuconf_pzpath, &ferr);
ulog(LOG_ERROR, "zabsolute %s", zabsolute);
if (zabsolute == NULL && ! ferr)
{
const char *azcmds[2];
if (! fqforward (zfrom, qsys->uuconf_pzforward_from, "from", zmail)
|| ! fqforward (zto, qsys->uuconf_pzforward_to, "to", zmail))
{
uqcleanup (zfile, iclean);
return;
}
if (fmany || zfrom == NULL || zto == NULL)
{
ulog (LOG_ERROR, "Bad uucp request %s", zQcmd);
if (zmail != NULL && ! fQno_ack)
{
const char *az[20];
i = 0;
az[i++] = "Your execution request failed because it was an";
az[i++] = " unsupported uucp request.\n";
az[i++] = "Execution requested was:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution failed", i, az);
}
uqcleanup (zfile, iclean);
return;
}
azcmds[0] = "uucp";
azcmds[1] = NULL;
zabsolute = zsysdep_find_command ("uucp", (char **) azcmds,
qsys->uuconf_pzpath, &ferr);
}
if (zabsolute == NULL)
{
if (! ferr)
ulog (LOG_ERROR, "Can't find uucp executable");
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
}
else
{
zabsolute = zsysdep_find_command (azQargs[0], qsys->uuconf_pzcmds,
qsys->uuconf_pzpath,
&ferr);
if (zabsolute == NULL)
{
if (ferr)
{
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
ulog (LOG_ERROR, "Not permitted to execute %s",
azQargs[0]);
if (zmail != NULL && ! fQno_ack)
{
const char *az[20];
i = 0;
az[i++] = "Your execution request failed because you are not";
az[i++] = " permitted to execute\n\t";
az[i++] = azQargs[0];
az[i++] = "\non this system.\n";
az[i++] = "Execution requested was:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution failed", i, az);
}
iclean = isave_files (qsys, zmail, zfile, iclean);
uqcleanup (zfile, iclean);
return;
}
}
ulog(LOG_ERROR, "Eh?");
ubuffree (azQargs[0]);
azQargs[0] = zabsolute;
ulog_azQargs("zabsolute");
ulog(LOG_ERROR, "azQargs[1] %p", azQargs[i]);
for (i = 1; azQargs[i] != NULL; i++)
{
char *zlocal;
zlocal = zsysdep_xqt_local_file (qsys, azQargs[i]);
if (zlocal != NULL)
{
ulog(LOG_ERROR, "[%d] zlocal %s, a %s", i, zlocal, azQargs[i]);
ubuffree (azQargs[i]);
azQargs[i] = zlocal;
}
}
ulog_azQargs("zsysdep_xqt_local_file");
#if ! ALLOW_FILENAME_ARGUMENTS
for (i = 1; azQargs[i] != NULL; i++)
{
if (! fsysdep_xqt_check_file (qsys, azQargs[i]))
{
if (zmail != NULL && ! fQno_ack)
{
const char *az[20];
const char *zfailed;
zfailed = azQargs[i];
i = 0;
az[i++] = "Your execution request failed because you are not";
az[i++] = " permitted to refer to file\n\t";
az[i++] = zfailed;
az[i++] = "\non this system.\n";
az[i++] = "Execution requested was:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution failed", i, az);
}
iclean = isave_files (qsys, zmail, zfile, iclean);
uqcleanup (zfile, iclean);
return;
}
}
#endif
ulog(LOG_ERROR, "Executing %s (%s)", zbase, zQcmd);
ulog (LOG_NORMAL, "Executing %s (%s)", zbase, zQcmd);
ulog(LOG_ERROR, "zQoutsys %p zQinput %p", zQoutsys, zQinput);
if (zQinput != NULL)
{
boolean fspool;
char *zreal;
fspool = fspool_file (zQinput);
if (! fspool)
zreal = zsysdep_local_file (zQinput, qsys->uuconf_zpubdir, &fbadname);
else
{
zreal = zsysdep_spool_file_name (qsys, zQinput, (pointer) NULL);
fbadname = FALSE;
}
if (zreal == NULL && ! fbadname)
{
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
if (zreal != NULL)
{
zQinput = zreal;
iclean |= FREE_QINPUT;
if (fspool)
iclean |= REMOVE_QINPUT;
}
if (zreal == NULL
|| (! fspool
&& ! fin_directory_list (zQinput, qsys->uuconf_pzremote_send,
qsys->uuconf_zpubdir, TRUE, TRUE,
(const char *) NULL)))
{
ulog (LOG_ERROR, "Not permitted to read %s", zQinput);
if (zmail != NULL && ! fQno_ack)
{
const char *az[20];
i = 0;
az[i++] = "Your execution request failed because you are";
az[i++] = " not permitted to read\n\t";
az[i++] = zQinput;
az[i++] = "\non this system.\n";
az[i++] = "Execution requested was:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution failed", i, az);
}
uqcleanup (zfile, iclean);
return;
}
}
zoutput = NULL;
if (zQoutfile == NULL)
qoutsys = NULL;
else if (zQoutsys != NULL
&& strcmp (zQoutsys, zlocalname) != 0)
{
char *zdata;
if (strcmp (zQoutsys, qsys->uuconf_zname) == 0)
qoutsys = qsys;
else
{
iuuconf = uuconf_system_info (puuconf, zQoutsys, &soutsys);
if (iuuconf != UUCONF_SUCCESS)
{
if (iuuconf != UUCONF_NOT_FOUND)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
if (! funknown_system (puuconf, zQoutsys, &soutsys))
{
ulog (LOG_ERROR,
"Can't send standard output to unknown system %s",
zQoutsys);
uqcleanup (zfile, iclean);
return;
}
}
qoutsys = &soutsys;
}
zdata = zsysdep_data_file_name (qoutsys, zlocalname,
BDEFAULT_UUX_GRADE, FALSE, abtemp,
abdata, (char *) NULL);
if (zdata == NULL)
{
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
zoutput = zdata;
zQoutput = zoutput;
iclean |= FREE_OUTPUT;
}
else
{
boolean fok;
qoutsys = NULL;
if (fspool_file (zQoutfile))
fok = FALSE;
else
{
zoutput = zsysdep_local_file (zQoutfile, qsys->uuconf_zpubdir,
&fbadname);
if (zoutput == NULL)
{
if (! fbadname)
{
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
fok = FALSE;
}
else
{
ubuffree (zQoutfile);
zQoutfile = zoutput;
fok = fin_directory_list (zQoutfile,
qsys->uuconf_pzremote_receive,
qsys->uuconf_zpubdir, TRUE, FALSE,
(const char *) NULL);
}
}
if (! fok)
{
ulog (LOG_ERROR, "Not permitted to write to %s", zQoutfile);
if (zmail != NULL && ! fQno_ack)
{
const char *az[20];
i = 0;
az[i++] = "Your execution request failed because you are";
az[i++] = " not permitted to write to\n\t";
az[i++] = zQoutfile;
az[i++] = "\non this system.\n";
az[i++] = "Execution requested was:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution failed", i, az);
}
uqcleanup (zfile, iclean);
return;
}
}
ulog(LOG_ERROR, "fsysdep_copy_uuxqt_files...");
zinput = zQinput;
if (! fsysdep_copy_uuxqt_files (cQfiles, (const char **) azQfiles,
(const char **) azQfiles_to,
iQlock_seq, &zinput))
{
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
if (zQinput != NULL && strcmp (zQinput, zinput) != 0)
{
if ((iclean & FREE_QINPUT) != 0)
ubuffree (zQinput);
zQinput = zinput;
iclean |= FREE_QINPUT;
}
#if ALLOW_SH_EXECUTION
fshell = fQuse_sh;
#else
fshell = FALSE;
#endif
clen = 0;
for (i = 0; azQargs[i] != NULL; i++) {
clen += strlen (azQargs[i]) + 1;
}
zfullcmd = zbufalc (clen);
strcpy (zfullcmd, azQargs[0]);
for (i = 1; azQargs[i] != NULL; i++)
{
strcat (zfullcmd, " ");
strcat (zfullcmd, azQargs[i]);
}
ulog(LOG_ERROR, "fsysdep_execute fshell %d zfullcmd: %s", fshell, zfullcmd);
if (! fsysdep_execute (qsys,
zQuser == NULL ? (const char *) "uucp" : zQuser,
(const char **) azQargs, zfullcmd, zQinput,
zoutput, zQwd, fshell, iQlock_seq, &zerror, &ftemp))
{
ubuffree (zfullcmd);
if (ftemp)
{
ulog (LOG_NORMAL, "Will retry later (%s)", zbase);
if (zoutput != NULL)
(void) remove (zoutput);
if (zerror != NULL)
{
(void) remove (zerror);
ubuffree (zerror);
}
uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
*pfprocessed = FALSE;
return;
}
ulog (LOG_NORMAL, "Execution failed (%s)", zbase);
if (zmail != NULL && ! fQno_ack)
{
const char **pz;
int cgot;
FILE *eerr;
int istart;
cgot = 20;
pz = (const char **) xmalloc (cgot * sizeof (const char *));
i = 0;
pz[i++] = "Execution request failed:\n\t";
pz[i++] = zQcmd;
pz[i++] = "\n";
if (zerror == NULL)
eerr = NULL;
else
eerr = fopen (zerror, "r");
if (eerr == NULL)
{
pz[i++] = "There was no output on standard error\n";
istart = i;
}
else
{
char *zline;
size_t cline;
pz[i++] = "Standard error output was:\n";
istart = i;
zline = NULL;
cline = 0;
while (getline (&zline, &cline, eerr) > 0)
{
if (i >= cgot)
{
cgot += 20;
pz = ((const char **)
xrealloc ((pointer) pz,
cgot * sizeof (const char *)));
}
pz[i++] = zbufcpy (zline);
}
(void) fclose (eerr);
xfree ((pointer) zline);
}
(void) fsysdep_mail (zmail, "Execution failed", i, pz);
for (; istart < i; istart++)
ubuffree ((char *) pz[istart]);
xfree ((pointer) pz);
}
if (qoutsys != NULL)
(void) remove (zoutput);
iclean = isave_files (qsys, zmail, zfile, iclean);
}
else
{
ubuffree (zfullcmd);
if (zmail != NULL && fQsuccess_ack)
{
const char *az[20];
i = 0;
az[i++] = "\nExecution request succeeded:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution succeded", i, az);
}
if (qoutsys != NULL)
{
struct scmd s;
s.bcmd = 'S';
s.bgrade = BDEFAULT_UUX_GRADE;
s.pseq = NULL;
s.zfrom = abtemp;
s.zto = zQoutfile;
if (zQuser != NULL)
s.zuser = zQuser;
else
s.zuser = "uucp";
if (zmail != NULL && fQsuccess_ack)
s.zoptions = "Cn";
else
s.zoptions = "C";
s.ztemp = abtemp;
s.imode = 0666;
if (zmail != NULL && fQsuccess_ack)
s.znotify = zmail;
else
s.znotify = "";
s.cbytes = -1;
s.zcmd = NULL;
s.ipos = 0;
ubuffree (zsysdep_spool_commands (qoutsys, BDEFAULT_UUX_GRADE,
1, &s, (boolean *) NULL));
}
}
chmod(zoutput, 0666);
if (zerror != NULL)
{
(void) remove (zerror);
ubuffree (zerror);
}
uqcleanup (zfile, iclean);
}
static int
isave_files (qsys, zmail, zfile, iclean)
const struct uuconf_system *qsys;
const char *zmail;
const char *zfile;
int iclean;
{
long cspace;
char *zsavecmd;
char **pzsave;
int c;
int ifile;
char *zsaveinput;
const char **pz;
int i;
cspace = csysdep_bytes_free (zfile);
if (cspace == -1)
cspace = FREE_SPACE_DELTA;
cspace -= qsys->uuconf_cfree_space + qsys->uuconf_cfree_space / 2;
if (cspace < 0)
return iclean;
zsavecmd = zsysdep_save_failed_file (zfile);
if (zsavecmd == NULL)
return iclean;
c = 1;
pzsave = (char **) xmalloc (cQfiles * sizeof (char *));
for (ifile = 0; ifile < cQfiles; ifile++)
{
if (azQfiles[ifile] != NULL)
{
++c;
pzsave[ifile] = zsysdep_save_failed_file (azQfiles[ifile]);
if (pzsave[ifile] == NULL)
{
ubuffree (zsavecmd);
for (i = 0; i < ifile; i++)
if (azQfiles[i] != NULL)
ubuffree (pzsave[i]);
xfree ((pointer) pzsave);
return iclean;
}
}
}
zsaveinput = NULL;
if ((iclean & REMOVE_QINPUT) != 0
&& fsysdep_file_exists (zQinput))
{
zsaveinput = zsysdep_save_failed_file (zQinput);
if (zsaveinput == NULL)
{
ubuffree (zsavecmd);
for (i = 0; i < cQfiles; i++)
if (azQfiles[i] != NULL)
ubuffree (pzsave[i]);
xfree ((pointer) pzsave);
return iclean;
}
}
pz = (const char **) xmalloc ((20 + 2 * cQfiles) * sizeof (char *));
i = 0;
pz[i++] = "A UUCP execution request failed:\n\t";
pz[i++] = zQcmd;
if (zmail != NULL)
{
pz[i++] = "\nThe request was made by\n\t";
pz[i++] = zmail;
}
else
{
pz[i++] = "\nThe request came from system\n\t";
pz[i++] = qsys->uuconf_zname;
}
if (c == 1 && zsaveinput == NULL)
pz[i++] = "\nThe following file has been saved:\n\t";
else
pz[i++] = "\nThe following files have been saved:\n\t";
pz[i++] = zsavecmd;
for (ifile = 0; ifile < cQfiles; ifile++)
{
if (azQfiles[ifile] != NULL)
{
pz[i++] = "\n\t";
pz[i++] = pzsave[ifile];
}
}
if (zsaveinput != NULL)
{
pz[i++] = "\n\t";
pz[i++] = zsaveinput;
}
pz[i++] = "\n";
(void) fsysdep_mail (OWNER,
"UUCP execution files saved after failure",
i, pz);
xfree ((pointer) pz);
ubuffree (zsavecmd);
for (ifile = 0; ifile < cQfiles; ifile++)
if (azQfiles[ifile] != NULL)
ubuffree (pzsave[ifile]);
xfree ((pointer) pzsave);
ubuffree (zsaveinput);
return iclean &~ (REMOVE_FILE | REMOVE_NEEDED);
}
static void
uqcleanup (zfile, iflags)
const char *zfile;
int iflags;
{
int i;
DEBUG_MESSAGE2 (DEBUG_SPOOLDIR,
"uqcleanup: %s, %d", zfile, iflags);
if ((iflags & REMOVE_FILE) != 0)
(void) remove (zfile);
if ((iflags & REMOVE_NEEDED) != 0)
{
for (i = 0; i < cQfiles; i++)
{
if (azQfiles[i] != NULL)
(void) remove (azQfiles[i]);
}
if ((iflags & REMOVE_QINPUT) != 0)
(void) remove (zQinput);
}
if (zQunlock_file != NULL)
{
(void) fsysdep_unlock_uuxqt_file (zQunlock_file);
zQunlock_file = NULL;
}
if ((iflags & FREE_QINPUT) != 0)
ubuffree (zQinput);
if ((iflags & FREE_OUTPUT) != 0)
ubuffree (zQoutput);
if ((iflags & FREE_MAIL) != 0)
ubuffree (zQmail);
if (fQunlock_directory)
{
(void) fsysdep_unlock_uuxqt_dir (iQlock_seq);
fQunlock_directory = FALSE;
}
for (i = 0; i < cQfiles; i++)
{
ubuffree (azQfiles[i]);
ubuffree (azQfiles_to[i]);
}
ubuffree (zQoutfile);
ubuffree (zQoutsys);
ubuffree (zQrequestor);
if (azQargs != NULL)
{
for (i = 0; azQargs[i] != NULL; i++)
ubuffree (azQargs[i]);
xfree ((pointer) azQargs);
azQargs = NULL;
}
xfree ((pointer) zQcmd);
zQcmd = NULL;
xfree ((pointer) azQfiles);
azQfiles = NULL;
xfree ((pointer) azQfiles_to);
azQfiles_to = NULL;
}
static boolean
fqforward (zfile, pzallowed, zlog, zmail)
const char *zfile;
char **pzallowed;
const char *zlog;
const char *zmail;
{
const char *zexclam;
if (zfile == NULL)
return TRUE;
zexclam = strchr (zfile, '!');
if (zexclam != NULL)
{
size_t clen;
char *zsys;
boolean fret;
clen = zexclam - zfile;
zsys = zbufalc (clen + 1);
memcpy (zsys, zfile, clen);
zsys[clen] = '\0';
fret = FALSE;
if (pzallowed != NULL)
{
char **pz;
for (pz = pzallowed; *pz != NULL; pz++)
{
if (strcmp (*pz, "ANY") == 0
|| strcmp (*pz, zsys) == 0)
{
fret = TRUE;
break;
}
}
}
if (! fret)
{
ulog (LOG_ERROR, "Not permitted to forward %s %s (%s)",
zlog, zsys, zQcmd);
if (zmail != NULL && ! fQno_ack)
{
int i;
const char *az[20];
i = 0;
az[i++] = "Your execution request failed because you are";
az[i++] = " not permitted to forward files\n";
az[i++] = zlog;
az[i++] = " the system\n\t";
az[i++] = zsys;
az[i++] = "\n";
az[i++] = "Execution requested was:\n\t";
az[i++] = zQcmd;
az[i++] = "\n";
(void) fsysdep_mail (zmail, "Execution failed", i, az);
}
}
ubuffree (zsys);
return fret;
}
return TRUE;
}