read.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       read.c (1771B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 
            4 int        multi;
            5 int        nlines;
            6 vlong        nchars;
            7 char        *status = nil;
            8 
            9 int
           10 line(int fd, char *file)
           11 {
           12         char c;
           13         int m, n, nalloc;
           14         char *buf;
           15 
           16         nalloc = 0;
           17         buf = nil;
           18         for(m=0; ; ){
           19                 n = read(fd, &c, 1);
           20                 if(n < 0){
           21                         fprint(2, "read: error reading %s: %r\n", file);
           22                         exits("read error");
           23                 }
           24                 if(n == 0){
           25                         if(m == 0)
           26                                 status = "eof";
           27                         break;
           28                 }
           29                 if(m == nalloc){
           30                         nalloc += 1024;
           31                         buf = realloc(buf, nalloc);
           32                         if(buf == nil){
           33                                 fprint(2, "read: malloc error: %r\n");
           34                                 exits("malloc");
           35                         }
           36                 }
           37                 buf[m++] = c;
           38                 if(c == '\n')
           39                         break;
           40         }
           41         if(m > 0)
           42                 write(1, buf, m);
           43         free(buf);
           44         return m;
           45 }
           46 
           47 void
           48 lines(int fd, char *file)
           49 {
           50         do{
           51                 if(line(fd, file) == 0)
           52                         break;
           53         }while(multi || --nlines>0);
           54 }
           55 
           56 void
           57 chars(int fd, char *file)
           58 {
           59         char buf[8*1024];
           60         vlong m;
           61         int n;
           62 
           63         for(m = 0; m < nchars; m += n){
           64                 n = sizeof(buf);
           65                 if(n > (nchars - m))
           66                         n = nchars - m;
           67                 if((n = read(fd, buf, n)) < 0){
           68                         fprint(2, "read: error reading %s: %r\n", file);
           69                         exits("read error");
           70                 }
           71                 if(n == 0){
           72                         if(m == 0)
           73                                 status = "eof";
           74                         break;
           75                 }
           76                 write(1, buf, n);
           77         }
           78 }
           79 
           80 void
           81 usage(void)
           82 {
           83         fprint(2, "usage: read [-m] [-n nlines] [-c nbytes] [files...]\n");
           84         exits("usage");
           85 }
           86 
           87 void
           88 main(int argc, char *argv[])
           89 {
           90         void (*proc)(int, char*);
           91         int i, fd;
           92 
           93         proc = lines;
           94         ARGBEGIN{
           95         case 'c':
           96                 nchars = atoll(EARGF(usage()));
           97                 proc = chars;
           98                 break;
           99         case 'n':
          100                 nlines = atoi(EARGF(usage()));
          101                 break;
          102         case 'm':
          103                 multi = 1;
          104                 break;
          105         default:
          106                 usage();
          107         }ARGEND
          108 
          109         if(argc == 0)
          110                 (*proc)(0, "<stdin>");
          111         else
          112                 for(i=0; i<argc; i++){
          113                         fd = open(argv[i], OREAD);
          114                         if(fd < 0){
          115                                 fprint(2, "read: can't open %s: %r\n", argv[i]);
          116                                 exits("open");
          117                         }
          118                         (*proc)(fd, argv[i]);
          119                         close(fd);
          120                 }
          121 
          122         exits(status);
          123 }