| 1 | #include "uucp.h" |
| 2 | #include "uucpdefs.h" |
| 3 | #include <sys/types.h> |
| 4 | #include <sys/stat.h> |
| 5 | #include <sys/dir.h> |
| 6 | |
| 7 | #define APPCMD(d) {\ |
| 8 | char *p;\ |
| 9 | for (p = d; *p != '\0';) *cmdp++ = *p++;\ |
| 10 | *cmdp++ = ' ';\ |
| 11 | *cmdp = '\0';} |
| 12 | |
| 13 | /* |
| 14 | * uuxqt will execute commands set up by a uux command, |
| 15 | * usually from a remote machine - set by uucp. |
| 16 | */ |
| 17 | |
| 18 | char *Cmds[] = { |
| 19 | "rmail", |
| 20 | "lpr", |
| 21 | "opr", |
| 22 | "fsend", |
| 23 | "fget", |
| 24 | NULL |
| 25 | }; |
| 26 | #define PATH "PATH=/bin:/usr/bin;" |
| 27 | /* to remove restrictions from uuxqt |
| 28 | * define ALLOK 1 |
| 29 | * |
| 30 | * to add allowable commands, add to the list under Cmds[] |
| 31 | */ |
| 32 | |
| 33 | main(argc, argv) |
| 34 | char *argv[]; |
| 35 | { |
| 36 | char xcmd[100]; |
| 37 | int cmdnok; |
| 38 | char xfile[MAXFULLNAME], user[10], buf[BUFSIZ]; |
| 39 | char lbuf[30]; |
| 40 | char cfile[NAMESIZE], dfile[MAXFULLNAME]; |
| 41 | char file[NAMESIZE]; |
| 42 | char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; |
| 43 | FILE *xfp, *dfp, *fp; |
| 44 | char path[MAXFULLNAME]; |
| 45 | char cmd[BUFSIZ]; |
| 46 | char *cmdp, prm[MAXFULLNAME], *ptr; |
| 47 | char *getprm(); |
| 48 | int uid, ret; |
| 49 | int stcico = 0; |
| 50 | char rnum[5]; |
| 51 | |
| 52 | uucpname(Myname); |
| 53 | Ofn = 1; |
| 54 | Ifn = 0; |
| 55 | while (argc>1 && argv[1][0] == '-') { |
| 56 | switch(argv[1][1]){ |
| 57 | case 'x': |
| 58 | Debug = atoi(&argv[1][2]); |
| 59 | if (Debug <= 0) |
| 60 | Debug = 1; |
| 61 | break; |
| 62 | default: |
| 63 | sprintf(stderr, "unknown flag %s\n", argv[1]); |
| 64 | break; |
| 65 | } |
| 66 | --argc; argv++; |
| 67 | } |
| 68 | |
| 69 | DEBUG(4, "\n\n** %s **\n", "START"); |
| 70 | chdir(Spool); |
| 71 | strcpy(Wrkdir, Spool); |
| 72 | uid = getuid(); |
| 73 | guinfo(uid, User, path); |
| 74 | DEBUG(4, "User - %s\n", User); |
| 75 | if (ulockf(X_LOCK, X_LOCKTIME) != 0) |
| 76 | exit(0); |
| 77 | |
| 78 | DEBUG(4, "process %s\n", ""); |
| 79 | while (gtxfile(xfile) > 0) { |
| 80 | DEBUG(4, "xfile - %s\n", xfile); |
| 81 | |
| 82 | xfp = fopen(xfile, "r"); |
| 83 | ASSERT(xfp != NULL, "CAN'T OPEN %s", xfile); |
| 84 | |
| 85 | /* initialize to default */ |
| 86 | strcpy(user, User); |
| 87 | strcpy(fin, "/dev/null"); |
| 88 | strcpy(fout, "/dev/null"); |
| 89 | sprintf(sysout, "%.7s", Myname); |
| 90 | while (fgets(buf, BUFSIZ, xfp) != NULL) { |
| 91 | switch (buf[0]) { |
| 92 | case X_USER: |
| 93 | sscanf(&buf[1], "%s%s", user, Rmtname); |
| 94 | break; |
| 95 | case X_STDIN: |
| 96 | sscanf(&buf[1], "%s", fin); |
| 97 | expfile(fin); |
| 98 | break; |
| 99 | case X_STDOUT: |
| 100 | sscanf(&buf[1], "%s%s", fout, sysout); |
| 101 | sysout[7] = '\0'; |
| 102 | if (fout[0] != '~' || prefix(sysout, Myname)) |
| 103 | expfile(fout); |
| 104 | break; |
| 105 | case X_CMD: |
| 106 | strcpy(cmd, &buf[2]); |
| 107 | if (*(cmd + strlen(cmd) - 1) == '\n') |
| 108 | *(cmd + strlen(cmd) - 1) = '\0'; |
| 109 | break; |
| 110 | default: |
| 111 | break; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | fclose(xfp); |
| 116 | DEBUG(4, "fin - %s, ", fin); |
| 117 | DEBUG(4, "fout - %s, ", fout); |
| 118 | DEBUG(4, "sysout - %s, ", sysout); |
| 119 | DEBUG(4, "user - %s\n", user); |
| 120 | DEBUG(4, "cmd - %s\n", cmd); |
| 121 | |
| 122 | /* command execution */ |
| 123 | if (strcmp(fout, "/dev/null") == SAME) |
| 124 | strcpy(dfile,"/dev/null"); |
| 125 | else |
| 126 | gename(DATAPRE, sysout, 'O', dfile); |
| 127 | |
| 128 | /* expand file names where necessary */ |
| 129 | expfile(dfile); |
| 130 | strcpy(buf, PATH); |
| 131 | cmdp = buf + strlen(buf); |
| 132 | ptr = cmd; |
| 133 | xcmd[0] = '\0'; |
| 134 | cmdnok = 0; |
| 135 | while ((ptr = getprm(ptr, prm)) != NULL) { |
| 136 | if (prm[0] == ';' || prm[0] == '^' |
| 137 | || prm[0] == '|') { |
| 138 | xcmd[0] = '\0'; |
| 139 | APPCMD(prm); |
| 140 | continue; |
| 141 | } |
| 142 | if ((cmdnok = cmdok(xcmd, prm)) != 0) |
| 143 | /* command not valid */ |
| 144 | break; |
| 145 | |
| 146 | if (prm[0] == '~') |
| 147 | expfile(prm); |
| 148 | APPCMD(prm); |
| 149 | } |
| 150 | if (cmdnok) { |
| 151 | sprintf(lbuf, "%s XQT DENIED", user); |
| 152 | logent(cmd, lbuf); |
| 153 | DEBUG(4, "bad command %s\n", prm); |
| 154 | notify(user, Rmtname, cmd, "DENIED"); |
| 155 | goto rmfiles; |
| 156 | } |
| 157 | sprintf(lbuf, "%s XQT", user); |
| 158 | logent(buf, lbuf); |
| 159 | DEBUG(4, "cmd %s\n", buf); |
| 160 | |
| 161 | mvxfiles(xfile); |
| 162 | chdir(XQTDIR); |
| 163 | ret = shio(buf, fin, dfile, user); |
| 164 | sprintf(rnum, "%d", ret); |
| 165 | if (strcmp(xcmd, "rmail") != SAME |
| 166 | && strcmp(xcmd, "mail") != SAME) |
| 167 | notify(user, Rmtname, cmd, rnum); |
| 168 | DEBUG(4, "exit cmd - %d\n", ret); |
| 169 | chdir(Spool); |
| 170 | rmxfiles(xfile); |
| 171 | if (ret != 0) { |
| 172 | /* exit status not zero */ |
| 173 | dfp = fopen(dfile, "a"); |
| 174 | ASSERT(dfp != NULL, "CAN'T OPEN %s", dfile); |
| 175 | fprintf(dfp, "exit status %d", ret); |
| 176 | fclose(dfp); |
| 177 | } |
| 178 | if (strcmp(fout, "/dev/null") != SAME) { |
| 179 | if (prefix(sysout, Myname)) { |
| 180 | xmv(dfile, fout); |
| 181 | } |
| 182 | else { |
| 183 | gename(CMDPRE, sysout, 'O', cfile); |
| 184 | fp = fopen(cfile, "w"); |
| 185 | ASSERT(fp != NULL, "OPEN %s", cfile); |
| 186 | chmod(cfile, 0666); |
| 187 | fprintf(fp, "S %s %s %s - %s 0666\n", |
| 188 | dfile, fout, user, lastpart(dfile)); |
| 189 | fclose(fp); |
| 190 | } |
| 191 | } |
| 192 | rmfiles: |
| 193 | xfp = fopen(xfile, "r"); |
| 194 | ASSERT(xfp != NULL, "CAN'T OPEN %s", xfile); |
| 195 | while (fgets(buf, BUFSIZ, xfp) != NULL) { |
| 196 | if (buf[0] != X_RQDFILE) |
| 197 | continue; |
| 198 | sscanf(&buf[1], "%s", file); |
| 199 | unlink(file); |
| 200 | } |
| 201 | unlink(xfile); |
| 202 | } |
| 203 | |
| 204 | if (stcico) |
| 205 | xuucico(""); |
| 206 | cleanup(0); |
| 207 | } |
| 208 | |
| 209 | |
| 210 | cleanup(code) |
| 211 | int code; |
| 212 | { |
| 213 | logcls(); |
| 214 | rmlock(NULL); |
| 215 | exit(code); |
| 216 | } |
| 217 | |
| 218 | |
| 219 | /******* |
| 220 | * gtxfile(file) get a file to execute |
| 221 | * char *file; |
| 222 | * |
| 223 | * return codes: 0 - no file | 1 - file to execute |
| 224 | */ |
| 225 | |
| 226 | gtxfile(file) |
| 227 | char *file; |
| 228 | { |
| 229 | static FILE *pdir; |
| 230 | char pre[2]; |
| 231 | |
| 232 | if (pdir == NULL) { |
| 233 | pdir = fopen(Spool, "r"); |
| 234 | ASSERT(pdir != NULL, "GTXFILE CAN'T OPEN %s", Spool); |
| 235 | } |
| 236 | |
| 237 | pre[0] = XQTPRE; |
| 238 | pre[1] = '\0'; |
| 239 | while (gnamef(pdir, file) != 0) { |
| 240 | DEBUG(4, "file - %s\n", file); |
| 241 | if (!prefix(pre, file)) |
| 242 | continue; |
| 243 | if (gotfiles(file)) |
| 244 | /* return file to execute */ |
| 245 | return(1); |
| 246 | } |
| 247 | |
| 248 | fclose(pdir); |
| 249 | return(0); |
| 250 | } |
| 251 | |
| 252 | |
| 253 | /*** |
| 254 | * gotfiles(file) check for needed files |
| 255 | * char *file; |
| 256 | * |
| 257 | * return codes: 0 - not ready | 1 - all files ready |
| 258 | */ |
| 259 | |
| 260 | gotfiles(file) |
| 261 | char *file; |
| 262 | { |
| 263 | struct stat stbuf; |
| 264 | FILE *fp; |
| 265 | char buf[BUFSIZ], rqfile[MAXFULLNAME]; |
| 266 | |
| 267 | fp = fopen(file, "r"); |
| 268 | if (fp == NULL) |
| 269 | return(0); |
| 270 | |
| 271 | while (fgets(buf, BUFSIZ, fp) != NULL) { |
| 272 | DEBUG(4, "%s\n", buf); |
| 273 | if (buf[0] != X_RQDFILE) |
| 274 | continue; |
| 275 | sscanf(&buf[1], "%s", rqfile); |
| 276 | expfile(rqfile); |
| 277 | if (stat(rqfile, &stbuf) == -1) { |
| 278 | fclose(fp); |
| 279 | return(0); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | fclose(fp); |
| 284 | return(1); |
| 285 | } |
| 286 | |
| 287 | |
| 288 | /*** |
| 289 | * rmxfiles(xfile) remove execute files to x-directory |
| 290 | * char *xfile; |
| 291 | * |
| 292 | * return codes - none |
| 293 | */ |
| 294 | |
| 295 | rmxfiles(xfile) |
| 296 | char *xfile; |
| 297 | { |
| 298 | FILE *fp; |
| 299 | char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; |
| 300 | char tfull[MAXFULLNAME]; |
| 301 | |
| 302 | if((fp = fopen(xfile, "r")) == NULL) |
| 303 | return; |
| 304 | |
| 305 | while (fgets(buf, BUFSIZ, fp) != NULL) { |
| 306 | if (buf[0] != X_RQDFILE) |
| 307 | continue; |
| 308 | if (sscanf(&buf[1], "%s%s", file, tfile) < 2) |
| 309 | continue; |
| 310 | sprintf(tfull, "%s/%s", XQTDIR, tfile); |
| 311 | unlink(tfull); |
| 312 | } |
| 313 | fclose(fp); |
| 314 | return; |
| 315 | } |
| 316 | |
| 317 | |
| 318 | /*** |
| 319 | * mvxfiles(xfile) move execute files to x-directory |
| 320 | * char *xfile; |
| 321 | * |
| 322 | * return codes - none |
| 323 | */ |
| 324 | |
| 325 | mvxfiles(xfile) |
| 326 | char *xfile; |
| 327 | { |
| 328 | FILE *fp; |
| 329 | char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; |
| 330 | char tfull[MAXFULLNAME]; |
| 331 | int ret; |
| 332 | |
| 333 | if((fp = fopen(xfile, "r")) == NULL) |
| 334 | return; |
| 335 | |
| 336 | while (fgets(buf, BUFSIZ, fp) != NULL) { |
| 337 | if (buf[0] != X_RQDFILE) |
| 338 | continue; |
| 339 | if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) |
| 340 | continue; |
| 341 | expfile(ffile); |
| 342 | sprintf(tfull, "%s/%s", XQTDIR, tfile); |
| 343 | unlink(tfull); |
| 344 | ret = link(ffile, tfull); |
| 345 | ASSERT(ret == 0, "LINK RET-%d", ret); |
| 346 | unlink(ffile); |
| 347 | } |
| 348 | fclose(fp); |
| 349 | return; |
| 350 | } |
| 351 | |
| 352 | |
| 353 | /*** |
| 354 | * cmdok(xc, cmd) check for valid command |
| 355 | * *NOTE - side effect is to set xc to the |
| 356 | * command to be executed. |
| 357 | * char *xc, *cmd; |
| 358 | * |
| 359 | * return 0 - ok | 1 nok |
| 360 | */ |
| 361 | |
| 362 | cmdok(xc, cmd) |
| 363 | char *xc, *cmd; |
| 364 | { |
| 365 | char **ptr; |
| 366 | |
| 367 | if (xc[0] != '\0') |
| 368 | return(0); |
| 369 | #ifndef ALLOK |
| 370 | ptr = Cmds; |
| 371 | while(*ptr != NULL) { |
| 372 | if (strcmp(cmd, *ptr) == SAME) |
| 373 | break; |
| 374 | ptr++; |
| 375 | } |
| 376 | if (*ptr == NULL) |
| 377 | return(1); |
| 378 | #endif |
| 379 | strcpy(xc, cmd); |
| 380 | return(0); |
| 381 | } |
| 382 | |
| 383 | |
| 384 | /*** |
| 385 | * notify send mail to user giving execution results |
| 386 | * return code - none |
| 387 | * This program assumes new mail command - send remote mail |
| 388 | */ |
| 389 | |
| 390 | notify(user, rmt, cmd, str) |
| 391 | char *user, *rmt, *cmd, *str; |
| 392 | { |
| 393 | char text[100]; |
| 394 | char ruser[100]; |
| 395 | |
| 396 | sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str); |
| 397 | if (prefix(rmt, Myname)) |
| 398 | strcpy(ruser, user); |
| 399 | else |
| 400 | sprintf(ruser, "%s!%s", rmt, user); |
| 401 | mailst(ruser, text); |
| 402 | return; |
| 403 | } |