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