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 = (int) (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 - ((int) 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: }