|
|
1.1 ! root 1: static char sccsid[] = "@(#)unixtraps.c 4.2 83/07/31"; ! 2: ! 3: /* ! 4: * Function to execute version 6 and version 7 UNIX system calls from ! 5: * compatability mode on UNIX-32V. ! 6: * Art Wetzel August 1979 ! 7: */ ! 8: ! 9: #include <stdio.h> ! 10: #include <signal.h> ! 11: #include <sys/types.h> ! 12: #include <sys/stat.h> ! 13: #include <sys/ioctl.h> ! 14: #include <sys/time.h> ! 15: #ifdef V6UNIX ! 16: #ifdef TRACE ! 17: #define RTSNAME "/../../../../usr/local/v6trc" ! 18: #else ! 19: #define RTSNAME "/../../../../usr/local/v6run" ! 20: #endif ! 21: #include "unix6sys.h" ! 22: #ifdef TRACE ! 23: #include "unix6sysn.h" ! 24: #endif ! 25: #endif ! 26: #ifdef V7UNIX ! 27: #ifdef TRACE ! 28: #define RTSNAME "/../../../../usr/local/v7trc" ! 29: #else ! 30: #define RTSNAME "/../../../../usr/local/v7run" ! 31: #endif ! 32: #include "unix7sys.h" ! 33: #ifdef TRACE ! 34: #include "unix7sysn.h" ! 35: #endif ! 36: #endif ! 37: #include "defs.h" ! 38: #define CARRY 1 ! 39: #define MAXSARGS 25 ! 40: #ifdef V6UNIX ! 41: #define ARGVLEN 512 ! 42: #define ENVLEN 0 ! 43: #endif ! 44: #ifdef V7UNIX ! 45: #define ARGVLEN 5120 ! 46: #define ENVLEN 1000 ! 47: #endif ! 48: char argvs[ARGVLEN+ENVLEN]; ! 49: int args[MAXSARGS]; ! 50: ! 51: /* 32v type stat structure */ ! 52: extern struct stat stat32v; ! 53: ! 54: /* place for times data so we can reverse the longs */ ! 55: struct timebuf { ! 56: long t1; ! 57: long t2; ! 58: long t3; ! 59: long t4; ! 60: } timebuf; ! 61: ! 62: /* place for pipe file descriptors */ ! 63: int pipes[2]; ! 64: ! 65: /* wait status */ ! 66: int wstatus; ! 67: ! 68: #ifdef V6UNIX ! 69: /* version 6 style stat structure */ ! 70: struct v6nod { ! 71: dev_t majmin; ! 72: ino_t inumber; ! 73: unsigned short flags; ! 74: unsigned char nlinks; ! 75: unsigned char uid; ! 76: unsigned char gid; ! 77: unsigned char size0; ! 78: unsigned short size1; ! 79: unsigned short addr[8]; ! 80: long actime; ! 81: long modtime; ! 82: } *v6stat; ! 83: #endif ! 84: ! 85: #ifdef V7UNIX ! 86: /* version 7 style stat structure */ ! 87: struct v7stat { ! 88: dev_t v7st_dev; ! 89: u_short v7st_ino; ! 90: u_short v7st_mode; ! 91: short v7st_nlink; ! 92: short v7st_uid; ! 93: short v7st_gid; ! 94: dev_t v7st_rdev; ! 95: int v7st_size; ! 96: int v7st_atime; ! 97: int v7st_mtime; ! 98: int v7st_ctime; ! 99: } statv7; ! 100: ! 101: struct timeb { ! 102: time_t time; ! 103: u_short millitm; ! 104: short timezone; ! 105: short dstflag; ! 106: } timeb; ! 107: #endif ! 108: ! 109: /* do the trap stuff for the trap with code */ ! 110: dotrap(code) ! 111: int code; ! 112: { ! 113: register unsigned short *argp, *savp, *savep; ! 114: register int i, j, indirflg; ! 115: register char *avp, *oavp; ! 116: extern sigcatch(); ! 117: extern errno; ! 118: ! 119: /* clear out condition codes of psl */ ! 120: psl &= ~017; ! 121: /* special case of indirect sys call */ ! 122: if (code == 0) { ! 123: /* remember this was indirect */ ! 124: indirflg = 1; ! 125: /* point to args */ ! 126: argp = (unsigned short *)*(pc++); ! 127: /* code for indirect sys call */ ! 128: code = *argp++; ! 129: /* is it legit */ ! 130: if (code>>8 != TRAPS) { ! 131: fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2); ! 132: pc++; ! 133: /* set carry flag */ ! 134: psl |= CARRY; ! 135: regs[0] = -1; ! 136: return(-1); ! 137: } ! 138: code &= 0377; ! 139: } else { ! 140: /* remember this was not indirect */ ! 141: indirflg = 0; ! 142: /* point to args */ ! 143: argp = pc; ! 144: } ! 145: /* check if code too high or bad sys code */ ! 146: if (code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) { ! 147: fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp); ! 148: /* set carry bit */ ! 149: psl |= CARRY; ! 150: regs[0] = -1; ! 151: return(-1); ! 152: } ! 153: /* copy args to known locations */ ! 154: i=0; ! 155: for (j=0; j<sysargs[code][0]; j++) ! 156: args[i++] = regs[j]; ! 157: for (j=0; j<(sysargs[code][1]); j++) ! 158: args[i++] = *argp++; ! 159: #ifdef TRACE ! 160: fprintf(stderr,"pid %d ",getpid()); ! 161: if (indirflg) ! 162: fprintf(stderr,"indirect "); ! 163: fprintf(stderr, "%s (%d) from 0%o with %d args", ! 164: sysnames[code], code, pc-1, i); ! 165: for (j=0; j<i; j++) ! 166: fprintf(stderr," 0%o",args[j]); ! 167: if (code==OPEN || code==STAT || code==CREAT || code==EXEC || ! 168: code==UNLNK || code==LINK || code==CHDIR || code==MKNOD) ! 169: fprintf(stderr," (%s)",args[0]); ! 170: #ifdef V7UNIX ! 171: if (code==EXECE) ! 172: fprintf(stderr," (%s)",args[0]); ! 173: #endif ! 174: if (code==LINK) ! 175: fprintf(stderr," (%s)",args[1]); ! 176: #endif ! 177: /* go do whatever sys call it is */ ! 178: switch (code) { ! 179: case FORK: ! 180: /* indirect forks return pids on both sides - must do here */ ! 181: /* this is possibly a bug in 32V */ ! 182: i = fork(); ! 183: break; ! 184: ! 185: case WAIT: ! 186: i = wait(&wstatus); ! 187: args[0] = i; ! 188: args[1] = wstatus; ! 189: break; ! 190: ! 191: case EXEC: ! 192: #ifdef V7UNIX ! 193: case EXECE: ! 194: #endif ! 195: /* ! 196: * have to do a lot of junk here to fix up an argv ! 197: * for execute since (1) the pdp-11 argv consists of 16 ! 198: * bit pointers and (2) the argv itself is in the ! 199: * pdp-11 program space where it would get clobbered ! 200: * when a new program is read in and before its ! 201: * argv is set up. ! 202: */ ! 203: avp = &argvs[0]; ! 204: savp = (unsigned short *)args[1]; ! 205: #ifdef V6UNIX ! 206: for (i=1; args[i] = *savp++; i++) ! 207: if (args[i] == 0177777) ! 208: break; ! 209: #ifdef TRACE ! 210: else ! 211: fprintf(stderr,"argv[%d]%s ",i-1,args[i]); ! 212: #endif ! 213: #endif ! 214: #ifdef V7UNIX ! 215: savep = (unsigned short *)args[2]; ! 216: for (i=1; args[i] = *savp++; i++) ! 217: #ifdef TRACE ! 218: fprintf(stderr,"argv[%d]%s ",i-1,args[i]); ! 219: #else ! 220: ; ! 221: #endif ! 222: #endif ! 223: if (stat(args[0], &stat32v)) { ! 224: /* return error here if file does not exist */ ! 225: #ifdef TRACE ! 226: fprintf(stderr," does not exist\n"); ! 227: #endif ! 228: i = -1; ! 229: break; ! 230: } ! 231: /* must have execute permission */ ! 232: if (stat32v.st_mode & (S_IEXEC>>6)) ! 233: goto experm; ! 234: if (stat32v.st_mode & (S_IEXEC>>3)) { ! 235: if (stat32v.st_gid == getegid()) ! 236: goto experm; ! 237: if (geteuid() == 0) ! 238: goto experm; ! 239: } ! 240: if (stat32v.st_mode & S_IEXEC) { ! 241: if (stat32v.st_uid == geteuid()) ! 242: goto experm; ! 243: if (geteuid() == 0) ! 244: goto experm; ! 245: } ! 246: /* return failure if no exec permision allowed */ ! 247: i = -1; ! 248: experm: ! 249: /* can't exec a directory */ ! 250: if ((stat32v.st_mode&S_IFMT) == S_IFDIR) ! 251: i = -1; ! 252: if (i == -1) ! 253: break; ! 254: args[i] = 0; ! 255: for (j=0; j<i; j++) { ! 256: oavp = (char *)args[j]; ! 257: args[j] = (int)avp; ! 258: while (*avp++ = *oavp++) ! 259: ; ! 260: } ! 261: #ifdef V7UNIX ! 262: if (code == EXECE) { ! 263: for (j = ++i; args[j] = *savep++; j++) ! 264: ; ! 265: for ( ; j > i; j--) { ! 266: oavp = (char *)args[j]; ! 267: args[j] = (int)avp; ! 268: while (*avp++ = *oavp++) ! 269: ; ! 270: } ! 271: } ! 272: #endif ! 273: /* SETUID and SETGID files must be started with a fresh RTS */ ! 274: if (stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) { ! 275: /* should add a check here for good magic # in header */ ! 276: args[1] = args[0]; ! 277: args[0] = (int)RTSNAME; ! 278: #ifdef TRACE ! 279: fprintf(stderr," SETUID-GID"); ! 280: #endif ! 281: if (args[i]) ! 282: i = execve(args[0], &args[0], &args[i]); ! 283: else ! 284: i = execv(args[0], &args[0]); ! 285: fprintf(stderr,"can't exec %s\n",RTSNAME); ! 286: break; ! 287: } ! 288: i = execute(args[0], &args[1], &args[i]); ! 289: /* shouldn't get here if exec works */ ! 290: break; ! 291: ! 292: case SEEK: ! 293: #ifdef V6UNIX ! 294: /* fix up negative offsets */ ! 295: if (args[2] != 0 && args[2] != 3) ! 296: if (args[1] >= 32768) ! 297: args[1] -= 65536; ! 298: if (args[2] <= 2) ! 299: i = lseek(args[0], args[1], args[2]); ! 300: else ! 301: i = lseek(args[0], args[1]*512, args[2]-3); ! 302: if (i != -1) ! 303: i = 0; ! 304: #endif ! 305: #ifdef V7UNIX ! 306: i = lseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]); ! 307: #endif ! 308: break; ! 309: ! 310: #ifdef V6UNIX ! 311: case MKNOD: ! 312: /* version 6 uses allocated bit which means regular file here */ ! 313: if (args[1] & S_IFBLK) ! 314: args[1] &= ~S_IFREG; ! 315: i = mknod(args[0], args[1], args[2]); ! 316: break; ! 317: #endif ! 318: ! 319: case PIPE: ! 320: i = pipe(pipes); ! 321: args[0] = pipes[0]; ! 322: args[1] = pipes[1]; ! 323: break; ! 324: ! 325: #ifdef V6UNIX ! 326: case TELL: ! 327: i = lseek(args[0], 0L, 1); ! 328: break; ! 329: ! 330: case STTY: ! 331: i = stty(args[0], args[1]); ! 332: break; ! 333: ! 334: case GTTY: ! 335: i = gtty(args[0], args[1]); ! 336: break; ! 337: #endif ! 338: ! 339: case STAT: ! 340: i = stat(args[0], &stat32v); ! 341: goto allstat; ! 342: ! 343: case FSTAT: ! 344: /* do the syscall to a local stat buffer */ ! 345: i = fstat(args[0], &stat32v); ! 346: ! 347: allstat: ! 348: /* reverse the longs */ ! 349: stat32v.st_size = longrev(stat32v.st_size); ! 350: stat32v.st_atime = longrev(stat32v.st_atime); ! 351: stat32v.st_mtime = longrev(stat32v.st_mtime); ! 352: stat32v.st_ctime = longrev(stat32v.st_ctime); ! 353: #ifdef V7UNIX ! 354: statv7.v7st_dev = stat32v.st_dev; ! 355: statv7.v7st_ino = stat32v.st_ino; ! 356: statv7.v7st_mode = stat32v.st_mode; ! 357: statv7.v7st_nlink = stat32v.st_nlink; ! 358: statv7.v7st_uid = stat32v.st_uid; ! 359: statv7.v7st_gid = stat32v.st_gid; ! 360: statv7.v7st_rdev = stat32v.st_rdev; ! 361: statv7.v7st_size = stat32v.st_size; ! 362: statv7.v7st_atime = stat32v.st_atime; ! 363: statv7.v7st_mtime = stat32v.st_mtime; ! 364: statv7.v7st_ctime = stat32v.st_ctime; ! 365: /* copy out otherwise unchanged stat buffer */ ! 366: /* in two pieces with st_size as the breaking point */ ! 367: /* note that st_rdev is a short but due to alingnmemt */ ! 368: /* problems the rest of the structure is out of sync */ ! 369: j = (int)((char *)(&statv7.v7st_size) - ! 370: (char *)(&statv7.v7st_dev)); ! 371: bcopy(&statv7, args[1], j); ! 372: bcopy(&statv7.v7st_size, args[1]+j-2, sizeof(struct v7stat)-j); ! 373: #endif ! 374: #ifdef V6UNIX ! 375: /* point to user area as v6stat structure */ ! 376: v6stat = (struct v6nod *)args[1]; ! 377: /* copy out piece by piece */ ! 378: v6stat->majmin = stat32v.st_dev; ! 379: v6stat->inumber = stat32v.st_ino; ! 380: v6stat->flags = stat32v.st_mode; ! 381: v6stat->nlinks = (unsigned char)stat32v.st_nlink; ! 382: v6stat->uid = (unsigned char)stat32v.st_uid; ! 383: v6stat->gid = (unsigned char)stat32v.st_gid; ! 384: /* note size already reversed */ ! 385: v6stat->size0 = (unsigned char)(stat32v.st_size & 0377); ! 386: v6stat->size1 = (unsigned short)(stat32v.st_size>>16); ! 387: v6stat->actime = stat32v.st_atime; ! 388: v6stat->modtime = stat32v.st_mtime; ! 389: /* patch up flags */ ! 390: /* for now just set 100000 bit if not a plain file */ ! 391: if (v6stat->flags & 060000) ! 392: v6stat->flags |= 0100000; ! 393: #endif ! 394: break; ! 395: ! 396: case TIMES: ! 397: i = times(&timebuf); ! 398: timebuf.t2 = longrev(timebuf.t2) + timebuf.t1; ! 399: timebuf.t3 = longrev(timebuf.t3); ! 400: timebuf.t4 = longrev(timebuf.t4); ! 401: bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long)); ! 402: break; ! 403: ! 404: #ifdef V6UNIX ! 405: case SLEEP: ! 406: /* do a sleep function - what about pwb which has alarm? */ ! 407: sleep(args[0]); ! 408: break; ! 409: #endif ! 410: ! 411: case GETUID: ! 412: args[0] = getuid(); ! 413: args[1] = geteuid(); ! 414: #ifdef V6UNIX ! 415: i = args[1]<<8 | (args[0] & 0377); ! 416: #endif ! 417: break; ! 418: ! 419: case GETGID: ! 420: args[0] = getgid(); ! 421: args[1] = getegid(); ! 422: #ifdef V6UNIX ! 423: i = args[1]<<8 | (args[0] & 0377); ! 424: #endif ! 425: break; ! 426: ! 427: /* uids and gids are 8 bits in version 6 */ ! 428: case SETUID: ! 429: case SETGID: ! 430: #ifdef V6UNIX ! 431: args[0] &= 0377; ! 432: #endif ! 433: if (code == SETUID) ! 434: i = setuid(args[0]); ! 435: else ! 436: i = setgid(args[0]); ! 437: break; ! 438: ! 439: case SIG: ! 440: /* if it is a good signal code */ ! 441: if (args[0] <= NSIG) { ! 442: /* get the current signal value */ ! 443: i = sigvals[args[0]]; ! 444: /* reset the signal to the new value */ ! 445: sigvals[args[0]] = args[1]; ! 446: /* actually do signal except don't reset SIGILL */ ! 447: if (args[0] != SIGILL) { ! 448: if (args[1] == (int)SIG_DFL || ! 449: args[1] & (int)SIG_IGN) { ! 450: if ((int)signal(args[0],args[1]) == -1) ! 451: i = -1; ! 452: } else { ! 453: if ((int)signal(args[0],sigcatch) == -1) ! 454: i = -1; ! 455: } ! 456: } ! 457: } else ! 458: i = -1; ! 459: break; ! 460: ! 461: case BRK: ! 462: /* brk is successful unless we run over the stack */ ! 463: /* NB: this assumes register usage which need not be used */ ! 464: i = 0; ! 465: if (args[0] >= regs[6]) ! 466: i = -1; ! 467: break; ! 468: ! 469: /* ! 470: * the next bunch are to cope with sys calls removed from 4.2 ! 471: */ ! 472: case TIME: ! 473: i = time(0); ! 474: break; ! 475: ! 476: case STIME: { ! 477: struct timeval tv; ! 478: ! 479: tv.tv_usec = 0; ! 480: tv.tv_sec = (args[0] & 0xffff) | ((args[1] & 0xffff) << 16); ! 481: i = settimeofday(&tv); ! 482: break; ! 483: } ! 484: ! 485: case NICE: ! 486: i = nice(args[0]); ! 487: break; ! 488: ! 489: #ifdef V7UNIX ! 490: case ALARM: ! 491: i = alarm(args[0]); ! 492: break; ! 493: ! 494: case PAUSE: ! 495: i = pause(); ! 496: break; ! 497: ! 498: case UTIME: ! 499: i = utime(args[0], args[1]); ! 500: break; ! 501: ! 502: case FTIME: ! 503: i = ftime(&timeb); ! 504: timeb.time = longrev(timeb.time); ! 505: bcopy(&timeb, args[0], sizeof timeb - 2); ! 506: break; ! 507: ! 508: case IOCTL: ! 509: args[1] = mapioctl(args[1]); ! 510: if (args[1] == 0) ! 511: i = -1; ! 512: else ! 513: i = ioctl(args[0], args[1], args[2]); ! 514: break; ! 515: #endif ! 516: ! 517: #ifdef V6UNIX ! 518: case PWBSYS: ! 519: /* ignore pwbsys for now */ ! 520: switch (args[2]) { ! 521: case UNAME: ! 522: #ifdef TRACE ! 523: fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]); ! 524: #endif ! 525: strcpy(args[0],"pwbname"); ! 526: i = 0; ! 527: break; ! 528: ! 529: case UDATA: ! 530: #ifdef TRACE ! 531: fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]); ! 532: #endif ! 533: i = 0; ! 534: break; ! 535: ! 536: case USTAT: ! 537: fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]); ! 538: i = 0; ! 539: break; ! 540: ! 541: case UTIME: ! 542: fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]); ! 543: i = 0; ! 544: break; ! 545: default: ! 546: fprintf(stderr,"bad PWBSYS %d\n",args[3]); ! 547: i = -1; ! 548: break; ! 549: } ! 550: break; ! 551: #endif ! 552: ! 553: default: ! 554: /* ! 555: * Many sys calls are easily done here since most ! 556: * system call codes are the same on version 6 and 7 UNIX ! 557: * as they are here. ! 558: */ ! 559: i = syscall(code,args[0],args[1],args[2],args[3],args[4]); ! 560: #ifdef V6UNIX ! 561: /* allow read write access to created files for (IDIS v6 mod) */ ! 562: if (code==CREAT) { ! 563: /* get actual file mode after create */ ! 564: fstat(i, &stat32v); ! 565: close(i); ! 566: /* ensure read/write access to owner */ ! 567: chmod(args[0], 0644); ! 568: i = open(args[0], 2); ! 569: /* change mode back the way it was */ ! 570: chmod(args[0], stat32v.st_mode); ! 571: } ! 572: #endif ! 573: break; ! 574: } ! 575: #ifdef TRACE ! 576: fprintf(stderr," sys val -> 0%o\n",i); ! 577: #endif ! 578: /* set carry bit if sys error */ ! 579: if (i == -1) ! 580: psl |= CARRY; ! 581: /* if not an indirect sys call, adjust the pc */ ! 582: if (indirflg == 0) ! 583: pc = argp; ! 584: /* do alternate return on one side of fork */ ! 585: if (code == FORK && i != 0) ! 586: pc++; ! 587: /* do the various return value formats */ ! 588: switch (sysargs[code][2]) { ! 589: case NORMRET: ! 590: /* normal case only one return value in r0 */ ! 591: regs[0] = i; ! 592: break; ! 593: case LONGRET: ! 594: /* return a long in r0 - r1 as in time */ ! 595: regs[1] = i; ! 596: regs[0] = i >> 16; ! 597: break; ! 598: case TWORET: ! 599: /* return two ints in r0 - r1 as in pipe */ ! 600: if (i == -1) ! 601: regs[0] = i; ! 602: else { ! 603: regs[1] = args[1]; ! 604: regs[0] = args[0]; ! 605: } ! 606: break; ! 607: } ! 608: if (i== -1) ! 609: regs[0] = errno; ! 610: } ! 611: ! 612: long ! 613: longrev(l) ! 614: long l; ! 615: { ! 616: /* function to reverse the halves of a long */ ! 617: union { ! 618: long lng; ! 619: short s[2]; ! 620: } u; ! 621: register short t; ! 622: u.lng = l; ! 623: t = u.s[0]; ! 624: u.s[0] = u.s[1]; ! 625: u.s[1] = t; ! 626: return(u.lng); ! 627: } ! 628: ! 629: /* ! 630: * Note: these tables are sorted by ! 631: * ioctl "code" (in ascending order). ! 632: */ ! 633: int fctls[] = { FIOCLEX, FIONCLEX, FIOASYNC, FIONBIO, FIONREAD, 0 }; ! 634: int tctls[] = { ! 635: TIOCGETD, TIOCSETD, TIOCHPCL, TIOCMODG, TIOCMODS, ! 636: TIOCGETP, TIOCSETP, TIOCSETN, TIOCEXCL, TIOCNXCL, ! 637: TIOCFLUSH,TIOCSETC, TIOCGETC, TIOCREMOTE,TIOCMGET, ! 638: TIOCMBIC, TIOCMBIS, TIOCMSET, TIOCSTART,TIOCSTOP, ! 639: TIOCPKT, TIOCNOTTY,TIOCSTI, TIOCOUTQ, TIOCGLTC, ! 640: TIOCSLTC, TIOCSPGRP,TIOCGPGRP,TIOCCDTR, TIOCSDTR, ! 641: TIOCCBRK, TIOCSBRK, TIOCLGET, TIOCLSET, TIOCLBIC, ! 642: TIOCLBIS, 0 ! 643: }; ! 644: ! 645: /* ! 646: * Map an old style ioctl command to new. ! 647: */ ! 648: mapioctl(cmd) ! 649: int cmd; ! 650: { ! 651: register int *map, c; ! 652: ! 653: switch ((cmd >> 8) & 0xff) { ! 654: ! 655: case 'f': ! 656: map = fctls; ! 657: break; ! 658: ! 659: case 't': ! 660: map = tctls; ! 661: break; ! 662: ! 663: default: ! 664: return (0); ! 665: } ! 666: while ((c = *map) && (c&0xff) < (cmd&0xff)) ! 667: map++; ! 668: if (c && (c&0xff) == (cmd&0xff)) ! 669: return (c); ! 670: return (0); ! 671: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.