1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* from SVR4 bnu:uuxqt.c 2.12.1.12 */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * Copyright 2000, 2003 Sun Microsystems, Inc. All rights reserved. 29*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "uucp.h" 35*7c478bd9Sstevel@tonic-gate #include "log.h" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * execute commands set up by a uux command, 39*7c478bd9Sstevel@tonic-gate * usually from a remote machine - set by uucp. 40*7c478bd9Sstevel@tonic-gate */ 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #ifndef V7 43*7c478bd9Sstevel@tonic-gate #define LOGNAME "LOGNAME=uucp" 44*7c478bd9Sstevel@tonic-gate #else 45*7c478bd9Sstevel@tonic-gate #define LOGNAME "USER=uucp" 46*7c478bd9Sstevel@tonic-gate #endif 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #define C_COMMAND 1 49*7c478bd9Sstevel@tonic-gate #define C_FILE 2 50*7c478bd9Sstevel@tonic-gate #define BAD_COMMAND 1 51*7c478bd9Sstevel@tonic-gate #define BAD_FILE 2 52*7c478bd9Sstevel@tonic-gate #define USAGEPREFIX "Usage:" 53*7c478bd9Sstevel@tonic-gate #define USAGE "[-x DEBUG] [-s SYSTEM]" 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate char _Xfile[MAXFULLNAME]; 56*7c478bd9Sstevel@tonic-gate char _Cmd[2 * BUFSIZ]; /* build up command buffer */ 57*7c478bd9Sstevel@tonic-gate int _CargType; /* argument type of next C argument */ 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate static void retosndr(), uucpst(); 60*7c478bd9Sstevel@tonic-gate static int chkFile(); 61*7c478bd9Sstevel@tonic-gate static int doFileChk(); 62*7c478bd9Sstevel@tonic-gate void cleanup(), xprocess(); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate main(argc, argv, envp) 65*7c478bd9Sstevel@tonic-gate char *argv[]; 66*7c478bd9Sstevel@tonic-gate char *envp[]; 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate DIR *fp1; 69*7c478bd9Sstevel@tonic-gate struct limits limitval; 70*7c478bd9Sstevel@tonic-gate int ret, maxnumb; 71*7c478bd9Sstevel@tonic-gate char dirname[MAXFULLNAME], lockname[MAXFULLNAME]; 72*7c478bd9Sstevel@tonic-gate void onintr(); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* Set locale environment variables local definitions */ 75*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 76*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 77*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 78*7c478bd9Sstevel@tonic-gate #endif 79*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate (void) signal(SIGILL, onintr); 82*7c478bd9Sstevel@tonic-gate (void) signal(SIGTRAP, onintr); 83*7c478bd9Sstevel@tonic-gate (void) signal(SIGIOT, onintr); 84*7c478bd9Sstevel@tonic-gate (void) signal(SIGEMT, onintr); 85*7c478bd9Sstevel@tonic-gate (void) signal(SIGFPE, onintr); 86*7c478bd9Sstevel@tonic-gate (void) signal(SIGBUS, onintr); 87*7c478bd9Sstevel@tonic-gate (void) signal(SIGSEGV, onintr); 88*7c478bd9Sstevel@tonic-gate (void) signal(SIGSYS, onintr); 89*7c478bd9Sstevel@tonic-gate (void) signal(SIGPIPE, onintr); 90*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, SIG_IGN); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* choose LOGFILE */ 93*7c478bd9Sstevel@tonic-gate (void) strcpy(Logfile, LOGUUXQT); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * get local system name 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate Env = envp; 99*7c478bd9Sstevel@tonic-gate Nstat.t_qtime = time((time_t *)0); 100*7c478bd9Sstevel@tonic-gate (void) strcpy(Progname, "uuxqt"); 101*7c478bd9Sstevel@tonic-gate Pchar = 'Q'; 102*7c478bd9Sstevel@tonic-gate uucpname(Myname); 103*7c478bd9Sstevel@tonic-gate Ofn = 1; 104*7c478bd9Sstevel@tonic-gate Ifn = 0; 105*7c478bd9Sstevel@tonic-gate dirname[0] = dirname[MAXFULLNAME-1] = NULLCHAR; 106*7c478bd9Sstevel@tonic-gate while ((ret = getopt(argc, argv, "s:x:")) != EOF) { 107*7c478bd9Sstevel@tonic-gate switch (ret) { 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * debugging level 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate case 'x': 113*7c478bd9Sstevel@tonic-gate Debug = atoi(optarg); 114*7c478bd9Sstevel@tonic-gate if (Debug <= 0) 115*7c478bd9Sstevel@tonic-gate Debug = 1; 116*7c478bd9Sstevel@tonic-gate break; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate case 's': 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * fake out uuxqt and use the argument as if 121*7c478bd9Sstevel@tonic-gate * it were the spool directory for the purpose 122*7c478bd9Sstevel@tonic-gate * of determining what subdirectories to search 123*7c478bd9Sstevel@tonic-gate * EX: mkdir /tmp/foo; touch /tmp/foo/[baz, gorp] 124*7c478bd9Sstevel@tonic-gate * uuxqt -s/tmp/foo 125*7c478bd9Sstevel@tonic-gate * this will cause uuxqt to only run on the sub 126*7c478bd9Sstevel@tonic-gate * baz and gorp in the Spool directory. Trust me. 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate (void) strlcpy(dirname, optarg, 129*7c478bd9Sstevel@tonic-gate (MAXFULLNAME - sizeof (SEQLOCK))); 130*7c478bd9Sstevel@tonic-gate break; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate default: 133*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s %s %s\n", 134*7c478bd9Sstevel@tonic-gate gettext(USAGEPREFIX), Progname, gettext(USAGE)); 135*7c478bd9Sstevel@tonic-gate exit(1); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate if (argc != optind) { 139*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s %s %s\n", 140*7c478bd9Sstevel@tonic-gate gettext(USAGEPREFIX), Progname, gettext(USAGE)); 141*7c478bd9Sstevel@tonic-gate exit(1); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate DEBUG(4, "\n\n** START **\n%s", ""); 145*7c478bd9Sstevel@tonic-gate acInit("rexe"); 146*7c478bd9Sstevel@tonic-gate scInit("rexe"); 147*7c478bd9Sstevel@tonic-gate if (scanlimit("uuxqt", &limitval) == FAIL) { 148*7c478bd9Sstevel@tonic-gate DEBUG(1, "No limits for uuxqt in %s\n", LIMITS); 149*7c478bd9Sstevel@tonic-gate } else { 150*7c478bd9Sstevel@tonic-gate maxnumb = limitval.totalmax; 151*7c478bd9Sstevel@tonic-gate if (maxnumb < 0) { 152*7c478bd9Sstevel@tonic-gate DEBUG(4, "Non-positive limit for uuxqt in %s\n", LIMITS); 153*7c478bd9Sstevel@tonic-gate DEBUG(1, "No limits for uuxqt\n%s", ""); 154*7c478bd9Sstevel@tonic-gate } else { 155*7c478bd9Sstevel@tonic-gate DEBUG(4, "Uuxqt limit %d -- ", maxnumb); 156*7c478bd9Sstevel@tonic-gate ret = cuantos(X_LOCKPRE, X_LOCKDIR); 157*7c478bd9Sstevel@tonic-gate DEBUG(4, "found %d -- ", ret); 158*7c478bd9Sstevel@tonic-gate if (maxnumb >= 0 && ret >= maxnumb) { 159*7c478bd9Sstevel@tonic-gate DEBUG(4, "exiting.%s\n", ""); 160*7c478bd9Sstevel@tonic-gate exit(0); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate DEBUG(4, "continuing.%s\n", ""); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * determine user who started uuxqt (in principle) 168*7c478bd9Sstevel@tonic-gate */ 169*7c478bd9Sstevel@tonic-gate strcpy(User, "uucp"); /* in case all else fails (can't happen) */ 170*7c478bd9Sstevel@tonic-gate Uid = getuid(); 171*7c478bd9Sstevel@tonic-gate Euid = geteuid(); /* this should be UUCPUID */ 172*7c478bd9Sstevel@tonic-gate guinfo(Euid, User); 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate if (Uid == 0) 175*7c478bd9Sstevel@tonic-gate (void) setuid(UUCPUID); 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate setuucp(User); 178*7c478bd9Sstevel@tonic-gate DEBUG(4, "User - %s\n", User); 179*7c478bd9Sstevel@tonic-gate guinfo(Uid, Loginuser); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate DEBUG(4, "process\n%s", ""); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate fp1 = opendir(Spool); 186*7c478bd9Sstevel@tonic-gate ASSERT(fp1 != NULL, Ct_OPEN, Spool, errno); 187*7c478bd9Sstevel@tonic-gate if (dirname[0] != NULLCHAR) { 188*7c478bd9Sstevel@tonic-gate /* look for special characters in remote name */ 189*7c478bd9Sstevel@tonic-gate if (strpbrk(dirname, Shchar) != NULL) { 190*7c478bd9Sstevel@tonic-gate /* ignore naughty name */ 191*7c478bd9Sstevel@tonic-gate DEBUG(4, "Bad remote name '%s'", dirname); 192*7c478bd9Sstevel@tonic-gate errent("BAD REMOTE NAME", dirname, 0, __FILE__, __LINE__); 193*7c478bd9Sstevel@tonic-gate closedir(fp1); 194*7c478bd9Sstevel@tonic-gate cleanup(101); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate (void) snprintf(lockname, sizeof (lockname), "%s.%s", 199*7c478bd9Sstevel@tonic-gate X_LOCK, dirname); 200*7c478bd9Sstevel@tonic-gate if (mklock(lockname) == SUCCESS) { 201*7c478bd9Sstevel@tonic-gate xprocess(dirname); 202*7c478bd9Sstevel@tonic-gate rmlock(CNULL); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate } else { 205*7c478bd9Sstevel@tonic-gate while (gdirf(fp1, dirname, Spool) == TRUE) { 206*7c478bd9Sstevel@tonic-gate if (strpbrk(dirname, Shchar) != NULL) { 207*7c478bd9Sstevel@tonic-gate /* skip naughty names */ 208*7c478bd9Sstevel@tonic-gate errent("BAD REMOTE NAME", dirname, 0, 209*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 210*7c478bd9Sstevel@tonic-gate continue; 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate (void) snprintf(lockname, sizeof (lockname), "%s.%s", 213*7c478bd9Sstevel@tonic-gate X_LOCK, dirname); 214*7c478bd9Sstevel@tonic-gate if (mklock(lockname) != SUCCESS) 215*7c478bd9Sstevel@tonic-gate continue; 216*7c478bd9Sstevel@tonic-gate xprocess(dirname); 217*7c478bd9Sstevel@tonic-gate rmlock(CNULL); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate closedir(fp1); 222*7c478bd9Sstevel@tonic-gate cleanup(0); 223*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate void 227*7c478bd9Sstevel@tonic-gate cleanup(code) 228*7c478bd9Sstevel@tonic-gate int code; 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate rmlock(CNULL); 231*7c478bd9Sstevel@tonic-gate exit(code); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * catch signal then cleanup and exit 236*7c478bd9Sstevel@tonic-gate */ 237*7c478bd9Sstevel@tonic-gate void 238*7c478bd9Sstevel@tonic-gate onintr(inter) 239*7c478bd9Sstevel@tonic-gate register int inter; 240*7c478bd9Sstevel@tonic-gate { 241*7c478bd9Sstevel@tonic-gate char str[30]; 242*7c478bd9Sstevel@tonic-gate (void) signal(inter, SIG_IGN); 243*7c478bd9Sstevel@tonic-gate (void) sprintf(str, "QSIGNAL %d", inter); 244*7c478bd9Sstevel@tonic-gate logent(str, "QCAUGHT"); 245*7c478bd9Sstevel@tonic-gate acEndexe(cpucycle(), PARTIAL); /* stop collecting accounting log */ 246*7c478bd9Sstevel@tonic-gate cleanup(-inter); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate #define XCACHESIZE (4096 / (MAXBASENAME + 1)) 250*7c478bd9Sstevel@tonic-gate static char xcache[XCACHESIZE][MAXBASENAME + 1]; /* cache for X. files */ 251*7c478bd9Sstevel@tonic-gate static int xcachesize = 0; /* how many left? */ 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * stash an X. file so we can process them sorted first by grade, then by 255*7c478bd9Sstevel@tonic-gate * sequence number 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate static void 258*7c478bd9Sstevel@tonic-gate xstash(file) 259*7c478bd9Sstevel@tonic-gate char *file; 260*7c478bd9Sstevel@tonic-gate { 261*7c478bd9Sstevel@tonic-gate if (xcachesize < XCACHESIZE) { 262*7c478bd9Sstevel@tonic-gate DEBUG(4, "stashing %s\n", file); 263*7c478bd9Sstevel@tonic-gate (void) strlcpy(xcache[xcachesize++], file, (MAXBASENAME + 1)); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* 268*7c478bd9Sstevel@tonic-gate * xcompare 269*7c478bd9Sstevel@tonic-gate * comparison routine for for qsort() 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate static int 272*7c478bd9Sstevel@tonic-gate xcompare(f1, f2) 273*7c478bd9Sstevel@tonic-gate const register void *f1, *f2; 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate /* assumes file name is X.siteG1234 */ 276*7c478bd9Sstevel@tonic-gate /* use -strcmp() so that xstash is sorted largest first */ 277*7c478bd9Sstevel@tonic-gate /* pull files out of the stash from largest index to smallest */ 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate return (-strcmp((char *)f1 + strlen((char *)f1) - 5, 280*7c478bd9Sstevel@tonic-gate (char *)f2 + strlen((char *)f2) - 5)); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate * xsort 285*7c478bd9Sstevel@tonic-gate * sort the cached X. files, 286*7c478bd9Sstevel@tonic-gate * largest (last) to smallest (next to be processed) 287*7c478bd9Sstevel@tonic-gate */ 288*7c478bd9Sstevel@tonic-gate static void 289*7c478bd9Sstevel@tonic-gate xsort() 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate DEBUG(4, "xsort: first was %s\n", xcache[0]); 292*7c478bd9Sstevel@tonic-gate qsort(xcache, xcachesize, MAXBASENAME + 1, xcompare); 293*7c478bd9Sstevel@tonic-gate DEBUG(4, "xsort: first is %s\n", xcache[0]); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * xget 298*7c478bd9Sstevel@tonic-gate * return smallest X. file in cache 299*7c478bd9Sstevel@tonic-gate * (hint: it's the last one in the array) 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate static int 302*7c478bd9Sstevel@tonic-gate xget(file) 303*7c478bd9Sstevel@tonic-gate char *file; 304*7c478bd9Sstevel@tonic-gate { 305*7c478bd9Sstevel@tonic-gate if (xcachesize > 0) { 306*7c478bd9Sstevel@tonic-gate strlcpy(file, xcache[--xcachesize], (MAXBASENAME + 1)); 307*7c478bd9Sstevel@tonic-gate DEBUG(4, "xget: returning %s\n", file); 308*7c478bd9Sstevel@tonic-gate return (1); 309*7c478bd9Sstevel@tonic-gate } else { 310*7c478bd9Sstevel@tonic-gate /* avoid horror of xcachesize < 0 (impossible, you say?)! */ 311*7c478bd9Sstevel@tonic-gate xcachesize = 0; 312*7c478bd9Sstevel@tonic-gate return (0); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * get a file to execute 319*7c478bd9Sstevel@tonic-gate * file -> a read to return filename in 320*7c478bd9Sstevel@tonic-gate * returns: 321*7c478bd9Sstevel@tonic-gate * 0 -> no file 322*7c478bd9Sstevel@tonic-gate * 1 -> file to execute 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate int 325*7c478bd9Sstevel@tonic-gate gt_Xfile(file, dir) 326*7c478bd9Sstevel@tonic-gate register char *file, *dir; 327*7c478bd9Sstevel@tonic-gate { 328*7c478bd9Sstevel@tonic-gate DIR *pdir; 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate if (xcachesize == 0) { 331*7c478bd9Sstevel@tonic-gate /* open spool directory */ 332*7c478bd9Sstevel@tonic-gate pdir = opendir(dir); 333*7c478bd9Sstevel@tonic-gate /* this was an ASSERT, but it's not so bad as all that */ 334*7c478bd9Sstevel@tonic-gate if (pdir == NULL) 335*7c478bd9Sstevel@tonic-gate return (0); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* scan spool directory looking for X. files to stash */ 338*7c478bd9Sstevel@tonic-gate while (gnamef(pdir, file) == TRUE) { 339*7c478bd9Sstevel@tonic-gate DEBUG(4, "gt_Xfile got %s\n", file); 340*7c478bd9Sstevel@tonic-gate /* look for x prefix */ 341*7c478bd9Sstevel@tonic-gate if (file[0] != XQTPRE) 342*7c478bd9Sstevel@tonic-gate continue; 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* check to see if required files have arrived */ 345*7c478bd9Sstevel@tonic-gate if (gotfiles(file)) 346*7c478bd9Sstevel@tonic-gate xstash(file); 347*7c478bd9Sstevel@tonic-gate if (xcachesize >= XCACHESIZE) 348*7c478bd9Sstevel@tonic-gate break; 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate closedir(pdir); 351*7c478bd9Sstevel@tonic-gate xsort(); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate return (xget(file)); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * check for needed files 359*7c478bd9Sstevel@tonic-gate * file -> name of file to check 360*7c478bd9Sstevel@tonic-gate * return: 361*7c478bd9Sstevel@tonic-gate * 0 -> not ready 362*7c478bd9Sstevel@tonic-gate * 1 -> all files ready 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate int 365*7c478bd9Sstevel@tonic-gate gotfiles(file) 366*7c478bd9Sstevel@tonic-gate register char *file; 367*7c478bd9Sstevel@tonic-gate { 368*7c478bd9Sstevel@tonic-gate register FILE *fp; 369*7c478bd9Sstevel@tonic-gate struct stat stbuf; 370*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ], rqfile[MAXNAMESIZE]; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate fp = fopen(file, "r"); 373*7c478bd9Sstevel@tonic-gate if (fp == NULL) 374*7c478bd9Sstevel@tonic-gate return (FALSE); 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp) != NULL) { 377*7c478bd9Sstevel@tonic-gate DEBUG(4, "%s\n", buf); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * look at required files 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate if (buf[0] != X_RQDFILE) 383*7c478bd9Sstevel@tonic-gate continue; 384*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%63s", rqfile); 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* 387*7c478bd9Sstevel@tonic-gate * expand file name 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate expfile(rqfile); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * see if file exists 393*7c478bd9Sstevel@tonic-gate */ 394*7c478bd9Sstevel@tonic-gate if (stat(rqfile, &stbuf) == -1) { 395*7c478bd9Sstevel@tonic-gate fclose(fp); 396*7c478bd9Sstevel@tonic-gate return (FALSE); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate fclose(fp); 401*7c478bd9Sstevel@tonic-gate return (TRUE); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate /* 405*7c478bd9Sstevel@tonic-gate * remove execute files to x-directory 406*7c478bd9Sstevel@tonic-gate * 407*7c478bd9Sstevel@tonic-gate * _Xfile is a global 408*7c478bd9Sstevel@tonic-gate * return: 409*7c478bd9Sstevel@tonic-gate * none 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate void 412*7c478bd9Sstevel@tonic-gate rm_Xfiles() 413*7c478bd9Sstevel@tonic-gate { 414*7c478bd9Sstevel@tonic-gate register FILE *fp; 415*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ], file[MAXNAMESIZE], tfile[MAXNAMESIZE]; 416*7c478bd9Sstevel@tonic-gate char tfull[MAXFULLNAME]; 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate if ((fp = fopen(_Xfile, "r")) == NULL) { 419*7c478bd9Sstevel@tonic-gate DEBUG(4, "rm_Xfiles: can't read %s\n", _Xfile); 420*7c478bd9Sstevel@tonic-gate return; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * (void) unlink each file belonging to job 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp) != NULL) { 427*7c478bd9Sstevel@tonic-gate if (buf[0] != X_RQDFILE) 428*7c478bd9Sstevel@tonic-gate continue; 429*7c478bd9Sstevel@tonic-gate if (sscanf(&buf[1], "%63s%63s", file, tfile) < 2) 430*7c478bd9Sstevel@tonic-gate continue; 431*7c478bd9Sstevel@tonic-gate (void) snprintf(tfull, sizeof (tfull), "%s/%s", XQTDIR, tfile); 432*7c478bd9Sstevel@tonic-gate (void) unlink(tfull); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate fclose(fp); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * move execute files to x-directory 439*7c478bd9Sstevel@tonic-gate * _Xfile is a global 440*7c478bd9Sstevel@tonic-gate * return: 441*7c478bd9Sstevel@tonic-gate * none 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate void 444*7c478bd9Sstevel@tonic-gate mv_Xfiles() 445*7c478bd9Sstevel@tonic-gate { 446*7c478bd9Sstevel@tonic-gate register FILE *fp; 447*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[MAXNAMESIZE]; 448*7c478bd9Sstevel@tonic-gate char tfull[MAXFULLNAME]; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate if ((fp = fopen(_Xfile, "r")) == NULL) { 451*7c478bd9Sstevel@tonic-gate DEBUG(4, "mv_Xfiles: can't read %s\n", _Xfile); 452*7c478bd9Sstevel@tonic-gate return; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp) != NULL) { 456*7c478bd9Sstevel@tonic-gate if (buf[0] != X_RQDFILE) 457*7c478bd9Sstevel@tonic-gate continue; 458*7c478bd9Sstevel@tonic-gate if (sscanf(&buf[1], "%63s%63s", ffile, tfile) < 2) 459*7c478bd9Sstevel@tonic-gate continue; 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * expand file names and move to 463*7c478bd9Sstevel@tonic-gate * execute directory 464*7c478bd9Sstevel@tonic-gate * Make files readable by anyone 465*7c478bd9Sstevel@tonic-gate */ 466*7c478bd9Sstevel@tonic-gate expfile(ffile); 467*7c478bd9Sstevel@tonic-gate (void) snprintf(tfull, sizeof (tfull), "%s/%s", XQTDIR, tfile); 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (chkpth(ffile, CK_READ) == FAIL) 470*7c478bd9Sstevel@tonic-gate continue; /* execution will fail later */ 471*7c478bd9Sstevel@tonic-gate if (chkpth(tfull, CK_WRITE) == FAIL) { 472*7c478bd9Sstevel@tonic-gate /* 473*7c478bd9Sstevel@tonic-gate * tfull will have been canonicalized. If 474*7c478bd9Sstevel@tonic-gate * it still points to XQTDIR, allow us to 475*7c478bd9Sstevel@tonic-gate * write there. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate if (!PREFIX(XQTDIR, tfull)) 478*7c478bd9Sstevel@tonic-gate continue; /* execution will fail later */ 479*7c478bd9Sstevel@tonic-gate /* otherwise, keep going */ 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate ASSERT(xmv(ffile, tfull) == 0, "XMV ERROR", tfull, errno); 483*7c478bd9Sstevel@tonic-gate chmod(tfull, PUB_FILEMODE); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate fclose(fp); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * undo what mv_Xfiles did 490*7c478bd9Sstevel@tonic-gate * _Xfile is a global 491*7c478bd9Sstevel@tonic-gate * return: 492*7c478bd9Sstevel@tonic-gate * none 493*7c478bd9Sstevel@tonic-gate */ 494*7c478bd9Sstevel@tonic-gate void 495*7c478bd9Sstevel@tonic-gate unmv_Xfiles() 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate FILE *fp; 498*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ], ffile[MAXNAMESIZE], tfile[MAXNAMESIZE]; 499*7c478bd9Sstevel@tonic-gate char tfull[MAXFULLNAME], ffull[MAXFULLNAME], xfull[MAXFULLNAME]; 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate (void) snprintf(xfull, MAXFULLNAME, "%s/%s", RemSpool, _Xfile); 502*7c478bd9Sstevel@tonic-gate if ((fp = fopen(xfull, "r")) == NULL) { 503*7c478bd9Sstevel@tonic-gate DEBUG(4, "unmv_Xfiles: can't read %s\n", xfull); 504*7c478bd9Sstevel@tonic-gate return; 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp) != NULL) { 508*7c478bd9Sstevel@tonic-gate if (buf[0] != X_RQDFILE) 509*7c478bd9Sstevel@tonic-gate continue; 510*7c478bd9Sstevel@tonic-gate if (sscanf(&buf[1], "%63s%63s", ffile, tfile) < 2) 511*7c478bd9Sstevel@tonic-gate continue; 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate /* 514*7c478bd9Sstevel@tonic-gate * expand file names and move back to 515*7c478bd9Sstevel@tonic-gate * spool directory 516*7c478bd9Sstevel@tonic-gate * Make files readable by uucp 517*7c478bd9Sstevel@tonic-gate */ 518*7c478bd9Sstevel@tonic-gate (void) snprintf(ffull, MAXFULLNAME, "%s/%s", RemSpool, ffile); 519*7c478bd9Sstevel@tonic-gate /* i know we're in .Xqtdir, but ... */ 520*7c478bd9Sstevel@tonic-gate (void) snprintf(tfull, MAXFULLNAME, "%s/%s", XQTDIR, tfile); 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (chkpth(ffull, CK_WRITE) == FAIL || 523*7c478bd9Sstevel@tonic-gate chkpth(tfull, CK_READ) == FAIL) 524*7c478bd9Sstevel@tonic-gate continue; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate ASSERT(xmv(tfull, ffull) == 0, "XMV ERROR", ffull, errno); 527*7c478bd9Sstevel@tonic-gate (void) chmod(ffull, (mode_t)0600); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate fclose(fp); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate * chkpart - checks the string (ptr points to it) for illegal command or 534*7c478bd9Sstevel@tonic-gate * file permission restriction - called recursively 535*7c478bd9Sstevel@tonic-gate * to check lines that have `string` or (string) form. 536*7c478bd9Sstevel@tonic-gate * _Cmd is the buffer where the command is built up. 537*7c478bd9Sstevel@tonic-gate * _CargType is the type of the next C line argument 538*7c478bd9Sstevel@tonic-gate * 539*7c478bd9Sstevel@tonic-gate * Return: 540*7c478bd9Sstevel@tonic-gate * BAD_FILE if a non permitted file is found 541*7c478bd9Sstevel@tonic-gate * BAD_COMMAND if non permitted command is found 542*7c478bd9Sstevel@tonic-gate * 0 - ok 543*7c478bd9Sstevel@tonic-gate */ 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate static int 546*7c478bd9Sstevel@tonic-gate chkpart(char *ptr) 547*7c478bd9Sstevel@tonic-gate { 548*7c478bd9Sstevel@tonic-gate char prm[BUFSIZ], whitesp[BUFSIZ], rqtcmd[BUFSIZ], xcmd[BUFSIZ]; 549*7c478bd9Sstevel@tonic-gate char savechar[2]; /* one character string with NULL */ 550*7c478bd9Sstevel@tonic-gate int ret; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate /* _CargType is the arg type for this iteration (cmd or file) */ 553*7c478bd9Sstevel@tonic-gate while ((ptr = getprm(ptr, whitesp, prm)) != NULL) { 554*7c478bd9Sstevel@tonic-gate DEBUG(4, "prm='%s'\n", prm); 555*7c478bd9Sstevel@tonic-gate switch (*prm) { 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* End of command delimiter */ 558*7c478bd9Sstevel@tonic-gate case ';': 559*7c478bd9Sstevel@tonic-gate case '^': 560*7c478bd9Sstevel@tonic-gate case '&': 561*7c478bd9Sstevel@tonic-gate case '|': 562*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 563*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, prm, sizeof (_Cmd)); 564*7c478bd9Sstevel@tonic-gate _CargType = C_COMMAND; 565*7c478bd9Sstevel@tonic-gate continue; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* Other delimiter */ 568*7c478bd9Sstevel@tonic-gate case '>': 569*7c478bd9Sstevel@tonic-gate case '<': 570*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 571*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, prm, sizeof (_Cmd)); 572*7c478bd9Sstevel@tonic-gate continue; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate case '`': /* don't allow any ` commands */ 575*7c478bd9Sstevel@tonic-gate case '\\': 576*7c478bd9Sstevel@tonic-gate return (BAD_COMMAND); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* Some allowable quoted string */ 579*7c478bd9Sstevel@tonic-gate case '(': 580*7c478bd9Sstevel@tonic-gate case '"': 581*7c478bd9Sstevel@tonic-gate case '\'': 582*7c478bd9Sstevel@tonic-gate /* must recurse */ 583*7c478bd9Sstevel@tonic-gate savechar[0] = *prm; 584*7c478bd9Sstevel@tonic-gate savechar[1] = NULLCHAR; 585*7c478bd9Sstevel@tonic-gate /* put leading white space & first char into command */ 586*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 587*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, savechar, sizeof (_Cmd)); 588*7c478bd9Sstevel@tonic-gate savechar[0] = prm[strlen(prm)-1]; 589*7c478bd9Sstevel@tonic-gate prm[strlen(prm)-1] = NULLCHAR; /* delete last character */ 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* recurse */ 592*7c478bd9Sstevel@tonic-gate if (ret = chkpart(prm+1)) { /* failed */ 593*7c478bd9Sstevel@tonic-gate return (ret); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate /* put last char into command */ 596*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, savechar, sizeof (_Cmd)); 597*7c478bd9Sstevel@tonic-gate continue; 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate case '2': 600*7c478bd9Sstevel@tonic-gate if (*(prm+1) == '>') { 601*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 602*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, prm, sizeof (_Cmd)); 603*7c478bd9Sstevel@tonic-gate continue; 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate /* fall through if not "2>" */ 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate default: /* check for command or file */ 608*7c478bd9Sstevel@tonic-gate break; 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate if (_CargType == C_COMMAND) { 612*7c478bd9Sstevel@tonic-gate (void) strlcpy(rqtcmd, prm, sizeof (rqtcmd)); 613*7c478bd9Sstevel@tonic-gate if (*rqtcmd == '~') 614*7c478bd9Sstevel@tonic-gate expfile(rqtcmd); 615*7c478bd9Sstevel@tonic-gate if ((cmdOK(rqtcmd, xcmd)) == FALSE) 616*7c478bd9Sstevel@tonic-gate return (BAD_COMMAND); 617*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 618*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, xcmd, sizeof (_Cmd)); 619*7c478bd9Sstevel@tonic-gate _CargType = C_FILE; 620*7c478bd9Sstevel@tonic-gate continue; 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate (void) strlcpy(rqtcmd, prm, sizeof (rqtcmd)); 624*7c478bd9Sstevel@tonic-gate if (*rqtcmd == '~') 625*7c478bd9Sstevel@tonic-gate expfile(rqtcmd); 626*7c478bd9Sstevel@tonic-gate if (chkFile(rqtcmd)) { 627*7c478bd9Sstevel@tonic-gate return (BAD_FILE); 628*7c478bd9Sstevel@tonic-gate } else { 629*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 630*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, rqtcmd, sizeof (_Cmd)); 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate } 633*7c478bd9Sstevel@tonic-gate if (whitesp[0] != '\0') 634*7c478bd9Sstevel@tonic-gate /* restore any trailing white space */ 635*7c478bd9Sstevel@tonic-gate (void) strlcat(_Cmd, whitesp, sizeof (_Cmd)); 636*7c478bd9Sstevel@tonic-gate return (0); /* all ok */ 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate /* 640*7c478bd9Sstevel@tonic-gate * chkFile - try to find a path name in the prm. 641*7c478bd9Sstevel@tonic-gate * if found, check it for access permission. 642*7c478bd9Sstevel@tonic-gate * 643*7c478bd9Sstevel@tonic-gate * check file access permissions 644*7c478bd9Sstevel@tonic-gate * if ! in name assume that access on local machine is required 645*7c478bd9Sstevel@tonic-gate * 646*7c478bd9Sstevel@tonic-gate * Return: 647*7c478bd9Sstevel@tonic-gate * BAD_FILE - not permitted 648*7c478bd9Sstevel@tonic-gate * 0 - ok 649*7c478bd9Sstevel@tonic-gate */ 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate static int 652*7c478bd9Sstevel@tonic-gate chkFile(char *prm) 653*7c478bd9Sstevel@tonic-gate { 654*7c478bd9Sstevel@tonic-gate char *p, buf[BUFSIZ]; 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate (void) strlcpy(buf, prm, sizeof (buf)); 657*7c478bd9Sstevel@tonic-gate switch (*prm) { 658*7c478bd9Sstevel@tonic-gate case '~': 659*7c478bd9Sstevel@tonic-gate case '/': 660*7c478bd9Sstevel@tonic-gate if (doFileChk(buf)) 661*7c478bd9Sstevel@tonic-gate return (BAD_FILE); 662*7c478bd9Sstevel@tonic-gate else 663*7c478bd9Sstevel@tonic-gate return (0); 664*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate case '!': 667*7c478bd9Sstevel@tonic-gate return (chkFile(buf+1)); 668*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate default: 671*7c478bd9Sstevel@tonic-gate break; 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate if ((p = strchr(buf, '!')) == NULL) { /* no "!", look for "/" */ 675*7c478bd9Sstevel@tonic-gate if ((p = strchr(buf, '/')) == NULL) { /* ok */ 676*7c478bd9Sstevel@tonic-gate return (0); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate if (doFileChk(p)) 679*7c478bd9Sstevel@tonic-gate return (BAD_FILE); 680*7c478bd9Sstevel@tonic-gate else 681*7c478bd9Sstevel@tonic-gate return (0); 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate /* there is at least one '!' - see if it refers to my system */ 685*7c478bd9Sstevel@tonic-gate if (PREFIX(Myname, buf)) /* my system so far, check further */ 686*7c478bd9Sstevel@tonic-gate return (chkFile(p+1)); /* recurse with thing after '!' */ 687*7c478bd9Sstevel@tonic-gate else /* not my system - not my worry */ 688*7c478bd9Sstevel@tonic-gate return (0); 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate /* 692*7c478bd9Sstevel@tonic-gate * doFileChk - check file path permission 693*7c478bd9Sstevel@tonic-gate * NOTE: file is assumed to be a buffer that expfile an 694*7c478bd9Sstevel@tonic-gate * write into. 695*7c478bd9Sstevel@tonic-gate * Return 696*7c478bd9Sstevel@tonic-gate * BAD_FILE - not allowed 697*7c478bd9Sstevel@tonic-gate * 0 - ok 698*7c478bd9Sstevel@tonic-gate */ 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate static int 701*7c478bd9Sstevel@tonic-gate doFileChk(char *file) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate expfile(file); 704*7c478bd9Sstevel@tonic-gate DEBUG(7, "fullname: %s\n", file); 705*7c478bd9Sstevel@tonic-gate if (chkpth(file, CK_READ) == FAIL || 706*7c478bd9Sstevel@tonic-gate chkpth(file, CK_WRITE) == FAIL) 707*7c478bd9Sstevel@tonic-gate return (BAD_FILE); 708*7c478bd9Sstevel@tonic-gate else 709*7c478bd9Sstevel@tonic-gate return (0); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * return stuff to user 715*7c478bd9Sstevel@tonic-gate * user -> user to notify 716*7c478bd9Sstevel@tonic-gate * rmt -> system name where user resides 717*7c478bd9Sstevel@tonic-gate * file -> file to return (generally contains input) 718*7c478bd9Sstevel@tonic-gate * cmd -> command that was to be executed 719*7c478bd9Sstevel@tonic-gate * buf -> user friendly face saving uplifting edifying missive 720*7c478bd9Sstevel@tonic-gate * errfile -> stderr output from cmd xeqn 721*7c478bd9Sstevel@tonic-gate * return: 722*7c478bd9Sstevel@tonic-gate * none 723*7c478bd9Sstevel@tonic-gate */ 724*7c478bd9Sstevel@tonic-gate static void 725*7c478bd9Sstevel@tonic-gate retosndr(user, rmt, file, cmd, buf, errfile) 726*7c478bd9Sstevel@tonic-gate char *user, *rmt, *file, *cmd, *buf, *errfile; 727*7c478bd9Sstevel@tonic-gate { 728*7c478bd9Sstevel@tonic-gate char ruser[BUFSIZ], msg[BUFSIZ], subj[BUFSIZ]; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), "%s\t[%s %s (%s)]\n\t%s\n%s\n", 731*7c478bd9Sstevel@tonic-gate gettext("remote execution"), gettext("uucp job"), 732*7c478bd9Sstevel@tonic-gate *Jobid ? Jobid : &_Xfile[2], timeStamp(), cmd, buf); 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate DEBUG(5, "retosndr %s, ", msg); 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate if (EQUALS(rmt, Myname)) 737*7c478bd9Sstevel@tonic-gate (void) strlcpy(ruser, user, sizeof (ruser)); 738*7c478bd9Sstevel@tonic-gate else 739*7c478bd9Sstevel@tonic-gate (void) snprintf(ruser, sizeof (ruser), "%s!%s", rmt, user); 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate (void) strlcpy(subj, gettext("remote execution status"), sizeof (subj)); 742*7c478bd9Sstevel@tonic-gate mailst(ruser, subj, msg, file, errfile); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* 747*7c478bd9Sstevel@tonic-gate * uucpst - send the status message back using a uucp command 748*7c478bd9Sstevel@tonic-gate * NOTE - this would be better if the file could be appended. 749*7c478bd9Sstevel@tonic-gate * - suggestion for the future - if rmail would take a file name 750*7c478bd9Sstevel@tonic-gate * instead of just person, then that facility would be correct, 751*7c478bd9Sstevel@tonic-gate * and this routine would not be needed. 752*7c478bd9Sstevel@tonic-gate */ 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate static void 755*7c478bd9Sstevel@tonic-gate uucpst(rmt, tofile, errfile, cmd, buf) 756*7c478bd9Sstevel@tonic-gate char *rmt, *tofile, *errfile, *cmd, *buf; 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate char arg[MAXFULLNAME], tmp[NAMESIZE], msg[BUFSIZ]; 759*7c478bd9Sstevel@tonic-gate pid_t pid, ret; 760*7c478bd9Sstevel@tonic-gate int status; 761*7c478bd9Sstevel@tonic-gate FILE *fp, *fi; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), "%s %s (%s) %s\n\t%s\n%s\n", 764*7c478bd9Sstevel@tonic-gate gettext("uucp job"), *Jobid ? Jobid : &_Xfile[2], timeStamp(), 765*7c478bd9Sstevel@tonic-gate gettext("remote execution"), cmd, buf); 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate (void) snprintf(tmp, sizeof (tmp), "%s.%ld", rmt, (long)getpid()); 768*7c478bd9Sstevel@tonic-gate if ((fp = fopen(tmp, "w")) == NULL) 769*7c478bd9Sstevel@tonic-gate return; 770*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", msg); 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate /* copy back stderr */ 773*7c478bd9Sstevel@tonic-gate if (*errfile != '\0' && NOTEMPTY(errfile) && 774*7c478bd9Sstevel@tonic-gate (fi = fopen(errfile, "r")) != NULL) { 775*7c478bd9Sstevel@tonic-gate fputs("\n\t===== stderr was =====\n", fp); 776*7c478bd9Sstevel@tonic-gate if (xfappend(fi, fp) != SUCCESS) 777*7c478bd9Sstevel@tonic-gate fputs("\n\t===== well, i tried =====\n", fp); 778*7c478bd9Sstevel@tonic-gate (void) fclose(fi); 779*7c478bd9Sstevel@tonic-gate fputc('\n', fp); 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 784*7c478bd9Sstevel@tonic-gate (void) snprintf(arg, sizeof (arg), "%s!%s", rmt, tofile); 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate /* start uucp */ 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate if ((pid = vfork()) == 0) { 789*7c478bd9Sstevel@tonic-gate (void) close(0); 790*7c478bd9Sstevel@tonic-gate (void) close(1); 791*7c478bd9Sstevel@tonic-gate (void) close(2); 792*7c478bd9Sstevel@tonic-gate (void) open("/dev/null", 2); 793*7c478bd9Sstevel@tonic-gate (void) open("/dev/null", 2); 794*7c478bd9Sstevel@tonic-gate (void) open("/dev/null", 2); 795*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 796*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); 797*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 798*7c478bd9Sstevel@tonic-gate ucloselog(); 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate (void) execle("/usr/bin/uucp", "UUCP", 801*7c478bd9Sstevel@tonic-gate "-C", tmp, arg, (char *)0, Env); 802*7c478bd9Sstevel@tonic-gate _exit(100); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate if (pid == -1) 806*7c478bd9Sstevel@tonic-gate return; 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate while ((ret = wait(&status)) != pid) 809*7c478bd9Sstevel@tonic-gate if (ret == -1 && errno != EINTR) 810*7c478bd9Sstevel@tonic-gate break; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate (void) unlink(tmp); 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate void 816*7c478bd9Sstevel@tonic-gate xprocess(dirname) 817*7c478bd9Sstevel@tonic-gate char *dirname; 818*7c478bd9Sstevel@tonic-gate { 819*7c478bd9Sstevel@tonic-gate char fdgrade(); /* returns default service grade on system */ 820*7c478bd9Sstevel@tonic-gate int return_stdin; /* return stdin for failed commands */ 821*7c478bd9Sstevel@tonic-gate int cmdok, ret, badfiles; 822*7c478bd9Sstevel@tonic-gate mode_t mask; 823*7c478bd9Sstevel@tonic-gate int send_zero; /* return successful completion status */ 824*7c478bd9Sstevel@tonic-gate int send_nonzero; /* return unsuccessful completion status */ 825*7c478bd9Sstevel@tonic-gate int send_nothing; /* request for no exit status */ 826*7c478bd9Sstevel@tonic-gate int store_status; /* store status of command in local file */ 827*7c478bd9Sstevel@tonic-gate char lbuf[BUFSIZ]; 828*7c478bd9Sstevel@tonic-gate char dqueue; /* var to hold the default service grade */ 829*7c478bd9Sstevel@tonic-gate char *errname = ""; /* name of local stderr output file */ 830*7c478bd9Sstevel@tonic-gate char *p; 831*7c478bd9Sstevel@tonic-gate char sendsys[MAXNAMESIZE]; 832*7c478bd9Sstevel@tonic-gate char dfile[MAXFULLNAME], cfile[MAXFULLNAME], incmd[BUFSIZ]; 833*7c478bd9Sstevel@tonic-gate char errDfile[BUFSIZ]; 834*7c478bd9Sstevel@tonic-gate char fin[MAXFULLNAME]; 835*7c478bd9Sstevel@tonic-gate char fout[MAXFULLNAME], sysout[NAMESIZE]; 836*7c478bd9Sstevel@tonic-gate char ferr[MAXFULLNAME], syserr[NAMESIZE]; 837*7c478bd9Sstevel@tonic-gate char file[MAXFULLNAME], tempname[NAMESIZE]; 838*7c478bd9Sstevel@tonic-gate char _Sfile[MAXFULLNAME]; /* name of local file for status */ 839*7c478bd9Sstevel@tonic-gate FILE *xfp, *fp; 840*7c478bd9Sstevel@tonic-gate struct stat sb; 841*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ], user[BUFSIZ], retaddr[BUFSIZ], retuser[BUFSIZ], 842*7c478bd9Sstevel@tonic-gate msgbuf[BUFSIZ]; 843*7c478bd9Sstevel@tonic-gate char origsys[MAXFULLNAME], origuser[MAXFULLNAME]; 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate (void) strlcpy(Rmtname, dirname, sizeof (Rmtname)); 846*7c478bd9Sstevel@tonic-gate chremdir(Rmtname); 847*7c478bd9Sstevel@tonic-gate (void) mchFind(Rmtname); 848*7c478bd9Sstevel@tonic-gate while (gt_Xfile(_Xfile, RemSpool) > 0) { 849*7c478bd9Sstevel@tonic-gate DEBUG(4, "_Xfile - %s\n", _Xfile); 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate if ((xfp = fopen(_Xfile, "r")) == NULL) { 852*7c478bd9Sstevel@tonic-gate toCorrupt(_Xfile); 853*7c478bd9Sstevel@tonic-gate continue; 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate ASSERT(xfp != NULL, Ct_OPEN, _Xfile, errno); 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate if (stat(_Xfile, &sb) != -1) 858*7c478bd9Sstevel@tonic-gate Nstat.t_qtime = sb.st_mtime; 859*7c478bd9Sstevel@tonic-gate /* 860*7c478bd9Sstevel@tonic-gate * initialize to defaults 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate (void) strlcpy(user, User, sizeof (user)); 863*7c478bd9Sstevel@tonic-gate (void) strcpy(fin, "/dev/null"); 864*7c478bd9Sstevel@tonic-gate (void) strcpy(fout, "/dev/null"); 865*7c478bd9Sstevel@tonic-gate (void) strcpy(ferr, "/dev/null"); 866*7c478bd9Sstevel@tonic-gate (void) sprintf(sysout, "%.*s", MAXBASENAME, Myname); 867*7c478bd9Sstevel@tonic-gate (void) sprintf(syserr, "%.*s", MAXBASENAME, Myname); 868*7c478bd9Sstevel@tonic-gate badfiles = 0; 869*7c478bd9Sstevel@tonic-gate *incmd = *retaddr = *retuser = *Jobid = NULLCHAR; 870*7c478bd9Sstevel@tonic-gate initSeq(); 871*7c478bd9Sstevel@tonic-gate send_zero = send_nonzero = send_nothing = 0; 872*7c478bd9Sstevel@tonic-gate store_status = 0; 873*7c478bd9Sstevel@tonic-gate return_stdin = 0; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, xfp) != NULL) { 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * interpret JCL card 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate switch (buf[0]) { 880*7c478bd9Sstevel@tonic-gate case X_USER: 881*7c478bd9Sstevel@tonic-gate /* 882*7c478bd9Sstevel@tonic-gate * user name 883*7c478bd9Sstevel@tonic-gate * (ignore Rmtname) 884*7c478bd9Sstevel@tonic-gate * The utmpx username field is 32 characters long; 885*7c478bd9Sstevel@tonic-gate * UUCP usage truncates system name to 14 bytes. 886*7c478bd9Sstevel@tonic-gate */ 887*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%32s%14s", user, origsys); 888*7c478bd9Sstevel@tonic-gate (void) strlcpy(origuser, user, sizeof (origuser)); 889*7c478bd9Sstevel@tonic-gate break; 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate case X_STDIN: 892*7c478bd9Sstevel@tonic-gate /* 893*7c478bd9Sstevel@tonic-gate * standard input 894*7c478bd9Sstevel@tonic-gate */ 895*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%256s", fin); 896*7c478bd9Sstevel@tonic-gate expfile(fin); 897*7c478bd9Sstevel@tonic-gate if (chkpth(fin, CK_READ)) { 898*7c478bd9Sstevel@tonic-gate DEBUG(4, "badfile - in: %s\n", fin); 899*7c478bd9Sstevel@tonic-gate badfiles = 1; 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate break; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate case X_STDOUT: 904*7c478bd9Sstevel@tonic-gate /* 905*7c478bd9Sstevel@tonic-gate * standard output 906*7c478bd9Sstevel@tonic-gate */ 907*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%256s%14s", fout, sysout); 908*7c478bd9Sstevel@tonic-gate if ((p = strpbrk(sysout, "!/")) != NULL) 909*7c478bd9Sstevel@tonic-gate *p = NULLCHAR; /* these are dangerous */ 910*7c478bd9Sstevel@tonic-gate if (*sysout != NULLCHAR && !EQUALS(sysout, Myname)) 911*7c478bd9Sstevel@tonic-gate break; 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate expfile(fout); 914*7c478bd9Sstevel@tonic-gate if (chkpth(fout, CK_WRITE)) { 915*7c478bd9Sstevel@tonic-gate badfiles = 1; 916*7c478bd9Sstevel@tonic-gate DEBUG(4, "badfile - out: %s\n", fout); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate break; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate case X_STDERR: /* standard error */ 921*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%256s%14s", ferr, syserr); 922*7c478bd9Sstevel@tonic-gate if ((p = strpbrk(syserr, "!/")) != NULL) 923*7c478bd9Sstevel@tonic-gate *p = NULLCHAR; /* these are dangerous */ 924*7c478bd9Sstevel@tonic-gate if (*syserr != NULLCHAR && !EQUALS(syserr, Myname)) 925*7c478bd9Sstevel@tonic-gate break; 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate expfile(ferr); 928*7c478bd9Sstevel@tonic-gate if (chkpth(ferr, CK_WRITE)) { 929*7c478bd9Sstevel@tonic-gate badfiles = 1; 930*7c478bd9Sstevel@tonic-gate DEBUG(4, "badfile - error: %s\n", ferr); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate break; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate case X_CMD: /* command to execute */ 936*7c478bd9Sstevel@tonic-gate (void) strlcpy(incmd, &buf[2], sizeof (incmd)); 937*7c478bd9Sstevel@tonic-gate if (*(incmd + strlen(incmd) - 1) == '\n') 938*7c478bd9Sstevel@tonic-gate *(incmd + strlen(incmd) - 1) = NULLCHAR; 939*7c478bd9Sstevel@tonic-gate break; 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate case X_MAILF: /* put status in _Sfile */ 942*7c478bd9Sstevel@tonic-gate store_status = 1; 943*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%256s", _Sfile); 944*7c478bd9Sstevel@tonic-gate break; 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate case X_SENDNOTHING: /* no failure notification */ 947*7c478bd9Sstevel@tonic-gate send_nothing++; 948*7c478bd9Sstevel@tonic-gate break; 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate case X_SENDZERO: /* success notification */ 951*7c478bd9Sstevel@tonic-gate send_zero++; 952*7c478bd9Sstevel@tonic-gate break; 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate case X_NONZERO: /* failure notification */ 955*7c478bd9Sstevel@tonic-gate send_nonzero++; 956*7c478bd9Sstevel@tonic-gate break; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate case X_BRINGBACK: /* return stdin on command failure */ 959*7c478bd9Sstevel@tonic-gate return_stdin = 1; 960*7c478bd9Sstevel@tonic-gate break; 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate case X_RETADDR: 964*7c478bd9Sstevel@tonic-gate /* 965*7c478bd9Sstevel@tonic-gate * return address -- is user's name 966*7c478bd9Sstevel@tonic-gate * put "Rmtname!" in front of it so mail 967*7c478bd9Sstevel@tonic-gate * will always get back to remote system. 968*7c478bd9Sstevel@tonic-gate */ 969*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%s", retuser); 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate /* 972*7c478bd9Sstevel@tonic-gate * Creates string of Rmtname!Rmtname!user which 973*7c478bd9Sstevel@tonic-gate * confuses rmail. 974*7c478bd9Sstevel@tonic-gate * (void) strcat(strcat(strcpy(retaddr, Rmtname), "!"), 975*7c478bd9Sstevel@tonic-gate * retuser); 976*7c478bd9Sstevel@tonic-gate */ 977*7c478bd9Sstevel@tonic-gate break; 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate case X_JOBID: 980*7c478bd9Sstevel@tonic-gate /* 981*7c478bd9Sstevel@tonic-gate * job id for notification 982*7c478bd9Sstevel@tonic-gate * (should be MAXBASENAME, not 14, but no can do) 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%14s", Jobid); 985*7c478bd9Sstevel@tonic-gate break; 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate default: 988*7c478bd9Sstevel@tonic-gate break; 989*7c478bd9Sstevel@tonic-gate } 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate fclose(xfp); 993*7c478bd9Sstevel@tonic-gate DEBUG(4, "fin - %s, ", fin); 994*7c478bd9Sstevel@tonic-gate DEBUG(4, "fout - %s, ", fout); 995*7c478bd9Sstevel@tonic-gate DEBUG(4, "ferr - %s, ", ferr); 996*7c478bd9Sstevel@tonic-gate DEBUG(4, "sysout - %s, ", sysout); 997*7c478bd9Sstevel@tonic-gate DEBUG(4, "syserr - %s, ", syserr); 998*7c478bd9Sstevel@tonic-gate DEBUG(4, "user - %s\n", user); 999*7c478bd9Sstevel@tonic-gate DEBUG(4, "incmd - %s\n", incmd); 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate scRexe(origsys, origuser, Loginuser, incmd); 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate if (retuser[0] != NULLCHAR) 1004*7c478bd9Sstevel@tonic-gate (void) strlcpy(user, retuser, sizeof (user)); /* pick on this guy */ 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate /* get rid of stuff that can be dangerous */ 1007*7c478bd9Sstevel@tonic-gate if ((p = strpbrk(user, Shchar)) != NULL) { 1008*7c478bd9Sstevel@tonic-gate *p = NULLCHAR; 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate if (incmd[0] == NULLCHAR) { 1012*7c478bd9Sstevel@tonic-gate /* this is a bad X. file - just get rid of it */ 1013*7c478bd9Sstevel@tonic-gate toCorrupt(_Xfile); 1014*7c478bd9Sstevel@tonic-gate continue; 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate /* 1018*7c478bd9Sstevel@tonic-gate * send_nothing must be explicitly requested to avert failure status 1019*7c478bd9Sstevel@tonic-gate * send_zero must be explicitly requested for success notification 1020*7c478bd9Sstevel@tonic-gate */ 1021*7c478bd9Sstevel@tonic-gate if (!send_nothing) 1022*7c478bd9Sstevel@tonic-gate send_nonzero++; 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate /* 1025*7c478bd9Sstevel@tonic-gate * command execution 1026*7c478bd9Sstevel@tonic-gate */ 1027*7c478bd9Sstevel@tonic-gate 1028*7c478bd9Sstevel@tonic-gate /* 1029*7c478bd9Sstevel@tonic-gate * generate a temporary file (if necessary) 1030*7c478bd9Sstevel@tonic-gate * to hold output to be shipped back 1031*7c478bd9Sstevel@tonic-gate */ 1032*7c478bd9Sstevel@tonic-gate if (EQUALS(fout, "/dev/null")) 1033*7c478bd9Sstevel@tonic-gate (void) strcpy(dfile, "/dev/null"); 1034*7c478bd9Sstevel@tonic-gate else { 1035*7c478bd9Sstevel@tonic-gate gename(DATAPRE, sysout, 'O', tempname); 1036*7c478bd9Sstevel@tonic-gate (void) snprintf(dfile, sizeof (dfile), "%s/%s", WORKSPACE, 1037*7c478bd9Sstevel@tonic-gate tempname); 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate /* 1041*7c478bd9Sstevel@tonic-gate * generate a temporary file (if necessary) 1042*7c478bd9Sstevel@tonic-gate * to hold errors to be shipped back 1043*7c478bd9Sstevel@tonic-gate */ 1044*7c478bd9Sstevel@tonic-gate /* 1045*7c478bd9Sstevel@tonic-gate * This is what really should be done. However for compatibility 1046*7c478bd9Sstevel@tonic-gate * for the interim at least, we will always create temp file 1047*7c478bd9Sstevel@tonic-gate * so we can return error output. If this temp file IS conditionally 1048*7c478bd9Sstevel@tonic-gate * created, we must remove the unlink() of errDfile at the end 1049*7c478bd9Sstevel@tonic-gate * because it may REALLY be /dev/null. 1050*7c478bd9Sstevel@tonic-gate * if (EQUALS(ferr, "/dev/null")) 1051*7c478bd9Sstevel@tonic-gate * (void) strcpy(errDfile, "/dev/null"); 1052*7c478bd9Sstevel@tonic-gate * else { 1053*7c478bd9Sstevel@tonic-gate */ 1054*7c478bd9Sstevel@tonic-gate gename(DATAPRE, syserr, 'E', tempname); 1055*7c478bd9Sstevel@tonic-gate (void) snprintf(errDfile, sizeof (errDfile), "%s/%s", 1056*7c478bd9Sstevel@tonic-gate WORKSPACE, tempname); 1057*7c478bd9Sstevel@tonic-gate /* 1058*7c478bd9Sstevel@tonic-gate * } 1059*7c478bd9Sstevel@tonic-gate */ 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate /* initialize command line */ 1062*7c478bd9Sstevel@tonic-gate /* set up two environment variables, remote machine name */ 1063*7c478bd9Sstevel@tonic-gate /* and remote user name if available from R line */ 1064*7c478bd9Sstevel@tonic-gate /* 1065*7c478bd9Sstevel@tonic-gate * xcu4 requires that uucp *does* expand wildcards and uux *does not* 1066*7c478bd9Sstevel@tonic-gate * expand wild cards... Further restrictions are that uux must work 1067*7c478bd9Sstevel@tonic-gate * with every other uucp / uux that initiated a request, so nothing 1068*7c478bd9Sstevel@tonic-gate * strange can been done to communicate that it was uucp that sent 1069*7c478bd9Sstevel@tonic-gate * the request and not uux, What we settle on here is looking for 1070*7c478bd9Sstevel@tonic-gate * the command name uucp and expanding wildcards in only that case. 1071*7c478bd9Sstevel@tonic-gate * It is true that a user can spoof this using uux, but in reality 1072*7c478bd9Sstevel@tonic-gate * this would be identical to using the uucp command to start with. 1073*7c478bd9Sstevel@tonic-gate */ 1074*7c478bd9Sstevel@tonic-gate if (strncmp(incmd, "uucp ", 5) == 0) { 1075*7c478bd9Sstevel@tonic-gate (void) snprintf(_Cmd, sizeof (_Cmd), 1076*7c478bd9Sstevel@tonic-gate "%s %s UU_MACHINE=%s UU_USER=%s " 1077*7c478bd9Sstevel@tonic-gate " export UU_MACHINE UU_USER PATH; ", 1078*7c478bd9Sstevel@tonic-gate PATH, LOGNAME, Rmtname, user); 1079*7c478bd9Sstevel@tonic-gate } else { 1080*7c478bd9Sstevel@tonic-gate (void) snprintf(_Cmd, sizeof (_Cmd), 1081*7c478bd9Sstevel@tonic-gate "%s %s UU_MACHINE=%s UU_USER=%s " 1082*7c478bd9Sstevel@tonic-gate " export UU_MACHINE UU_USER PATH; set -f; ", 1083*7c478bd9Sstevel@tonic-gate PATH, LOGNAME, Rmtname, user); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate /* 1087*7c478bd9Sstevel@tonic-gate * check to see if command can be executed 1088*7c478bd9Sstevel@tonic-gate */ 1089*7c478bd9Sstevel@tonic-gate _CargType = C_COMMAND; /* the first thing is a command */ 1090*7c478bd9Sstevel@tonic-gate cmdok = chkpart(incmd); 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate if (badfiles || (cmdok == BAD_COMMAND) || cmdok == BAD_FILE) { 1093*7c478bd9Sstevel@tonic-gate if (cmdok == BAD_COMMAND) { 1094*7c478bd9Sstevel@tonic-gate (void) snprintf(lbuf, sizeof (lbuf), "%s!%s XQT DENIED", 1095*7c478bd9Sstevel@tonic-gate Rmtname, user); 1096*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 1097*7c478bd9Sstevel@tonic-gate "execution permission denied to %s!%s", Rmtname, user); 1098*7c478bd9Sstevel@tonic-gate } else { 1099*7c478bd9Sstevel@tonic-gate (void) snprintf(lbuf, sizeof (lbuf), 1100*7c478bd9Sstevel@tonic-gate "%s!%s XQT - STDIN/STDOUT/FILE ACCESS DENIED", 1101*7c478bd9Sstevel@tonic-gate Rmtname, user); 1102*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 1103*7c478bd9Sstevel@tonic-gate "file access denied to %s!%s", Rmtname, user); 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate logent(incmd, lbuf); 1106*7c478bd9Sstevel@tonic-gate DEBUG(4, "bad command %s\n", incmd); 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate scWlog(); /* log security vialotion */ 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate if (send_nonzero) 1111*7c478bd9Sstevel@tonic-gate retosndr(user, Rmtname, return_stdin ? fin : "", 1112*7c478bd9Sstevel@tonic-gate incmd, msgbuf, ""); 1113*7c478bd9Sstevel@tonic-gate if (store_status) 1114*7c478bd9Sstevel@tonic-gate uucpst(Rmtname, _Sfile, "", incmd, msgbuf); 1115*7c478bd9Sstevel@tonic-gate goto rmfiles; 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate (void) snprintf(lbuf, sizeof (lbuf), "%s!%s XQT", Rmtname, user); 1119*7c478bd9Sstevel@tonic-gate logent(_Cmd, lbuf); 1120*7c478bd9Sstevel@tonic-gate DEBUG(4, "cmd %s\n", _Cmd); 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate /* move files to execute directory and change to that directory */ 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate mv_Xfiles(); 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate ASSERT(chdir(XQTDIR) == 0, Ct_CHDIR, XQTDIR, errno); 1127*7c478bd9Sstevel@tonic-gate acRexe(&_Xfile[2], origsys, origuser, Myname, Loginuser, incmd); 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate /* invoke shell to execute command */ 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate mask = umask(0); 1132*7c478bd9Sstevel@tonic-gate DEBUG(7, "full cmd: %s\n", _Cmd); 1133*7c478bd9Sstevel@tonic-gate 1134*7c478bd9Sstevel@tonic-gate cpucycle(); 1135*7c478bd9Sstevel@tonic-gate ret = shio(_Cmd, fin, dfile, errDfile); 1136*7c478bd9Sstevel@tonic-gate if (ret == 0) 1137*7c478bd9Sstevel@tonic-gate acEndexe(cpucycle(), COMPLETE); 1138*7c478bd9Sstevel@tonic-gate else 1139*7c478bd9Sstevel@tonic-gate acEndexe(cpucycle(), PARTIAL); 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate umask(mask); 1142*7c478bd9Sstevel@tonic-gate if (ret == -1) { /* -1 means the fork() failed */ 1143*7c478bd9Sstevel@tonic-gate unmv_Xfiles(); /* put things back */ 1144*7c478bd9Sstevel@tonic-gate errent(Ct_FORK, buf, errno, __FILE__, __LINE__); 1145*7c478bd9Sstevel@tonic-gate cleanup(1); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate if (ret == 0) { /* exit == signal == 0 */ 1149*7c478bd9Sstevel@tonic-gate (void) strcpy(msgbuf, "exited normally"); 1150*7c478bd9Sstevel@tonic-gate } else { /* exit != 0 */ 1151*7c478bd9Sstevel@tonic-gate int exitcode = (ret >> 8) & 0377; 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate if (exitcode) { 1154*7c478bd9Sstevel@tonic-gate /* exit != 0 */ 1155*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 1156*7c478bd9Sstevel@tonic-gate "exited with status %d", exitcode); 1157*7c478bd9Sstevel@tonic-gate } else { 1158*7c478bd9Sstevel@tonic-gate /* signal != 0 */ 1159*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 1160*7c478bd9Sstevel@tonic-gate "terminated by signal %d", ret & 0177); 1161*7c478bd9Sstevel@tonic-gate } 1162*7c478bd9Sstevel@tonic-gate DEBUG(5, "%s\n", msgbuf); 1163*7c478bd9Sstevel@tonic-gate (void) snprintf(lbuf, sizeof (lbuf), "%s - %s", incmd, msgbuf); 1164*7c478bd9Sstevel@tonic-gate logent(lbuf, "COMMAND FAIL"); 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate /* change back to spool directory */ 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate chremdir(Rmtname); 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate /* remove file */ 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate rm_Xfiles(); 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate /* 1176*7c478bd9Sstevel@tonic-gate * We used to append stderr to stdout. Since stderr can 1177*7c478bd9Sstevel@tonic-gate * now be specified separately, never append it to stdout. 1178*7c478bd9Sstevel@tonic-gate * It can still be gotten via -s status file option. 1179*7c478bd9Sstevel@tonic-gate */ 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate if (!EQUALS(fout, "/dev/null")) { 1182*7c478bd9Sstevel@tonic-gate /* 1183*7c478bd9Sstevel@tonic-gate * if output is on this machine copy output 1184*7c478bd9Sstevel@tonic-gate * there, otherwise spawn job to send to send 1185*7c478bd9Sstevel@tonic-gate * output elsewhere. 1186*7c478bd9Sstevel@tonic-gate */ 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate if (EQUALS(sysout, Myname)) { 1189*7c478bd9Sstevel@tonic-gate if ((xmv(dfile, fout)) != 0) { 1190*7c478bd9Sstevel@tonic-gate logent("FAILED", "COPY"); 1191*7c478bd9Sstevel@tonic-gate scWrite(); 1192*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf + strlen(msgbuf), 1193*7c478bd9Sstevel@tonic-gate (sizeof (msgbuf) - strlen(msgbuf)), 1194*7c478bd9Sstevel@tonic-gate "\nCould not move stdout to %s,", fout); 1195*7c478bd9Sstevel@tonic-gate if (putinpub(fout, dfile, origuser) == 0) 1196*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf + strlen(msgbuf), 1197*7c478bd9Sstevel@tonic-gate (sizeof (msgbuf) - strlen(msgbuf)), 1198*7c478bd9Sstevel@tonic-gate "\n\tstdout left in %s.", fout); 1199*7c478bd9Sstevel@tonic-gate else 1200*7c478bd9Sstevel@tonic-gate (void) strlcat(msgbuf, " stdout lost.", 1201*7c478bd9Sstevel@tonic-gate sizeof (msgbuf)); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate } else { 1204*7c478bd9Sstevel@tonic-gate if (eaccess(GRADES, 04) != -1) 1205*7c478bd9Sstevel@tonic-gate dqueue = fdgrade(); 1206*7c478bd9Sstevel@tonic-gate else 1207*7c478bd9Sstevel@tonic-gate dqueue = Grade; 1208*7c478bd9Sstevel@tonic-gate gename(CMDPRE, sysout, dqueue, tempname); 1209*7c478bd9Sstevel@tonic-gate (void) snprintf(cfile, sizeof (cfile), "%s/%s", 1210*7c478bd9Sstevel@tonic-gate WORKSPACE, tempname); 1211*7c478bd9Sstevel@tonic-gate fp = fdopen(ret = creat(cfile, CFILEMODE), "w"); 1212*7c478bd9Sstevel@tonic-gate ASSERT(ret >= 0 && fp != NULL, Ct_OPEN, cfile, errno); 1213*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "S %s %s %s -d %s 0666\n", 1214*7c478bd9Sstevel@tonic-gate BASENAME(dfile, '/'), fout, user, BASENAME(dfile, '/')); 1215*7c478bd9Sstevel@tonic-gate fclose(fp); 1216*7c478bd9Sstevel@tonic-gate (void) snprintf(sendsys, sizeof (sendsys), "%s/%c", sysout, 1217*7c478bd9Sstevel@tonic-gate dqueue); 1218*7c478bd9Sstevel@tonic-gate sendsys[MAXNAMESIZE-1] = '\0'; 1219*7c478bd9Sstevel@tonic-gate wfcommit(dfile, BASENAME(dfile, '/'), sendsys); 1220*7c478bd9Sstevel@tonic-gate wfcommit(cfile, BASENAME(cfile, '/'), sendsys); 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate if (!EQUALS(ferr, "/dev/null")) { 1224*7c478bd9Sstevel@tonic-gate /* 1225*7c478bd9Sstevel@tonic-gate * if stderr is on this machine copy output 1226*7c478bd9Sstevel@tonic-gate * there, otherwise spawn job to send to send 1227*7c478bd9Sstevel@tonic-gate * it elsewhere. 1228*7c478bd9Sstevel@tonic-gate */ 1229*7c478bd9Sstevel@tonic-gate if (EQUALS(syserr, Myname)) { 1230*7c478bd9Sstevel@tonic-gate errname = ferr; 1231*7c478bd9Sstevel@tonic-gate if ((xmv(errDfile, ferr)) != 0) { 1232*7c478bd9Sstevel@tonic-gate logent("FAILED", "COPY"); 1233*7c478bd9Sstevel@tonic-gate scWrite(); 1234*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf + strlen(msgbuf), 1235*7c478bd9Sstevel@tonic-gate (sizeof (msgbuf) - strlen(msgbuf)), 1236*7c478bd9Sstevel@tonic-gate "\nCould not move stderr to %s,", ferr); 1237*7c478bd9Sstevel@tonic-gate if (putinpub(ferr, errDfile, origuser) == 0) { 1238*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf+strlen(msgbuf), 1239*7c478bd9Sstevel@tonic-gate (sizeof (msgbuf) - strlen(msgbuf)), 1240*7c478bd9Sstevel@tonic-gate "\n\tstderr left in %s", ferr); 1241*7c478bd9Sstevel@tonic-gate } else { 1242*7c478bd9Sstevel@tonic-gate errname = errDfile; 1243*7c478bd9Sstevel@tonic-gate (void) strlcat(msgbuf, " stderr lost.", 1244*7c478bd9Sstevel@tonic-gate sizeof (msgbuf)); 1245*7c478bd9Sstevel@tonic-gate } 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate } else { 1248*7c478bd9Sstevel@tonic-gate if (eaccess(GRADES, 04) != -1) 1249*7c478bd9Sstevel@tonic-gate dqueue = fdgrade(); 1250*7c478bd9Sstevel@tonic-gate else 1251*7c478bd9Sstevel@tonic-gate dqueue = Grade; 1252*7c478bd9Sstevel@tonic-gate gename(CMDPRE, syserr, dqueue, tempname); 1253*7c478bd9Sstevel@tonic-gate (void) snprintf(cfile, sizeof (cfile), "%s/%s", 1254*7c478bd9Sstevel@tonic-gate WORKSPACE, tempname); 1255*7c478bd9Sstevel@tonic-gate fp = fdopen(ret = creat(cfile, CFILEMODE), "w"); 1256*7c478bd9Sstevel@tonic-gate ASSERT(ret >= 0 && fp != NULL, Ct_OPEN, cfile, errno); 1257*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "S %s %s %s -d %s 0666\n", 1258*7c478bd9Sstevel@tonic-gate BASENAME(errDfile, '/'), ferr, user, 1259*7c478bd9Sstevel@tonic-gate BASENAME(errDfile, '/')); 1260*7c478bd9Sstevel@tonic-gate fclose(fp); 1261*7c478bd9Sstevel@tonic-gate (void) snprintf(sendsys, sizeof (sendsys), "%s/%c", 1262*7c478bd9Sstevel@tonic-gate syserr, dqueue); 1263*7c478bd9Sstevel@tonic-gate sendsys[MAXNAMESIZE-1] = '\0'; 1264*7c478bd9Sstevel@tonic-gate wfcommit(errDfile, BASENAME(errDfile, '/'), sendsys); 1265*7c478bd9Sstevel@tonic-gate wfcommit(cfile, BASENAME(cfile, '/'), sendsys); 1266*7c478bd9Sstevel@tonic-gate } 1267*7c478bd9Sstevel@tonic-gate } else { 1268*7c478bd9Sstevel@tonic-gate /* 1269*7c478bd9Sstevel@tonic-gate * If we conditionally create stderr tempfile, we must 1270*7c478bd9Sstevel@tonic-gate * remove this unlink() since errDfile may REALLY be /dev/null 1271*7c478bd9Sstevel@tonic-gate */ 1272*7c478bd9Sstevel@tonic-gate unlink(errDfile); 1273*7c478bd9Sstevel@tonic-gate } 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate if (ret == 0) { 1276*7c478bd9Sstevel@tonic-gate if (send_zero) 1277*7c478bd9Sstevel@tonic-gate retosndr(user, Rmtname, "", incmd, msgbuf, ""); 1278*7c478bd9Sstevel@tonic-gate if (store_status) 1279*7c478bd9Sstevel@tonic-gate uucpst(Rmtname, _Sfile, "", incmd, msgbuf); 1280*7c478bd9Sstevel@tonic-gate } else { 1281*7c478bd9Sstevel@tonic-gate if (send_nonzero) 1282*7c478bd9Sstevel@tonic-gate retosndr(user, Rmtname, return_stdin ? fin : "", 1283*7c478bd9Sstevel@tonic-gate incmd, msgbuf, errname); 1284*7c478bd9Sstevel@tonic-gate if (store_status) 1285*7c478bd9Sstevel@tonic-gate uucpst(Rmtname, _Sfile, errname, incmd, msgbuf); 1286*7c478bd9Sstevel@tonic-gate } 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate rmfiles: 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* delete job files in spool directory */ 1291*7c478bd9Sstevel@tonic-gate xfp = fopen(_Xfile, "r"); 1292*7c478bd9Sstevel@tonic-gate ASSERT(xfp != NULL, Ct_OPEN, _Xfile, errno); 1293*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, xfp) != NULL) { 1294*7c478bd9Sstevel@tonic-gate if (buf[0] != X_RQDFILE) 1295*7c478bd9Sstevel@tonic-gate continue; 1296*7c478bd9Sstevel@tonic-gate (void) sscanf(&buf[1], "%63s", file); 1297*7c478bd9Sstevel@tonic-gate expfile(file); 1298*7c478bd9Sstevel@tonic-gate if (chkpth(file, CK_WRITE) != FAIL) 1299*7c478bd9Sstevel@tonic-gate (void) unlink(file); 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate (void) unlink(_Xfile); 1302*7c478bd9Sstevel@tonic-gate fclose(xfp); 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate } 1305