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