read.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
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", a… | |
116 exits("open"); | |
117 } | |
118 (*proc)(fd, argv[i]); | |
119 close(fd); | |
120 } | |
121 | |
122 exits(status); | |
123 } |