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