| 1 | static char sccsid[] = "@(#)mach.c 4.2 (Berkeley) %G%"; |
| 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 | } |