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