|
|
1.1 ! root 1: /* tail command ! 2: * ! 3: * tail where [file] ! 4: * where is +_n[type] ! 5: * - means n lines before end ! 6: * + means nth line from beginning ! 7: * type 'b' means tail n blocks, not lines ! 8: * type 'c' means tail n characters ! 9: * Type 'r' means in lines in reverse order from end ! 10: * (for -r, default is entire buffer ) ! 11: * option 'f' means loop endlessly trying to read more ! 12: * characters after the end of file, on the assumption ! 13: * that the file is growing ! 14: */ ! 15: ! 16: #include <stdio.h> ! 17: #include <ctype.h> ! 18: #include <sys/types.h> ! 19: #include <sys/stat.h> ! 20: #include <errno.h> ! 21: ! 22: #define LBIN 16383 ! 23: struct stat statb; ! 24: int follow; ! 25: int piped; ! 26: char bin[LBIN]; ! 27: int errno; ! 28: int infd = 0; ! 29: ! 30: main(argc,argv) ! 31: char **argv; ! 32: { ! 33: long n,di; ! 34: register i,j,k; ! 35: char *arg; ! 36: int partial,bylines,bkwds,fromend,lastnl; ! 37: char *p; ! 38: int anydigit = 0; ! 39: ! 40: arg = argv[1]; ! 41: if(argc<=1 || *arg!='-'&&*arg!='+') { ! 42: arg = "-10l"; ! 43: argc++; ! 44: argv--; ! 45: } ! 46: n = 0; ! 47: fromend = *arg=='-'; ! 48: arg++; ! 49: while(isdigit(*arg)) { ! 50: anydigit++; ! 51: n = n*10 + *arg++ - '0'; ! 52: } ! 53: if(!fromend&&n>0) ! 54: n--; ! 55: if(argc>2) { ! 56: if((infd = open(argv[2],0))<0) { ! 57: perror(argv[2]); ! 58: exit(1); ! 59: } ! 60: } ! 61: lseek(infd,(long)0,1); ! 62: piped = errno==ESPIPE; ! 63: bylines = -1; bkwds = 0; ! 64: while(*arg) ! 65: switch(*arg++) { ! 66: ! 67: case 'b': ! 68: n *= BUFSIZ; ! 69: if(bylines!=-1) goto errcom; ! 70: bylines=0; ! 71: break; ! 72: case 'c': ! 73: if(bylines!=-1) goto errcom; ! 74: bylines=0; ! 75: break; ! 76: case 'f': ! 77: follow = 1; ! 78: break; ! 79: case 'r': ! 80: if(!anydigit) n = LBIN; ! 81: bkwds = 1; fromend = 1; bylines = 1; ! 82: break; ! 83: case 'l': ! 84: if(bylines!=-1) goto errcom; ! 85: bylines = 1; ! 86: break; ! 87: default: ! 88: goto errcom; ! 89: } ! 90: if(fromend && !bkwds && !anydigit) n = 10; ! 91: if(bylines==-1) bylines = 1; ! 92: if(bkwds) follow=0; ! 93: if(fromend) ! 94: goto keep; ! 95: ! 96: /*seek from beginning */ ! 97: ! 98: if(bylines) { ! 99: j = 0; ! 100: while(n-->0) { ! 101: do { ! 102: if(j--<=0) { ! 103: p = bin; ! 104: j = read(infd,p,BUFSIZ); ! 105: if(j--<=0) ! 106: fexit(); ! 107: } ! 108: } while(*p++ != '\n'); ! 109: } ! 110: if(j>0) ! 111: zwrite(1,p,j); ! 112: } else if(n>0) { ! 113: if(!piped) ! 114: fstat(infd,&statb); ! 115: if(piped||(statb.st_mode&S_IFMT)==S_IFCHR) ! 116: while(n>0) { ! 117: i = n>BUFSIZ?BUFSIZ:n; ! 118: i = read(infd,bin,i); ! 119: if(i<=0) ! 120: fexit(); ! 121: n -= i; ! 122: } ! 123: else ! 124: lseek(infd,n,0); ! 125: } ! 126: copy: ! 127: while((i=read(infd,bin,BUFSIZ))>0) ! 128: zwrite(1,bin,i); ! 129: fexit(); ! 130: ! 131: /*seek from end*/ ! 132: ! 133: keep: ! 134: if(n <= 0) { ! 135: lseek(infd,0L,2); ! 136: fexit(); ! 137: } ! 138: if(!piped) { ! 139: fstat(infd,&statb); ! 140: di = !bylines&&n<LBIN?n:LBIN-1; ! 141: if(statb.st_size > di) ! 142: lseek(infd,-di,2); ! 143: if(!bylines) ! 144: goto copy; ! 145: } ! 146: partial = 1; ! 147: for(;;) { ! 148: i = 0; ! 149: do { ! 150: j = read(infd,&bin[i],LBIN-i); ! 151: if(j<=0) ! 152: goto brka; ! 153: i += j; ! 154: } while(i<LBIN); ! 155: partial = 0; ! 156: } ! 157: brka: ! 158: if(!bylines) { ! 159: k = n<=i ? i-n: partial ? 0: n>=LBIN ? i+1: i-n+LBIN; ! 160: k--; ! 161: } else { ! 162: if(bkwds && bin[i==0?LBIN-1:i-1]!='\n'){ /* force trailing newline */ ! 163: bin[i]='\n'; ! 164: if(++i>=LBIN) {i = 0; partial = 0;} ! 165: } ! 166: k = i; ! 167: j = 0; ! 168: do { ! 169: lastnl = k; ! 170: do { ! 171: if(--k<0) { ! 172: if(partial) { ! 173: if(bkwds) zwrite(1,bin,lastnl+1); ! 174: goto brkb; ! 175: } ! 176: k = LBIN -1; ! 177: } ! 178: } while(bin[k]!='\n'&&k!=i); ! 179: if(bkwds && j>0){ ! 180: if(k<lastnl) zwrite(1,&bin[k+1],lastnl-k); ! 181: else { ! 182: if(k<LBIN-1) ! 183: zwrite(1,&bin[k+1],LBIN-k-1); ! 184: zwrite(1,bin,lastnl+1); ! 185: } ! 186: } ! 187: } while(j++<n&&k!=i); ! 188: brkb: ! 189: if(bkwds) exit(0); ! 190: if(k==i) do { ! 191: if(++k>=LBIN) ! 192: k = 0; ! 193: } while(bin[k]!='\n'&&k!=i); ! 194: } ! 195: if(k<i) ! 196: zwrite(1,&bin[k+1],i-k-1); ! 197: else { ! 198: if(k<LBIN-1) ! 199: zwrite(1,&bin[k+1],LBIN-k-1); ! 200: if(i>0) ! 201: zwrite(1,bin,i); ! 202: } ! 203: fexit(); ! 204: errcom: ! 205: fprintf(stderr, "usage: tail [+_[n][lbc][rf]] [file]\n"); ! 206: exit(2); ! 207: } ! 208: ! 209: fexit() ! 210: { register int n; ! 211: long amtread; ! 212: if (!follow || piped) exit(0); ! 213: amtread = lseek(infd, 0L, 1); ! 214: for (;;) { ! 215: sleep(5); ! 216: if(fstat(infd, &statb) == -1) ! 217: exit(1); ! 218: if(statb.st_size < amtread) { ! 219: fprintf(stderr, "tail: file truncated; restarting\n"); ! 220: lseek(infd, 0L, 0); ! 221: amtread = 0; ! 222: } ! 223: while ((n = read (infd, bin, BUFSIZ)) > 0) { ! 224: zwrite (1, bin, n); ! 225: amtread += n; ! 226: } ! 227: if(n < 0) ! 228: exit(1); ! 229: } ! 230: } ! 231: ! 232: zwrite(f, b, n) ! 233: char *b; ! 234: { ! 235: if (n!=0) ! 236: write(f, b, n); ! 237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.