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.2 (Berkeley) 1/10/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:             (void)write (1, bin, n);
 236:     }
 237: }

Defined functions

fexit defined in line 229; used 5 times
main defined in line 48; never used

Defined variables

bin defined in line 45; used 18 times
copyright defined in line 8; never used
errno defined in line 46; used 1 times
  • in line 81
follow defined in line 43; used 3 times
piped defined in line 44; used 5 times
sccsid defined in line 14; never used
statb defined in line 42; used 4 times

Defined macros

BUFSIZ defined in line 41; used 6 times
LBIN defined in line 39; used 13 times
Last modified: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1038
Valid CSS Valid XHTML 1.0 Strict