| #include <u.h> |
| #include <libc.h> |
| |
| int multi; |
| int nlines; |
| char *status = nil; |
| |
| int |
| line(int fd, char *file) |
| { |
| char c; |
| int m, n, nalloc; |
| char *buf; |
| |
| nalloc = 0; |
| buf = nil; |
| for(m=0; ; ){ |
| n = read(fd, &c, 1); |
| if(n < 0){ |
| fprint(2, "read: error reading %s: %r\n", file); |
| exits("read error"); |
| } |
| if(n == 0){ |
| if(m == 0) |
| status = "eof"; |
| break; |
| } |
| if(m == nalloc){ |
| nalloc += 1024; |
| buf = realloc(buf, nalloc); |
| if(buf == nil){ |
| fprint(2, "read: malloc error: %r\n"); |
| exits("malloc"); |
| } |
| } |
| buf[m++] = c; |
| if(c == '\n') |
| break; |
| } |
| if(m > 0) |
| write(1, buf, m); |
| free(buf); |
| return m; |
| } |
| |
| void |
| lines(int fd, char *file) |
| { |
| do{ |
| if(line(fd, file) == 0) |
| break; |
| }while(multi || --nlines>0); |
| } |
| |
| void |
| main(int argc, char *argv[]) |
| { |
| int i, fd; |
| char *s; |
| |
| ARGBEGIN{ |
| case 'm': |
| multi = 1; |
| break; |
| case 'n': |
| s = ARGF(); |
| if(s){ |
| nlines = atoi(s); |
| break; |
| } |
| /* fall through */ |
| default: |
| fprint(2, "usage: read [-m] [-n nlines] [files...]\n"); |
| exits("usage"); |
| }ARGEND |
| |
| if(argc == 0) |
| lines(0, "<stdin>"); |
| else |
| for(i=0; i<argc; i++){ |
| fd = open(argv[i], OREAD); |
| if(fd < 0){ |
| fprint(2, "read: can't open %s: %r\n", argv[i]); |
| exits("open"); |
| } |
| lines(fd, argv[i]); |
| close(fd); |
| } |
| |
| exits(status); |
| } |