#include "uucp.h"
#if USE_RCS_ID
const char xcmd_rcsid[] = "$Id: xcmd.c,v 1.24 2002/03/05 19:10:42 ian Rel $";
#endif
#include <errno.h>
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
#include "prot.h"
#include "trans.h"
static boolean flocal_xcmd_request P((struct stransfer *qtrans,
struct sdaemon *qdaemon));
static boolean flocal_xcmd_await_reply P((struct stransfer *qtrans,
struct sdaemon *qdaemon,
const char *zdata, size_t cdata));
static boolean fremote_xcmd_reply P((struct stransfer *qtrans,
struct sdaemon *qdaemon));
boolean
flocal_xcmd_init (qdaemon, qcmd)
struct sdaemon *qdaemon;
struct scmd *qcmd;
{
struct stransfer *qtrans;
qtrans = qtransalc (qcmd);
qtrans->psendfn = flocal_xcmd_request;
return fqueue_local (qdaemon, qtrans);
}
static boolean
flocal_xcmd_request (qtrans, qdaemon)
struct stransfer *qtrans;
struct sdaemon *qdaemon;
{
boolean fquote;
const struct scmd *qcmd;
struct scmd squoted;
size_t clen;
char *zsend;
boolean fret;
ulog (LOG_NORMAL, "Requesting work: %s to %s", qtrans->s.zfrom,
qtrans->s.zto);
qtrans->fcmd = TRUE;
qtrans->precfn = flocal_xcmd_await_reply;
fquote = fcmd_needs_quotes (&qtrans->s);
if (! fquote)
qcmd = &qtrans->s;
else
{
if ((qdaemon->ifeatures & FEATURE_QUOTES) == 0)
{
ulog (LOG_ERROR,
"%s: remote system does not support required quoting",
qtrans->s.zfrom);
(void) fmail_transfer (FALSE, qtrans->s.zuser, (const char *) NULL,
"remote system does not support required quoting",
qtrans->s.zfrom, qdaemon->qsys->uuconf_zname,
qtrans->s.zto, (const char *) NULL,
(const char *) NULL);
(void) fsysdep_did_work (qtrans->s.pseq);
utransfree (qtrans);
return TRUE;
}
uquote_cmd (&qtrans->s, &squoted);
qcmd = &squoted;
}
if (! fqueue_receive (qdaemon, qtrans))
return FALSE;
clen = (strlen (qcmd->zfrom) + strlen (qcmd->zto)
+ strlen (qcmd->zuser) + strlen (qcmd->zoptions) + 7);
zsend = zbufalc (clen);
sprintf (zsend, "X %s %s %s -%s", qcmd->zfrom, qcmd->zto,
qcmd->zuser, qcmd->zoptions);
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
qtrans->iremote);
ubuffree (zsend);
if (fquote)
ufree_quoted_cmd (&squoted);
return fret;
}
static boolean
flocal_xcmd_await_reply (qtrans, qdaemon, zdata, cdata)
struct stransfer *qtrans;
struct sdaemon *qdaemon;
const char *zdata;
size_t cdata ATTRIBUTE_UNUSED;
{
qtrans->precfn = NULL;
if (zdata[0] != 'X'
|| (zdata[1] != 'Y' && zdata[1] != 'N'))
{
ulog (LOG_ERROR, "Bad response to work request");
utransfree (qtrans);
return FALSE;
}
if (zdata[1] == 'N')
{
ulog (LOG_ERROR, "%s: work request denied", qtrans->s.zfrom);
(void) fmail_transfer (FALSE, qtrans->s.zuser, (const char *) NULL,
"work request denied",
qtrans->s.zfrom, qdaemon->qsys->uuconf_zname,
qtrans->s.zto, (const char *) NULL,
(const char *) NULL);
}
(void) fsysdep_did_work (qtrans->s.pseq);
utransfree (qtrans);
return TRUE;
}
boolean
fremote_xcmd_init (qdaemon, qcmd, iremote)
struct sdaemon *qdaemon;
struct scmd *qcmd;
int iremote;
{
const struct uuconf_system *qsys;
const char *zexclam;
const struct uuconf_system *qdestsys;
struct uuconf_system sdestsys;
char *zdestfile;
boolean fmkdirs;
struct stransfer *qtrans;
char *zuser;
char aboptions[5];
char *zfrom;
boolean fret;
char *zfile;
ulog (LOG_NORMAL, "Work requested: %s to %s", qcmd->zfrom,
qcmd->zto);
qsys = qdaemon->qsys;
zexclam = strchr (qcmd->zto, '!');
if (zexclam == NULL
|| zexclam == qcmd->zto
|| strncmp (qdaemon->zlocalname, qcmd->zto,
(size_t) (zexclam - qcmd->zto)) == 0)
{
const char *zconst;
qdestsys = NULL;
if (zexclam == NULL)
zconst = qcmd->zto;
else
zconst = zexclam + 1;
zdestfile = zsysdep_local_file (zconst, qsys->uuconf_zpubdir,
(boolean *) NULL);
if (zdestfile == NULL)
return FALSE;
zuser = NULL;
fmkdirs = strchr (qcmd->zoptions, 'f') != NULL;
}
else
{
size_t clen;
char *zcopy;
int iuuconf;
char *zoptions;
clen = zexclam - qcmd->zto;
zcopy = zbufalc (clen + 1);
memcpy (zcopy, qcmd->zto, clen);
zcopy[clen] = '\0';
iuuconf = uuconf_system_info (qdaemon->puuconf, zcopy, &sdestsys);
if (iuuconf == UUCONF_NOT_FOUND)
{
if (! funknown_system (qdaemon->puuconf, zcopy, &sdestsys))
{
ulog (LOG_ERROR, "%s: System not found", zcopy);
ubuffree (zcopy);
qtrans = qtransalc (qcmd);
qtrans->psendfn = fremote_xcmd_reply;
qtrans->pinfo = (pointer) "XN";
qtrans->iremote = iremote;
return fqueue_remote (qdaemon, qtrans);
}
}
else if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, qdaemon->puuconf, iuuconf);
ubuffree (zcopy);
return FALSE;
}
ubuffree (zcopy);
qdestsys = &sdestsys;
zdestfile = zbufcpy (zexclam + 1);
zuser = zbufalc (strlen (qdestsys->uuconf_zname)
+ strlen (qcmd->zuser) + sizeof "!");
sprintf (zuser, "%s!%s", qdestsys->uuconf_zname, qcmd->zuser);
zoptions = aboptions;
*zoptions++ = 'C';
if (strchr (qcmd->zoptions, 'd') != NULL)
*zoptions++ = 'd';
if (strchr (qcmd->zoptions, 'm') != NULL)
*zoptions++ = 'm';
*zoptions = '\0';
fmkdirs = TRUE;
}
qtrans = qtransalc (qcmd);
qtrans->psendfn = fremote_xcmd_reply;
qtrans->pinfo = (pointer) "XY";
qtrans->iremote = iremote;
if (! fqueue_remote (qdaemon, qtrans))
{
ubuffree (zdestfile);
ubuffree (zuser);
return FALSE;
}
zfrom = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir,
(boolean *) NULL);
if (zfrom == NULL)
{
ubuffree (zdestfile);
ubuffree (zuser);
return FALSE;
}
if (! fsysdep_wildcard_start (zfrom))
{
ubuffree (zfrom);
ubuffree (zdestfile);
ubuffree (zuser);
return FALSE;
}
fret = TRUE;
while ((zfile = zsysdep_wildcard (zfrom)) != NULL)
{
char *zto;
char abtname[CFILE_NAME_LEN];
if (! fsysdep_file_exists (zfile))
{
ulog (LOG_ERROR, "%s: no such file", zfile);
continue;
}
if (! fin_directory_list (zfile, qsys->uuconf_pzremote_send,
qsys->uuconf_zpubdir, TRUE, TRUE,
(const char *) NULL))
{
ulog (LOG_ERROR, "%s: not permitted to send", zfile);
break;
}
if (qdestsys != NULL)
{
zto = zsysdep_data_file_name (qdestsys, qdaemon->zlocalname,
BDEFAULT_UUCP_GRADE, FALSE,
abtname, (char *) NULL,
(char *) NULL);
if (zto == NULL)
{
fret = FALSE;
break;
}
}
else
{
zto = zsysdep_add_base (zdestfile, zfile);
if (zto == NULL)
{
fret = FALSE;
break;
}
if (! fin_directory_list (zto, qsys->uuconf_pzremote_receive,
qsys->uuconf_zpubdir, TRUE, FALSE,
(const char *) NULL))
{
ulog (LOG_ERROR, "%s: not permitted to receive", zto);
ubuffree (zto);
break;
}
}
if (! fcopy_file (zfile, zto, qdestsys == NULL, fmkdirs, FALSE))
{
ubuffree (zto);
break;
}
ubuffree (zto);
if (qdestsys != NULL)
{
struct scmd ssend;
char *zjobid;
ssend.bcmd = 'S';
ssend.bgrade = BDEFAULT_UUCP_GRADE;
ssend.pseq = NULL;
ssend.zfrom = zfile;
ssend.zto = zdestfile;
ssend.zuser = zuser;
ssend.zoptions = aboptions;
ssend.ztemp = abtname;
ssend.imode = ixsysdep_file_mode (zfile);
ssend.znotify = "";
ssend.cbytes = -1;
ssend.zcmd = NULL;
ssend.ipos = 0;
zjobid = zsysdep_spool_commands (qdestsys, BDEFAULT_UUCP_GRADE,
1, &ssend, (boolean *) NULL);
if (zjobid == NULL)
break;
ubuffree (zjobid);
}
ubuffree (zfile);
}
if (zfile != NULL)
ubuffree (zfile);
(void) fsysdep_wildcard_end ();
ubuffree (zdestfile);
if (qdestsys != NULL)
(void) uuconf_system_free (qdaemon->puuconf, &sdestsys);
ubuffree (zfrom);
ubuffree (zuser);
return fret;
}
static boolean
fremote_xcmd_reply (qtrans, qdaemon)
struct stransfer *qtrans;
struct sdaemon *qdaemon;
{
boolean fret;
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon,
(const char *) qtrans->pinfo,
qtrans->ilocal,
qtrans->iremote);
utransfree (qtrans);
return fret;
}