1*44e19819Sbostic /*- 2*44e19819Sbostic * Copyright (c) 1985, 1988 The Regents of the University of California. 3*44e19819Sbostic * All rights reserved. 4*44e19819Sbostic * 5*44e19819Sbostic * %sccs.include.proprietary.c% 6*44e19819Sbostic */ 7*44e19819Sbostic 852081424Ssam #ifndef lint 9*44e19819Sbostic char copyright[] = 10*44e19819Sbostic "@(#) Copyright (c) 1985, 1988 The Regents of the University of California.\n\ 11*44e19819Sbostic All rights reserved.\n"; 12*44e19819Sbostic #endif /* not lint */ 13*44e19819Sbostic 14*44e19819Sbostic #ifndef lint 15*44e19819Sbostic static char sccsid[] = "@(#)uuxqt.c 5.14 (Berkeley) 04/24/91"; 16*44e19819Sbostic #endif /* not lint */ 1752081424Ssam 1852081424Ssam #include "uucp.h" 1952081424Ssam #include <sys/stat.h> 2052081424Ssam #ifdef NDIR 2152081424Ssam #include "ndir.h" 2252081424Ssam #else 23109b7051Ssam #include <sys/dir.h> 2452081424Ssam #endif 25e21537dbSralph #include <signal.h> 2652081424Ssam 272f96a7e7Sralph #define BADCHARS "&^|(`\\<>;\"{}\n'" 282f96a7e7Sralph #define RECHECKTIME 60*10 /* 10 minutes */ 29dbb6249cSralph 3052081424Ssam #define APPCMD(d) {\ 3152081424Ssam char *p;\ 32e21537dbSralph for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';} 3352081424Ssam 342bba3b8bSrick extern char Filent[LLEN][NAMESIZE]; 352bba3b8bSrick 3652081424Ssam /* 3752081424Ssam * uuxqt will execute commands set up by a uux command, 3852081424Ssam * usually from a remote machine - set by uucp. 3952081424Ssam */ 4052081424Ssam 4152081424Ssam #define NCMDS 50 42e21537dbSralph char *Cmds[NCMDS+1]; 43e21537dbSralph int Notify[NCMDS+1]; 44e21537dbSralph #define NT_YES 0 /* if should notify on execution */ 45e21537dbSralph #define NT_ERR 1 /* if should notify if non-zero exit status (-z equivalent) */ 46e21537dbSralph #define NT_NO 2 /* if should not notify ever (-n equivalent) */ 47e21537dbSralph 48e21537dbSralph extern int Nfiles; 4952081424Ssam 502f96a7e7Sralph int TransferSucceeded = 1; 5152081424Ssam int notiok = 1; 5252081424Ssam int nonzero = 0; 5352081424Ssam 5498a5b756Sbloom struct timeb Now; 5598a5b756Sbloom 56290a350eStrent char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin"; 572cbba08fSrick char UU_MACHINE[MAXFULLNAME]; 582f96a7e7Sralph char Shell[MAXFULLNAME]; 592f96a7e7Sralph char HOME[MAXFULLNAME]; 602f96a7e7Sralph 612f96a7e7Sralph extern char **environ; 622f96a7e7Sralph char *nenv[] = { 632f96a7e7Sralph PATH, 642f96a7e7Sralph Shell, 652f96a7e7Sralph HOME, 662cbba08fSrick UU_MACHINE, 672f96a7e7Sralph 0 682f96a7e7Sralph }; 692f96a7e7Sralph 7052081424Ssam /* to remove restrictions from uuxqt 7152081424Ssam * define ALLOK 1 7252081424Ssam * 7352081424Ssam * to add allowable commands, add to the file CMDFILE 7452081424Ssam * A line of form "PATH=..." changes the search path 7552081424Ssam */ 7652081424Ssam main(argc, argv) 7752081424Ssam char *argv[]; 7852081424Ssam { 792bba3b8bSrick char xcmd[BUFSIZ*2]; 8052081424Ssam int argnok; 81e21537dbSralph int notiflg; 822bba3b8bSrick char xfile[MAXFULLNAME], user[MAXFULLNAME], buf[BUFSIZ*2]; 83e21537dbSralph char lbuf[MAXFULLNAME]; 8452081424Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME]; 8552081424Ssam char file[NAMESIZE]; 8652081424Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; 8752081424Ssam register FILE *xfp, *fp; 8852081424Ssam FILE *dfp; 8952081424Ssam char path[MAXFULLNAME]; 902bba3b8bSrick char cmd[BUFSIZ*2]; 9152081424Ssam char *cmdp, prm[1000], *ptr; 9252081424Ssam char *getprm(), *lastpart(); 932cbba08fSrick int uid, ret, badfiles; 9452081424Ssam register int i; 9552081424Ssam int stcico = 0; 962f96a7e7Sralph time_t xstart, xnow; 9752081424Ssam char retstat[30]; 982cbba08fSrick extern char *optarg; 992cbba08fSrick extern int optind; 10052081424Ssam 10152081424Ssam strcpy(Progname, "uuxqt"); 10252081424Ssam uucpname(Myname); 103f2386554Srick strcpy(Rmtname, Myname); 10452081424Ssam 10552081424Ssam umask(WFMASK); 10652081424Ssam Ofn = 1; 10752081424Ssam Ifn = 0; 1082cbba08fSrick while ((i = getopt(argc, argv, "x:S:")) != EOF) 1092cbba08fSrick switch(i) { 11052081424Ssam case 'x': 111e21537dbSralph chkdebug(); 1122cbba08fSrick Debug = atoi(optarg); 11352081424Ssam if (Debug <= 0) 11452081424Ssam Debug = 1; 11552081424Ssam break; 1162bba3b8bSrick case 'S': 1172cbba08fSrick Spool = optarg; 1182bba3b8bSrick DEBUG(1, "Spool set to %s", Spool); 1192bba3b8bSrick break; 1202cbba08fSrick case '?': 12152081424Ssam default: 1222cbba08fSrick fprintf(stderr, "unknown flag %s\n", argv[optind-1]); 12352081424Ssam break; 12452081424Ssam } 12552081424Ssam 1262f96a7e7Sralph DEBUG(4, "\n\n** START **\n", CNULL); 1272cbba08fSrick if (subchdir(Spool) < 0) { 1282cbba08fSrick syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool); 1292cbba08fSrick cleanup(1); 1302cbba08fSrick } 13152081424Ssam strcpy(Wrkdir, Spool); 13252081424Ssam uid = getuid(); 1332bba3b8bSrick if (guinfo(uid, User, path) != SUCCESS) { 1342cbba08fSrick syslog(LOG_WARNING, "Can't find username for uid %d", uid); 1352bba3b8bSrick DEBUG(1, "Using username", "uucp"); 1362bba3b8bSrick strcpy(User, "uucp"); 1372bba3b8bSrick } 138e21537dbSralph setgid(getegid()); 139e21537dbSralph setuid(geteuid()); 140e21537dbSralph 14152081424Ssam DEBUG(4, "User - %s\n", User); 1421a575e59Sbloom if (ulockf(X_LOCK, X_LOCKTIME) != 0) 14352081424Ssam exit(0); 14452081424Ssam 14552081424Ssam fp = fopen(CMDFILE, "r"); 14652081424Ssam if (fp == NULL) { 147e21537dbSralph logent(CANTOPEN, CMDFILE); 14852081424Ssam Cmds[0] = "rmail"; 14952081424Ssam Cmds[1] = "rnews"; 15052081424Ssam Cmds[2] = "ruusend"; 15152081424Ssam Cmds[3] = NULL; 15252081424Ssam goto doprocess; 15352081424Ssam } 15452081424Ssam DEBUG(5, "%s opened\n", CMDFILE); 155e21537dbSralph for (i=0; i<NCMDS && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) { 156e21537dbSralph int j; 157e21537dbSralph /* strip trailing whitespace */ 158e21537dbSralph for (j = strlen(xcmd)-1; j >= 0; --j) 159e21537dbSralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t') 160e21537dbSralph xcmd[j] = '\0'; 161e21537dbSralph else 162e21537dbSralph break; 163e21537dbSralph /* look for imbedded whitespace */ 164e21537dbSralph for (; j >= 0; --j) 165e21537dbSralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t') 166e21537dbSralph break; 167e21537dbSralph /* skip this entry if it has embedded whitespace */ 168e21537dbSralph /* This defends against a bad PATH=, for example */ 169e21537dbSralph if (j >= 0) { 170e21537dbSralph logent(xcmd, "BAD WHITESPACE"); 171e21537dbSralph continue; 172e21537dbSralph } 17352081424Ssam if (strncmp(xcmd, "PATH=", 5) == 0) { 17452081424Ssam strcpy(PATH, xcmd); 17552081424Ssam i--; /*kludge */ 17652081424Ssam continue; 17752081424Ssam } 17852081424Ssam DEBUG(5, "xcmd = %s\n", xcmd); 179e21537dbSralph 180e21537dbSralph if ((ptr = index(xcmd, ',')) != NULL) { 181e21537dbSralph *ptr++ = '\0'; 182e21537dbSralph if (strncmp(ptr, "Err", 3) == SAME) 183e21537dbSralph Notify[i] = NT_ERR; 184e21537dbSralph else if (strcmp(ptr, "No") == SAME) 185e21537dbSralph Notify[i] = NT_NO; 186e21537dbSralph else 187e21537dbSralph Notify[i] = NT_YES; 188e21537dbSralph } else 189e21537dbSralph Notify[i] = NT_YES; 190e21537dbSralph if ((Cmds[i] = malloc((unsigned)(strlen(xcmd)+1))) == NULL) { 191e21537dbSralph DEBUG(1, "MALLOC FAILED", CNULL); 192e21537dbSralph break; 193e21537dbSralph } 19452081424Ssam strcpy(Cmds[i], xcmd); 19552081424Ssam } 196e21537dbSralph Cmds[i] = CNULL; 19752081424Ssam fclose(fp); 19852081424Ssam 19952081424Ssam doprocess: 2002f96a7e7Sralph 2012f96a7e7Sralph (void) sprintf(HOME, "HOME=%s", Spool); 2022f96a7e7Sralph (void) sprintf(Shell, "SHELL=%s", SHELL); 2032f96a7e7Sralph environ = nenv; /* force use if our environment */ 2042f96a7e7Sralph 2052f96a7e7Sralph DEBUG(11,"path = %s\n", getenv("PATH")); 2062f96a7e7Sralph 207e21537dbSralph DEBUG(4, "process %s\n", CNULL); 2082bba3b8bSrick 2092f96a7e7Sralph time(&xstart); 21052081424Ssam while (gtxfile(xfile) > 0) { 211e21537dbSralph /* if /etc/nologin exists, exit cleanly */ 21298a5b756Sbloom #if defined(BSD4_2) || defined(USG) 21398a5b756Sbloom if (access(NOLOGIN) == 0) { 21498a5b756Sbloom #else !BSD4_2 && ! USG 21598a5b756Sbloom ultouch(); 216e21537dbSralph if (nologinflag) { 21798a5b756Sbloom #endif !BSD4_2 && !USG 218e21537dbSralph logent(NOLOGIN, "UUXQT SHUTDOWN"); 219e21537dbSralph if (Debug) 220e21537dbSralph logent("debugging", "continuing anyway"); 221e21537dbSralph else 222e21537dbSralph break; 223e21537dbSralph } 22452081424Ssam DEBUG(4, "xfile - %s\n", xfile); 22552081424Ssam 22652081424Ssam xfp = fopen(subfile(xfile), "r"); 2272cbba08fSrick if (xfp == NULL) { 2282cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", subfile(xfile)); 2292cbba08fSrick cleanup(1); 2302cbba08fSrick } 23152081424Ssam 23252081424Ssam /* initialize to default */ 23352081424Ssam strcpy(user, User); 234e21537dbSralph strcpy(fin, DEVNULL); 235e21537dbSralph strcpy(fout, DEVNULL); 2361a575e59Sbloom strcpy(sysout, Myname); 237e21537dbSralph badfiles = 0; 23852081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 2392bba3b8bSrick if(buf[0] != '\0' && buf[0] != '#' && 2402bba3b8bSrick buf[1] != ' ' && buf[1] != '\0' && buf[1] != '\n') { 2412bba3b8bSrick char *bnp, cfilename[BUFSIZ]; 2422bba3b8bSrick DEBUG(4, "uuxqt: buf = %s\n", buf); 2432bba3b8bSrick bnp = rindex(xfile, '/'); 2442bba3b8bSrick sprintf(cfilename, "%s/%s", CORRUPT, 2452bba3b8bSrick bnp ? bnp + 1 : xfile); 2462bba3b8bSrick DEBUG(4, "uuxqt: move %s to ", xfile); 2472bba3b8bSrick DEBUG(4, "%s\n", cfilename); 2482bba3b8bSrick xmv(xfile, cfilename); 249a92c1dbeSrick syslog(LOG_WARNING, "%s: X. FILE CORRUPTED", 250a92c1dbeSrick xfile); 2512bba3b8bSrick fclose(xfp); 2522bba3b8bSrick goto doprocess; 2532bba3b8bSrick } 25452081424Ssam switch (buf[0]) { 255a92c1dbeSrick case X_USER: { 256a92c1dbeSrick char ORmtname[MAXFULLNAME]; 257a92c1dbeSrick strcpy(ORmtname, Rmtname); 25852081424Ssam sscanf(&buf[1], "%s %s", user, Rmtname); 2592cbba08fSrick sprintf(UU_MACHINE, "UU_MACHINE=%s", Rmtname); 260a92c1dbeSrick if (strcmp(ORmtname, Rmtname) != 0) 261a92c1dbeSrick logcls(); 262a92c1dbeSrick break;} 263e21537dbSralph case X_RETURNTO: 264e21537dbSralph sscanf(&buf[1], "%s", user); 265e21537dbSralph break; 26652081424Ssam case X_STDIN: 26752081424Ssam sscanf(&buf[1], "%s", fin); 26852081424Ssam i = expfile(fin); 26952081424Ssam /* rti!trt: do not check permissions of 27052081424Ssam * vanilla spool file */ 27152081424Ssam if (i != 0 27252081424Ssam && (chkpth("", "", fin) || anyread(fin) != 0)) 27352081424Ssam badfiles = 1; 27452081424Ssam break; 27552081424Ssam case X_STDOUT: 27652081424Ssam sscanf(&buf[1], "%s%s", fout, sysout); 2771a575e59Sbloom sysout[MAXBASENAME] = '\0'; 27852081424Ssam /* rti!trt: do not check permissions of 27952081424Ssam * vanilla spool file. DO check permissions 28052081424Ssam * of writing on a non-vanilla file */ 28152081424Ssam i = 1; 28252081424Ssam if (fout[0] != '~' || prefix(sysout, Myname)) 28352081424Ssam i = expfile(fout); 28452081424Ssam if (i != 0 28552081424Ssam && (chkpth("", "", fout) 28652081424Ssam || chkperm(fout, (char *)1))) 28752081424Ssam badfiles = 1; 28852081424Ssam break; 28952081424Ssam case X_CMD: 29052081424Ssam strcpy(cmd, &buf[2]); 29152081424Ssam if (*(cmd + strlen(cmd) - 1) == '\n') 29252081424Ssam *(cmd + strlen(cmd) - 1) = '\0'; 29352081424Ssam break; 29452081424Ssam case X_NONOTI: 29552081424Ssam notiok = 0; 29652081424Ssam break; 29752081424Ssam case X_NONZERO: 29852081424Ssam nonzero = 1; 29952081424Ssam break; 30052081424Ssam default: 30152081424Ssam break; 30252081424Ssam } 30352081424Ssam } 30452081424Ssam 30552081424Ssam fclose(xfp); 30652081424Ssam DEBUG(4, "fin - %s, ", fin); 30752081424Ssam DEBUG(4, "fout - %s, ", fout); 30852081424Ssam DEBUG(4, "sysout - %s, ", sysout); 30952081424Ssam DEBUG(4, "user - %s\n", user); 31052081424Ssam DEBUG(4, "cmd - %s\n", cmd); 31152081424Ssam 31252081424Ssam /* command execution */ 313e21537dbSralph if (strcmp(fout, DEVNULL) == SAME) 314e21537dbSralph strcpy(dfile,DEVNULL); 31552081424Ssam else 31652081424Ssam gename(DATAPRE, sysout, 'O', dfile); 31752081424Ssam 31852081424Ssam /* expand file names where necessary */ 31952081424Ssam expfile(dfile); 3202f96a7e7Sralph cmdp = buf; 32152081424Ssam ptr = cmd; 32252081424Ssam xcmd[0] = '\0'; 32352081424Ssam argnok = 0; 32452081424Ssam while ((ptr = getprm(ptr, prm)) != NULL) { 32552081424Ssam if (prm[0] == ';' || prm[0] == '^' 32652081424Ssam || prm[0] == '&' || prm[0] == '|') { 32752081424Ssam xcmd[0] = '\0'; 32852081424Ssam APPCMD(prm); 32952081424Ssam continue; 33052081424Ssam } 33152081424Ssam 332e21537dbSralph if ((argnok = argok(xcmd, prm)) != SUCCESS) 33352081424Ssam /* command not valid */ 33452081424Ssam break; 33552081424Ssam 33652081424Ssam if (prm[0] == '~') 33752081424Ssam expfile(prm); 33852081424Ssam APPCMD(prm); 33952081424Ssam } 340e21537dbSralph /* 341e21537dbSralph * clean up trailing ' ' in command. 342e21537dbSralph */ 343e21537dbSralph if (cmdp > buf && cmdp[0] == '\0' && cmdp[-1] == ' ') 344e21537dbSralph *--cmdp = '\0'; 34552081424Ssam if (argnok || badfiles) { 34652081424Ssam sprintf(lbuf, "%s XQT DENIED", user); 34752081424Ssam logent(cmd, lbuf); 34852081424Ssam DEBUG(4, "bad command %s\n", prm); 34952081424Ssam notify(user, Rmtname, cmd, "DENIED"); 35052081424Ssam goto rmfiles; 35152081424Ssam } 35252081424Ssam sprintf(lbuf, "%s XQT", user); 35352081424Ssam logent(buf, lbuf); 35452081424Ssam DEBUG(4, "cmd %s\n", buf); 35552081424Ssam 35652081424Ssam mvxfiles(xfile); 3572cbba08fSrick if (subchdir(XQTDIR) < 0) { 3582cbba08fSrick syslog(LOG_ERR, "chdir(%s) failed: %m", XQTDIR); 3592cbba08fSrick cleanup(1); 3602cbba08fSrick } 3612f96a7e7Sralph ret = shio(buf, fin, dfile); 36252081424Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377, 36352081424Ssam (ret>>8) & 0377); 36452081424Ssam if (strcmp(xcmd, "rmail") == SAME) 36552081424Ssam notiok = 0; 36652081424Ssam if (strcmp(xcmd, "rnews") == SAME) 36752081424Ssam nonzero = 1; 368e21537dbSralph notiflg = chknotify(xcmd); 369e21537dbSralph if (notiok && notiflg != NT_NO && 370e21537dbSralph (ret != 0 || (!nonzero && notiflg == NT_YES))) 37152081424Ssam notify(user, Rmtname, cmd, retstat); 37252081424Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) { 37352081424Ssam /* mail failed - return letter to sender */ 374e21537dbSralph #ifdef DANGEROUS 375e21537dbSralph /* NOT GUARANTEED SAFE!!! */ 376e21537dbSralph if (!nonzero) 37752081424Ssam retosndr(user, Rmtname, fin); 378e21537dbSralph #else 379e21537dbSralph notify(user, Rmtname, cmd, retstat); 380e21537dbSralph #endif 381e21537dbSralph sprintf(buf, "%s (%s) from %s!%s", buf, retstat, Rmtname, user); 38252081424Ssam logent("MAIL FAIL", buf); 38352081424Ssam } 38452081424Ssam DEBUG(4, "exit cmd - %d\n", ret); 3852cbba08fSrick if (subchdir(Spool) < 0) { 3862cbba08fSrick syslog(LOG_ERR, "chdir(%s) failed: %m", Spool); 3872cbba08fSrick cleanup(1); 3882cbba08fSrick } 38952081424Ssam rmxfiles(xfile); 39052081424Ssam if (ret != 0) { 39152081424Ssam /* exit status not zero */ 39252081424Ssam dfp = fopen(subfile(dfile), "a"); 3932cbba08fSrick if (dfp == NULL) { 3942cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", 3952cbba08fSrick subfile(dfile)); 3962cbba08fSrick cleanup(1); 3972cbba08fSrick } 39852081424Ssam fprintf(dfp, "exit status %d", ret); 39952081424Ssam fclose(dfp); 40052081424Ssam } 401e21537dbSralph if (strcmp(fout, DEVNULL) != SAME) { 40252081424Ssam if (prefix(sysout, Myname)) { 40352081424Ssam xmv(dfile, fout); 40452081424Ssam chmod(fout, BASEMODE); 4052f96a7e7Sralph } else { 406e21537dbSralph char *cp = rindex(user, '!'); 40752081424Ssam gename(CMDPRE, sysout, 'O', cfile); 40852081424Ssam fp = fopen(subfile(cfile), "w"); 4092cbba08fSrick if (fp == NULL) { 4102cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", 4112cbba08fSrick subfile(cfile)); 4122cbba08fSrick cleanup(1); 4132cbba08fSrick } 414e21537dbSralph fprintf(fp, "S %s %s %s - %s 0666\n", dfile, 415e21537dbSralph fout, cp ? cp : user, lastpart(dfile)); 41652081424Ssam fclose(fp); 41752081424Ssam } 41852081424Ssam } 41952081424Ssam rmfiles: 42052081424Ssam xfp = fopen(subfile(xfile), "r"); 4212cbba08fSrick if (xfp == NULL) { 4222cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", 4232cbba08fSrick subfile(xfile)); 4242cbba08fSrick cleanup(1); 4252cbba08fSrick } 42652081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 42752081424Ssam if (buf[0] != X_RQDFILE) 42852081424Ssam continue; 42952081424Ssam sscanf(&buf[1], "%s", file); 43052081424Ssam unlink(subfile(file)); 43152081424Ssam } 43252081424Ssam unlink(subfile(xfile)); 43352081424Ssam fclose(xfp); 4342f96a7e7Sralph 4352f96a7e7Sralph /* rescan X. for new work every RECHECKTIME seconds */ 4362f96a7e7Sralph time(&xnow); 4372f96a7e7Sralph if (xnow > (xstart + RECHECKTIME)) { 4382f96a7e7Sralph extern int Nfiles; 4392f96a7e7Sralph Nfiles = 0; /*force rescan for new work */ 4402f96a7e7Sralph } 4412f96a7e7Sralph xstart = xnow; 44252081424Ssam } 44352081424Ssam 44452081424Ssam if (stcico) 44552081424Ssam xuucico(""); 44652081424Ssam cleanup(0); 44752081424Ssam } 44852081424Ssam 44952081424Ssam 45052081424Ssam cleanup(code) 45152081424Ssam int code; 45252081424Ssam { 45352081424Ssam logcls(); 45452081424Ssam rmlock(CNULL); 455e21537dbSralph #ifdef VMS 456e21537dbSralph /* 457e21537dbSralph * Since we run as a BATCH job we must wait for all processes to 458e21537dbSralph * to finish 459e21537dbSralph */ 4602f96a7e7Sralph while(wait(0) != -1) 4612f96a7e7Sralph ; 462e21537dbSralph #endif VMS 46352081424Ssam exit(code); 46452081424Ssam } 46552081424Ssam 46652081424Ssam 4672f96a7e7Sralph /* 4682f96a7e7Sralph * get a file to execute 46952081424Ssam * 47052081424Ssam * return codes: 0 - no file | 1 - file to execute 47152081424Ssam */ 47252081424Ssam 47352081424Ssam gtxfile(file) 47452081424Ssam register char *file; 47552081424Ssam { 47652081424Ssam char pre[3]; 4772bba3b8bSrick register int rechecked, i; 478e21537dbSralph time_t ystrdy; /* yesterday */ 479e21537dbSralph struct stat stbuf; /* for X file age */ 48052081424Ssam 48152081424Ssam pre[0] = XQTPRE; 48252081424Ssam pre[1] = '.'; 48352081424Ssam pre[2] = '\0'; 48452081424Ssam rechecked = 0; 48552081424Ssam retry: 4862bba3b8bSrick if (Nfiles-- <= 0) { 4872bba3b8bSrick Nfiles = 0; 48852081424Ssam if (rechecked) 489e21537dbSralph return 0; 49052081424Ssam rechecked = 1; 491e21537dbSralph DEBUG(4, "iswrk\n", CNULL); 4922bba3b8bSrick return iswrk(file, "get", Spool, pre); 49352081424Ssam } 4942bba3b8bSrick sprintf(file, "%s/%s", Spool, Filent[0]); 4952bba3b8bSrick for (i=0; i<Nfiles;i++) 4962bba3b8bSrick strcpy(Filent[i], Filent[i+1]); 4972bba3b8bSrick 49852081424Ssam DEBUG(4, "file - %s\n", file); 49952081424Ssam /* skip spurious subdirectories */ 50052081424Ssam if (strcmp(pre, file) == SAME) 50152081424Ssam goto retry; 50252081424Ssam if (gotfiles(file)) 503e21537dbSralph return 1; 504e21537dbSralph /* check for old X. file with no work files and remove them. */ 505e21537dbSralph if (Nfiles > LLEN/2) { 506e21537dbSralph time(&ystrdy); 507e21537dbSralph ystrdy -= (4 * 3600L); /* 4 hours ago */ 508e21537dbSralph DEBUG(4, "gtxfile: Nfiles > LLEN/2\n", CNULL); 5092bba3b8bSrick while (Nfiles-- > 0) { 5102bba3b8bSrick sprintf(file, "%s/%s", Spool, Filent[0]); 5112bba3b8bSrick for (i=0; i<Nfiles; i++) 5122bba3b8bSrick strcpy(Filent[i], Filent[i+1]); 5132bba3b8bSrick 5142bba3b8bSrick if (gotfiles(file)) 5152bba3b8bSrick return 1; 516e21537dbSralph if (stat(subfile(file), &stbuf) == 0) 517e21537dbSralph if (stbuf.st_mtime <= ystrdy) { 518e21537dbSralph char *bnp, cfilename[NAMESIZE]; 519e21537dbSralph DEBUG(4, "gtxfile: move %s to CORRUPT \n", file); 5202bba3b8bSrick bnp = rindex(file, '/'); 521e21537dbSralph sprintf(cfilename, "%s/%s", CORRUPT, 5222bba3b8bSrick bnp ? bnp + 1 : file); 5232bba3b8bSrick xmv(file, cfilename); 5242cbba08fSrick syslog(LOG_WARNING, "%s: X. FILE MISSING FILES", file); 525e21537dbSralph } 526e21537dbSralph } 5272bba3b8bSrick Nfiles = 0; 528e21537dbSralph DEBUG(4, "iswrk\n", CNULL); 529e21537dbSralph if (!iswrk(file, "get", Spool, pre)) 530e21537dbSralph return 0; 531e21537dbSralph } 53252081424Ssam goto retry; 53352081424Ssam } 53452081424Ssam 5352f96a7e7Sralph /* 5362f96a7e7Sralph * check for needed files 53752081424Ssam * 53852081424Ssam * return codes: 0 - not ready | 1 - all files ready 53952081424Ssam */ 54052081424Ssam 54152081424Ssam gotfiles(file) 54252081424Ssam register char *file; 54352081424Ssam { 54452081424Ssam struct stat stbuf; 54552081424Ssam register FILE *fp; 54652081424Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME]; 54752081424Ssam 54852081424Ssam fp = fopen(subfile(file), "r"); 54952081424Ssam if (fp == NULL) 550e21537dbSralph return 0; 55152081424Ssam 55252081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 55352081424Ssam DEBUG(4, "%s\n", buf); 55452081424Ssam if (buf[0] != X_RQDFILE) 55552081424Ssam continue; 55652081424Ssam sscanf(&buf[1], "%s", rqfile); 55752081424Ssam expfile(rqfile); 55852081424Ssam if (stat(subfile(rqfile), &stbuf) == -1) { 55952081424Ssam fclose(fp); 560e21537dbSralph return 0; 56152081424Ssam } 56252081424Ssam } 56352081424Ssam 56452081424Ssam fclose(fp); 565e21537dbSralph return 1; 56652081424Ssam } 56752081424Ssam 56852081424Ssam 5692f96a7e7Sralph /* 5702f96a7e7Sralph * remove execute files to x-directory 57152081424Ssam */ 57252081424Ssam 57352081424Ssam rmxfiles(xfile) 57452081424Ssam register char *xfile; 57552081424Ssam { 57652081424Ssam register FILE *fp; 57752081424Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; 57852081424Ssam char tfull[MAXFULLNAME]; 57952081424Ssam 58052081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 58152081424Ssam return; 58252081424Ssam 58352081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 58452081424Ssam if (buf[0] != X_RQDFILE) 58552081424Ssam continue; 58652081424Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2) 58752081424Ssam continue; 58852081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 58952081424Ssam unlink(subfile(tfull)); 59052081424Ssam } 59152081424Ssam fclose(fp); 59252081424Ssam return; 59352081424Ssam } 59452081424Ssam 59552081424Ssam 5962f96a7e7Sralph /* 5972f96a7e7Sralph * move execute files to x-directory 59852081424Ssam */ 59952081424Ssam 60052081424Ssam mvxfiles(xfile) 60152081424Ssam char *xfile; 60252081424Ssam { 60352081424Ssam register FILE *fp; 60452081424Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; 60552081424Ssam char tfull[MAXFULLNAME]; 60652081424Ssam 60752081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 60852081424Ssam return; 60952081424Ssam 61052081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 61152081424Ssam if (buf[0] != X_RQDFILE) 61252081424Ssam continue; 61352081424Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) 61452081424Ssam continue; 61552081424Ssam expfile(ffile); 61652081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 61752081424Ssam unlink(subfile(tfull)); 6182cbba08fSrick if (xmv(ffile, tfull) != 0) { 6192cbba08fSrick syslog(LOG_WARNING, "xmv(%s,%s) failed: %m", 6202cbba08fSrick ffile, tfull); 6212cbba08fSrick cleanup(1); 6222cbba08fSrick } 62352081424Ssam } 62452081424Ssam fclose(fp); 62552081424Ssam } 62652081424Ssam 6272f96a7e7Sralph /* 6282f96a7e7Sralph * check for valid command/argument 6292f96a7e7Sralph * *NOTE - side effect is to set xc to the command to be executed. 63052081424Ssam * 63152081424Ssam * return 0 - ok | 1 nok 63252081424Ssam */ 63352081424Ssam 63452081424Ssam argok(xc, cmd) 63552081424Ssam register char *xc, *cmd; 63652081424Ssam { 63752081424Ssam register char **ptr; 63852081424Ssam 63952081424Ssam #ifndef ALLOK 6402f96a7e7Sralph if (strpbrk(cmd, BADCHARS) != NULL) { 641e21537dbSralph DEBUG(1,"MAGIC CHARACTER FOUND\n", CNULL); 6422f96a7e7Sralph logent(cmd, "NASTY MAGIC CHARACTER FOUND"); 643e21537dbSralph return FAIL; 644e21537dbSralph } 645e21537dbSralph #endif !ALLOK 64652081424Ssam 64752081424Ssam if (xc[0] != '\0') 648e21537dbSralph return SUCCESS; 64952081424Ssam 65052081424Ssam #ifndef ALLOK 65152081424Ssam ptr = Cmds; 652e21537dbSralph DEBUG(9, "Compare %s and\n", cmd); 65352081424Ssam while(*ptr != NULL) { 654e21537dbSralph DEBUG(9, "\t%s\n", *ptr); 65552081424Ssam if (strcmp(cmd, *ptr) == SAME) 65652081424Ssam break; 65752081424Ssam ptr++; 65852081424Ssam } 659e21537dbSralph if (*ptr == NULL) { 660e21537dbSralph DEBUG(1,"COMMAND NOT FOUND\n", CNULL); 661e21537dbSralph return FAIL; 662e21537dbSralph } 66352081424Ssam #endif 66452081424Ssam strcpy(xc, cmd); 665e21537dbSralph DEBUG(9, "MATCHED %s\n", xc); 666e21537dbSralph return SUCCESS; 66752081424Ssam } 66852081424Ssam 66952081424Ssam 6702f96a7e7Sralph /* 6712f96a7e7Sralph * if notification should be sent for successful execution of cmd 672e21537dbSralph * 673e21537dbSralph * return NT_YES - do notification 674e21537dbSralph * NT_ERR - do notification if exit status != 0 675e21537dbSralph * NT_NO - don't do notification ever 676e21537dbSralph */ 677e21537dbSralph 678e21537dbSralph chknotify(cmd) 679e21537dbSralph char *cmd; 680e21537dbSralph { 681e21537dbSralph register char **ptr; 682e21537dbSralph register int *nptr; 683e21537dbSralph 684e21537dbSralph ptr = Cmds; 685e21537dbSralph nptr = Notify; 686e21537dbSralph while (*ptr != NULL) { 687e21537dbSralph if (strcmp(cmd, *ptr) == SAME) 688e21537dbSralph return *nptr; 689e21537dbSralph ptr++; 690e21537dbSralph nptr++; 691e21537dbSralph } 692e21537dbSralph return NT_YES; /* "shouldn't happen" */ 693e21537dbSralph } 694e21537dbSralph 695e21537dbSralph 696e21537dbSralph 6972f96a7e7Sralph /* 6982f96a7e7Sralph * send mail to user giving execution results 69952081424Ssam */ 70052081424Ssam 70152081424Ssam notify(user, rmt, cmd, str) 70252081424Ssam char *user, *rmt, *cmd, *str; 70352081424Ssam { 7042bba3b8bSrick char text[BUFSIZ*2]; 70552081424Ssam char ruser[MAXFULLNAME]; 70652081424Ssam 707bd1b9349Sbloom if (strpbrk(user, BADCHARS) != NULL) { 708bd1b9349Sbloom char lbuf[MAXFULLNAME]; 709bd1b9349Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user); 710bd1b9349Sbloom logent(cmd, lbuf); 711bd1b9349Sbloom strcpy(user, "postmaster"); 712bd1b9349Sbloom } 713e21537dbSralph sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str); 71452081424Ssam if (prefix(rmt, Myname)) 71552081424Ssam strcpy(ruser, user); 71652081424Ssam else 71752081424Ssam sprintf(ruser, "%s!%s", rmt, user); 718e21537dbSralph mailst(ruser, text, CNULL); 71952081424Ssam } 72052081424Ssam 7212f96a7e7Sralph /* 7222f96a7e7Sralph * return mail to sender 72352081424Ssam * 72452081424Ssam */ 72552081424Ssam retosndr(user, rmt, file) 72652081424Ssam char *user, *rmt, *file; 72752081424Ssam { 728e21537dbSralph char ruser[MAXFULLNAME]; 72952081424Ssam 730bd1b9349Sbloom if (strpbrk(user, BADCHARS) != NULL) { 731bd1b9349Sbloom char lbuf[MAXFULLNAME]; 732bd1b9349Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user); 733bd1b9349Sbloom logent(file, lbuf); 734bd1b9349Sbloom strcpy(user, "postmaster"); 735bd1b9349Sbloom } 73652081424Ssam if (strcmp(rmt, Myname) == SAME) 73752081424Ssam strcpy(ruser, user); 73852081424Ssam else 73952081424Ssam sprintf(ruser, "%s!%s", rmt, user); 74052081424Ssam 74152081424Ssam if (anyread(file) == 0) 74252081424Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file); 74352081424Ssam else 744e21537dbSralph mailst(ruser, "Mail failed. Letter returned to sender.\n", CNULL); 74552081424Ssam return; 74652081424Ssam } 747dbb6249cSralph 748dbb6249cSralph /* 7492f96a7e7Sralph * execute shell of command with fi and fo as standard input/output 7502f96a7e7Sralph */ 7512f96a7e7Sralph 7522f96a7e7Sralph shio(cmd, fi, fo) 7532f96a7e7Sralph char *cmd, *fi, *fo; 7542f96a7e7Sralph { 7552f96a7e7Sralph int status, f; 7562cbba08fSrick int pid, ret; 7572bba3b8bSrick char *args[256]; 7582f96a7e7Sralph extern int errno; 7592f96a7e7Sralph 7602f96a7e7Sralph if (fi == NULL) 7612f96a7e7Sralph fi = DEVNULL; 7622f96a7e7Sralph if (fo == NULL) 7632f96a7e7Sralph fo = DEVNULL; 7642f96a7e7Sralph 7652bba3b8bSrick getargs(cmd, args, 256); 7662f96a7e7Sralph DEBUG(3, "shio - %s\n", cmd); 7672f96a7e7Sralph #ifdef SIGCHLD 7682f96a7e7Sralph signal(SIGCHLD, SIG_IGN); 7692f96a7e7Sralph #endif SIGCHLD 7702f96a7e7Sralph if ((pid = fork()) == 0) { 7712f96a7e7Sralph signal(SIGINT, SIG_IGN); 7722f96a7e7Sralph signal(SIGHUP, SIG_IGN); 7732f96a7e7Sralph signal(SIGQUIT, SIG_IGN); 7742f96a7e7Sralph close(Ifn); 7752f96a7e7Sralph close(Ofn); 7762f96a7e7Sralph close(0); 7772f96a7e7Sralph setuid(getuid()); 7782f96a7e7Sralph f = open(subfile(fi), 0); 7792f96a7e7Sralph if (f != 0) { 7802f96a7e7Sralph logent(fi, "CAN'T READ"); 7812f96a7e7Sralph exit(-errno); 7822f96a7e7Sralph } 7832f96a7e7Sralph close(1); 7842f96a7e7Sralph f = creat(subfile(fo), 0666); 7852f96a7e7Sralph if (f != 1) { 7862f96a7e7Sralph logent(fo, "CAN'T WRITE"); 7872f96a7e7Sralph exit(-errno); 7882f96a7e7Sralph } 7892f96a7e7Sralph execvp(args[0], args); 7902f96a7e7Sralph exit(100+errno); 7912f96a7e7Sralph } 7922f96a7e7Sralph while ((ret = wait(&status)) != pid && ret != -1) 7932f96a7e7Sralph ; 7942f96a7e7Sralph DEBUG(3, "status %d\n", status); 7952f96a7e7Sralph return status; 7962f96a7e7Sralph } 797