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

Defined functions

fexit defined in line 231; used 5 times
main defined in line 50; never used

Defined variables

bin defined in line 47; used 18 times
copyright defined in line 8; never used
errno defined in line 48; used 1 times
  • in line 83
follow defined in line 45; used 3 times
piped defined in line 46; used 5 times
sccsid defined in line 12; never used
statb defined in line 44; used 4 times

Defined macros

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