# char copr[] "Copyright (c) 1976 Thomas S. Duff"; /* "Thomas S. Duff is a shit-head"*/ /* "RAW devices are as safe as playing with a tactical thermonuclear device" */ #define AUSAM /* mainly 16-bit uid in inodes */ struct{ int flags; char nlinks; #ifndef AUSAM char uid; char gid; #endif #ifdef AUSAM char uidlob; char uidhib; #endif char size0; int size1; int addr[8]; long actime; long modtime; }inode; int f; int pflag; char lastc; int isize; char peekc '\0'; getc(){ if(peekc!='\0'){ lastc=peekc; peekc='\0'; } else if(read(0, &lastc, 1)!=1) lastc='\0'; return(lastc); } endline(){ register char c; while(any(c=getc(), " \t")); if(c=='p'){ pflag++; while(any(c=getc(), " \t")); } if(c!='\n') error(); } error(){ printf("\7?\n"); if(lastc!='\n') while(getc()!='\n'); reset(); } any(ac, as) char as[]; { register char c, *s; c=ac; s=as; while(*s) if(c == *s++) return(1); return(0); } #define INTR 2 #define QUIT 3 intr(){ signal(INTR, intr); lastc='\n'; /* cryptic */ error(); } main(argc, argv) char *argv[]; { register j, i; int n,inum; char c; int savintr, savquit; int buf[18]; /* needed for fstat */ if(argc!=3){ write(2,"arg count\n",10); exit(-1); } if((f=open(argv[1],2))<0){ perror(argv[1]); exit(-1); } if( (fstat(f,buf)<0) || ((buf[2]&060000)!=060000) ) { /* it ain't a fu..ing block device !! */ /* using raw devices is fatal !! */ /* enable for raw if ya game */ printf("%s is not a block device !!\n",argv[1]); exit(-1); } seek(f, 1, 3); if(read(f, &isize, sizeof isize)!=sizeof isize){ perror("super block"); exit(-1); } if(!iget(inum=atoi(argv[2]))){ write(2, "can't read inode\n", 16); exit(-1); } setexit(); signal(INTR, intr); for(;;){ write(2,".",1); while(any(c=getc(), " \t")); switch(c){ default: error(); case 'q': endline(); case '\0': exit(0); case '\n': break; case 'e': i=rin(); endline(); if(iget(i)) inum=i; else error(); break; case '!': savintr=signal(INTR, 1); savquit=signal(QUIT, 1); i=fork(); if(i== -1) printf("Try again.\n"); else if(i==0){ execl("/bin/sh", "sh", "-t", 0); perror("/bin/sh"); exit(-1); } else{ wait(); printf("!\n"); signal(INTR, savintr); signal(QUIT, savquit); } break; case 'p': endline(); pflag++; break; case 'f': i=rin(); endline(); inode.flags=i; break; case 'l': i=rin(); endline(); inode.nlinks=i; break; case 'u': i=rin(); endline(); #ifndef AUSAM inode.uid=i; #endif #ifdef AUSAM inode.uidhib=(i>>8)&0377; inode.uidlob=(i&0377); #endif break; #ifndef AUSAM case 'g': i=rin(); endline(); inode.gid=i; break; #endif case 's': i=rin(); j=rin(); endline(); inode.size0=i; inode.size1=j; break; case 'a': n=rin(); if(n<0 || n>7) error(); i=rin(); endline(); inode.addr[n]=i; break; case 'w': endline(); seek(f,-sizeof inode,1); if(write(f,&inode,sizeof inode)!=sizeof inode) perror("write"); break; } if(pflag){ pflag=0; #ifndef AUSAM printf("flags: %o links: %l uid: %l gid: %l size: %s (%o,%o)\n", #endif #ifdef AUSAM printf( "flags: %o links: %l uid: %l size: %s (%o,%o)\n", #endif inode.flags,inode.nlinks, #ifndef AUSAM inode.uid,inode.gid, #endif #ifdef AUSAM (inode.uidhib<<8)+(inode.uidlob&0377), #endif locv(inode.size0&0377,inode.size1), inode.size0&0377,inode.size1); printf("addr:\n"); for(i=0;i<8;i++) printf("%l\t(%o)\n",inode.addr[i],inode.addr[i]); printf("\nactime: %s", ctime(inode.actime)); printf("modtime: %s",ctime(inode.modtime)); } } } rin(){ char c; register n, base; n=0; while(any(c=getc(), " \t")); if(c<'0' || c>'9'){ peekc=c; error(); } base=c=='0'?8:10; do n=n*base+c-'0'; while('0'<=(c=getc()) && c<='9'); peekc=c; return(n); } iget(inum){ register block; register nread; block=(inum+31)/16; if(block>=isize+2 || block<2) return(0); seek(f, block, 3); seek(f, 32*((inum+31)%16), 1); nread=read(f, &inode, sizeof inode); if(nread== -1){ perror("iget"); return(0); } else if(nread<sizeof inode){ write(2, "iget: eof on read\n", 18); return(0); } return(1); }