1*6809Srrh # 2*6809Srrh static char sccsid[] = " unixtraps.c 1.1 82/05/12 "; 3*6809Srrh /* Function to execute version 6 and version 7 UNIX system calls from 4*6809Srrh * compatability mode on UNIX-32V. 5*6809Srrh * Art Wetzel August 1979 6*6809Srrh */ 7*6809Srrh #include <stdio.h> 8*6809Srrh #include <signal.h> 9*6809Srrh #include <sys/types.h> 10*6809Srrh #include <sys/stat.h> 11*6809Srrh #ifdef V6UNIX 12*6809Srrh #ifdef TRACE 13*6809Srrh #define RTSNAME "/../../../../usr/local/v6trc" 14*6809Srrh #else 15*6809Srrh #define RTSNAME "/../../../../usr/local/v6run" 16*6809Srrh #endif 17*6809Srrh #include "unix6sys.h" 18*6809Srrh #ifdef TRACE 19*6809Srrh #include "unix6sysn.h" 20*6809Srrh #endif 21*6809Srrh #endif 22*6809Srrh #ifdef V7UNIX 23*6809Srrh #ifdef TRACE 24*6809Srrh #define RTSNAME "/../../../../usr/local/v7trc" 25*6809Srrh #else 26*6809Srrh #define RTSNAME "/../../../../usr/local/v7run" 27*6809Srrh #endif 28*6809Srrh #include "unix7sys.h" 29*6809Srrh #ifdef TRACE 30*6809Srrh #include "unix7sysn.h" 31*6809Srrh #endif 32*6809Srrh #endif 33*6809Srrh #include "defs.h" 34*6809Srrh #define CARRY 1 35*6809Srrh #define MAXSARGS 25 36*6809Srrh #ifdef V6UNIX 37*6809Srrh #define ARGVLEN 512 38*6809Srrh #define ENVLEN 0 39*6809Srrh #endif 40*6809Srrh #ifdef V7UNIX 41*6809Srrh #define ARGVLEN 5120 42*6809Srrh #define ENVLEN 1000 43*6809Srrh #endif 44*6809Srrh char argvs[ARGVLEN+ENVLEN]; 45*6809Srrh int args[MAXSARGS]; 46*6809Srrh /* 32v type stat structure */ 47*6809Srrh extern struct stat stat32v; 48*6809Srrh /* place for times data so we can reverse the longs */ 49*6809Srrh struct timebuf { 50*6809Srrh long t1; 51*6809Srrh long t2; 52*6809Srrh long t3; 53*6809Srrh long t4; 54*6809Srrh } timebuf; 55*6809Srrh /* place for pipe file descriptors */ 56*6809Srrh int pipes[2]; 57*6809Srrh /* wait status */ 58*6809Srrh int wstatus; 59*6809Srrh #ifdef V6UNIX 60*6809Srrh /* version 6 style stat structure */ 61*6809Srrh struct v6nod { 62*6809Srrh dev_t majmin; 63*6809Srrh ino_t inumber; 64*6809Srrh unsigned short flags; 65*6809Srrh unsigned char nlinks; 66*6809Srrh unsigned char uid; 67*6809Srrh unsigned char gid; 68*6809Srrh unsigned char size0; 69*6809Srrh unsigned short size1; 70*6809Srrh unsigned short addr[8]; 71*6809Srrh long actime; 72*6809Srrh long modtime; 73*6809Srrh } *v6stat; 74*6809Srrh #endif 75*6809Srrh /* do the trap stuff for the trap with code */ 76*6809Srrh dotrap(code) int code; { 77*6809Srrh register unsigned short *argp, *savp, *savep; 78*6809Srrh register int i, j, indirflg; 79*6809Srrh register char *avp, *oavp; 80*6809Srrh extern sigcatch(); 81*6809Srrh extern errno; 82*6809Srrh /* clear out condition codes of psl */ 83*6809Srrh psl &= ~017; 84*6809Srrh /* special case of indirect sys call */ 85*6809Srrh if(code == 0) { 86*6809Srrh /* remember this was indirect */ 87*6809Srrh indirflg = 1; 88*6809Srrh /* point to args */ 89*6809Srrh argp = (unsigned short *)*(pc++); 90*6809Srrh /* code for indirect sys call */ 91*6809Srrh code = *argp++; 92*6809Srrh /* is it legit */ 93*6809Srrh if(code>>8 != TRAPS) { 94*6809Srrh fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2); 95*6809Srrh pc++; 96*6809Srrh /* set carry flag */ 97*6809Srrh psl |= CARRY; 98*6809Srrh regs[0] = -1; 99*6809Srrh return(-1); 100*6809Srrh } 101*6809Srrh code &= 0377; 102*6809Srrh } 103*6809Srrh else { 104*6809Srrh /* remember this was not indirect */ 105*6809Srrh indirflg = 0; 106*6809Srrh /* point to args */ 107*6809Srrh argp = pc; 108*6809Srrh } 109*6809Srrh /* check if code too high or bad sys code */ 110*6809Srrh if(code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) { 111*6809Srrh fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp); 112*6809Srrh /* set carry bit */ 113*6809Srrh psl |= CARRY; 114*6809Srrh regs[0] = -1; 115*6809Srrh return(-1); 116*6809Srrh } 117*6809Srrh /* copy args to known locations */ 118*6809Srrh i=0; 119*6809Srrh for(j=0; j<sysargs[code][0]; j++) args[i++] = regs[j]; 120*6809Srrh for(j=0; j<(sysargs[code][1]); j++) args[i++] = *argp++; 121*6809Srrh #ifdef TRACE 122*6809Srrh fprintf(stderr,"pid %d ",getpid()); 123*6809Srrh if(indirflg) fprintf(stderr,"indirect "); 124*6809Srrh fprintf(stderr,"%s (%d) from 0%o with %d args",sysnames[code],code,pc-1,i); 125*6809Srrh for(j=0; j<i; j++) 126*6809Srrh fprintf(stderr," 0%o",args[j]); 127*6809Srrh if(code==OPEN||code==STAT||code==CREAT||code==EXEC||code==UNLNK||code==LINK||code==CHDIR||code==MKNOD) 128*6809Srrh fprintf(stderr," (%s)",args[0]); 129*6809Srrh #ifdef V7UNIX 130*6809Srrh if(code==EXECE) 131*6809Srrh fprintf(stderr," (%s)",args[0]); 132*6809Srrh #endif 133*6809Srrh if(code==LINK) 134*6809Srrh fprintf(stderr," (%s)",args[1]); 135*6809Srrh #endif 136*6809Srrh /* go do whatever sys call it is */ 137*6809Srrh switch(code) { 138*6809Srrh case FORK: 139*6809Srrh /* indirect forks return pids on both sides - must do here */ 140*6809Srrh /* this is possibly a bug in 32V */ 141*6809Srrh i = fork(); 142*6809Srrh break; 143*6809Srrh case WAIT: 144*6809Srrh i = wait(&wstatus); 145*6809Srrh args[0] = i; 146*6809Srrh args[1] = wstatus; 147*6809Srrh break; 148*6809Srrh case EXEC: 149*6809Srrh #ifdef V7UNIX 150*6809Srrh case EXECE: 151*6809Srrh #endif 152*6809Srrh /* 153*6809Srrh * have to do a lot of junk here to fix up an argv 154*6809Srrh * for execute since (1) the pdp-11 argv consists of 16 155*6809Srrh * bit pointers and (2) the argv itself is in the 156*6809Srrh * pdp-11 program space where it would get clobbered 157*6809Srrh * when a new program is read in and before its 158*6809Srrh * argv is set up. 159*6809Srrh */ 160*6809Srrh avp = &argvs[0]; 161*6809Srrh savp = (unsigned short *)args[1]; 162*6809Srrh #ifdef V6UNIX 163*6809Srrh for(i=1; args[i] = *savp++; i++) 164*6809Srrh if(args[i] == 0177777) break; 165*6809Srrh #ifdef TRACE 166*6809Srrh else fprintf(stderr,"argv[%d]%s ",i-1,args[i]); 167*6809Srrh #endif 168*6809Srrh #endif 169*6809Srrh #ifdef V7UNIX 170*6809Srrh savep = (unsigned short *)args[2]; 171*6809Srrh for(i=1; args[i] = *savp++; i++) 172*6809Srrh #ifdef TRACE 173*6809Srrh fprintf(stderr,"argv[%d]%s ",i-1,args[i]); 174*6809Srrh #else 175*6809Srrh ; 176*6809Srrh #endif 177*6809Srrh #endif 178*6809Srrh if(stat(args[0], &stat32v)) { 179*6809Srrh /* return error here if file does not exist */ 180*6809Srrh #ifdef TRACE 181*6809Srrh fprintf(stderr," does not exist\n"); 182*6809Srrh #endif 183*6809Srrh i = -1; 184*6809Srrh break; 185*6809Srrh } 186*6809Srrh /* must have execute permission */ 187*6809Srrh if(stat32v.st_mode & (S_IEXEC>>6)) goto experm; 188*6809Srrh if(stat32v.st_mode & (S_IEXEC>>3)) { 189*6809Srrh if(stat32v.st_gid == getegid()) goto experm; 190*6809Srrh if(geteuid() == 0) goto experm; 191*6809Srrh } 192*6809Srrh if(stat32v.st_mode & S_IEXEC) { 193*6809Srrh if(stat32v.st_uid == geteuid()) goto experm; 194*6809Srrh if(geteuid() == 0) goto experm; 195*6809Srrh } 196*6809Srrh /* return failure if no exec permision allowed */ 197*6809Srrh i = -1; 198*6809Srrh experm: 199*6809Srrh /* can't exec a directory */ 200*6809Srrh if(stat32v.st_mode & S_IFDIR) 201*6809Srrh i = -1; 202*6809Srrh if(i == -1) break; 203*6809Srrh args[i] = 0; 204*6809Srrh for(j=0; j<i; j++) { 205*6809Srrh oavp = (char *)args[j]; 206*6809Srrh args[j] = (int)avp; 207*6809Srrh while(*avp++ = *oavp++) ; 208*6809Srrh } 209*6809Srrh #ifdef V7UNIX 210*6809Srrh if(code == EXECE) { 211*6809Srrh for(j = ++i; args[j] = *savep++; j++) ; 212*6809Srrh for( ; j>i; j--) { 213*6809Srrh oavp = (char *)args[j]; 214*6809Srrh args[j] = (int)avp; 215*6809Srrh while(*avp++ = *oavp++) ; 216*6809Srrh } 217*6809Srrh } 218*6809Srrh #endif 219*6809Srrh /* SETUID and SETGID files must be started with a fresh RTS */ 220*6809Srrh if(stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) { 221*6809Srrh /* should add a check here for good magic # in header */ 222*6809Srrh args[1] = args[0]; 223*6809Srrh args[0] = (int)RTSNAME; 224*6809Srrh #ifdef TRACE 225*6809Srrh fprintf(stderr," SETUID-GID"); 226*6809Srrh #endif 227*6809Srrh if(args[i]) 228*6809Srrh i = execve(args[0], &args[0], &args[i]); 229*6809Srrh else 230*6809Srrh i = execv(args[0], &args[0]); 231*6809Srrh fprintf(stderr,"can't exec %s\n",RTSNAME); 232*6809Srrh break; 233*6809Srrh } 234*6809Srrh i = execute(args[0], &args[1], &args[i]); 235*6809Srrh /* shouldn't get here if exec works */ 236*6809Srrh break; 237*6809Srrh case SEEK: 238*6809Srrh #ifdef V6UNIX 239*6809Srrh /* fix up negative offsets */ 240*6809Srrh if(args[2] != 0 && args[2] != 3) 241*6809Srrh if(args[1] >= 32768) args[1] -= 65536; 242*6809Srrh if(args[2] <= 2) 243*6809Srrh i = lseek(args[0], args[1], args[2]); 244*6809Srrh else 245*6809Srrh i = lseek(args[0], args[1]*512, args[2]-3); 246*6809Srrh if(i != -1) i = 0; 247*6809Srrh #endif 248*6809Srrh #ifdef V7UNIX 249*6809Srrh i = lseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]); 250*6809Srrh #endif 251*6809Srrh break; 252*6809Srrh #ifdef V6UNIX 253*6809Srrh case MKNOD: 254*6809Srrh /* version 6 uses allocated bit which means regular file here */ 255*6809Srrh if(args[1] & S_IFBLK) 256*6809Srrh args[1] &= ~S_IFREG; 257*6809Srrh i = mknod(args[0], args[1], args[2]); 258*6809Srrh break; 259*6809Srrh #endif 260*6809Srrh case PIPE: 261*6809Srrh i = pipe(pipes); 262*6809Srrh args[0] = pipes[0]; 263*6809Srrh args[1] = pipes[1]; 264*6809Srrh break; 265*6809Srrh #ifdef V6UNIX 266*6809Srrh case TELL: 267*6809Srrh i = lseek(args[0], 0L, 1); 268*6809Srrh break; 269*6809Srrh #endif 270*6809Srrh case STAT: 271*6809Srrh case FSTAT: 272*6809Srrh /* do the syscall to a local stat buffer */ 273*6809Srrh i = syscall(code, args[0], &stat32v); 274*6809Srrh /* reverse the longs */ 275*6809Srrh stat32v.st_size = longrev(stat32v.st_size); 276*6809Srrh stat32v.st_atime = longrev(stat32v.st_atime); 277*6809Srrh stat32v.st_mtime = longrev(stat32v.st_mtime); 278*6809Srrh stat32v.st_ctime = longrev(stat32v.st_ctime); 279*6809Srrh #ifdef V7UNIX 280*6809Srrh /* copy out otherwise unchanged stat buffer */ 281*6809Srrh /* in two pieces with st_size as the breaking point */ 282*6809Srrh /* note that st_rdev is a short but due to alingnmemt */ 283*6809Srrh /* problems the rest of the structure is out of sync */ 284*6809Srrh j = (int)((char *)(&stat32v.st_size)-(char *)(&stat32v.st_dev)); 285*6809Srrh bcopy(&stat32v, args[1], j); 286*6809Srrh bcopy(&stat32v.st_size, args[1]+j-2, sizeof(struct stat)-j); 287*6809Srrh #endif 288*6809Srrh #ifdef V6UNIX 289*6809Srrh /* point to user area as v6stat structure */ 290*6809Srrh v6stat = (struct v6nod *)args[1]; 291*6809Srrh /* copy out piece by piece */ 292*6809Srrh v6stat->majmin = stat32v.st_dev; 293*6809Srrh v6stat->inumber = stat32v.st_ino; 294*6809Srrh v6stat->flags = stat32v.st_mode; 295*6809Srrh v6stat->nlinks = (unsigned char)stat32v.st_nlink; 296*6809Srrh v6stat->uid = (unsigned char)stat32v.st_uid; 297*6809Srrh v6stat->gid = (unsigned char)stat32v.st_gid; 298*6809Srrh /* note size already reversed */ 299*6809Srrh v6stat->size0 = (unsigned char)(stat32v.st_size & 0377); 300*6809Srrh v6stat->size1 = (unsigned short)(stat32v.st_size>>16); 301*6809Srrh v6stat->actime = stat32v.st_atime; 302*6809Srrh v6stat->modtime = stat32v.st_mtime; 303*6809Srrh /* patch up flags */ 304*6809Srrh /* for now just set 100000 bit if not a plain file */ 305*6809Srrh if(v6stat->flags & 060000) 306*6809Srrh v6stat->flags |= 0100000; 307*6809Srrh #endif 308*6809Srrh break; 309*6809Srrh case TIMES: 310*6809Srrh i = times(&timebuf); 311*6809Srrh timebuf.t2 = longrev(timebuf.t2) + timebuf.t1; 312*6809Srrh timebuf.t3 = longrev(timebuf.t3); 313*6809Srrh timebuf.t4 = longrev(timebuf.t4); 314*6809Srrh bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long)); 315*6809Srrh break; 316*6809Srrh #ifdef V6UNIX 317*6809Srrh case SLEEP: 318*6809Srrh /* do a sleep function - what about pwb which has alarm? */ 319*6809Srrh sleep(args[0]); 320*6809Srrh break; 321*6809Srrh #endif 322*6809Srrh case GETUID: 323*6809Srrh args[0] = getuid(); 324*6809Srrh args[1] = geteuid(); 325*6809Srrh #ifdef V6UNIX 326*6809Srrh i = args[1]<<8 | args[0]; 327*6809Srrh #endif 328*6809Srrh break; 329*6809Srrh case GETGID: 330*6809Srrh args[0] = getgid(); 331*6809Srrh args[1] = getegid(); 332*6809Srrh #ifdef V6UNIX 333*6809Srrh i = args[1]<<8 | args[0]; 334*6809Srrh #endif 335*6809Srrh break; 336*6809Srrh #ifdef V6UNIX 337*6809Srrh case SETUID: 338*6809Srrh case SETGID: 339*6809Srrh /* uids and gids are 8 bits in version 6 */ 340*6809Srrh i = syscall(code,args[0]&0377); 341*6809Srrh break; 342*6809Srrh #endif 343*6809Srrh case SIG: 344*6809Srrh /* if it is a good signal code */ 345*6809Srrh if(args[0] <= NSIG) { 346*6809Srrh /* get the current signal value */ 347*6809Srrh i = sigvals[args[0]]; 348*6809Srrh /* reset the signal to the new value */ 349*6809Srrh sigvals[args[0]] = args[1]; 350*6809Srrh /* actually do signal except don't reset SIGILL */ 351*6809Srrh if(args[0] != SIGILL) { 352*6809Srrh if(args[1] == (int)SIG_DFL || args[1] & (int)SIG_IGN) { 353*6809Srrh if((int)signal(args[0],args[1]) == -1) 354*6809Srrh i = -1; 355*6809Srrh } else { 356*6809Srrh if((int)signal(args[0], sigcatch) == -1) 357*6809Srrh i = -1; 358*6809Srrh } 359*6809Srrh } 360*6809Srrh } 361*6809Srrh else i = -1; 362*6809Srrh break; 363*6809Srrh case BRK: 364*6809Srrh /* brk is successful unless we run over the stack */ 365*6809Srrh i = 0; 366*6809Srrh if(args[0] >= regs[6]) i = -1; 367*6809Srrh break; 368*6809Srrh #ifdef V6UNIX 369*6809Srrh case PWBSYS: 370*6809Srrh /* ignore pwbsys for now */ 371*6809Srrh switch(args[2]) { 372*6809Srrh case UNAME: 373*6809Srrh #ifdef TRACE 374*6809Srrh fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]); 375*6809Srrh #endif 376*6809Srrh strcpy(args[0],"pwbname"); 377*6809Srrh i = 0; 378*6809Srrh break; 379*6809Srrh case UDATA: 380*6809Srrh #ifdef TRACE 381*6809Srrh fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]); 382*6809Srrh #endif 383*6809Srrh i = 0; 384*6809Srrh break; 385*6809Srrh case USTAT: 386*6809Srrh fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]); 387*6809Srrh i = 0; 388*6809Srrh break; 389*6809Srrh case UTIME: 390*6809Srrh fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]); 391*6809Srrh i = 0; 392*6809Srrh break; 393*6809Srrh default: 394*6809Srrh fprintf(stderr,"bad PWBSYS %d\n",args[3]); 395*6809Srrh i = -1; 396*6809Srrh break; 397*6809Srrh } 398*6809Srrh break; 399*6809Srrh #endif 400*6809Srrh default: 401*6809Srrh /* 402*6809Srrh * Many sys calls are easily done here since most 403*6809Srrh * system call codes are the same on version 6 and 7 UNIX 404*6809Srrh * as they are here. 405*6809Srrh */ 406*6809Srrh i = syscall(code,args[0],args[1],args[2],args[3],args[4]); 407*6809Srrh #ifdef V6UNIX 408*6809Srrh /* allow read write access to created files for(IDIS v6 mod) */ 409*6809Srrh if(code==CREAT) { 410*6809Srrh /* get actual file mode after create */ 411*6809Srrh fstat(i, &stat32v); 412*6809Srrh close(i); 413*6809Srrh /* ensure read/write access to owner */ 414*6809Srrh chmod(args[0], 0644); 415*6809Srrh i = open(args[0], 2); 416*6809Srrh /* change mode back the way it was */ 417*6809Srrh chmod(args[0], stat32v.st_mode); 418*6809Srrh } 419*6809Srrh #endif 420*6809Srrh break; 421*6809Srrh } 422*6809Srrh #ifdef TRACE 423*6809Srrh fprintf(stderr," sys val -> 0%o\n",i); 424*6809Srrh #endif 425*6809Srrh /* set carry bit if sys error */ 426*6809Srrh if(i == -1) 427*6809Srrh psl |= CARRY; 428*6809Srrh /* if not an indirect sys call, adjust the pc */ 429*6809Srrh if(indirflg == 0) 430*6809Srrh pc = argp; 431*6809Srrh /* do alternate return on one side of fork */ 432*6809Srrh if(code == FORK && i != 0) 433*6809Srrh pc++; 434*6809Srrh /* do the various return value formats */ 435*6809Srrh switch(sysargs[code][2]) { 436*6809Srrh case NORMRET: 437*6809Srrh /* normal case only one return value in r0 */ 438*6809Srrh regs[0] = i; 439*6809Srrh break; 440*6809Srrh case LONGRET: 441*6809Srrh /* return a long in r0 - r1 as in time */ 442*6809Srrh regs[1] = i; 443*6809Srrh regs[0] = i >> 16; 444*6809Srrh break; 445*6809Srrh case TWORET: 446*6809Srrh /* return two ints in r0 - r1 as in pipe */ 447*6809Srrh if(i == -1) 448*6809Srrh regs[0] = i; 449*6809Srrh else { 450*6809Srrh regs[1] = args[1]; 451*6809Srrh regs[0] = args[0]; 452*6809Srrh } 453*6809Srrh break; 454*6809Srrh } 455*6809Srrh if(i== -1) 456*6809Srrh regs[0] = errno; 457*6809Srrh } 458*6809Srrh long longrev(l) long l; { 459*6809Srrh /* function to reverse the halves of a long */ 460*6809Srrh union { 461*6809Srrh long lng; 462*6809Srrh short s[2]; 463*6809Srrh } u; 464*6809Srrh register short t; 465*6809Srrh u.lng = l; 466*6809Srrh t = u.s[0]; 467*6809Srrh u.s[0] = u.s[1]; 468*6809Srrh u.s[1] = t; 469*6809Srrh return(u.lng); 470*6809Srrh } 471