|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.