1*8207Smckusick static char sccsid[] = "@(#)sub.c 4.1 (Berkeley) 09/12/82"; 2*8207Smckusick 3*8207Smckusick /* 4*8207Smckusick sub.c 5*8207Smckusick 6*8207Smckusick support procedures 7*8207Smckusick 8*8207Smckusick the following procedures end up reading the passwd file 9*8207Smckusick or the passwdf file and are to be avoided. 10*8207Smckusick 11*8207Smckusick getpwuid(uid) 12*8207Smckusick getpwnam(sn) 13*8207Smckusick PwdCurrent() 14*8207Smckusick getenv("HOME") maybe if hget, hgethome don't work 15*8207Smckusick SnFromUid(uid) maybe if hashed passwd stuff doesn't work 16*8207Smckusick SnCurrent() maybe if getlogin fails calls SnFromUid(uid) 17*8207Smckusick getpwf() 18*8207Smckusick passwdent(uid,sn) 19*8207Smckusick */ 20*8207Smckusick 21*8207Smckusick # include "defs.h" 22*8207Smckusick # include "config.h" 23*8207Smckusick # ifndef V6 24*8207Smckusick # include <varargs.h> 25*8207Smckusick # endif V6 26*8207Smckusick 27*8207Smckusick /* global variables */ 28*8207Smckusick int debugflg = DBV; /* debug flag */ 29*8207Smckusick char local = LOCAL; /* the machine we're on */ 30*8207Smckusick struct userinfo status; 31*8207Smckusick 32*8207Smckusick char netcmd[] = NETCMD; 33*8207Smckusick char resfile[] = RESFILE; 34*8207Smckusick char senddir[] = SENDDIR; 35*8207Smckusick char Bsh[] = BINSH; 36*8207Smckusick 37*8207Smckusick char shomedir[100]; 38*8207Smckusick 39*8207Smckusick /* 40*8207Smckusick passwdent() 41*8207Smckusick 42*8207Smckusick Read the password file looking for current user's entry. 43*8207Smckusick Fill in the status structure. 44*8207Smckusick Has the (dangerous) side effect of giving a value to getenv("HOME"). 45*8207Smckusick */ 46*8207Smckusick passwdent() 47*8207Smckusick { 48*8207Smckusick register char *u; 49*8207Smckusick register struct passwd *pwd; 50*8207Smckusick #ifdef CRN 51*8207Smckusick register struct gecos *gcos; 52*8207Smckusick #endif 53*8207Smckusick pwd = PwdCurrent(); 54*8207Smckusick if(pwd == NULL){ 55*8207Smckusick err("Bad uid/username\n"); 56*8207Smckusick return; 57*8207Smckusick } 58*8207Smckusick strcpy(status.localname,pwd->pw_name); 59*8207Smckusick status.muid = guid(pwd->pw_uid,pwd->pw_gid); 60*8207Smckusick status.mgid = pwd->pw_gid; 61*8207Smckusick #ifdef CRN 62*8207Smckusick if( (gcos=pwgecos( pwd->pw_gecos) ) == NULL ) 63*8207Smckusick strcpy( status.jobno, MAGICCRN ); 64*8207Smckusick else { 65*8207Smckusick if( debugflg ) 66*8207Smckusick debug( "crn found = %s\n", gcos->gc_crn ); 67*8207Smckusick if( isalpha( gcos->gc_crn[0] ) || 68*8207Smckusick isdigit( gcos->gc_crn[0] ) ) 69*8207Smckusick strcpy( status.jobno, gcos->gc_crn ); 70*8207Smckusick else 71*8207Smckusick strcpy( status.jobno, MAGICCRN ); 72*8207Smckusick } 73*8207Smckusick #else 74*8207Smckusick strcpy( status.jobno, "XYZZ" ); 75*8207Smckusick #endif 76*8207Smckusick strcpy(status.dir,pwd->pw_dir); 77*8207Smckusick strcpy(shomedir,pwd->pw_dir); /* side effect */ 78*8207Smckusick u = pwd->pw_shell; 79*8207Smckusick if(u[0] == 0 || strcmp(u,"/bin/sbash") == 0)u= Bsh; 80*8207Smckusick strcpy(status.loginshell,u); 81*8207Smckusick } 82*8207Smckusick /* 83*8207Smckusick promptlogin(mchto) 84*8207Smckusick 85*8207Smckusick ask user for login and passwd on mchto. 86*8207Smckusick make sure status.localname has a value before calling 87*8207Smckusick this. One way is to call passwdent(). 88*8207Smckusick */ 89*8207Smckusick promptlogin(mchto) 90*8207Smckusick char mchto; 91*8207Smckusick { 92*8207Smckusick char buf[BUFSIZ], mch; 93*8207Smckusick FILE *wf; 94*8207Smckusick int c; 95*8207Smckusick if(status.mpasswd[0] == 0 || status.login[0] == 0 || status.force){ 96*8207Smckusick wf = fopen("/dev/tty","r"); 97*8207Smckusick if(wf != NULL){ 98*8207Smckusick if(status.login[0]==0 || status.force){ 99*8207Smckusick fprintf(stderr,"Name (%s:%s): ",longname(mchto), 100*8207Smckusick status.localname); 101*8207Smckusick if(fgets(buf, BUFSIZ, wf) != buf){ 102*8207Smckusick perror("fgets"); 103*8207Smckusick exit(EX_OSERR); 104*8207Smckusick } 105*8207Smckusick c = strlen(buf); 106*8207Smckusick buf[c > 0 ? c-1 : 0] = 0; 107*8207Smckusick if(c > 10){ 108*8207Smckusick err("Login name too long.\n"); 109*8207Smckusick exit(EX_USAGE); 110*8207Smckusick } 111*8207Smckusick if(FMemberSCh(buf,' ')){ 112*8207Smckusick err("Login names don't have blanks in them.\n"); 113*8207Smckusick exit(EX_USAGE); 114*8207Smckusick } 115*8207Smckusick if(buf[0] == 0)strcpy(buf,status.localname); 116*8207Smckusick mch = MchSFromAddr(status.login,buf); 117*8207Smckusick if(mch != local && mch != mchto){ 118*8207Smckusick err( 119*8207Smckusick "Must specify login name on %s machine\n", 120*8207Smckusick longname(mchto)); 121*8207Smckusick exit(EX_USAGE); 122*8207Smckusick } 123*8207Smckusick } 124*8207Smckusick if(strcmp(status.login,"network") != 0 125*8207Smckusick && (status.mpasswd[0]== 0 || status.force)){ 126*8207Smckusick sprintf(buf,"Password (%s:%s):", 127*8207Smckusick longname(mchto), status.login); 128*8207Smckusick strcpy(status.mpasswd,getpass(buf)); 129*8207Smckusick } 130*8207Smckusick fclose(wf); 131*8207Smckusick } 132*8207Smckusick } 133*8207Smckusick if(status.login[0] == 0) strcpy(status.login,status.localname); 134*8207Smckusick if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\""); 135*8207Smckusick status.force = 0; 136*8207Smckusick } 137*8207Smckusick 138*8207Smckusick #define tst(a,b) (*mode == 'r'? (b) : (a)) 139*8207Smckusick #define RDR 0 140*8207Smckusick #define WTR 1 141*8207Smckusick static int popen_pid[20]; 142*8207Smckusick 143*8207Smckusick /* return a file descriptor suitable for writing, send to 144*8207Smckusick user toaddress from fromaddress, 145*8207Smckusick if cautious != 0 then don't do any forwarding 146*8207Smckusick hopcnt is passed thru the mail program. 147*8207Smckusick normal value is 0 148*8207Smckusick */ 149*8207Smckusick FILE * 150*8207Smckusick mailopen(toaddress, fromaddress, cautious, hopcnt) 151*8207Smckusick char *toaddress, *fromaddress; 152*8207Smckusick int cautious, hopcnt; 153*8207Smckusick { 154*8207Smckusick char cmd[100]; 155*8207Smckusick char *mode = "w"; 156*8207Smckusick int p[2]; 157*8207Smckusick register myside, hisside, pid; 158*8207Smckusick char shopcnt[20]; 159*8207Smckusick 160*8207Smckusick if(pipe(p) < 0) 161*8207Smckusick return NULL; 162*8207Smckusick myside = tst(p[WTR], p[RDR]); 163*8207Smckusick hisside = tst(p[RDR], p[WTR]); 164*8207Smckusick while((pid = fork()) == -1)sleep(2); 165*8207Smckusick if(pid == 0) { 166*8207Smckusick /* myside and hisside reverse roles in child */ 167*8207Smckusick close(myside); 168*8207Smckusick /* 169*8207Smckusick dup2(hisside, tst(0, 1)); 170*8207Smckusick */ 171*8207Smckusick close(0); 172*8207Smckusick dup(hisside); 173*8207Smckusick close(hisside); 174*8207Smckusick sprintf(shopcnt,"%d",hopcnt); 175*8207Smckusick if(fromaddress != NULL){ 176*8207Smckusick /* by convention, MAILFWD1 may forward this mail 177*8207Smckusick and response messages shouldn't be forwarded */ 178*8207Smckusick if(!cautious && !FMemberSCh(toaddress,'/')){ 179*8207Smckusick # ifdef DELIVERM 180*8207Smckusick mexecl("/etc/delivermail", 181*8207Smckusick "delivermail", "-ee", "-r", fromaddress, 182*8207Smckusick "-h",shopcnt, toaddress, 0); 183*8207Smckusick # endif 184*8207Smckusick mexecl(MAILFWD1, "mail","-r",fromaddress, 185*8207Smckusick "-h",shopcnt,toaddress,0); 186*8207Smckusick } 187*8207Smckusick mexecl(SYSMAIL2, "mail","-d","-r",fromaddress, 188*8207Smckusick "-h", shopcnt,toaddress,0); 189*8207Smckusick } else { 190*8207Smckusick if(!cautious && !FMemberSCh(toaddress,'/')){ 191*8207Smckusick # ifdef DELIVERM 192*8207Smckusick mexecl("/etc/delivermail", 193*8207Smckusick "delivermail", "-ee", "-h", shopcnt, 194*8207Smckusick toaddress, 0); 195*8207Smckusick # endif 196*8207Smckusick mexecl(MAILFWD1, "mail","-h", shopcnt, 197*8207Smckusick toaddress,0); 198*8207Smckusick } 199*8207Smckusick mexecl(SYSMAIL2, "mail","-d","-h", shopcnt,toaddress,0); 200*8207Smckusick } 201*8207Smckusick perror(SYSMAIL2); 202*8207Smckusick exit(EX_UNAVAILABLE); 203*8207Smckusick } 204*8207Smckusick if(pid == -1) 205*8207Smckusick return NULL; 206*8207Smckusick popen_pid[myside] = pid; 207*8207Smckusick close(hisside); 208*8207Smckusick return(fdopen(myside, mode)); 209*8207Smckusick } 210*8207Smckusick 211*8207Smckusick mailclose(ptr) 212*8207Smckusick FILE *ptr; 213*8207Smckusick { 214*8207Smckusick register f, r, (*hstat)(), (*istat)(), (*qstat)(); 215*8207Smckusick int status; 216*8207Smckusick 217*8207Smckusick f = fileno(ptr); 218*8207Smckusick fclose(ptr); 219*8207Smckusick istat = signal(SIGINT, SIG_IGN); 220*8207Smckusick qstat = signal(SIGQUIT, SIG_IGN); 221*8207Smckusick hstat = signal(SIGHUP, SIG_IGN); 222*8207Smckusick while((r = wait(&status)) != popen_pid[f] && r != -1) 223*8207Smckusick ; 224*8207Smckusick if(r == -1) 225*8207Smckusick status = -1; 226*8207Smckusick signal(SIGINT, istat); 227*8207Smckusick signal(SIGQUIT, qstat); 228*8207Smckusick signal(SIGHUP, hstat); 229*8207Smckusick return(status); 230*8207Smckusick } 231*8207Smckusick 232*8207Smckusick /* 233*8207Smckusick ch means 'a'-'z', inx in 0..25 234*8207Smckusick ch means '0'-'9', inx in 26..35 235*8207Smckusick */ 236*8207Smckusick chtoinx(ch) { 237*8207Smckusick if('a' <= ch && ch <= 'z') 238*8207Smckusick return(ch - 'a'); 239*8207Smckusick if('0' <= ch && ch <= '9') 240*8207Smckusick return((ch - '0') + 26); 241*8207Smckusick err("bad ch"); 242*8207Smckusick } 243*8207Smckusick 244*8207Smckusick /* 245*8207Smckusick inx is 0..25 means 'a'-'z' 246*8207Smckusick inx is 26..35 means '0'-'9' 247*8207Smckusick */ 248*8207Smckusick inxtoch(inx) { 249*8207Smckusick if(0 <= inx && inx <= 25) 250*8207Smckusick return(inx + 'a'); 251*8207Smckusick if(26 <= inx && inx <= 35) 252*8207Smckusick return('0' + (inx - 26)); 253*8207Smckusick err("bad ch"); 254*8207Smckusick } 255*8207Smckusick 256*8207Smckusick /* determine through machine */ 257*8207Smckusick gothru(from,to){ 258*8207Smckusick register int i; 259*8207Smckusick switch(from){ 260*8207Smckusick # ifdef RAND 261*8207Smckusick case 'a': i = configA[chtoinx(to)]; break; 262*8207Smckusick case 'b': i = configB[chtoinx(to)]; break; 263*8207Smckusick case 'c': i = configC[chtoinx(to)]; break; 264*8207Smckusick # endif 265*8207Smckusick # ifdef NOSC 266*8207Smckusick case 'a': i = configA[chtoinx(to)]; break; 267*8207Smckusick case 'c': i = configC[chtoinx(to)]; break; 268*8207Smckusick case 'm': i = configM[chtoinx(to)]; break; 269*8207Smckusick # endif 270*8207Smckusick # ifdef BERKELEY 271*8207Smckusick /* for Berkeley */ 272*8207Smckusick case 'a': i = configA[chtoinx(to)]; break; 273*8207Smckusick case 'b': i = configB[chtoinx(to)]; break; 274*8207Smckusick case 'c': i = configC[chtoinx(to)]; break; 275*8207Smckusick case 'd': i = configD[chtoinx(to)]; break; 276*8207Smckusick case 'e': i = configE[chtoinx(to)]; break; 277*8207Smckusick case 'f': i = configF[chtoinx(to)]; break; 278*8207Smckusick case 'g': i = configG[chtoinx(to)]; break; 279*8207Smckusick case 'i': i = configI[chtoinx(to)]; break; 280*8207Smckusick case 'j': i = configJ[chtoinx(to)]; break; 281*8207Smckusick case 'k': i = configK[chtoinx(to)]; break; 282*8207Smckusick case 'l': i = configL[chtoinx(to)]; break; 283*8207Smckusick case 'm': i = configM[chtoinx(to)]; break; 284*8207Smckusick case 'n': i = configN[chtoinx(to)]; break; 285*8207Smckusick case 'o': i = configO[chtoinx(to)]; break; 286*8207Smckusick case 'p': i = configP[chtoinx(to)]; break; 287*8207Smckusick case 'q': i = configQ[chtoinx(to)]; break; 288*8207Smckusick case 'r': i = configR[chtoinx(to)]; break; 289*8207Smckusick case 's': i = configS[chtoinx(to)]; break; 290*8207Smckusick case 't': i = configT[chtoinx(to)]; break; 291*8207Smckusick case 'v': i = configV[chtoinx(to)]; break; 292*8207Smckusick case 'x': i = configX[chtoinx(to)]; break; 293*8207Smckusick case 'y': i = configY[chtoinx(to)]; break; 294*8207Smckusick case 'z': i = configZ[chtoinx(to)]; break; 295*8207Smckusick # endif 296*8207Smckusick default: i = 0; break; 297*8207Smckusick } 298*8207Smckusick return(i); 299*8207Smckusick } 300*8207Smckusick 301*8207Smckusick # define NPARMS 20 302*8207Smckusick /* prints out commands before executing them */ 303*8207Smckusick /*VARARGS0*/ 304*8207Smckusick mexecl(va_alist) 305*8207Smckusick va_dcl 306*8207Smckusick { 307*8207Smckusick char *arr[NPARMS], *file, *f; 308*8207Smckusick va_list ap; 309*8207Smckusick register int i; 310*8207Smckusick va_start(ap); 311*8207Smckusick file = va_arg(ap, char *); 312*8207Smckusick i = 0; 313*8207Smckusick while(f = va_arg(ap, char *)){ 314*8207Smckusick if(i >= NPARMS){ 315*8207Smckusick err("too many args"); 316*8207Smckusick arr[NPARMS-1] = NULL; 317*8207Smckusick break; 318*8207Smckusick } 319*8207Smckusick if(debugflg) err("'%s' ",f); 320*8207Smckusick arr[i++] = f; 321*8207Smckusick } 322*8207Smckusick arr[i] = NULL; 323*8207Smckusick va_end(ap); 324*8207Smckusick if(debugflg) putc('\n',stderr); 325*8207Smckusick execv(file, arr); 326*8207Smckusick } 327*8207Smckusick 328*8207Smckusick /* prints out commands before executing them */ 329*8207Smckusick mexecv(s,p) 330*8207Smckusick register char *s, **p;{ 331*8207Smckusick register int i; 332*8207Smckusick if(debugflg){ 333*8207Smckusick err("'%s' ",s); 334*8207Smckusick for(i=0; p[i]; i++)err("'%s' ",p[i]); 335*8207Smckusick putc('\n',stderr); 336*8207Smckusick } 337*8207Smckusick execv(s,p); 338*8207Smckusick } 339*8207Smckusick 340*8207Smckusick /*VARARGS0*/ 341*8207Smckusick /* fills in -l - -p from commands like rcp */ 342*8207Smckusick /* must be called with at least two arguments */ 343*8207Smckusick kexecl(va_alist) 344*8207Smckusick va_dcl 345*8207Smckusick { 346*8207Smckusick char *a[NPARMS], i = 1, *file; 347*8207Smckusick va_list ap; 348*8207Smckusick va_start(ap); 349*8207Smckusick file = va_arg(ap, char *); 350*8207Smckusick a[0] = va_arg(ap, char *); 351*8207Smckusick if(status.login[0]){ 352*8207Smckusick a[i++] = "-l"; 353*8207Smckusick a[i++] = status.login; 354*8207Smckusick } 355*8207Smckusick if(status.mpasswd[0]){ 356*8207Smckusick a[i++] = "-p"; 357*8207Smckusick a[i++] = status.mpasswd; 358*8207Smckusick } 359*8207Smckusick if(status.nonotify)a[i++] = "-b"; 360*8207Smckusick if(status.force) a[i++] = "-f"; 361*8207Smckusick if(status.quiet) a[i++] = "-q"; 362*8207Smckusick if(status.nowrite) a[i++] = "-n"; 363*8207Smckusick while (a[i++] = va_arg(ap, char *)){ 364*8207Smckusick if(i >= NPARMS){ 365*8207Smckusick err("too many args"); 366*8207Smckusick a[NPARMS-1] = NULL; 367*8207Smckusick break; 368*8207Smckusick } 369*8207Smckusick }; 370*8207Smckusick mexecv(file, a); 371*8207Smckusick } 372*8207Smckusick 373*8207Smckusick /* 374*8207Smckusick MchSFromAddr(sn,addr) 375*8207Smckusick 376*8207Smckusick take an address of the form "mach:username" 377*8207Smckusick and return mch as the 1 char code of "mach" and 378*8207Smckusick in sn put "username". 379*8207Smckusick If addr has no colon in it, return mch==local, sn==addr. 380*8207Smckusick Return 0 for mch if host unknown. 381*8207Smckusick */ 382*8207Smckusick MchSFromAddr(sn,addr) 383*8207Smckusick char *sn, *addr; 384*8207Smckusick { 385*8207Smckusick char fcolon = 0, *s, mch, stemp[BUFSIZ]; 386*8207Smckusick 387*8207Smckusick /* assume addr is a local address */ 388*8207Smckusick 389*8207Smckusick strcpy(stemp,addr); 390*8207Smckusick s = stemp; 391*8207Smckusick while(*s){ 392*8207Smckusick if(*s == ':'){ 393*8207Smckusick fcolon = 1; 394*8207Smckusick *s++ = 0; 395*8207Smckusick break; 396*8207Smckusick } 397*8207Smckusick s++; 398*8207Smckusick } 399*8207Smckusick if(fcolon != 1){ 400*8207Smckusick /* sn better be the right size for addr */ 401*8207Smckusick mch = local; 402*8207Smckusick strcpy(sn,addr); 403*8207Smckusick return(mch); 404*8207Smckusick } 405*8207Smckusick 406*8207Smckusick /* addr has a colon in it, s pts to name */ 407*8207Smckusick mch = lookup(stemp); 408*8207Smckusick strcpy(sn,s); 409*8207Smckusick return(mch); 410*8207Smckusick } 411*8207Smckusick 412*8207Smckusick 413*8207Smckusick /* returns a single character for machine S */ 414*8207Smckusick /* returns 0 for unknown host */ 415*8207Smckusick lookup(s) 416*8207Smckusick register char *s; { 417*8207Smckusick register struct tt *t; 418*8207Smckusick if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s); 419*8207Smckusick for(t = table; t->bigname; t++) 420*8207Smckusick if(streql(s,t->bigname) == 0)return(t->lname); 421*8207Smckusick return(0); 422*8207Smckusick } 423*8207Smckusick 424*8207Smckusick /* returns a long name (string) for single character machine c */ 425*8207Smckusick char *longname(c) 426*8207Smckusick register char c; 427*8207Smckusick { 428*8207Smckusick register struct tt *t; 429*8207Smckusick if(c == 0)return("UNKNOWN"); 430*8207Smckusick for(t = table; t->bigname; t++) 431*8207Smckusick if(c == t->lname)return(t->bigname); 432*8207Smckusick return("UNKNOWN"); 433*8207Smckusick } 434*8207Smckusick /* 435*8207Smckusick FMemberSCh(s,ch) 436*8207Smckusick 437*8207Smckusick return 1 if ch is a character in string s. 438*8207Smckusick 0 otherwise. 439*8207Smckusick */ 440*8207Smckusick FMemberSCh(s,ch) 441*8207Smckusick register char *s, ch; 442*8207Smckusick { 443*8207Smckusick while(*s)if(*s++ == ch)return(1); 444*8207Smckusick return(0); 445*8207Smckusick } 446*8207Smckusick 447*8207Smckusick /* return a static string with the form "X hrs X mins X secs" */ 448*8207Smckusick /* t is # of secs */ 449*8207Smckusick char *comptime(t) 450*8207Smckusick long t; { 451*8207Smckusick static char str[30]; 452*8207Smckusick char buf[20]; 453*8207Smckusick long w; 454*8207Smckusick str[0] = 0; 455*8207Smckusick w = t/3600L; 456*8207Smckusick if(w > 0L){ 457*8207Smckusick sprintf(buf,"%ld hr ",w); 458*8207Smckusick strcat(str,buf); 459*8207Smckusick } 460*8207Smckusick t = t % 3600L; 461*8207Smckusick w = t/60L; 462*8207Smckusick if(w > 0L){ 463*8207Smckusick sprintf(buf,"%ld min ",w); 464*8207Smckusick strcat(str,buf); 465*8207Smckusick } 466*8207Smckusick t = t % 60L; 467*8207Smckusick sprintf(buf,"%ld sec",t); 468*8207Smckusick strcat(str,buf); 469*8207Smckusick return(str); 470*8207Smckusick } 471*8207Smckusick /* 472*8207Smckusick parseparmlist(string) 473*8207Smckusick 474*8207Smckusick parses variable parameter lists in string, 475*8207Smckusick as defined in genparmlist in net.c 476*8207Smckusick */ 477*8207Smckusick parseparmlist(parmlist) 478*8207Smckusick char *parmlist; 479*8207Smckusick { 480*8207Smckusick while(*parmlist && *parmlist != '(')parmlist++; 481*8207Smckusick } 482*8207Smckusick 483*8207Smckusick /* just like strcmp except upper- and lower-case are ignored */ 484*8207Smckusick streql(s1,s2) 485*8207Smckusick char *s1, *s2; { 486*8207Smckusick char a,b; 487*8207Smckusick while(*s1 && *s2){ 488*8207Smckusick a = isupper(*s1) ? tolower(*s1) : *s1; 489*8207Smckusick b = isupper(*s2) ? tolower(*s2) : *s2; 490*8207Smckusick if(a < b)return(-1); 491*8207Smckusick if(a > b)return(1); 492*8207Smckusick s1++, s2++; 493*8207Smckusick } 494*8207Smckusick if(*s2)return(-1); 495*8207Smckusick if(*s1)return(1); 496*8207Smckusick return(0); 497*8207Smckusick } 498*8207Smckusick /* VARARGS0 */ 499*8207Smckusick err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) { 500*8207Smckusick fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r); 501*8207Smckusick } 502