home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / tail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-05-14  |  3.0 KB  |  185 lines

  1. /* tail command 
  2.  *
  3.  *    tail where [file]
  4.  *    where is +_n[type]
  5.  *    - means n lines before end
  6.  *    + means nth line from beginning
  7.  *    type 'b' means tail n blocks, not lines
  8.  *    type 'c' means tail n characters
  9.  *    Type 'r' means in lines in reverse order from end
  10.  *     (for -r, default is entire buffer )
  11. */
  12. #include    <sys/types.h>
  13. #include    <sys/stat.h>
  14. #include    <errno.h>
  15. #define LBIN 4097
  16. struct    stat    statb;
  17. char bin[LBIN];
  18. int errno;
  19.  
  20. main(argc,argv)
  21. char **argv;
  22. {
  23.     long n,di;
  24.     register i,j,k;
  25.     char *p;
  26.     int partial,piped,bylines,bkwds,fromend,lastnl;
  27.     char *arg;
  28.     lseek(0,(long)0,1);
  29.     piped = errno==ESPIPE;
  30.     arg = argv[1];
  31.     if(argc<=1 || *arg!='-'&&*arg!='+') {
  32.         arg = "-10l";
  33.         argc++;
  34.         argv--;
  35.     }
  36.     fromend = *arg=='-';
  37.     arg++;
  38.     n = 0;
  39.     while(digit(*arg))
  40.         n = n*10 + *arg++ - '0';
  41.     if(!fromend&&n>0)
  42.         n--;
  43.     if(argc>2) {
  44.         close(0);
  45.         if(open(argv[2],0)!=0) {
  46.             write(2,"tail: can't open ",17);
  47.             write(2,argv[2],strlen(argv[2]));
  48.             write(2,"\n",1);
  49.             exit(1);
  50.         }
  51.     }
  52.     bylines = 0; bkwds = 0;
  53.     switch(*arg) {
  54.     case 'b':
  55.         n <<= 9;
  56.         break;
  57.     case 'c':
  58.         break;
  59.     case 'r':
  60.         if(n==0) n = LBIN;
  61.         bkwds = 1; fromend = 1; bylines = 1;
  62.         break;
  63.     case '\0':
  64.     case 'l':
  65.         bylines = 1;
  66.         break;
  67.     default:
  68.         goto errcom;
  69.     }
  70.     if(fromend)
  71.         goto keep;
  72.  
  73.             /*seek from beginning */
  74.  
  75.     if(bylines) {
  76.         j = 0;
  77.         while(n-->0) {
  78.             do {
  79.                 if(j--<=0) {
  80.                     p = bin;
  81.                     j = read(0,p,512);
  82.                     if(j--<=0) exit(0);
  83.                 }
  84.             } while(*p++ != '\n');
  85.         }
  86.         write(1,p,j);
  87.     } else  if(n>0) {
  88.         if(!piped)
  89.             fstat(0,&statb);
  90.         if(piped||(statb.st_mode&S_IFMT)==S_IFCHR)
  91.             while(n>0) {
  92.                 i = n>512?512:n;
  93.                 i = read(0,bin,i);
  94.                 if(i<=0) exit(0);
  95.                 n -= i;
  96.             }
  97.         else
  98.             lseek(0,n,0);
  99.     }
  100. copy:
  101.     while((i=read(0,bin,512))>0)
  102.         write(1,bin,i);
  103.     exit(0);
  104.  
  105.             /*seek from end*/
  106.  
  107. keep:
  108.     if(n<=0) exit(0);
  109.     if(!piped) {
  110.         fstat(0,&statb);
  111.         di = !bylines? n: LBIN-1;
  112.         if(statb.st_size > di)
  113.             lseek(0,-di,2);
  114.         if(!bylines)
  115.             goto copy;
  116.     }
  117.     partial = 1;
  118.     for(;;) {
  119.         i = 0;
  120.         do {
  121.             j = read(0,&bin[i],LBIN-i);
  122.             if(j<=0)
  123.                 goto brka;
  124.             i += j;
  125.         } while(i<LBIN);
  126.         partial = 0;
  127.     }
  128. brka:
  129.     if(!bylines) {
  130.         k =
  131.             n<=i ? i-n:
  132.             partial ? 0:
  133.             n>=LBIN ? i+1:
  134.             i-n+LBIN;
  135.         k--;
  136.     } else {
  137.         if(bkwds && bin[i==0?LBIN-1:i-1]!='\n'){    /* force trailing newline */
  138.             bin[i]='\n';
  139.             if(++i>=LBIN) {i = 0; partial = 0;}
  140.         }
  141.         k = i;
  142.         j = 0;
  143.         do {
  144.             lastnl = k;
  145.             do {
  146.                 if(--k<0) {
  147.                     if(partial) {
  148.                         if(bkwds) write(1,bin,lastnl+1);
  149.                         goto brkb;
  150.                     }
  151.                     k = LBIN -1;
  152.                 }
  153.             } while(bin[k]!='\n'&&k!=i);
  154.             if(bkwds && j>0){
  155.                 if(k<lastnl) write(1,&bin[k+1],lastnl-k);
  156.                 else {
  157.                     write(1,&bin[k+1],LBIN-k-1);
  158.                     write(1,bin,lastnl+1);
  159.                 }
  160.             }
  161.         } while(j++<n&&k!=i);
  162. brkb:
  163.         if(bkwds) exit(0);
  164.         if(k==i) do {
  165.             if(++k>=LBIN)
  166.                 k = 0;
  167.         } while(bin[k]!='\n'&&k!=i);
  168.     }
  169.     if(k<i)
  170.         write(1,&bin[k+1],i-k-1);
  171.     else {
  172.         write(1,&bin[k+1],LBIN-k-1);
  173.         write(1,bin,i);
  174.     }
  175.     exit(0);
  176. errcom:
  177.     write(2,"usage: tail +_n[lbcr] [file]\n",30);
  178.     exit(1);
  179. }
  180.  
  181. digit(c)
  182. {
  183.     return(c>='0'&&c<='9');
  184. }
  185.