/* Program: uux.c 27 August 1991 Author: Mitch Mitchell Email: mitch@harlie.lonestar.org Much of this code is shamelessly taken from extant code in UUPC/Extended. Usage: uux [ options ] command-string Where [ options ] are: -aname Use name as the user identification replacing the initiator user-id. (Notification will be returned to the user.) -b Return whatever standard input was provided to the uux command if the exit status is non-zero. -c Do not copy local file to the spool directory for transfer to the remote machine (default). -C Force the copy of local files to the spool directory for transfer. -e Remote system should use sh to execute commands. -E Remote system should use exec to execute commands. -ggrade Grade is a single letter/number; lower ASCII sequence characters will cause the job to be transmitted earlier during a particular conversation. -j Output the jobid ASCII string on the standard output which is the job identification. This job identification can be used by uustat to obtain the status or terminate a job. -n Do not notify the user if the command fails. -p The standard input to uux is made the standard input to the command-string. -r Do not start the file transfer, just queue the job. (Currently uux does not attempt to start the transfer regardless of the presense of this option). -sfile Report status of the transfer in file. -xdebug_level Produce debugging output on the standard output. The debug_level is a number between 0 and ??; higher numbers give more detailed information. -z Send success notification to the user. The command-string is made up of one or more arguments that look like a normal command line, except that the command and filenames may be prefixed by system-name!. A null system-name is interpreted as the local system. */ /*--------------------------------------------------------------------*/ /* System include files */ /*--------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include /*--------------------------------------------------------------------*/ /* Local include files */ /*--------------------------------------------------------------------*/ #include "lib.h" #include "hlib.h" #include "getopt.h" #include "getseq.h" #include "expath.h" #include "import.h" #include "pushpop.h" #include "security.h" #include "hostable.h" #include "timestmp.h" /*--------------------------------------------------------------------*/ /* Define current file name for panic() and printerr() */ /*--------------------------------------------------------------------*/ currentfile(); /*--------------------------------------------------------------------*/ /* Global variables */ /*--------------------------------------------------------------------*/ typedef enum { FLG_USE_USERID, FLG_OUTPUT_JOBID, FLG_READ_STDIN, FLG_QUEUE_ONLY, FLG_NOTIFY_SUCCESS, FLG_NONOTIFY_FAIL, FLG_COPY_SPOOL, FLG_RETURN_STDIN, FLG_STATUS_FILE, FLG_USE_EXEC, FLG_MAXIMUM } UuxFlags; typedef enum { DATA_FILE = 0, /* Normal data file passed argument */ INPUT_FILE = 1, /* Redirected stdin file */ OUTPUT_FILE = 2 /* Redirected stdout file */ } FileType; static boolean flags[FLG_MAXIMUM] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }; static char* st_out = NULL; static char* user_id = NULL; static char grade = 'Z'; /* Default grade of service */ static char job_id[15]; static char* spool_fmt = SPOOLFMT; static char* dataf_fmt = DATAFFMT; static char* send_cmd = "S %s %s %s - %s 0666\n"; /*--------------------------------------------------------------------*/ /* Internal prototypes */ /*--------------------------------------------------------------------*/ void main(int argc, char **argv); static void usage( void ); static char *SwapSlash(char *p); static boolean cp(char *from, char *to); static boolean split_path(char *path, char *system, char *file, boolean expand, char *default_sys); static boolean CopyData( const char *input, const char *output); static boolean remove_parens(char *string); static boolean do_uuxqt(char *job_name, char *src_syst, char *src_file, char *dest_syst, char *dest_file); static boolean do_copy(char *src_syst, char *src_file, char *dest_syst, char *dest_file); static boolean do_remote(int optind, int argc, char **argv); static void preamble(FILE* stream); static char subseq( void ); /*--------------------------------------------------------------------*/ /* u s a g e */ /* */ /* Report flags used by program */ /*--------------------------------------------------------------------*/ static void usage() { fprintf(stderr, "Usage: uux\t[-c|-C] [-e|-E] [-b] [-gGRADE] " "[-p] [-j] [-n] [-r] [-sFILE]\\\n" "\t\t[-aNAME] [-z] [-] [-xDEBUG_LEVEL] " "command-string\n"); } /*--------------------------------------------------------------------*/ /* s w a p s l a s h */ /* */ /* Change backslash in a directory path to forward slash */ /*--------------------------------------------------------------------*/ static char *SwapSlash(char *p) { char *q = p; while (*q) { if (*q == '\\') *q = '/'; q++; } return p; }; /*--------------------------------------------------------------------*/ /* c p */ /* */ /* Copy Local Files */ /*--------------------------------------------------------------------*/ static boolean cp(char *from, char *to) { int fd_from, fd_to; int nr; int nw = -1; char buf[BUFSIZ]; /* faster if we alloc a big buffer */ /* This would be even faster if we determined that both files were on the same device, dos >= 3.0, and used the dos move function */ if ((fd_from = open(from, O_RDONLY | O_BINARY)) == -1) return FALSE; /* failed */ /* what if the to is a directory? */ /* possible with local source & dest uucp */ if ((fd_to = open(to, O_CREAT | O_BINARY | O_WRONLY, S_IWRITE | S_IREAD)) == -1) { close(fd_from); return FALSE; /* failed */ /* NOTE - this assumes all the required directories exist! */ } while ((nr = read(fd_from, buf, sizeof buf)) > 0 && (nw = write(fd_to, buf, nr)) == nr) ; close(fd_to); close(fd_from); if (nr != 0 || nw == -1) return FALSE; /* failed in copy */ return TRUE; } /*--------------------------------------------------------------------*/ /* C o p y D a t a */ /* */ /* Copy data into its final resting spot */ /*--------------------------------------------------------------------*/ static boolean CopyData( const char *input, const char *output) { FILE *datain; FILE *dataout; char buf[BUFSIZ]; boolean status = TRUE; int len; if ( (dataout = FOPEN(output, "w", BINARY_MODE)) == NULL ) { printerr(output); printmsg(0,"uux: Cannot open spool file \"%s\" for output", output); return FALSE; } /*--------------------------------------------------------------------*/ /* Verify the input opened */ /*--------------------------------------------------------------------*/ if (input == NULL) { datain = stdin; setmode(fileno(datain), O_BINARY); /* Don't die on control-Z, etc */ } else datain = FOPEN(input, "r", BINARY_MODE); if (datain == NULL) { printerr(input); printmsg(0,"Unable to open input file \"%s\"", (input == NULL ? "stdin" : input)); fclose(dataout); return FALSE; } /* datain */ /*--------------------------------------------------------------------*/ /* Loop to copy the data */ /*--------------------------------------------------------------------*/ while ( (len = fread( buf, 1, BUFSIZ, datain)) != 0) { if (fwrite( buf, 1, len, dataout ) != len) /* I/O error? */ { printerr("dataout"); printmsg(0,"I/O error on \"%s\"", output); fclose(dataout); return FALSE; } /* if */ } /* while */ /*--------------------------------------------------------------------*/ /* Close up shop and return */ /*--------------------------------------------------------------------*/ if (ferror(datain)) /* Clean end of file on input? */ { printerr(input); clearerr(datain); status = FALSE; } if (input != NULL) fclose(datain); fclose(dataout); return status; } /* CopyData */ /*--------------------------------------------------------------------*/ /* r e m o v e _ p a r e n s */ /* */ /*--------------------------------------------------------------------*/ static boolean remove_parens(char *string) { int len = strlen(string); if ((string[0] != '(') || (string[len - 1] != ')')) return FALSE; strcpy(string, &string[1]); string[len - 2] = '\0'; return TRUE; /* and we're done */ } /*--------------------------------------------------------------------*/ /* s p l i t _ p a t h */ /*--------------------------------------------------------------------*/ static boolean split_path(char *path, char *sysname, char *file, boolean expand, char *default_sys ) { char *p_left; char *p_right; char *p = path; *sysname = *file = '\0'; /* init to nothing */ /*--------------------------------------------------------------------*/ /* if path is wildcarded then error */ /*--------------------------------------------------------------------*/ if (strcspn(path, "*?[") < strlen(path)) { printmsg(0,"uux - Wildcards not allowed in operand: %s",p ); return FALSE; } /*--------------------------------------------------------------------*/ /* Find the first and last bangs */ /*--------------------------------------------------------------------*/ p_left = strchr(p, '!'); /* look for the first bang */ p_right = strrchr(p, '!'); /* look for the last bang */ /*--------------------------------------------------------------------*/ /* If no bangs, then the file is on the remote system. We hope. */ /*--------------------------------------------------------------------*/ if ( p_left == NULL ) { strcpy( file, p); /* Entire string is file name */ strcpy( sysname, default_sys ); /* Use default system name */ if ( equal(sysname, E_nodename ) && expand && (expand_path(file, NULL, E_homedir, NULL) == NULL)) return FALSE; /* expand_path will delivery any needed nasty-gram to user */ } /* if ( p_left == NULL ) */ /*--------------------------------------------------------------------*/ /* If the first bang is the first character, it's a local file */ /*--------------------------------------------------------------------*/ if (p_left == p) /* First character in path? */ { /* Yes --> not a remote path */ if ( p_left != p_right ) /* More bangs? */ { printmsg(0,"uux - Invalid syntax for local file: %s", p ); return FALSE; /* Yes --> I don't grok this */ } strcpy(file, p+1); /* Just return filename */ if ( expand && (expand_path(file, NULL, E_homedir, NULL) == NULL)) return FALSE; /* expand_path will delivery any needed nasty-gram to user */ strcpy(sysname, E_nodename); return TRUE; } /* p_left == p */ /*--------------------------------------------------------------------*/ /* It's not a local file, continue processing */ /*--------------------------------------------------------------------*/ strcpy(file, p_right + 1); /* and thats our filename */ strncpy(sysname, p, p_left - p); /* and we have a system thats not us */ sysname[p_left - p] = '\0'; /*--------------------------------------------------------------------*/ /* Now see if there is an intermediate path */ /*--------------------------------------------------------------------*/ if (p_left != p_right) { char c = *p_right; *p_right = '\0'; /* Terminate the system name */ printmsg(0,"uux - Intermediate system %s not supported", p_left+1); *p_right = c; /* Restore original string */ return FALSE; } /* if (p_left != p_right) */ #if 0 if (expand && (strcspn(file, "~") >= strlen(file)) ) if (expand_path(file, NULL, E_homedir, NULL) == NULL) return FALSE; #endif return TRUE; /* and we're done */ } /* split_path */ /*--------------------------------------------------------------------*/ /* d o _ u u x q t */ /* */ /* Generate a UUXQT command file for local system */ /*--------------------------------------------------------------------*/ static boolean do_uuxqt(char *job_name, char *src_syst, char *src_file, char *dest_syst, char *dest_file) { long seqno = 0; char *seq = NULL; FILE *stream; /* For writing out data */ char msfile[FILENAME_MAX]; /* MS-DOS format name of files */ char msname[22]; /* MS-DOS format w/o path name */ char ixfile[15]; /* eXecute file for local system, UNIX format name for local system */ /*--------------------------------------------------------------------*/ /* Create the UNIX format of the file names we need */ /*--------------------------------------------------------------------*/ seqno = getseq(); seq = JobNumber( seqno ); sprintf(ixfile, spool_fmt, 'X', E_nodename, grade , seq); /*--------------------------------------------------------------------*/ /* create local X (xqt) file */ /*--------------------------------------------------------------------*/ importpath( msname, ixfile, E_nodename); mkfilename( msfile, E_spooldir, msname); if ( (stream = FOPEN(msfile, "w", BINARY_MODE)) == NULL ) { printerr(msfile); printmsg(0, "uux: cannot open X file %s", msfile); return FALSE; } /* if */ fprintf(stream, "# third party request, job id\n" ); fprintf(stream, "J %s\n", job_name ); fprintf(stream, "F %s/%s/%s %s\n", E_spooldir, src_syst, dest_file, src_file ); fprintf(stream, "C uucp -C %s %s!%s\n", src_file, dest_syst, dest_file ); fclose (stream); return TRUE; } /* do_uuxqt */ /*--------------------------------------------------------------------*/ /* d o _ c o p y */ /* */ /* At this point only one of the systems can be remote and only */ /* 1 hop away. All the rest have been filtered out */ /*--------------------------------------------------------------------*/ static boolean do_copy(char *src_syst, char *src_file, char *dest_syst, char *dest_file) { char tmfile[25]; /* Unix style name for c file */ char idfile[25]; /* Unix style name for data file copy */ char work[66]; /* temp area for filename hacking */ char icfilename[66]; /* our hacked c file path */ char idfilename[66]; /* our hacked d file path */ struct stat statbuf; long int sequence; char *remote_syst; /* Non-local system in copy */ char *sequence_s; FILE *cfile; sequence = getseq(); sequence_s = JobNumber( sequence ); remote_syst = equal(src_syst, E_nodename) ? dest_syst : src_syst; sprintf(tmfile, spool_fmt, 'C', remote_syst, grade, sequence_s); importpath(work, tmfile, remote_syst); mkfilename(icfilename, E_spooldir, work); if (!equal(src_syst, E_nodename)) { if (expand_path(dest_file, NULL, E_homedir, NULL) == NULL) return FALSE; SwapSlash(src_file); printmsg(1, "uux - from \"%s\" - control = %s", src_syst, tmfile); if ((cfile = FOPEN(icfilename, "a",TEXT_MODE)) == NULL) { printerr( icfilename ); printmsg(0, "uux: cannot append to %s\n", icfilename); return FALSE; } fprintf(cfile, "R %s %s %s -c D.0 0666", src_file, dest_file, E_mailbox); if (flags[FLG_USE_USERID]) fprintf(cfile, " %s\n", user_id); else fprintf(cfile, " %s\n", E_mailbox); fclose(cfile); return TRUE; } else if (!equal(dest_syst, E_nodename)) { printmsg(1,"uux - spool %s - execute %s", flags[FLG_COPY_SPOOL] ? "on" : "off", flags[FLG_QUEUE_ONLY] ? "do" : "don't"); printmsg(1," - dest m/c = %s sequence = %ld control = %s", dest_syst, sequence, tmfile); if (expand_path(src_file, NULL, E_homedir, NULL) == NULL) return FALSE; SwapSlash(dest_file); if (stat(src_file, &statbuf) != 0) { printerr( src_file ); return FALSE; } if (statbuf.st_mode & S_IFDIR) { printf("uux - directory name \"%s\" illegal\n", src_file ); return FALSE; } if (flags[FLG_COPY_SPOOL]) { sprintf(idfile , dataf_fmt, 'D', E_nodename, sequence_s, subseq()); importpath(work, idfile, remote_syst); mkfilename(idfilename, E_spooldir, work); /* Do we need a MKDIR here for the system? */ if (!cp(src_file, idfilename)) { printmsg(0, "copy \"%s\" to \"%s\" failed", src_file, idfilename); /* copy data */ return FALSE; } } else strcpy(idfile, "D.0"); if ((cfile = FOPEN(icfilename, "a",TEXT_MODE)) == NULL) { printerr( icfilename ); printf("uux: cannot append to %s\n", icfilename); return FALSE; } /* if ((cfile = FOPEN(icfilename, "a",TEXT_MODE)) == NULL) */ fprintf(cfile, "S %s %s %s -%s %s 0666", src_file, dest_file, E_mailbox, flags[FLG_COPY_SPOOL] ? "c" : " ", idfile); if (flags[FLG_USE_USERID]) fprintf(cfile, " %s\n", user_id); else fprintf(cfile, " %s\n", E_mailbox); fclose(cfile); return TRUE; } else { if (expand_path(src_file, NULL, E_homedir, NULL) == NULL) return FALSE; if (expand_path(dest_file, NULL, E_homedir, NULL) == NULL) return FALSE; if (strcmp(src_file, dest_file) == 0) { printmsg(0, "%s %s - same file; can't copy\n", src_file, dest_file); return FALSE; } /* if (strcmp(src_file, dest_file) == 0) */ return(cp(src_file, dest_file)); } /* else */ } /* do_copy */ /*--------------------------------------------------------------------*/ /* p r e a m b l e */ /* */ /* write the execute file preamble based on the global flags */ /*--------------------------------------------------------------------*/ static void preamble(FILE* stream) { fprintf(stream, "U %s %s\n", E_mailbox, E_nodename); if (flags[FLG_RETURN_STDIN]) { fprintf(stream, "# return input on abnormal exit\n"); fprintf(stream, "B\n"); } if (flags[FLG_NOTIFY_SUCCESS]) { fprintf(stream, "# return status on success\n"); fprintf(stream, "n\n"); } if (flags[FLG_NONOTIFY_FAIL]) { fprintf(stream, "# don't return status on failure\n"); fprintf(stream, "N\n"); } else { fprintf(stream, "# return status on failure\n"); fprintf(stream, "Z\n"); } if (flags[FLG_USE_EXEC]) { fprintf(stream, "# use exec to execute\n"); fprintf(stream, "E\n"); } else { fprintf(stream, "# use sh execute\n"); fprintf(stream, "e\n"); } if (flags[FLG_STATUS_FILE]) { fprintf(stream, "M %s\n", st_out ); } if (flags[FLG_USE_USERID]) { fprintf(stream, "# return address for status or input return\n"); fprintf(stream, "R %s\n", user_id ); } fprintf(stream, "# job id for status reporting\n"); fprintf(stream, "J %s\n", job_id ); return; } /* preamble */ /*--------------------------------------------------------------------*/ /* d o _ r e m o t e */ /* */ /* gather data files to ship to execution system and build X file */ /*--------------------------------------------------------------------*/ static boolean do_remote(int optind, int argc, char **argv) { FILE *stream; /* For writing out data */ char *sequence_s; boolean s_remote; boolean d_remote; boolean i_remote = FALSE; boolean o_remote = FALSE; long sequence; char src_system[100]; char dest_system[100]; char src_file[FILENAME_MAX]; char dest_file[FILENAME_MAX]; char command[BUFSIZ]; char msfile[FILENAME_MAX]; /* MS-DOS format name of files */ char msname[22]; /* MS-DOS format w/o path name */ char tmfile[15]; /* Call file, UNIX format name */ char lxfile[15]; /* eXecute file for remote system, UNIX format name for local system */ char rxfile[15]; /* Remote system UNIX name of eXecute file */ char lifile[15]; /* Data file, UNIX format name */ char rifile[15]; /* Data file name on remote system, UNIX format */ char* jobid_fmt = &spool_fmt[3]; /*--------------------------------------------------------------------*/ /* Get the remote system and command to execute on that system */ /*--------------------------------------------------------------------*/ if (!split_path(argv[optind++], dest_system, command, FALSE, E_nodename)) { printmsg(0, "uux - illegal syntax %s", argv[--optind]); return FALSE; } d_remote = equal(dest_system, E_nodename) ? FALSE : TRUE ; /*--------------------------------------------------------------------*/ /* OK - we have a destination system - do we know him? */ /*--------------------------------------------------------------------*/ if ((d_remote) && (checkreal(dest_system) == BADHOST)) { printmsg(0, "uux - bad system: %s", dest_system); return FALSE; } printmsg(9,"xsys -> %s", dest_system); printmsg(9, "system \"%s\", rest \"%s\"", dest_system, command); sequence = getseq(); sequence_s = JobNumber( sequence ); sprintf(job_id, jobid_fmt, dest_system, grade, sequence_s); /*--------------------------------------------------------------------*/ /* create remote X (xqt) file */ /*--------------------------------------------------------------------*/ sprintf(rxfile, dataf_fmt, 'X', E_nodename, sequence_s, subseq()); sprintf(lxfile, dataf_fmt, d_remote ? 'D' : 'X', E_nodename, sequence_s, subseq()); importpath( msname, lxfile, dest_system); mkfilename( msfile, E_spooldir, msname); if ( (stream = FOPEN(msfile, "w", BINARY_MODE)) == NULL ) { printerr(msfile); printmsg(0, "uux: cannot open X file %s", msfile); return FALSE; } /* if */ preamble(stream); /*--------------------------------------------------------------------*/ /* Process options for the remote command */ /*--------------------------------------------------------------------*/ for (; optind < argc; optind++) { FileType f_remote = DATA_FILE; if (*argv[optind] == '-') { strcat(command," "); strcat(command,argv[optind]); printmsg(9, "prm -> %s", argv[optind]); continue; } else if (equal(argv[optind], "<")) { if (i_remote) { printmsg(0, "uux - multiple input files specified"); return FALSE; } else i_remote = TRUE; f_remote = INPUT_FILE; printmsg(9, "prm -> %s", argv[optind]); optind++; } else if (equal(argv[optind], ">")) { if (o_remote) { printmsg(0, "uux - multiple output files specified"); return FALSE; } else o_remote = TRUE; f_remote = OUTPUT_FILE; printmsg(9, "prm -> %s", argv[optind]); optind++; } else if (equal(argv[optind], "|")) { strcat(command," "); strcat(command,argv[optind]); printmsg(9, "prm -> %s", argv[optind]); continue; } else if (remove_parens(argv[optind])) { strcat(command," "); strcat(command,argv[optind]); printmsg(9, "prm -> %s", argv[optind]); continue; } printmsg(9, "prm -> %s", argv[optind]); if (!split_path(argv[optind], src_system, src_file, TRUE, dest_system)) { printmsg(0, "uux - illegal syntax %s", argv[optind]); return FALSE; } /* if (!split_path()) */ s_remote = equal(src_system, E_nodename) ? FALSE : TRUE ; /*--------------------------------------------------------------------*/ /* Do we know the source system? */ /*--------------------------------------------------------------------*/ if ((s_remote) && (checkreal(src_system) == BADHOST)) { printmsg(0, "uux - bad system %s\n", src_system); return FALSE; } /* if ((s_remote) && (checkreal(src_system) == BADHOST)) */ if (f_remote == DATA_FILE) { strcat(command, " "); strcat(command, src_file); } /* if (f_remote == DATA_FILE) */ if (f_remote == OUTPUT_FILE) { fprintf(stream, "O %s %s\n", src_file, (equal(src_system, dest_system) ? " " : src_system) ); continue; } /* if (f_remote == OUTPUT_FILE) */ else if (f_remote == INPUT_FILE) fprintf(stream, "I %s\n", src_file); /*--------------------------------------------------------------------*/ /* if both source & dest are not the same we must copy src_file */ /*--------------------------------------------------------------------*/ if ( !equal(src_system, dest_system) ) { sprintf(dest_file, dataf_fmt, 'D', src_system, sequence_s, subseq()); fprintf(stream, "F %s %s\n", dest_file, src_file ); /*--------------------------------------------------------------------*/ /* if source is remote and dest is local copy source to local */ /* if source is local and dest is remote copy source to remote */ /*--------------------------------------------------------------------*/ if ((s_remote && !d_remote) || (!s_remote && d_remote)) { if (!do_copy(src_system, src_file, dest_system, dest_file)) return FALSE; } /* if ((s_remote && !d_remote) || (!s_remote && d_remote)) */ /*--------------------------------------------------------------------*/ /* if both source & dest are on remote nodes we need uuxqt */ /*--------------------------------------------------------------------*/ else if (s_remote && d_remote) { if (!do_uuxqt(job_id, src_system, src_file, dest_system, dest_file)) return FALSE; if (!do_copy(src_system, src_file, E_nodename, dest_file)) return FALSE; } /* else if (s_remote && d_remote) */ continue; } /* if ( !equal(src_system, dest_system) ) */ printmsg(4, "system \"%s\", rest \"%s\"", src_system, src_file); } /* for (; optind < argc; optind++) */ /*--------------------------------------------------------------------*/ /* Create the data file if any to send to the remote system */ /*--------------------------------------------------------------------*/ if (flags[FLG_READ_STDIN]) { if (i_remote) { printmsg(0, "uux - multiple input files specified"); return FALSE; } sprintf(rifile, dataf_fmt, 'D', E_nodename, sequence_s, subseq()); sprintf(lifile, dataf_fmt, 'D', E_nodename, sequence_s, subseq()); importpath(msname, lifile, dest_system); mkfilename(msfile, E_spooldir, msname); if (!CopyData( NULL, msfile )) { remove( msfile ); return FALSE; } fprintf(stream, "F %s\n", rifile); fprintf(stream, "I %s\n", rifile); } /*--------------------------------------------------------------------*/ /* here finish writing parameters to the X file */ /*--------------------------------------------------------------------*/ printmsg(4, "command \"%s\"", command); fprintf(stream, "C %s\n", command); fclose(stream); /*--------------------------------------------------------------------*/ /* create local C (call) file */ /*--------------------------------------------------------------------*/ if (d_remote) { sprintf(tmfile, spool_fmt, 'C', dest_system, grade, sequence_s); importpath( msname, tmfile, dest_system); mkfilename( msfile, E_spooldir, msname); if ( (stream = FOPEN(msfile, "a",TEXT_MODE)) == NULL) { printerr( msname ); printmsg(0, "uux: cannot write/append to C file %s", msfile); return FALSE; } fprintf(stream, send_cmd, lxfile, rxfile, E_mailbox, lxfile); if (flags[FLG_READ_STDIN]) fprintf(stream, send_cmd, lifile, rifile, E_mailbox, lifile); fclose(stream); } return TRUE; } /* do_remote */ /*--------------------------------------------------------------------*/ /* m a i n */ /* */ /* main program */ /*--------------------------------------------------------------------*/ void main(int argc, char **argv) { int c; extern char *optarg; extern int optind; /*--------------------------------------------------------------------*/ /* Report our version number and date/time compiled */ /*--------------------------------------------------------------------*/ debuglevel = 0; banner( argv ); #if defined(__CORE__) copywrong = strdup(copyright); checkref(copywrong); #endif if (!configure( B_UUCP )) exit(1); /* system configuration failed */ /*--------------------------------------------------------------------*/ /* Switch to the spool directory */ /*--------------------------------------------------------------------*/ tzset(); /* Set up time zone information */ PushDir( E_spooldir ); atexit( PopDir ); user_id = E_mailbox; /*--------------------------------------------------------------------*/ /* Process our arguments */ /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------* * * -aname Use name as the user identification replacing the initiator * -b Return whatever standard input was provided to the uux command * -c Do not copy local file to the spool directory for transfer to * -C Force the copy of local files to the spool directory for * -E run job using exec * -e run job using sh * -ggrade Grade is a single letter number; lower ASCII sequence * -j Output the jobid ASCII string on the standard output which is * -n Do not notify the user if the command fails. * -p Same as -: The standard input to uux is made the standard * -r Do not start the file transfer, just queue the job. * -sfile Report status of the transfer in file. * -xdebug_level * -z Send success notification to the user. * /*--------------------------------------------------------------------*/ while ((c = getopt(argc, argv, "-a:bcCEejg:nprs:x:z")) != EOF) switch(c) { case '-': flags[FLG_READ_STDIN] = TRUE; break; case 'a': flags[FLG_USE_USERID] = TRUE; user_id = optarg; break; case 'b': flags[FLG_RETURN_STDIN] = TRUE; break; case 'c': /* don't spool */ flags[FLG_COPY_SPOOL] = FALSE; break; case 'C': /* force spool */ flags[FLG_COPY_SPOOL] = TRUE; break; case 'E': /* use exec to execute */ flags[FLG_USE_EXEC] = TRUE; break; case 'e': /* use sh to execute */ flags[FLG_USE_EXEC] = FALSE; break; case 'j': /* output job id to stdout */ flags[FLG_OUTPUT_JOBID] = TRUE; break; case 'n': /* do not notify user if command fails */ flags[FLG_NONOTIFY_FAIL] = TRUE; break; case 'p': flags[FLG_READ_STDIN] = TRUE; break; case 'r': /* queue job only */ flags[FLG_QUEUE_ONLY] = TRUE; break; case 'z': flags[FLG_NOTIFY_SUCCESS] = TRUE; break; case 'g': /* set grade of transfer */ grade = *optarg; break; case 's': /* report status of transfer to file */ flags[FLG_STATUS_FILE] = TRUE; st_out = optarg; break; case 'x': debuglevel = atoi( optarg ); break; case '?': usage(); exit(1); break; default: printmsg(0, "uux - bad argument from getopt \"%c\"", c); exit(1); break; } if (argc - optind < 1) /* Verify we have at least a command */ { printmsg(0,"uux - no command to execute!"); usage(); exit(1); } if (!do_remote(optind, argc, argv)) { printmsg(0, "uux command failed"); exit(1); }; if (flags[FLG_OUTPUT_JOBID]) printf("%s\n", job_id); exit(0); } /* main */ /*--------------------------------------------------------------------*/ /* s u b s e q */ /* */ /* Generate a valid sub-sequence number */ /*--------------------------------------------------------------------*/ static char subseq( void ) { static char next = '0' - 1; switch( next ) { case '9': next = 'A'; break; case 'Z': next = 'a'; break; default: next += 1; } /* switch */ return next; } /* subseq */