113697Ssam #ifndef lint 2*13702Ssam static char sccsid[] = "@(#)uuxqt.c 5.2 (Berkeley) 07/02/83"; 313697Ssam #endif 413697Ssam 513697Ssam #include "uucp.h" 613697Ssam #include <sys/types.h> 713697Ssam #include <sys/stat.h> 813697Ssam #ifdef NDIR 913697Ssam #include "ndir.h" 1013697Ssam #else 11*13702Ssam #include <sys/dir.h> 1213697Ssam #endif 1313697Ssam 1413697Ssam #define APPCMD(d) {\ 1513697Ssam char *p;\ 1613697Ssam for (p = d; *p != '\0';) *cmdp++ = *p++;\ 1713697Ssam *cmdp++ = ' ';\ 1813697Ssam *cmdp = '\0';} 1913697Ssam 2013697Ssam /* 2113697Ssam * uuxqt will execute commands set up by a uux command, 2213697Ssam * usually from a remote machine - set by uucp. 2313697Ssam */ 2413697Ssam 2513697Ssam #define NCMDS 50 2613697Ssam char *Cmds[NCMDS]; 2713697Ssam 2813697Ssam int notiok = 1; 2913697Ssam int nonzero = 0; 3013697Ssam 3113697Ssam char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin"; 3213697Ssam /* to remove restrictions from uuxqt 3313697Ssam * define ALLOK 1 3413697Ssam * 3513697Ssam * to add allowable commands, add to the file CMDFILE 3613697Ssam * A line of form "PATH=..." changes the search path 3713697Ssam */ 3813697Ssam 3913697Ssam 4013697Ssam main(argc, argv) 4113697Ssam char *argv[]; 4213697Ssam { 4313697Ssam char xcmd[MAXFULLNAME]; 4413697Ssam int argnok; 4513697Ssam char xfile[MAXFULLNAME], user[32], buf[BUFSIZ]; 4613697Ssam char lbuf[30]; 4713697Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME]; 4813697Ssam char file[NAMESIZE]; 4913697Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; 5013697Ssam register FILE *xfp, *fp; 5113697Ssam FILE *dfp; 5213697Ssam char path[MAXFULLNAME]; 5313697Ssam char cmd[BUFSIZ]; 5413697Ssam /* set size of prm to something large -- cmcl2!salkind */ 5513697Ssam char *cmdp, prm[1000], *ptr; 5613697Ssam char *getprm(), *lastpart(); 5713697Ssam int uid, ret, badfiles; 5813697Ssam register int i; 5913697Ssam int stcico = 0; 6013697Ssam char retstat[30]; 6113697Ssam int orig_uid = getuid(); 6213697Ssam 6313697Ssam strcpy(Progname, "uuxqt"); 6413697Ssam uucpname(Myname); 6513697Ssam 6613697Ssam /* Try to run as uucp -- rti!trt */ 6713697Ssam setgid(getegid()); 6813697Ssam setuid(geteuid()); 6913697Ssam 7013697Ssam umask(WFMASK); 7113697Ssam Ofn = 1; 7213697Ssam Ifn = 0; 7313697Ssam while (argc>1 && argv[1][0] == '-') { 7413697Ssam switch(argv[1][1]){ 7513697Ssam case 'x': 7613697Ssam chkdebug(orig_uid); 7713697Ssam Debug = atoi(&argv[1][2]); 7813697Ssam if (Debug <= 0) 7913697Ssam Debug = 1; 8013697Ssam break; 8113697Ssam default: 8213697Ssam fprintf(stderr, "unknown flag %s\n", argv[1]); 8313697Ssam break; 8413697Ssam } 8513697Ssam --argc; argv++; 8613697Ssam } 8713697Ssam 8813697Ssam DEBUG(4, "\n\n** %s **\n", "START"); 8913697Ssam subchdir(Spool); 9013697Ssam strcpy(Wrkdir, Spool); 9113697Ssam uid = getuid(); 9213697Ssam guinfo(uid, User, path); 9313697Ssam DEBUG(4, "User - %s\n", User); 9413697Ssam if (ulockf(X_LOCK, (time_t) X_LOCKTIME) != 0) 9513697Ssam exit(0); 9613697Ssam 9713697Ssam fp = fopen(CMDFILE, "r"); 9813697Ssam if (fp == NULL) { 9913697Ssam /* Fall-back if CMDFILE missing. Sept 1982, rti!trt */ 10013697Ssam logent("CAN'T OPEN", CMDFILE); 10113697Ssam Cmds[0] = "rmail"; 10213697Ssam Cmds[1] = "rnews"; 10313697Ssam Cmds[2] = "ruusend"; 10413697Ssam Cmds[3] = NULL; 10513697Ssam goto doprocess; 10613697Ssam } 10713697Ssam DEBUG(5, "%s opened\n", CMDFILE); 10813697Ssam for (i=0; i<NCMDS-1 && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) { 10913697Ssam xcmd[strlen(xcmd)-1] = '\0'; 11013697Ssam if (strncmp(xcmd, "PATH=", 5) == 0) { 11113697Ssam strcpy(PATH, xcmd); 11213697Ssam i--; /* kludge */ 11313697Ssam continue; 11413697Ssam } 11513697Ssam DEBUG(5, "xcmd = %s\n", xcmd); 11613697Ssam Cmds[i] = malloc((unsigned)(strlen(xcmd)+1)); 11713697Ssam strcpy(Cmds[i], xcmd); 11813697Ssam } 11913697Ssam Cmds[i] = 0; 12013697Ssam fclose(fp); 12113697Ssam 12213697Ssam doprocess: 12313697Ssam DEBUG(4, "process %s\n", ""); 12413697Ssam while (gtxfile(xfile) > 0) { 12513697Ssam ultouch(); /* rti!trt */ 12613697Ssam DEBUG(4, "xfile - %s\n", xfile); 12713697Ssam 12813697Ssam xfp = fopen(subfile(xfile), "r"); 12913697Ssam ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0); 13013697Ssam 13113697Ssam /* initialize to default */ 13213697Ssam strcpy(user, User); 13313697Ssam strcpy(fin, "/dev/null"); 13413697Ssam strcpy(fout, "/dev/null"); 13513697Ssam sprintf(sysout, "%.7s", Myname); 13613697Ssam badfiles = 0; /* this was missing -- rti!trt */ 13713697Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 13813697Ssam switch (buf[0]) { 13913697Ssam case X_USER: 14013697Ssam sscanf(&buf[1], "%s%s", user, Rmtname); 14113697Ssam break; 14213697Ssam case X_STDIN: 14313697Ssam sscanf(&buf[1], "%s", fin); 14413697Ssam i = expfile(fin); 14513697Ssam /* rti!trt: do not check permissions of 14613697Ssam * vanilla spool file */ 14713697Ssam if (i != 0 14813697Ssam && (chkpth("", "", fin) || anyread(fin) != 0)) 14913697Ssam badfiles = 1; 15013697Ssam break; 15113697Ssam case X_STDOUT: 15213697Ssam sscanf(&buf[1], "%s%s", fout, sysout); 15313697Ssam sysout[7] = '\0'; 15413697Ssam /* rti!trt: do not check permissions of 15513697Ssam * vanilla spool file. DO check permissions 15613697Ssam * of writing on a non-vanilla file */ 15713697Ssam i = 1; 15813697Ssam if (fout[0] != '~' || prefix(sysout, Myname)) 15913697Ssam i = expfile(fout); 16013697Ssam if (i != 0 16113697Ssam && (chkpth("", "", fout) 16213697Ssam || chkperm(fout, (char *)1))) 16313697Ssam badfiles = 1; 16413697Ssam break; 16513697Ssam case X_CMD: 16613697Ssam strcpy(cmd, &buf[2]); 16713697Ssam if (*(cmd + strlen(cmd) - 1) == '\n') 16813697Ssam *(cmd + strlen(cmd) - 1) = '\0'; 16913697Ssam break; 17013697Ssam case X_NONOTI: 17113697Ssam notiok = 0; 17213697Ssam break; 17313697Ssam case X_NONZERO: 17413697Ssam nonzero = 1; 17513697Ssam break; 17613697Ssam default: 17713697Ssam break; 17813697Ssam } 17913697Ssam } 18013697Ssam 18113697Ssam fclose(xfp); 18213697Ssam DEBUG(4, "fin - %s, ", fin); 18313697Ssam DEBUG(4, "fout - %s, ", fout); 18413697Ssam DEBUG(4, "sysout - %s, ", sysout); 18513697Ssam DEBUG(4, "user - %s\n", user); 18613697Ssam DEBUG(4, "cmd - %s\n", cmd); 18713697Ssam 18813697Ssam /* command execution */ 18913697Ssam if (strcmp(fout, "/dev/null") == SAME) 19013697Ssam strcpy(dfile,"/dev/null"); 19113697Ssam else 19213697Ssam gename(DATAPRE, sysout, 'O', dfile); 19313697Ssam 19413697Ssam /* expand file names where necessary */ 19513697Ssam expfile(dfile); 19613697Ssam strcpy(buf, PATH); 19713697Ssam strcat(buf, ";export PATH;"); 19813697Ssam cmdp = buf + strlen(buf); 19913697Ssam ptr = cmd; 20013697Ssam xcmd[0] = '\0'; 20113697Ssam argnok = 0; 20213697Ssam while ((ptr = getprm(ptr, prm)) != NULL) { 20313697Ssam if (prm[0] == ';' || prm[0] == '^' 20413697Ssam || prm[0] == '&' || prm[0] == '|') { 20513697Ssam xcmd[0] = '\0'; 20613697Ssam APPCMD(prm); 20713697Ssam continue; 20813697Ssam } 20913697Ssam 21013697Ssam if ((argnok = argok(xcmd, prm)) != 0) 21113697Ssam /* command not valid */ 21213697Ssam break; 21313697Ssam 21413697Ssam if (prm[0] == '~') 21513697Ssam expfile(prm); 21613697Ssam APPCMD(prm); 21713697Ssam } 21813697Ssam if (argnok || badfiles) { 21913697Ssam sprintf(lbuf, "%s XQT DENIED", user); 22013697Ssam logent(cmd, lbuf); 22113697Ssam DEBUG(4, "bad command %s\n", prm); 22213697Ssam notify(user, Rmtname, cmd, "DENIED"); 22313697Ssam goto rmfiles; 22413697Ssam } 22513697Ssam sprintf(lbuf, "%s XQT", user); 22613697Ssam logent(buf, lbuf); 22713697Ssam DEBUG(4, "cmd %s\n", buf); 22813697Ssam 22913697Ssam mvxfiles(xfile); 23013697Ssam subchdir(XQTDIR); 23113697Ssam ret = shio(buf, fin, dfile, (char *)NULL); 23213697Ssam /* watcgl.11, dmmartindale, signal and exit values were reversed */ 23313697Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377, 23413697Ssam (ret>>8) & 0377); 23513697Ssam if (strcmp(xcmd, "rmail") == SAME) 23613697Ssam notiok = 0; 23713697Ssam if (strcmp(xcmd, "rnews") == SAME) 23813697Ssam nonzero = 1; 23913697Ssam if (notiok && (!nonzero || (nonzero && ret != 0))) 24013697Ssam notify(user, Rmtname, cmd, retstat); 24113697Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) { 24213697Ssam /* mail failed - return letter to sender */ 24313697Ssam retosndr(user, Rmtname, fin); 24413697Ssam sprintf(buf, "ret (%o) from %s!%s", ret, Rmtname, user); 24513697Ssam logent("MAIL FAIL", buf); 24613697Ssam } 24713697Ssam DEBUG(4, "exit cmd - %d\n", ret); 24813697Ssam subchdir(Spool); 24913697Ssam rmxfiles(xfile); 25013697Ssam if (ret != 0) { 25113697Ssam /* exit status not zero */ 25213697Ssam dfp = fopen(subfile(dfile), "a"); 25313697Ssam ASSERT(dfp != NULL, "CAN'T OPEN", dfile, 0); 25413697Ssam fprintf(dfp, "exit status %d", ret); 25513697Ssam fclose(dfp); 25613697Ssam } 25713697Ssam if (strcmp(fout, "/dev/null") != SAME) { 25813697Ssam if (prefix(sysout, Myname)) { 25913697Ssam xmv(dfile, fout); 26013697Ssam chmod(fout, BASEMODE); 26113697Ssam } 26213697Ssam else { 26313697Ssam gename(CMDPRE, sysout, 'O', cfile); 26413697Ssam fp = fopen(subfile(cfile), "w"); 26513697Ssam ASSERT(fp != NULL, "OPEN", cfile, 0); 26613697Ssam fprintf(fp, "S %s %s %s - %s 0666\n", 26713697Ssam dfile, fout, user, lastpart(dfile)); 26813697Ssam fclose(fp); 26913697Ssam } 27013697Ssam } 27113697Ssam rmfiles: 27213697Ssam xfp = fopen(subfile(xfile), "r"); 27313697Ssam ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0); 27413697Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 27513697Ssam if (buf[0] != X_RQDFILE) 27613697Ssam continue; 27713697Ssam sscanf(&buf[1], "%s", file); 27813697Ssam unlink(subfile(file)); 27913697Ssam } 28013697Ssam unlink(subfile(xfile)); 28113697Ssam fclose(xfp); 28213697Ssam } 28313697Ssam 28413697Ssam if (stcico) 28513697Ssam xuucico(""); 28613697Ssam cleanup(0); 28713697Ssam } 28813697Ssam 28913697Ssam 29013697Ssam cleanup(code) 29113697Ssam int code; 29213697Ssam { 29313697Ssam logcls(); 29413697Ssam rmlock(CNULL); 29513697Ssam exit(code); 29613697Ssam } 29713697Ssam 29813697Ssam 29913697Ssam /******* 30013697Ssam * gtxfile(file) get a file to execute 30113697Ssam * char *file; 30213697Ssam * 30313697Ssam * return codes: 0 - no file | 1 - file to execute 30413697Ssam * Mod to recheck for X-able files. Sept 1982, rti!trt. 30513697Ssam * Suggested by utzoo.2458 (utzoo!henry) 30613697Ssam * Uses iswrk/gtwrkf to keep files in sequence, May 1983. 30713697Ssam */ 30813697Ssam 30913697Ssam gtxfile(file) 31013697Ssam register char *file; 31113697Ssam { 31213697Ssam char pre[3]; 31313697Ssam register int rechecked; 31413697Ssam 31513697Ssam pre[0] = XQTPRE; 31613697Ssam pre[1] = '.'; 31713697Ssam pre[2] = '\0'; 31813697Ssam rechecked = 0; 31913697Ssam retry: 32013697Ssam if (!gtwrkf(Spool, file)) { 32113697Ssam if (rechecked) 32213697Ssam return(0); 32313697Ssam rechecked = 1; 32413697Ssam DEBUG(4, "iswrk\n", ""); 32513697Ssam if (!iswrk(file, "get", Spool, pre)) 32613697Ssam return(0); 32713697Ssam } 32813697Ssam DEBUG(4, "file - %s\n", file); 32913697Ssam #ifndef UUDIR 33013697Ssam /* skip spurious subdirectories */ 33113697Ssam if (strcmp(pre, file) == SAME) 33213697Ssam goto retry; 33313697Ssam #endif 33413697Ssam if (gotfiles(file)) 33513697Ssam return(1); 33613697Ssam goto retry; 33713697Ssam } 33813697Ssam 33913697Ssam 34013697Ssam /*** 34113697Ssam * gotfiles(file) check for needed files 34213697Ssam * char *file; 34313697Ssam * 34413697Ssam * return codes: 0 - not ready | 1 - all files ready 34513697Ssam */ 34613697Ssam 34713697Ssam gotfiles(file) 34813697Ssam register char *file; 34913697Ssam { 35013697Ssam struct stat stbuf; 35113697Ssam register FILE *fp; 35213697Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME]; 35313697Ssam 35413697Ssam fp = fopen(subfile(file), "r"); 35513697Ssam if (fp == NULL) 35613697Ssam return(0); 35713697Ssam 35813697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 35913697Ssam DEBUG(4, "%s\n", buf); 36013697Ssam if (buf[0] != X_RQDFILE) 36113697Ssam continue; 36213697Ssam sscanf(&buf[1], "%s", rqfile); 36313697Ssam expfile(rqfile); 36413697Ssam if (stat(subfile(rqfile), &stbuf) == -1) { 36513697Ssam fclose(fp); 36613697Ssam return(0); 36713697Ssam } 36813697Ssam } 36913697Ssam 37013697Ssam fclose(fp); 37113697Ssam return(1); 37213697Ssam } 37313697Ssam 37413697Ssam 37513697Ssam /*** 37613697Ssam * rmxfiles(xfile) remove execute files to x-directory 37713697Ssam * char *xfile; 37813697Ssam * 37913697Ssam * return codes - none 38013697Ssam */ 38113697Ssam 38213697Ssam rmxfiles(xfile) 38313697Ssam register char *xfile; 38413697Ssam { 38513697Ssam register FILE *fp; 38613697Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; 38713697Ssam char tfull[MAXFULLNAME]; 38813697Ssam 38913697Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 39013697Ssam return; 39113697Ssam 39213697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 39313697Ssam if (buf[0] != X_RQDFILE) 39413697Ssam continue; 39513697Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2) 39613697Ssam continue; 39713697Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 39813697Ssam unlink(subfile(tfull)); 39913697Ssam } 40013697Ssam fclose(fp); 40113697Ssam return; 40213697Ssam } 40313697Ssam 40413697Ssam 40513697Ssam /*** 40613697Ssam * mvxfiles(xfile) move execute files to x-directory 40713697Ssam * char *xfile; 40813697Ssam * 40913697Ssam * return codes - none 41013697Ssam */ 41113697Ssam 41213697Ssam mvxfiles(xfile) 41313697Ssam char *xfile; 41413697Ssam { 41513697Ssam register FILE *fp; 41613697Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; 41713697Ssam char tfull[MAXFULLNAME]; 41813697Ssam int ret; 41913697Ssam 42013697Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 42113697Ssam return; 42213697Ssam 42313697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 42413697Ssam if (buf[0] != X_RQDFILE) 42513697Ssam continue; 42613697Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) 42713697Ssam continue; 42813697Ssam expfile(ffile); 42913697Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 43013697Ssam /* duke!rti, ncsu!mcm: use xmv, not link(II) */ 43113697Ssam unlink(subfile(tfull)); 43213697Ssam ret = xmv(ffile, tfull); 43313697Ssam ASSERT(ret == 0, "XQTDIR ERROR", "", ret); 43413697Ssam } 43513697Ssam fclose(fp); 43613697Ssam return; 43713697Ssam } 43813697Ssam 43913697Ssam 44013697Ssam /*** 44113697Ssam * argok(xc, cmd) check for valid command/argumanet 44213697Ssam * *NOTE - side effect is to set xc to the 44313697Ssam * command to be executed. 44413697Ssam * char *xc, *cmd; 44513697Ssam * 44613697Ssam * return 0 - ok | 1 nok 44713697Ssam */ 44813697Ssam 44913697Ssam argok(xc, cmd) 45013697Ssam register char *xc, *cmd; 45113697Ssam { 45213697Ssam register char **ptr; 45313697Ssam 45413697Ssam #ifndef ALLOK 45513697Ssam /* don't allow sh command strings `....` */ 45613697Ssam /* don't allow redirection of standard in or out */ 45713697Ssam /* don't allow other funny stuff */ 45813697Ssam /* but there are probably total holes here */ 45913697Ssam /* post-script. ittvax!swatt has a uuxqt that solves this. */ 46013697Ssam /* This version of uuxqt will shortly disappear */ 46113697Ssam if (index(cmd, '`') != NULL 46213697Ssam || index(cmd, '>') != NULL 46313697Ssam || index(cmd, ';') != NULL 46413697Ssam || index(cmd, '^') != NULL 46513697Ssam || index(cmd, '&') != NULL 46613697Ssam || index(cmd, '|') != NULL 46713697Ssam || index(cmd, '<') != NULL) 46813697Ssam return(1); 46913697Ssam #endif 47013697Ssam 47113697Ssam if (xc[0] != '\0') 47213697Ssam return(0); 47313697Ssam 47413697Ssam #ifndef ALLOK 47513697Ssam ptr = Cmds; 47613697Ssam while(*ptr != NULL) { 47713697Ssam if (strcmp(cmd, *ptr) == SAME) 47813697Ssam break; 47913697Ssam ptr++; 48013697Ssam } 48113697Ssam if (*ptr == NULL) 48213697Ssam return(1); 48313697Ssam #endif 48413697Ssam strcpy(xc, cmd); 48513697Ssam return(0); 48613697Ssam } 48713697Ssam 48813697Ssam 48913697Ssam /*** 49013697Ssam * notify send mail to user giving execution results 49113697Ssam * return code - none 49213697Ssam * This program assumes new mail command - send remote mail 49313697Ssam */ 49413697Ssam 49513697Ssam notify(user, rmt, cmd, str) 49613697Ssam char *user, *rmt, *cmd, *str; 49713697Ssam { 49813697Ssam char text[MAXFULLNAME]; 49913697Ssam char ruser[MAXFULLNAME]; 50013697Ssam 50113697Ssam sprintf(text, "uuxqt cmd (%.50s) status (%s)", cmd, str); 50213697Ssam if (prefix(rmt, Myname)) 50313697Ssam strcpy(ruser, user); 50413697Ssam else 50513697Ssam sprintf(ruser, "%s!%s", rmt, user); 50613697Ssam mailst(ruser, text, ""); 50713697Ssam return; 50813697Ssam } 50913697Ssam 51013697Ssam /*** 51113697Ssam * retosndr - return mail to sender 51213697Ssam * 51313697Ssam * return code - none 51413697Ssam */ 51513697Ssam 51613697Ssam retosndr(user, rmt, file) 51713697Ssam char *user, *rmt, *file; 51813697Ssam { 51913697Ssam char ruser[100]; 52013697Ssam 52113697Ssam if (strcmp(rmt, Myname) == SAME) 52213697Ssam strcpy(ruser, user); 52313697Ssam else 52413697Ssam sprintf(ruser, "%s!%s", rmt, user); 52513697Ssam 52613697Ssam if (anyread(file) == 0) 52713697Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file); 52813697Ssam else 52913697Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", ""); 53013697Ssam return; 53113697Ssam } 532