1: static char sccsid[] = "@(#)mach.c 4.2 (Berkeley) 10/2/82"; 2: 3: /* sccs id variable */ 4: static char *mach_sid = "@(#)mach.c 1.6"; 5: /* 6: 7: This file is meant to handle all the machine 8: dependencies in the network code. 9: Everything is conditionally compiled. 10: 11: It can be uses w/o network stuff to simulate 12: v7 for other programs, too. 13: */ 14: # include <stdio.h> 15: # include "mach.h" 16: 17: char shomedir[100]; 18: 19: int debugflg; 20: 21: /* the CC and SRC machines have the submit() call */ 22: # ifndef CC 23: # ifndef SRC 24: submit(a) {} 25: # endif 26: # endif 27: 28: # ifdef FUID 29: setgid() {}; 30: # endif 31: 32: /* 33: Set the owner uid/gid of a file. 34: On v7, this is done by the chown command 35: with three args - (file, uid, gid). 36: On Vanilla V6 this is done using the 37: top byte of the second parameter as the gid byte. 38: On Berkeley Funny uids on V6, no gid is specified. 39: */ 40: mchown(sfn,uid,gid) 41: char *sfn; 42: int uid; 43: int gid; 44: { 45: # ifndef V6 46: chown(sfn,uid,gid); 47: # else 48: # ifndef FUID 49: uid = uidmask(uid); 50: uid = ((gid&0377) << 8) | (uid & 0377); 51: # endif 52: chown(sfn,uid); 53: if(debugflg) 54: fprintf(stderr, "chown %s to %d(%o)\n",sfn,uid,uid); 55: # endif 56: } 57: 58: 59: /* 60: SnFromuid(uid) 61: 62: The login name corresponding to uid. 63: Reads the password file. 64: Successive calls overwrite the static string returned. 65: Returns NULL if error. 66: */ 67: char *SnFromUid(uid) 68: register int uid; 69: { 70: register struct passwd *pwd; 71: static int ouid = -1; 72: static char oresult[20] = ""; 73: uid = uidmask(uid); 74: if(uid == ouid) 75: return(oresult); 76: # ifdef HPASSWD 77: if(getname(uid,oresult) == 0){ 78: ouid = uid; 79: return(oresult); 80: } 81: # endif 82: pwd = getpwuid(uid); 83: if(pwd != NULL){ 84: strcpy(oresult,pwd->pw_name); 85: ouid = uid; 86: return(oresult); 87: } 88: return(NULL); 89: } 90: uidfromsn(sn) 91: register char *sn; 92: { 93: register int him = -1; 94: register struct passwd *pwd; 95: # ifdef HPASSWD 96: him = getuserid(sn); 97: # endif 98: if(him == -1){ 99: pwd = getpwnam(sn); 100: if(pwd != NULL)him = guid(pwd->pw_uid,pwd->pw_gid); 101: } 102: return(him); 103: } 104: 105: /* handle the regular unix and local mods difference for user id's */ 106: /* this call returns the 1 word uid = to what getuid will return */ 107: guid(uid,gid){ 108: uid = uidmask(uid); 109: # ifdef FUID 110: return((uid & 0377) | (gid << 8)); 111: # else 112: return(uid); 113: # endif 114: } 115: 116: # ifdef OLDTTY 117: isatty(i){ 118: return(ttyn(i) != 'x'); 119: } 120: char *ttyname(i){ /* return NULL if not TTY */ 121: char c; 122: static char ttystr[] = "/dev/ttyx"; 123: c = ttyn(i); 124: ttystr[8] = c; 125: return(c == 'x' ? NULL : ttystr); 126: } 127: # endif 128: 129: # ifdef CCTTY 130: # undef ttyname() 131: char *myttyname(i){ /* return NULL for non tty */ 132: static char s[15],*p; 133: p = ttyname(i); 134: if(p == NULL)return(NULL); 135: strcpy(s,"/dev/"); 136: strcat(s,p); 137: return(s); 138: } 139: # define ttyname(S) myttyname(S) 140: # endif 141: 142: /* expand control chars in string s */ 143: expandcc(s) 144: register char *s; { 145: char stemp[100]; 146: register char *p; 147: 148: if(s == NULL)return; 149: strcpy(stemp,s); 150: p = stemp; 151: while(*p){ 152: if(!isprint(*p)){ 153: *s++ = '^'; 154: *s++ = *p++ + 0140; 155: } 156: else *s++ = *p++; 157: } 158: } 159: 160: /* get passwd from passwdf */ 161: getpwdf(pwd) 162: struct passwd *pwd; { 163: # ifdef PASSWDF 164: # ifndef TESTING 165: register char *p, *q; 166: char buf1[BUFSIZ], found; 167: FILE *pw; 168: debug("reading passwdf\n"); 169: pwd->pw_passwd[0] = 0; 170: pw = fopen("/etc/passwdf","r"); 171: if(pw == NULL) return; 172: found = 0; 173: while(fgets(buf1,BUFSIZ,pw) != NULL){ 174: for(p=buf1; *p && *p != ':'; p++); 175: *p = 0; 176: if(strcmp(buf1,pwd->pw_name) == 0){ 177: found = 1; 178: break; 179: } 180: } 181: fclose(pw); 182: if(!found)return; 183: q = ++p; 184: for(;*p && *p != ':';p++); 185: *p = 0; 186: strcpy(pwd->pw_passwd,q); 187: /* 188: debug("user %s passwd %s %s",pwd->pw_name,pwd->pw_passwd); 189: */ 190: # endif 191: # endif 192: } 193: /* 194: getutmp() 195: return a pointer to the system utmp structure associated with 196: terminal sttyname, e.g. "/dev/tty3" 197: Is version independent-- will work on v6 systems 198: return NULL if error 199: */ 200: struct utmp *getutmp(sttyname) 201: char *sttyname; 202: { 203: # ifdef OLDTTY 204: struct v6utmp { 205: char v6ut_name[8]; 206: char v6ut_tty; 207: char v6ut_fill; 208: long v6ut_time; 209: int v6ut_fl1; 210: } v6utmpstr; 211: # endif 212: static struct utmp utmpstr; 213: FILE *fdutmp; 214: 215: debug("reading utmp\n"); 216: if(sttyname == NULL || sttyname[0] == 0)return(NULL); 217: 218: fdutmp = fopen("/etc/utmp","r"); 219: if(fdutmp == NULL)return(NULL); 220: 221: # ifndef OLDTTY 222: while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr) 223: if(strcmp(utmpstr.ut_line,sttyname+5) == 0){ 224: fclose(fdutmp); 225: return(&utmpstr); 226: } 227: # else 228: while(fread(&v6utmpstr,1,sizeof v6utmpstr,fdutmp) == sizeof v6utmpstr) 229: if(v6utmpstr.v6ut_tty == sttyname[8]){ 230: strcpy(utmpstr.ut_name,v6utmpstr.v6ut_name); 231: strcpy(utmpstr.ut_line,"ttyx"); 232: utmpstr.ut_line[3] = v6utmpstr.v6ut_tty; 233: utmpstr.ut_time = v6utmpstr.v6ut_time; 234: fclose(fdutmp); 235: return(&utmpstr); 236: } 237: # endif 238: fclose(fdutmp); 239: return(NULL); 240: } 241: 242: /* 243: these are all the v7 routines not available on the v6 machines 244: */ 245: 246: # ifdef V6 247: 248: char **environ; /* global environment pointer */ 249: 250: ioctl(a,b,c){ 251: return(0); /* always succeeds */ 252: } 253: long atol(s) 254: register char *s; { 255: long i = 0; 256: while('0' <= *s && *s <= '9') 257: i = i * 10 + (*s++ - '0'); 258: return(i); 259: } 260: long gettime(){ 261: long tt; 262: time(&tt); 263: return(tt); 264: } 265: long getsize(str) 266: struct stat *str; { 267: long wk; 268: wk = ((long)(str->st_size0 & 0377)) << 16; 269: wk += (long)((unsigned)str->st_size1); 270: return(wk); 271: } 272: /* 273: getenv("HOME") 274: 275: always returns home directory. 276: returns NULL if there is error. 277: */ 278: char *getenv(){ 279: register char *shdir = NULL; 280: register struct passwd *pwd; 281: register int it; 282: if(shomedir[0] != 0)return(shomedir); 283: # ifdef BERKELEY 284: /* hget only works on Berkeley machines */ 285: it = ttyn(2); 286: # ifdef OLDTTY 287: if(it == 'x')it = ttyn(1); 288: if(it == 'x')it = ttyn(0); 289: if(it != 'x' && hget(it) == 0)shdir = hgethome(); 290: # endif 291: # ifdef CCTTY 292: if(it == -1)it = ttyn(1); 293: if(it == -1)it = ttyn(0); 294: if(it != -1 && hget(it) == 0)shdir = hgethome(); 295: # endif 296: # endif 297: if(shdir == NULL){ 298: pwd = PwdCurrent(); 299: if(pwd != NULL)shdir = pwd->pw_dir; 300: } 301: if(shdir != NULL)strcpy(shomedir,shdir); 302: return(shdir); 303: } 304: 305: /* doesn't handle split passwd files */ 306: struct passwd * 307: getpwuid(uid) 308: register uid; 309: { 310: register struct passwd *p; 311: struct passwd *getpwent(); 312: 313: uid = uidmask(uid); 314: setpwent(); 315: while( (p = getpwent()) && guid(p->pw_uid,p->pw_gid) != uid ); 316: endpwent(); 317: return(p); 318: } 319: 320: static char PASSWD[] = "/etc/passwd"; 321: static char EMPTY[] = ""; 322: static FILE *pwf = NULL; 323: static char line[BUFSIZ+1]; 324: static struct passwd passwd; 325: 326: setpwent() 327: { 328: debug("reading passwd\n"); 329: if( pwf == NULL ) 330: pwf = fopen( PASSWD, "r" ); 331: else 332: rewind( pwf ); 333: } 334: 335: endpwent() 336: { 337: if( pwf != NULL ){ 338: fclose( pwf ); 339: pwf = NULL; 340: } 341: } 342: 343: static char * 344: pwskip(p) 345: register char *p; 346: { 347: while( *p && *p != ':' ) 348: ++p; 349: if( *p ) *p++ = 0; 350: return(p); 351: } 352: 353: struct passwd * 354: getpwent() 355: { 356: register char *p; 357: 358: if (pwf == NULL) { 359: if( (pwf = fopen( PASSWD, "r" )) == NULL ) 360: return(0); 361: } 362: p = fgets(line, BUFSIZ, pwf); 363: if (p==NULL) 364: return(0); 365: passwd.pw_name = p; 366: p = pwskip(p); 367: passwd.pw_passwd = p; 368: p = pwskip(p); 369: passwd.pw_uid = atoi(p); 370: passwd.pw_uid = uidmask(passwd.pw_uid); 371: p = pwskip(p); 372: passwd.pw_gid = atoi(p); 373: passwd.pw_quota = 0; 374: passwd.pw_comment = EMPTY; 375: p = pwskip(p); 376: passwd.pw_gecos = p; 377: p = pwskip(p); 378: passwd.pw_dir = p; 379: p = pwskip(p); 380: passwd.pw_shell = p; 381: while(*p && *p != '\n') p++; 382: *p = '\0'; 383: return(&passwd); 384: } 385: 386: struct passwd * 387: getpwnam(name) 388: char *name; 389: { 390: register struct passwd *p; 391: struct passwd *getpwent(); 392: 393: setpwent(); 394: while( (p = getpwent()) && strcmp(name,p->pw_name) ); 395: endpwent(); 396: return(p); 397: } 398: /* 399: getlogin() 400: 401: Return current user name by looking at /etc/utmp (calls getutmp()). 402: Returns NULL if not found. 403: */ 404: char *getlogin() 405: { 406: register struct utmp *putmp; 407: register char *s; 408: char sttyname[30]; 409: 410: if(isatty(2))strcpy(sttyname,ttyname(2)); 411: else if(isatty(0))strcpy(sttyname,ttyname(0)); 412: else if(isatty(1))strcpy(sttyname,ttyname(1)); 413: else return(NULL); 414: 415: putmp = getutmp(sttyname); 416: if(putmp == NULL)return(NULL); 417: s = putmp->ut_name; 418: while(*s != 0 && *s != ' ')s++; 419: *s = 0; 420: if(putmp->ut_name[0] == 0)return(NULL); 421: return(putmp->ut_name); 422: } 423: /* 424: * Unix routine to do an "fopen" on file descriptor 425: * The mode has to be repeated because you can't query its 426: * status 427: */ 428: 429: FILE * 430: fdopen(fd, mode) 431: register char *mode; 432: { 433: extern int errno; 434: register FILE *iop; 435: extern FILE *_lastbuf; 436: 437: for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++) 438: if (iop >= _lastbuf) 439: return(NULL); 440: iop->_cnt = 0; 441: iop->_file = fd; 442: if (*mode != 'r') { 443: iop->_flag |= _IOWRT; 444: if (*mode == 'a') 445: lseek(fd, 0L, 2); 446: } else 447: iop->_flag |= _IOREAD; 448: return(iop); 449: } 450: system(s) 451: char *s; 452: { 453: int status, pid, w; 454: register int (*istat)(), (*qstat)(); 455: 456: while((pid = fork()) == -1)sleep(2); 457: if (pid == 0) { 458: execl("/bin/sh", "sh", "-c", s, 0); 459: _exit(127); 460: } 461: istat = signal(SIGINT, SIG_IGN); 462: qstat = signal(SIGQUIT, SIG_IGN); 463: while ((w = wait(&status)) != pid && w != -1) 464: ; 465: if (w == -1) 466: status = -1; 467: signal(SIGINT, istat); 468: signal(SIGQUIT, qstat); 469: return(status); 470: } 471: 472: char * 473: getpass(prompt) 474: char *prompt; 475: { 476: struct sgttyb ttyb; 477: int flags; 478: register char *p; 479: register c; 480: FILE *fi = NULL; 481: static char pbuf[9]; 482: int (*signal())(); 483: int (*sig)(); 484: 485: /* modified because Cory needs super-user to stty /dev/tty */ 486: if ((fi = fopen("/dev/tty", "r")) == NULL) 487: fi = stdin; 488: else 489: setbuf(fi, (char *)NULL); 490: if(gtty(fileno(fi),&ttyb) < 0){ 491: pbuf[0] = 0; 492: return(pbuf); 493: } 494: /* 495: if(gtty(0,&ttyb) >= 0)fi = stdin; 496: else if(gtty(2,&ttyb) >= 0)fi = stderr; 497: else { 498: pbuf[0] = 0; 499: return(pbuf); 500: } 501: */ 502: sig = signal(SIGINT, SIG_IGN); 503: flags = ttyb.sg_flags; 504: ttyb.sg_flags &= ~ECHO; 505: if(stty(fileno(fi), &ttyb) < 0) perror("stty:"); 506: fprintf(stderr, prompt); 507: for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { 508: if (p < &pbuf[8]) 509: *p++ = c; 510: } 511: *p = '\0'; 512: fprintf(stderr, "\n"); 513: ttyb.sg_flags = flags; 514: stty(fileno(fi), &ttyb); 515: signal(SIGINT, sig); 516: if (fi != stdin) 517: fclose(fi); 518: return(pbuf); 519: } 520: /* 521: * Compare strings (at most n bytes): s1>s2: >0 s1==s2: 0 s1<s2: <0 522: */ 523: 524: strncmp(s1, s2, n) 525: register char *s1, *s2; 526: register n; 527: { 528: 529: while (--n >= 0 && *s1 == *s2++) 530: if (*s1++ == '\0') 531: return(0); 532: return(n<0 ? 0 : *s1 - *--s2); 533: } 534: 535: /* set the umask, ignore in v6 */ 536: 537: umask(n){} 538: 539: /* end of non-vax v7 routines */ 540: # endif 541: /* 542: PwdCurrent() 543: 544: Read the password file and return pwd to 545: entry for current user. 546: Return NULL if error. 547: 548: This code is a little screwed up because of the conventions 549: regarding the state of the utmp file after someone su's-- 550: either to root or to another person. 551: The final decision was to return getpwuid(getuid) if 552: the machine has one login name per userid, 553: and if there are multiple login names per userid, to 554: search the passwd file for the getlogin() name and return 555: the passwd file entry for that. 556: If there is no utmp entry, just use the userid. 557: This means that people who su on machine with multiple 558: user-id's will get the passwd entry for the account recorded 559: in the utmp file, not their current userid. 560: */ 561: struct passwd * 562: PwdCurrent() 563: { 564: register struct passwd *pwd; 565: register char *sn; 566: 567: # ifdef MULTNAMS 568: sn = getlogin(); 569: if(sn != NULL && sn[0] != 0 && sn[0] != ' '){ 570: pwd = getpwnam(sn); 571: if(pwd != NULL)return(pwd); 572: } 573: # endif 574: 575: return(getpwuid(uidmask(getuid()))); 576: } 577: /*VARARGS0*/ 578: debug(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t) 579: char *s; { 580: if(debugflg){ 581: printf(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t); 582: putchar('\n'); 583: } 584: }