home *** CD-ROM | disk | FTP | other *** search
- /*
- * UUCICO.C
- *
- * (C) Copyright 1987 by John Gilmore.
- * Copying and use of this program are controlled by the terms of the Free
- * Software Foundation's GNU Emacs General Public License.
- *
- * Derived from:
- * i[$]uuslave.c 1.7 08/12/85 14:04:20
- * which came from the ACGNJ BBS system at +1 201 753 9758. Original
- * author unknown.
- *
- * Ported to Amiga by William Loftus
- * Amiga Changes Copyright 1988 by William Loftus. All rights reserved.
- * Additional Major Changes (c)Copyright 1989-91 by Matthew Dillon, All rights reserved
- * Additional Changes (alternate send-expect) by Chris Hind Genly),
- * (c)Copyright 1991 by Chris Hind Genly, All rights Reserved
- *
- * Added variable packetsize (-Pn). <CB>
- *
- * JJB - Xferstat support (patches posted to .patches).
- *
- * sd:.1 - Added Mail notify on failure/success file copies
- * - Added Packet retry logging and Force failure if > %25 in error.
- * - Added 8K (setvbuf) to buffer writes to disk.
- * - Fixed bug with send_file returning COPYFAIL (lost files on send)
- * - Logging of number dailed to logfile
- * - Record device used and phone number dailed in xferstat
- * - Added Converstation failed msgs & failed msg to xferstat
- * sd:.2 - Now run sendmail so as not to hold up uucico
- * sd:.3 - Mods to gio.c & sysdep.c to decrease cpu load during highspeed
- * receiving of files: delays to read more serial data in one read
- * (also fixed host_name overwritting thanks to Kai.)
- *
- * Hierarchical Spool Conversion 1 Dec 93,
- * Mike J. Bruins. bruins@hal9000.apana.org.au
- */
-
-
- #include "includes.h" /* System include files, system dependent */
- #include "uucp.h" /* Uucp definitions and parameters */
- #include <log.h>
- #include "version.h"
- #include <owndevunit.h>
-
- #define PROTOF_SHEREEQUALS 0x0001 /* ProtoHacks */
-
- Prototype int getname(int);
- Prototype int get_proto(void);
- Prototype int instr(char *, int, int);
- Prototype int inline(int, char *, int);
- Prototype int twrite(const char *, int);
- Prototype void xlat_str(char *);
- Prototype int read_ctl(void);
- Prototype int do_outbound(void);
- Prototype int call_system(char *, int);
- Prototype int call_sysline(char *);
- Prototype int do_session(int);
- Prototype int top_level(int);
- Prototype int do_one_slave(void);
- Prototype int do_one_master(void);
- Prototype int yesno(char, int, int);
- Prototype int host_send_file(char *);
- Prototype int host_receive_file(char *);
- Prototype int local_send_file(char *, int *);
- Prototype int local_receive_file(void);
- Prototype int receive_file(FILE *, char *, char *, char *, int);
- Prototype int send_file(FILE *);
-
- Prototype short ProtoHacks;
- Prototype short PriMode;
- Prototype short OldPri;
- Prototype short BigGOpt;
- Prototype short IgnoreDTR;
- Prototype int PacketTimeout;
- Prototype int SendExpectTimeout;
- Prototype int ExitCode;
-
- Prototype long BytesIn;
- Prototype long BytesOut;
-
- void LogTimes(short);
-
- #define MAX_FLAGS 40
-
- extern int errno;
-
- IDENT(".23 sd.3");
-
- char *ver= "$VER: 1.16.23.sd.3";
-
- static char *Copyright = COPYRIGHT;
-
- char ttynam[NAMESIZE], /* Name of tty we use as serial port */
- srcnam[NAMESIZE], /* Source file name */
- dstnam[NAMESIZE], /* Dest file name */
- Who[NAMESIZE] = "-", /* Who sent the file */
- flags[MAX_FLAGS], /* Flags from file xfer cmd */
- temp[NAMESIZE]; /* Temp file name */
-
- int ourpid = 0, /* Our process ID */
- ignore_time_restrictions = 0, /* Call out even if L.sys sez no */
- mode; /* File mode from file xfer cmd */
-
- char host_name[MAX_HOST] = "AmigaUUCP"; /* Other guy's host name */
- char our_name[MAX_HOST]; /* Our uucp hostname, set from usenet.ctl */
- char path[128];
- int debug = -1; /* -1 indicates not set by command line or ctl file */
- int f_wait = 0; /* wait for a call (-w) or calls (-w -e) after outbnd */
- int loop = 0; /* Loop accepting logins if tty name specified */
- int Overide = 0; /* overide modem protocol */
- int Getty = 0; /* -Getty initiated */
- int IgnoreCD= 0; /* xgetc() should ignore carrier? */
- int OurNameOv= 0;
- int WindowSize = 999;
- int SegSize = 2;
- int NoReScan = 0; /* do not rescan for work after error */
- int SevenWire= 0;
- int XDebug = 0; /* do not pass debug parameter to remote */
- int DebugHandshake = 0;
- int PacketTimeout = 0;
- int SendExpectTimeout = SENDEXPECT_TO;
- int ExitCode = 0;
- short ProtoHacks; /* protocol hacks */
- short PriMode;
- short OldPri;
- short IgnoreDTR = 0;
- short DoAttempt = 0;
- short BigGOpt;
-
- long BytesIn;
- long BytesOut;
- time_t TimeBegin1;
- time_t TimeBegin2;
-
- int copynotify; /* mail notify bits */
- char mailsub[NAMESIZE+100];
- #define CTRLFILE(f) (f[1] == '.' && (f[0] == 'D' || f[0] == 'X' || f[0] == 'C'))
-
- struct Library *OwnDevUnitBase;
-
- #define MAX_STRING 200 /* Max length string to send/expect */
-
- #define MSGO2IDX 6
-
- /* We print these prompts */
-
- char msgo0[] = "login: ";
- char msgo1[] = "Password:";
- char msgo2[10+MAX_HOST] = { "\20Shere" }; /* NO = */
- char msgo3[] = "\20ROK\0";
- char msgo3a[]= "\20P";
- char msgo3bg[]= "\20Pg\0";
- char msgo3bG[]= "\20PG\0";
- char msgo4[] = "\20OOOOOOO\0";
-
- /* We expect to receive these strings */
-
- char msgi0[] = "uucp\r";
- char msgi1[] = "s8000\r";
- /* char msgi2[] = "\20S*\0"; We now scan it specially FIXME */
- char msgi3g[] = "\20Ug\0";
- char msgi3G[] = "\20UG\0";
- char msgi4[] = "OOOOOO";
-
- /*
- * Protocol switch data structure
- */
-
- #define turnon gturnon
- #define rdmsg grdmsg
- #define wrmsg gwrmsg
- #define rddata grddata
- #define wrdata gwrdata
- #define turnoff gturnoff
-
-
- int
- getname(isshere)
- int isshere;
- {
- int data, count = 0;
- static char msgi[MAX_STRING+SLOP]; /* Incoming trash buffer */
- char system_name[32], dir[256];
-
- /* Read data until null character */
-
- while ((data = xgetc(BYTE_TO,0)) != EOF) {
- data &= 0x7F;
- if (data == 020)
- break;
- }
- if (data == EOF)
- return FAIL;
-
- while ((data = xgetc(BYTE_TO,0)) != EOF && (data & 0x7F)) {
- data &= 0x7F;
- if (count == 0 && data != 'S')
- continue;
- if (count > sizeof(msgi) - 2)
- continue;
- if (data == 0x0A) /* hack fix for tuvie ? */
- break;
- msgi[count++] = (char)data;
- }
- msgi[count] = 0;
-
- if (debug > 8)
- printf("GETNAME MSG (%d): %s\n", count, msgi);
-
- if (msgi[0] != 'S')
- return FAIL;
- if (isshere) {
- for (count = 1; msgi[count] && msgi[count] != '='; ++count);
- if (msgi[count] == '=')
- ++count;
- } else {
- count = 1;
- }
- if (msgi[count]) {
- strncpy(host_name, msgi + count, MAX_HOST-1);
- host_name[MAX_HOST-1] = '\0';
- if (debug > 8)
- printf("Compare host names: '%s' '%s'\n", host_name, msgi + count);
- }
- strtok(host_name, " \t"); /* put \0 after hostname */
- if (debug > 8)
- printf("Hostname is '%s'\n", host_name);
- strcpy(system_name,host_name); /* hierarch - bruins */
- system_name[7] = '\0';
- strcpy(dir,MakeConfigPath(UUSPOOL,system_name));
- if(dir==NULL || *dir=='\0'){
- ulog(-1,"Can't create spool for \"%s\".",system_name);
- return FAIL;
- }
- if(chdir(dir)){
- ulog(-1,"Can't find spool \"%s\", creating.",dir);
- if(mkdir(dir)){
- ulog(-1,"Failed to make spool: \"%s\".",dir);
- return FAIL;
- }
- chdir(dir);
- }
- return SUCCESS;
- }
-
- /*
- * get_proto() checks the list of protos given by the foriegn machine
- * checking for 'g' (which is the only proto we have). Use only in master
- * mode.
- */
-
- int
- get_proto()
- {
- int data;
-
- while ((data = xgetc(BYTE_TO,0)) != EOF) {
- data &= 0x7F;
- if (data == 0)
- break;
- if (data == 'g')
- return(SUCCESS);
- }
- return FAIL;
- }
-
- /*
- * Medium level input routine.
- *
- * Look for an input string for the send-expect sequence.
- * Return 0 for matching string, 1 for timeout before we found it.
- * FIXME: we only time out if the other end stops sending. If it
- * keeps sending, we keep listening forever.
- */
-
- instr(s, n, to)
- char *s;
- int n;
- int to; /* timeout */
- {
- int data,count,j;
- int i;
- static char msgi[512]; /* Incoming trash buffer */
-
- count = 0;
- if (to == 0)
- to = BYTE_TO;
-
- if (debug > 8) {
- printf("Expecting ");
- for (i = 0; i < n; i++)
- printc(s[i]);
- printf("\n");
- }
- if (DebugHandshake) {
- printf("recvd: '");
- fflush(stdout);
- }
-
- while ((data = xgetc(to,0)) != EOF) {
- data &= 0x7F;
-
- msgi[count++] = data;
-
- if (DebugHandshake) {
- if (data < 0x20)
- printf("^%c", data + '@');
- else
- printf("%c", data);
- fflush(stdout);
- }
-
- if (count == sizeof(msgi)) { /* throw away first half */
- count = sizeof(msgi) / 2;
- bcopy(msgi + sizeof(msgi) / 2, msgi, sizeof(msgi) / 2);
- }
-
- if (count >= n) {
- for (i = n - 1, j = count - 1; i >= 0; i--, j--) {
- if (*(s+i) != msgi[j])
- break;
- }
- if (i < 0) {
- if (debug > 8)
- printf("\n");
- if (DebugHandshake)
- printf("' (GOTIT!)\n");
- return(0);
- }
- }
- }
- if (DebugHandshake)
- printf("' (TIMEOUT!)\n");
-
- if (debug > 8)
- printf("\n");
- msgi[count] = (char)0;
- return(1);
- }
-
- /*
- * Medium level input routine.
- *
- * input a line, return -1 on timeout condition else 0
- */
-
- inline(to, buf, max)
- int to;
- char *buf;
- int max;
- {
- short c;
- short i = 0;
-
- --max;
- if (to == 0)
- to = BYTE_TO;
-
- if (debug > 8 || DebugHandshake) {
- printf("Inline: ");
- fflush(stdout);
- }
-
- while ((c = xgetc(to,0)) != EOF && i < max) {
- if (c == '\n' || c == '\r')
- break;
- if (debug > 8 || DebugHandshake)
- printf("%c", c);
- buf[i++] = c;
- }
- if (debug > 8 || DebugHandshake)
- printf(" (%d c=%d)\n", i, c);
- buf[i] = 0;
- if (c == EOF)
- return(-1);
- return(0);
- }
-
- /*
- * Debugging hack for stuff written to the modem.
- */
-
- int
- twrite(s, n)
- const char *s;
- int n;
- {
- int i;
-
- if (debug > 8) {
- printf("Wrote: ");
- for (i = 0; i < n; i++)
- printc(s[i]);
- printf("\n");
- }
- return xwrite(s, n);
- }
-
- void
- myexit()
- {
- if (PriMode) {
- long task = FindTask(NULL);
- SetTaskPri(task, OldPri);
- }
-
- UnLockFiles();
-
- if (OwnDevUnitBase) {
- CloseLibrary(OwnDevUnitBase);
- OwnDevUnitBase = NULL;
- }
- }
-
- /*
- * MAIN ROUTINE.
- *
- * This is called at program startup. It parses the arguments to the
- * program (if any) and sets up to receive a call on the modem.
- *
- * If there are no arguments, we assume the caller is already on standard
- * input, waiting to do uucp protocols (past the login prompt), and we
- * just handle one caller.
- *
- * If there is an argument, it is the name of the tty device where we
- * should listen for multiple callers and handle login and password.
- */
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int i;
- char *poll_sys = (char *)NULL; /* System name to poll, or none */
- short rmode = 0; /* 1 = master, 0 = slave */
-
- LogProgram = "uucico";
- LogHost = host_name;
- LogWho = Who;
-
- signal(SIGINT, sigint);
- atexit(myexit);
-
- if ((OwnDevUnitBase = OpenLibrary(ODU_NAME, 0)) == NULL) {
- printf("Unable to open %s\n", ODU_NAME);
- exit(20);
- }
-
- /* FIXME, use getopt */
- /* scan command line arguments, kinda kludgy but it works */
-
- for (i = 1; i < argc; ++i) {
- char *ptr = argv[i];
-
- if (*ptr != '-') {
- printf("uucico: warning, extra args ignored: %s\n", argv[i]);
- break;
- }
- ptr += 2;
- switch (ptr[-1]) {
- case 'N':
- strcpy(our_name, ptr);
- OurNameOv = 1;
- break;
- case 'D': /* Serial Device */
- {
- extern char *DeviceName;
- DeviceName = argv[++i];
- }
- break;
- case 'U': /* Serial Unit */
- {
- extern long DeviceUnit;
- DeviceUnit = ((*ptr >= '0' && *ptr <= '9') ? atoi(ptr) : atoi(argv[++i]));
- }
- break;
- case 'p': /* protocol hacks */
- if (strcmp(ptr, "ri") == 0) { /* -pri */
- long task = FindTask(NULL);
-
- PriMode = 1;
- OldPri = SetTaskPri(task, 5);
- SetTaskPri(task, OldPri + 1);
- } else if (strcmp(ptr, "G") == 0) {
- /*
- * XXX in development, does NOT work yet!
- */
-
- BigGOpt = 1;
- } else { /* -proto */
- ProtoHacks |= (*ptr) ? atoi(ptr) : atoi(argv[++i]);
- }
- break;
- case 'g':
- case 'G':
- Getty = 1;
- break;
- case 'h':
- IgnoreCD = 1;
- break;
- case 'w':
- ++f_wait;
- break;
- case 'r':
- rmode = atoi(&argv[i][2]);
- break;
- case 'X':
- XDebug = 1;
- case 'x':
- if (argv[i][2] == 'x') {
- DebugHandshake = 1;
- break;
- }
-
- debug = atoi(&argv[i][2]);
- LogLevel = debug;
- LogToStdout = 0;
- printf("uucico: debug level set to %d\n", debug);
- break;
- case 'o':
- Overide = 1;
- break;
- case 'n':
- WindowSize = (*ptr) ? atoi(ptr) : 1;
- break;
- case 'P':
- SegSize = (*ptr) ? atoi(ptr) : 1;
- break;
- case 'b':
- system(GetConfigProgram(BATCHNEWS));
- break;
- case 'S':
- ignore_time_restrictions++;
- case 's':
- poll_sys = &argv[i][2];
- break;
- case 'e':
- ++loop;
- break;
- case 't':
- PacketTimeout = (*ptr) ? atoi(ptr) : atoi(argv[++i]);
- break;
- case 'T':
- SendExpectTimeout = (*ptr) ? atoi(ptr) : atoi(argv[++i]);
- break;
- case '7':
- SevenWire = 1;
- break;
- case 'd':
- IgnoreDTR = (*ptr) ? !atoi(ptr) : 1;
- break;
- case 'H':
- IgnoreCD = 1;
- Overide = 1;
- break;
- case 'B':
- i++; /* throw away baud rate argument */
- break;
- case 'A':
- DoAttempt = 1;
- break;
- default:
- printf("uucico: warning, bad flag %s\n", argv[i]);
- break;
- }
- }
-
- /* If argument provided, use it as name of comm port */
-
- /* FIXME, this needs some thought. */
-
- getcwd(path,128);
- if (chdir(GetConfigDir(UUSPOOL))) {
- perror("Can't chdir to Spool directory");
- exit(2);
- }
-
- read_ctl();
-
- /*
- * If running via getty/login, our debug stdout had better
- * go to a file, not to the usual stdout!
- */
-
- if (debug > 0 && Getty) {
- freopen("T:uuslave.log", "a", stdout);
- }
-
- /*setvbuf(stdout, NULL, _IOLBF, 0);*/
-
- /* Timestamp the long debug log */
-
- if (debug > 0) {
- long clock;
-
- time(&clock);
- printf("\014\nuuslave log on tty '%s' starting %s\n",
- ttynam, ctime(&clock));
- }
-
- /* Log our presence so we humans reading the logs can find the
- entries created by uuslave. */
-
- ulog(-1, "Startup %s", VERSION);
-
- amiga_setup();
-
- modem_init();
-
- if (poll_sys) {
- if (*poll_sys == '\0')
- poll_sys = (char *)NULL;
-
- if (call_system(poll_sys, rmode) == FAIL)
- ExitCode = 5;
-
- if (!f_wait)
- goto end;
- } else {
- if (rmode) {
- if (do_outbound() == FAIL)
- ExitCode = 5;
- if (!f_wait)
- goto end;
- }
- }
-
- do {
- /*
- * Set up serial channel, wait for incoming call.
- */
-
- DEBUG(0, "\nRestarting\n", 0);
-
- if (Getty == 0 && Overide == 0)
- openline();
-
- do_session(Getty);
- LogTimes(0);
- hangup();
- DEBUG(0, "\nEnd of call\n", 0);
- } while (loop && !Getty);
-
- end:
- cleanup();
- return(ExitCode);
- }
-
- /*
- * translate embedded escape characters
- */
-
- void
- xlat_str(msg)
- char *msg;
- {
- int i = 0;
- int cr = 1;
-
- while (msg[i]) {
- if (msg[i] == '\\') {
- switch (msg[++i]) {
- case 'r': /* carriage return */
- twrite("\r", 1);
- break;
- case 'n': /* line feed */
- twrite("\n", 1);
- break;
- case '\\': /* back slash */
- twrite("\\", 1);
- break;
- case 't': /* tab */
- twrite("\t", 1);
- break;
- case 'b':
- SendBreak();
- break;
- case 'd': /* delay */
- Delay(180);
- break;
- case 's': /* space */
- twrite(" ", 1);
- break;
- case 'c': /* no CR at end */
- cr = 0;
- break;
- default: /* don't know so skip it */
- break;
- }
- ++i;
- } else {
- twrite(msg + i, 1);
- ++i;
- }
- }
- if (cr) {
- twrite("\r", 1);
- }
- }
-
-
- /*
- * Read the control file and grab a few parameters.
- */
-
-
- int
- read_ctl()
- {
- char *nodename = FindConfig(NODENAME);
- char *debugstr = FindConfig(DEBUGNAME);
- char *tmp;
-
- if (nodename && OurNameOv == 0)
- strcpy(our_name, nodename);
- if (debugstr && debug < 0)
- debug = atoi(debugstr);
-
- /*
- * sd, get copy notify bits
- *
- * 1 - notify of send failures that will not be retried (ie denied)
- * 2 - notify of send failures that will be retried (ie protocol errors)
- * 4 - notify of successfull outgoing file copy (uucp'd copies only)
- * 8 - notify of incoming file (uucp'd file copies only)
- *16 - notify of incoming failure of anykind
- *
- * ie set to 31 for all features.
- * mail is sent to username config entry for incoming file and to
- * originator of outgoing file copies (usually the same username)
- */
- #define NOTIFY_FAILED 1
- #define NOTIFY_RETRY 2
- #define NOTIFY_SUCCESS 4
- #define NOTIFY_INCOMING 8
- #define NOTIFY_INCOMING_FAILURE 16
-
- tmp = FindConfig("CopyNotify");
- if (tmp) {
- copynotify = atoi(tmp);
- }
-
- return (1);
- }
-
- /*
- * Search spool queues for work, call the systems we need to call.
- *
- * return FAIL if any system has failed, SUCCESS otherwise.
- */
-
- int
- do_outbound()
- {
- return call_system((char *)NULL, 1);
- }
-
- /*
- * Call a specific system, or all systems that have work pending.
- *
- * If a failure occurs with any system, return FAIL, else return
- * SUCCESS.
- */
-
- int
- call_system(sys, ifworkpend)
- char *sys;
- {
- FILE *lsys;
- static char buf[MAX_LSYS];
- static char sysnam[MAX_HOST];
- static char prev_name[MAX_HOST];
- int called = FAIL;
- int status = SUCCESS;
-
- /*
- * Unix uucico just reads the directory, and calls the systems
- * in the order of the files in the directory. We want more
- * control than that, though I'm not sure that L.sys order is
- * best either. For example, in the first call after 11PM,
- * I'd like to call the sites that haven't been callable before
- * 11PM first, and finish up with the ones I've been able to call
- * all day. FIXME.
- */
-
- if (! (lsys = fopen(MakeConfigPath(UULIB, "L.sys"), "r"))) {
- DEBUG(0, "uucico: can't open L.sys, errno %d\n", errno);
- return FAIL;
- }
- sysnam[0] = '\0'; /* Initially, no previous sys */
-
- /* Once per system in L.sys... */
- /* FIXME, handle continuation lines (trailing "\") */
-
- while (fgets(buf, sizeof buf, lsys)) {
- if (buf[0] == '#' || buf[0] == '\n')
- continue;
-
- /*
- * Grab the system name. If same as previous, and
- * the previous call worked, skip it.
- */
-
- strcpy(prev_name, sysnam);
- (void) sscanf(buf, "%s", sysnam);
- if (!strcmp(sysnam, prev_name)) {
- if (called == SUCCESS)
- continue;
- }
-
- /*
- * If a system name was specified, skip til we find it
- * If none was specified, only call if there is work.
- */
-
- if (sys) {
- if (strcmp(sys, sysnam) != 0)
- continue;
- if (ifworkpend && !work_scan(sysnam)) {
- ulog(-1, "No work for system %s", sysnam);
- called = SUCCESS;
- continue;
- }
- } else {
- DEBUG(3,"searching for outbound to %s\n", sysnam);
- if (!work_scan(sysnam)) {
- DEBUG(3,"no work for %s\n", sysnam);
- called = SUCCESS; /* Don't try further */
- continue;
- }
- DEBUG(2, "uucico: found work for %s\n", sysnam);
- }
-
- /*
- * call system. If calling a single system and it succeeds, break
- * out of loop. If calling a single system with multiple L.Sys
- * lines, a later success overides an initial failure in terms of
- * the return code.
- *
- * If calling all systems any failure causes a failure return code
- * XXX FIXME, handling multiple L.Sys entries for same system ???
- */
-
- called = call_sysline(buf);
-
- if (sys) {
- status = called;
- if (called == SUCCESS)
- break;
- } else {
- if (called == FAIL)
- status = FAIL;
- }
- }
- fclose(lsys);
- return(status);
- }
-
- /*
- * Call out to a system, given its L.sys line.
- *
- * Return FAIL if any failure occurs, SUCCESS if all went well.
- */
-
- int
- call_sysline(lsysline)
- char *lsysline;
- {
- static char tempname[MAX_HOST + 30 + SLOP];
- char dir[256],system_name[32];
- char *sysnam,
- *times,
- *acu,
- *sbaud,
- *telno,
- *send,
- *expct,
- *expct1,
- *errm;
- int baud, sendexpectok;
- int r;
- char *pnum;
-
- Who[0] = '-'; Who[1] = '\0'; /* No user now (for logit) */
-
- /* FIXME, use the values it is ignoring here */
-
- sysnam = strtok(lsysline, " \t");
- times = strtok(NULL, " \t"); /* Time */
- acu = strtok(NULL, " \t"); /* ACU */
- sbaud = strtok(NULL, " \t"); /* Baud */
- telno = strtok(NULL," \t"); /* phone*/
-
- strcpy(host_name, sysnam);
-
-
- strcpy(system_name,host_name); /* hierarch - bruins */
- system_name[7] = '\0';
- strcpy(dir,MakeConfigPath(UUSPOOL,system_name));
-
- if(dir==NULL || *dir=='\0'){
- ulog(-1,"Can't create spool for \"%s\".",system_name);
- return FAIL;
- }
- if(chdir(dir)){
- ulog(-1,"Can't find spool \"%s\", creating.",dir);
- if(mkdir(dir)){
- ulog(-1,"Failed to make spool: \"%s\".",dir);
- return FAIL;
- }
- chdir(dir);
- }
-
-
- if (ignore_time_restrictions == 0) {
- if (CheckTimeRestrictions(times) == FAIL) {
- ulog(-1, "Wrong Time To Call %s", sysnam);
- return(FAIL);
- }
- }
-
- baud = atoi(sbaud);
-
- /* FIX ME, acu not implemented ? */
- DEBUG(4, "Opening outgoing line %s\n", acu);
-
- if (openout(acu, baud) != SUCCESS)
- return (FAIL);
-
- /* sd added telno logging */
- for (pnum = (telno + strlen(telno)) -1 ; pnum > telno; --pnum) {
- if (isalpha(*pnum)) {
- ++pnum;
- break;
- }
- }
-
- if (Overide == 0) {
- char *errmsg;
- if (errmsg = dial_nbr(telno)) {
- ulog(-1, "FAILED call to %s (%s): %s", host_name, pnum, errmsg);
- return (FAIL);
- }
- }
-
- TimeBegin1 = time(NULL);
- TimeBegin2 = 0;
- BytesIn = 0;
- BytesOut= 0;
-
- /* FIXME, log tty, baud rate, ... */
-
- ulog(-1, "DIALED %s (%s)", host_name,pnum);
-
- /*
- * Process send-expect strings.
- * FIXME, deal with "-", BREAK, etc.
- */
-
- if (DebugHandshake)
- puts("CONNECTED, running send-expect strings");
-
- sendexpectok = TRUE;
-
- do {
- expct = (char *)strtok((char *)NULL, " \t");
- if (expct == NULL)
- break;
-
- if (DebugHandshake)
- printf("Expect = %s\n", expct);
-
- expct1 = strtokp(&expct, "-");
-
- while (expct1) {
- if (expct1[0] != '"' || expct1[1] != '"' || expct1[2] != '\0') {
- if (DebugHandshake)
- printf("Expect %s\n", expct1);
- if (instr(expct1, strlen(expct1), SendExpectTimeout) == SUCCESS)
- break;
- } else {
- if (DebugHandshake)
- puts("Expect Nothing");
- break;
- }
- /*
- * expect failed, check for alternates
- */
-
- errm = expct1;
- if (expct1 = (char *)strtokp(&expct, "-")) {
- if (DebugHandshake)
- printf("Send = %s\n", expct1);
- xlat_str(expct1);
- } else {
- sendexpectok = FALSE;
- strtok("", " ");
- break;
- }
- expct1 = strtokp(&expct, "-");
- }
- if (send = (char*)strtok((char *)NULL, " \t\n")) {
- if (DebugHandshake)
- printf("Send %s\n", send);
- xlat_str(send);
- }
- } while (send);
-
- TimeBegin2 = time(NULL);
-
- if (sendexpectok)
- ulog(-1, "SUCCEEDED call to %s", host_name);
- else {
- ulog(-1, "FAILED call to %s. Expected %s", host_name, errm);
- goto bort1;
- }
-
- if (getname(1)) /* get name */
- goto bort1;
- /* send response */
- sprintf(tempname, "\20S%s -Q0 -x%d\0", our_name, (XDebug) ? 0 : debug);
- twrite(tempname, strlen(tempname)+1); /* Including null */
-
- /* wait for ok message, wait for protocol request
- * send protocol 'g' response */
- /* FIXME, we don't actually wait for the ROK message, since
- * it is immediately followed by the Pprotos message. We
- * currently just look for a Pg message. This needs work.
- * FIXME, WE CAN'T TALK TO SITES THAT SUPPORT more than 'g'.
- */
-
- if (instr(msgo3a, sizeof(msgo3a)-1, 0)) {
- if (!get_proto())
- goto bort1;
- }
-
- if (BigGOpt)
- twrite( msgi3G, sizeof(msgi3G)-1);
- else
- twrite( msgi3g, sizeof(msgi3g)-1);
-
- ResetGIO(); /* reset GIO protocol */
-
- if (turnon(1))
- goto bort1;
-
- ulog(-1, "OK Startup");
-
- xferinit(host_name);
- xfer.flags |= XFERF_OUTGOING;
-
- r = top_level(1);
- hangup();
-
- xfer.time_stop = time(NULL);
- if (r == FAIL) { /* sd */
- ulog(-1, "Conversation FAILED");
- }
- xferstat(pnum, (r == FAIL) ? "# Conversation FAILED => LOGFILE" : NULL);
-
- LogTimes(r);
- return (r);
-
- bort1:
- hangup();
- LogTimes(FAIL);
- return (FAIL);
- }
-
- void
- LogTimes(r)
- short r;
- {
- time_t e = time(NULL);
- time_t t1 = (TimeBegin1) ? e - TimeBegin1 : 0;
- time_t t2 = (TimeBegin2) ? e - TimeBegin2 : 0;
- FILE *fi;
- char *logFile = MakeConfigPath(UUSPOOL, "TimeLog");
- char buf[64];
-
- if (fi = fopen(logFile, "a")) {
- strftime(buf, sizeof(buf), "%d-%b-%y", localtime(&e));
- fprintf(fi, "%s %02d:%02d %2d:%02d in=%-8d out=%-8d %s\n",
- buf,
- e / 3600 % 24, e / 60 % 60,
- t2 / 60, t2 % 60,
- BytesIn,
- BytesOut,
- host_name
- );
- fclose(fi);
- }
- }
-
- /* Handle a single uucp [slave] login session */
-
- int
- do_session(ontheline)
- int ontheline;
- {
- TimeBegin1 = 0;
- TimeBegin2 = time(NULL);
- BytesIn = 0;
- BytesOut= 0;
- int r;
-
- if (ontheline == 0) {
- /* output login request, verify uucp */
- twrite(msgo0,sizeof(msgo0)-1);
- if (instr(msgi0, sizeof(msgi0)-1, 0)) {
- printf("uucico: invalid login name\n");
- goto bort;
- }
-
- /* output password request, verify s8000 */
- twrite(msgo1,sizeof(msgo1)-1);
- if (instr(msgi1, sizeof(msgi1)-1, 0)) {
- printf("uucico: invalid password\n");
- goto bort;
- }
-
- printf("uucico: correct login\n");
- }
-
- /*
- * send Shere=<myhost>
- *
- * Apparently mac UUCP has a bug that only allows 7
- * char host names, and it fails if it gets shere=<myhost>
- * where <myhost> is > 7 chars.
- *
- * Apparently some implementations of AmigaUUCP do not accept
- * an SHere with an =<myhost>, so this is disabled unless -p1 is used.
- */
-
- if (ProtoHacks & PROTOF_SHEREEQUALS)
- sprintf(msgo2 + MSGO2IDX, "=%s", our_name);
- twrite(msgo2,strlen(msgo2)+1);
-
- /*
- * get \020S<host> -Qn n (??)
- */
-
- if (getname(0))
- goto bort;
-
- /* output ok message, output protocol request, wait for response */
-
- twrite(msgo3,sizeof(msgo3)-1);
-
- /* FIXME, make the protocol list here, and use it */
-
- if (BigGOpt)
- twrite(msgo3bG,sizeof(msgo3bG)-1);
- else
- twrite(msgo3bg,sizeof(msgo3bg)-1);
-
- if (BigGOpt) {
- if (instr(msgi3G, sizeof(msgi3G)-1, 0))
- goto bort;
- } else {
- if (instr(msgi3g, sizeof(msgi3g)-1, 0))
- goto bort;
- }
- ResetGIO(); /* reset GIO protocol */
-
- if (turnon(0))
- goto bort;
-
- ulog(-1, "OK Startup");
-
- xferinit(host_name);
-
- r = top_level(0);
-
- xfer.time_stop = time(NULL);
- if (r == FAIL) { /* sd */
- ulog(-1, "Conversation FAILED");
- }
- xferstat(NULL, (r == FAIL) ? "# Conversation FAILED => LOGFILE" : NULL);
-
- bort:
- if (debug > 0)
- printf("uucico: call complete\n");
- return (1);
- }
-
- /*
- * Handle transactions "at top level", as Unix uucp's debug log says.
- *
- * As master, we scan our queues for work and send requests to the
- * other side. When done, we send a hangup request and switch to slave mode.
- *
- * As slave, we accept requests from the other side; when it is done,
- * it sends a hangup request, and we switch to master mode, if we have
- * any work queued up for that system.
- *
- * This repeats as long as either side has work to do. When all the
- * queued work is done, we agree to hang up, terminate the packet protocol,
- * and return to the caller. (We still haven't hung up the phone line yet.)
- *
- * A curious feature of the hangup protocol is that it is not a simple
- * question-answer. The master says "H", asking about hangup. The
- * slave responds "HY" saying OK. The master then says "HY" also,
- * then both of them hang up. Maybe this is to make sure the first HY
- * got ack'ed? Anyway, an "H" is reported as HANGUP and an "HY" as
- * HANGNOW. After we send an HY, we go back to listening for commands;
- * if the master sends something other than HY, we'll do it.
- */
-
- #define HANGUP 2 /* Signal to switch master/slave roles */
- #define HANGNOW 3 /* Signal to hang up now */
- #define COPYFAIL 4 /* File copy failed */
-
- int
- top_level(master_mode)
- int master_mode;
- {
- static char buf[MAXMSGLEN]; /* For hangup responses */
-
- if (master_mode) {
- (void) work_scan(host_name); /* Kick off queue scan */
- goto master;
- }
-
- for (;;) {
- slave: /* SLAVE SIDE */
- for (;;) {
- DEBUG(4, "*** TOP *** - slave\n", 0);
- switch (do_one_slave()) {
- case SUCCESS:
- break;
- case FAIL:
- DEBUG(4, "*** DO_ONE_SLAVE FAIL *** - slave\n", 0);
- return (FAIL);
- case HANGUP:
- if (work_scan(host_name)) {
- if (wrmsg("HN") != SUCCESS) {
- DEBUG(4, "*** WRMSG HN FAIL *** - slave\n", 0);
- return (FAIL);
- }
- goto master;
- } else {
- if (wrmsg("HY") != SUCCESS) {
- DEBUG(4, "*** WRMSG HY FAIL *** - slave\n", 0);
- return (FAIL);
- }
- break; /* go to master mode */
- }
- case HANGNOW:
- goto quit;
- }
- }
- master: /* MASTER SIDE */
- for (;;) {
- DEBUG(4, "*** TOP *** - master\n", 0);
- switch (do_one_master()) {
- case SUCCESS:
- break;
- case FAIL:
- DEBUG(4, "*** DO_ONE_MASTER FAIL *** - master\n", 0);
- return (FAIL);
- case HANGUP:
- /* We wrote an H command, what's the resp? */
- if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- DEBUG(4, "*** RDMSG HANGUP FAIL *** - master\n", 0);
- return (FAIL);
- }
- if (buf[0] != 'H') {
- DEBUG(4, "*** RDMSG HANGUP != 'H' *** - master\n", 0);
- return (FAIL);
- }
- if (buf[1] == 'N') {
- goto slave;
- } else {
- /*
- * send final HY? not sure if this should happen, will
- * necessarily fail if the other side does not expect
- * it so do not return... continue on w/ exit code.
- *
- * however, reduce timeout parameters
- */
-
- ++ReducedTimeout;
- wrmsg("HY");
- --ReducedTimeout;
- goto quit;
- }
- }
- }
- }
-
- quit:
- /* Shut down the packet protocol */
-
- turnoff();
-
- /* Write the closing sequence */
-
- twrite(msgo4, sizeof(msgo4)-1);
- (void) instr(msgi4, sizeof(msgi4)-1, 0);
-
- twrite(msgo4, sizeof(msgo4)-1);
-
- strcpy(Who, "-");
- ulog(-1, "OK Conversation complete");
-
- return (SUCCESS); /* Go byebye */
- }
-
- /*
- * We are slave; get a command from the other side and execute it.
- *
- * Result is SUCCESS, FAIL, HANGUP, or HANGNOW.
- */
-
- int
- do_one_slave()
- {
- static char msg[MAXMSGLEN]; /* Master's message to us */
-
- /* Get master's command */
- if (rdmsg(msg, MAXMSGLEN) != SUCCESS)
- return (FAIL);
-
- /* Print it for easy debugging */
- DEBUG(5,"\nCommand: %s\n\n", msg);
-
- switch (msg[0]) {
- case 'S':
- if (msg[1] != ' ')
- break;
- return host_send_file(msg);
- case 'R':
- if (msg[1] != ' ')
- break;
- return host_receive_file(msg);
- case 'X':
- break;
- case 'H':
- if (msg[1] == '\0') return (HANGUP);
- if (msg[1] == 'Y') return (HANGNOW);
- if (msg[1] == 'N') return (SUCCESS); /* Ignore HN to slave */
- break;
- }
-
- /* Unrecognized packet from the other end */
-
- DEBUG(0, "Bad control packet refused: %s\n", msg);
-
- if (ExitCode < 2)
- ExitCode = 2;
-
- return(yesno(msg[0], 0, 0));
- }
-
- /*
- * Do one piece of work as master.
- *
- * FIXME: we don't handle the flags, e.g. -c, properly!
- *
- * Now only dequeues queue file if all transfers were successful.
- */
-
- int
- do_one_master()
- {
- FILE *fd;
- char *sname;
- static char cmnd[256]; /* Command character */
- static char buf[256];
- int fail = SUCCESS;
- int failAction = SUCCESS;
- int failaccum = 0;
- int num;
- int delmeflag;
- static char notify[NAMESIZE]; /* A bit large...FIXME */
- char *delList[16]; /* delete files list */
- short di = 0;
-
- /*
- * Get the next work item. If no work left re-scan the directory
- * just to be sure, and if still no work then do the right thing.
- */
-
- sname = work_next();
- if (!sname && NoReScan == 0) {
- if (work_scan(host_name))
- sname = work_next();
- }
- if (!sname) {
- /* No more work, time to hang up. */
- if (wrmsg("H") != SUCCESS)
- return (FAIL);
- return (HANGUP);
- }
-
- DEBUG(2, "Request file %s\n", sname);
-
- LockFile(sname);
-
- fd = fopen(sname, "r");
- if (fd == NULL) {
- UnLockFile(sname);
- DEBUG(0, "uucico: couldn't open %s\n", sname);
- return (SUCCESS);
- }
-
- while (fgets(buf, sizeof(buf), fd)) {
- DEBUG(3, "Queued request: %s", buf);
-
- if (buf[1] != ' ')
- goto badnum;
-
- num = sscanf(buf, "%s %s %s %s %s %s %o\n",
- cmnd, srcnam, dstnam, Who, flags, temp, &mode, notify
- );
-
- switch (cmnd[0]) {
- case 'S':
- if (num < 7 || num > 8)
- goto badnum;
- fail = local_send_file(buf, &delmeflag);
- if (delmeflag) {
- if (di == sizeof(delList)/sizeof(delList[0])) {
- ulog(-1, "Too many source files in Cmd file! %s", sname);
- } else {
- delList[di] = malloc(strlen(temp) + 1);
- strcpy(delList[di], temp);
- ++di;
- }
- }
- break;
- case 'R':
- if (num != 5) {
- if (debug > 7)
- printf("Invalid scanf %d/5 :%s:%s:%s\n", num, cmnd, srcnam, dstnam);
- goto badnum;
- }
- fail = local_receive_file();
- break;
- default:
- badnum:
- ulog(-1, "Illegal Work Request (%s): %s", sname, buf);
- fail = REFUSED;
- break;
- }
-
- switch(fail) {
- case SUCCESS:
- break;
- case FAIL:
- ++failaccum;
- if (failAction == SUCCESS)
- failAction = FAIL;
- ulog(-1, "Protocol Failure at (%s): %s", sname, buf);
- NoReScan = 1;
- break;
- case REFUSED:
- ++failaccum;
- failAction = REFUSED;
- ulog(-1, "Work Refused (%s): %s", sname, buf);
- break;
- }
- }
- fclose(fd);
-
- switch(failAction) {
- case SUCCESS:
- while (di) {
- --di;
- remove(delList[di]);
- free(delList[di]);
- }
- fail = remove(sname);
- UnLockFile(sname);
- if (fail != 0) {
- ulog(-1, "Unable to remove work file %s", sname);
- DEBUG(0, "Can't remove, errno %d\n", errno);
- } else {
- DEBUG(4, "Removed work file %s\n", sname);
- }
- break;
- case FAIL:
- UnLockFile(sname);
- break;
- case REFUSED:
- UnLockFile(sname);
- strcpy(buf, sname);
- {
- short i;
- for (i = strlen(buf); i >= 0 && buf[i] != ':' && buf[i] != '/'; --i);
- ++i;
- if ((buf[i]|0x20) == 'c')
- buf[i] = 'E';
- }
- if (strcmp(sname, buf) == 0) {
- ulog(-1, "Removing %s", sname);
- remove(sname);
- } else {
- ulog(-1, "Renaming %s to %s", sname, buf);
- rename(sname, buf);
- }
- break;
- }
- if (failAction == FAIL)
- return(FAIL);
- return(SUCCESS);
- }
-
- /*
- * Send a yes/no packet
- */
-
- int
- yesno(c, true, err)
- char c;
- int true;
- int err;
- {
- char buf[21];
-
- buf[0] = c;
- buf[1] = true? 'Y': 'N';
- buf[2] = 0;
- if (err && !true)
- sprintf(buf+2,"%d", err);
-
- return (wrmsg(buf));
- }
-
- /*
- * SLAVE MODE, Master wishes to send a file to us
- *
- * SECURITY: If file is not in list of allowed directories
- * disallow transfer. UUSPOOL: is always in the
- * list.
- *
- * If file is for UUSPOOL: (the current dir), disallow "C." files
- * NOTE: success return and file redirected to T: as this can
- * occur only if somebody purposefully is trying to break us.
- *
- * NOTE: for received files to UUSPOOL: (no path element),
- * case insensitivity munging will occur. UUXQT will handle
- * name translations for X. files so we do not modify their
- * contents.
- *
- * Return 0 = success
- */
-
- int
- host_send_file(msg)
- char *msg;
- {
- FILE *fddsk; /* Disk file pointer */
- static char cmnd[256]; /* Command character */
- int r;
- int nor = 0;
-
- sscanf(msg,"%s %s %s %s %s %s %o",
- cmnd, srcnam, dstnam, Who, flags, temp, &mode);
-
- ulog(-1, "REQUESTED %s", msg);
- munge_filename(dstnam, dstnam); /* Translate to local name */
- mungecase_filename(dstnam, dstnam); /* Handle case insensitivity */
- strcpy (temp, TmpFileName(dstnam)); /* Create a handy temp file */
-
- if (SecurityDisallow(dstnam, 'w')) {
- ulog(-1, "REQUEST FAILED -- SECURITY");
- return(yesno('S', 0, 4));
- }
- if (SecurityDisallow(dstnam, 'c') > 0) {
- ulog(-1, "REQUEST FAILED -- SECURITY, REMOTE TRIED TO SEND");
- ulog(-1, "US A COMMAND FILE: %s, FILE COPIED TO T:Bad-Cmd", dstnam);
- strcpy(dstnam, "T:Bad-Cmd");
- nor = 1;
- }
-
- /* FIXME: deal with file modes now that we fopen. */
-
- LockFile(temp);
-
- fddsk = fopen(temp, "wb" /*, mode|0600 */);
- if (fddsk == NULL) {
- UnLockFile(temp);
- /* Can't open file -- send error response */
- if (debug > 0) {
- printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
- temp,
- dstnam,
- errno
- );
- }
- ulog(-1, "REQUEST FAILED -- TEMP FILE");
- return (yesno('S', 0, 4));
- }
-
- /* FIXME: Are the above permissions right?? */
- /* FIXME: Should we create directories for the file? */
-
- if (yesno('S',1, 0) != SUCCESS) {
- fclose(fddsk);
- unlink(temp);
- UnLockFile(temp);
- return(FAIL);
- }
- r = receive_file(fddsk, temp, dstnam, srcnam, nor);
- UnLockFile(temp);
-
- /*
- * sd
- * Notify username of incoming file, cept if D. or X. or C. ctrl files.
- * Notify of any incoming failure (if NOTIFY_INCOMING_FAILURE bit set)
- */
- {
- char from[80];
- char *GetUserName();
-
- sprintf(from,"%s!%s",host_name,Who);
- if (r == SUCCESS && ((copynotify & NOTIFY_INCOMING)
- && !CTRLFILE(dstnam))) {
- sprintf(mailsub,"NEW FILE: %s",dstnam);
- mail_notify(from,Who,mailsub);
- }
- else if (r != SUCCESS && (copynotify & NOTIFY_INCOMING_FAILURE)) {
- sprintf(mailsub,"INCOMING FAILURE: %s",dstnam);
- mail_notify(from,Who,mailsub);
- }
- }
-
- return(r);
- }
-
- /*
- * SLAVE MODE, Master wants us to send a file to it
- *
- * SECURITY: If file is not in list of allowed directories
- * disallow transfer. UUSPOOL: is always in the
- * list.
- *
- * 0 = success
- */
-
- int
- host_receive_file(msg)
- char *msg;
- {
- FILE *fddsk; /* Disk file descriptor */
- int x;
- static char cmnd[256]; /* Command character */
-
- ulog(-1, "REQUESTED %s", msg);
-
- sscanf(msg,"%s %s %s",cmnd,srcnam,dstnam);
- munge_filename(srcnam, temp);
-
- if (SecurityDisallow(temp, 'r')) {
- ulog(-1, "COPY FAILED -- SECURITY");
- return (yesno('R', 0, 4));
- }
-
- fddsk = fopen(temp, "rb"); /* Try to open the file */
- if (fddsk == NULL) {
- /* File didn't open, sigh. */
- if (debug > 0) {
- printf("Cannot open file %s (%s) for reading, errno=%d\n",
- temp, srcnam, errno
- );
- }
- ulog(-1, "DENIED CAN'T OPEN %s", temp);
- return(yesno('R', 0, 2));
- }
-
- if (yesno('R',1, 0) != SUCCESS) {
- fclose(fddsk);
- return(FAIL);
- }
-
- x = send_file(fddsk);
-
- /*
- * if copy failed, don't care since master asked for the file and knows
- * the result if it failed.
- */
-
- if (x == COPYFAIL)
- return(SUCCESS);
- return(x);
- }
-
- /*
- * MASTER MODE, We want to send a file.
- *
- * Return FAIL, SUCCESS, or COPYFAIL.
- *
- * SUCCESS is returned either if the file was not found locally (local
- * error, and the queued transfer should be flushed) or if it was moved
- * successfully. COPYFAIL indicates that the queued transfer should be
- * left queued, and later retried. FIXME, there are several failure points
- * in the transaction and we need finer control here.
- */
-
- int
- local_send_file(workstr, delmeflag)
- char *workstr;
- int *delmeflag;
- {
- static char buf[MAXMSGLEN]; /* Used for both xmit and receive */
- FILE *fddsk; /* Disk file descriptor */
- int res; /* Result and file removal status */
-
- *delmeflag = 0;
-
- /* WHY are temp and srcnam switched? FIXME! And no notify? */
-
- sprintf(buf,"S %s %s %s %s %s 0%o %s",
- temp, dstnam, Who, flags, srcnam, mode, Who
- );
-
- ulog(-1, "REQUEST %s", buf);
-
- if (strchr(flags, 'c')) {
- munge_filename(srcnam, temp);
- } else {
- munge_filename(temp, temp);
- }
- LockFile(temp);
- fddsk = fopen(temp, "rb");
- if (fddsk == NULL) {
- UnLockFile(temp);
- /* FIXME -- handle queued request for nonexistent file */
- if (debug > 0)
- printf("Can't open file %s (%s), errno=%d\n",
- temp,
- srcnam,
- errno
- );
- ulog(-1, "NOT FOUND %s", temp);
- /*
- * sd: Notify of failure, file to send could not be found
- */
- sprintf(mailsub,"FAILED: Can't open %s",srcnam);
-
- if (copynotify & NOTIFY_FAILED)
- mail_notify("uucico","uucico",mailsub);
-
- /* return COPYFAIL;*/
- return SUCCESS; /* assume file previously sent */
- }
-
- /* Tell the other side we want to send this file */
-
- if (wrmsg(buf) != SUCCESS) {
- fclose(fddsk);
- UnLockFile(temp);
- return (FAIL);
- }
-
- /* See what they have to say about it */
-
- if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- fclose(fddsk);
- UnLockFile(temp);
- return FAIL;
- }
- if ((buf[0] != 'S') || (buf[1] != 'Y')) {
- ulog(-1, "REQUEST DENIED %s", buf);
- fclose(fddsk);
- UnLockFile(temp);
- /*
- * sd - send mail indicating request was denied
- */
- sprintf(mailsub,"REFUSED by %s: %s",host_name,dstnam);
- if (copynotify & NOTIFY_FAILED)
- mail_notify("uucico","uucico",mailsub);
-
- return(REFUSED);
- }
- res = send_file(fddsk); /* FAIL, SUCCESS, or COPYFAIL */
-
- /*
- * sd - since our caller does not seem to pay any attention to
- * COPYFAIL, it defaults to success?? It also reties on FAIL.
- * Without this patch, sending files can be lost and assume sent ok
- * even though may of failed due to protocol errors.
- */
- if (res == COPYFAIL)
- res = FAIL;
-
-
- /*
- * sd - send mail indicating copy failed.
- */
- if (res != SUCCESS) {
- sprintf(mailsub,"COPY FAILED: (will retry) to %s!%s from %s",
- host_name,dstnam,srcnam);
- if (copynotify & NOTIFY_RETRY)
- mail_notify("uucico","uucico",mailsub);
- }
- else if (!CTRLFILE(srcnam)) {
- sprintf(mailsub,"COPY DONE: %s!%s from %s",
- host_name,dstnam,srcnam);
- if (copynotify & NOTIFY_SUCCESS)
- mail_notify("uucico","uucico",mailsub);
- }
-
-
- /* Delete the source file if it was just a copy */
-
- if (res != SUCCESS) {
- UnLockFile(temp);
- return res;
- }
- if (strchr(flags, 'c')) { /* If copied direct from source */
- UnLockFile(temp);
- return res; /* ...just return. */
- }
- *delmeflag = 1;
- UnLockFile(temp);
-
- return (res);
- }
-
- /*
- * MASTER MODE, We wish to receive a specific file so we ask for it
- *
- * Return 0 = success
- */
-
- int
- local_receive_file()
- {
- static char buf[MAXMSGLEN];
- FILE *fddsk; /* Disk file pointer */
- int r;
-
- /* FIXME, test dest file access before we ask for it. */
-
- sprintf(buf,"R %s %s %s %s %s 0%o %s",
- srcnam, dstnam, Who, flags, temp, mode, Who
- );
-
- munge_filename(dstnam, dstnam); /* tlate to local name */
- strcpy (temp, TmpFileName(dstnam)); /* Create a handy temp file */
-
- /* FIXME: deal with file modes now that we fopen. */
- /* FIXME: Are the above permissions right?? */
- /* FIXME: Should we create directories for the file? */
-
- LockFile(temp);
- fddsk = fopen(temp, "wb" /*, mode|060 */);
-
- if (fddsk == NULL) {
- UnLockFile(temp);
- /* Can't open temp file -- send error response */
- if (debug > 0) {
- printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
- temp,
- dstnam,
- errno
- );
- }
- ulog(-1, "REQUEST FAILED -- TEMPFILE %s", temp);
- return FAIL;
- }
-
- ulog(-1, "REQUEST %s", buf);
- if (wrmsg(buf) != SUCCESS) {
- fclose(fddsk);
- UnLockFile(temp);
- printf("uucico: problem sending request\n");
- return (FAIL);
- }
-
- /* See what the other side has to say about it */
-
- if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- fclose(fddsk);
- UnLockFile(temp);
- return (FAIL);
- }
- if ((buf[0] != 'R') || (buf[1] != 'Y')) {
- ulog(-1, "REQUEST DENIED %s", buf);
- fclose(fddsk);
- UnLockFile(temp);
- /*
- * sd - send mail indicating request was denied
- */
- sprintf(mailsub,"REFUSED by %s: %s",host_name,srcnam);
- if (copynotify & NOTIFY_FAILED)
- mail_notify("uucico","uucico",mailsub);
- return (REFUSED);
- }
-
- r = receive_file(fddsk, temp, dstnam, srcnam, 0);
- UnLockFile(temp);
- /*
- * sd - send mail indicating copy failed.
- */
- if (r != SUCCESS) {
- sprintf(mailsub,"COPY FAILED: (will retry) %s!%s",host_name,srcnam);
- if (copynotify & NOTIFY_RETRY)
- mail_notify("uucico","uucico",mailsub);
- }
- else {
- sprintf(mailsub,"COPY DONE: %s!%s to %s",host_name,srcnam,dstnam);
- if (copynotify & NOTIFY_SUCCESS)
- mail_notify("uucico","uucico",mailsub);
- }
- return(r);
- }
-
- /*
- * General receive file
- */
-
- int
- receive_file(fddsk, temp, dstnam, srcnam, norename)
- FILE *fddsk;
- char *temp, *dstnam, *srcnam;
- {
- int status;
- int error = 0; /* No errors so far */
- extern long Tot_Retries;
- extern long Tot_Packets;
- static char *fbuf = NULL;
-
- Tot_Packets = Tot_Retries = 0;
-
- if (fbuf == NULL) fbuf = malloc(8192); /* just call malloc once, and reuse*/
-
- if (fbuf) setvbuf(fddsk,fbuf,_IOFBF,8192);
-
- if (rddata(fddsk) != SUCCESS)
- error++;
-
- xfer.files_recv++;
- xfer.fbytes_recv += ftell(fddsk);
-
- if (Tot_Retries) {
- ulog(-1,"Retransmitted/Total Packets: %d/%d",Tot_Retries,Tot_Packets);
- }
-
- status = fclose(fddsk); /* Make sure the data got here */
-
- if (status != 0) {
- error++;
- DEBUG(0, "fclose errno=%d\n", errno);
- }
-
- /*
- * Move the file from its temp location to its real location,
- * This needs to be able to copy a file if a simple rename
- * does not suffice. Should create directories if necesary.
- * should use source ]name if target is a directory (i.e. no
- * target source name
- */
-
- unlink(dstnam);
-
- if (norename) { /* for security redirect */
- status = 0;
- } else {
- status = rename(temp, dstnam);
- if (status < 0) {
- ulog(-1, "RENAME TO %s FAILED, DELETING FILE AND TRYING AGAIN", dstnam);
- remove(dstnam);
- status = rename(temp, dstnam);
- }
- }
-
- if (status != 0) {
- error++;
- if (debug > 0) {
- printf("Cannot rename file %s to %s, errno=%d\n",
- temp, dstnam, errno);
- }
- }
-
- ulog(-1, "COPY %s", error ? "FAILED": "SUCCEEDED");
-
- return(yesno('C', error == 0, 5));
- }
-
- /*
- * general file send routine
- * Return SUCCESS, FAIL, or COPYFAIL.
- */
-
- int
- send_file(fddsk)
- FILE *fddsk; /* Disk file pointer */
- {
- static char ansbuf[MAXMSGLEN];
- int s;
- extern long Tot_Packets;
- extern long Tot_Retries;
-
- Tot_Packets = Tot_Retries = 0;
-
- s = wrdata(fddsk);
-
- xfer.files_send++;
- xfer.fbytes_send += ftell(fddsk);
-
- if (Tot_Retries) {
- ulog(-1,"Retransmitted/Total Packets: %d/%d",Tot_Retries,Tot_Packets);
- }
- if (s != SUCCESS) {
- fclose(fddsk);
- return COPYFAIL;
- }
- fclose(fddsk);
-
- /* Await the "CY" or "CNddd" packet, and toss it. */
-
- for (;;) {
- if (rdmsg(ansbuf, MAXMSGLEN) != SUCCESS)
- return (FAIL);
- if (ansbuf[0] != 'C') {
- DEBUG(0,"\nDidn't get 'CY' or 'CN', got %s\n", ansbuf);
- /* and loop looking for C message */
- } else if (ansbuf[1] == 'Y') {
- ulog(-1, "REQUESTED %s", ansbuf);
- return (SUCCESS);
- } else {
- ulog(-1, "COPY FAILED %s", ansbuf);
- return (COPYFAIL);
- }
- }
- return (COPYFAIL); /* NOTREACHED */
- }
-
-
- mail_notify(from,real,subject)
- char *from;
- char *real;
- char *subject;
- {
- char mailcmd[NAMESIZE+100];
- char *to = "postmaster";
- /*
- * should really inquire on SENDMAIL variable in config file
- */
- char *sendmail = "sendmail";
-
- if (strlen(subject) > 200) subject[200] = '\0'; /* cli input limits */
-
- sprintf(mailcmd, "run %s <nil: >nil: -f %s -R \"%s\" -t %s -s \"%s\" -raw",
- sendmail,from,real,to,subject);
-
- Execute(mailcmd,NULL,NULL);
- }
-