1 #include <u.h>
2 #include <libc.h>
3 
4 int	multi;
5 int	nlines;
6 char	*status = nil;
7 
8 int
line(int fd,char * file)9 line(int fd, char *file)
10 {
11 	char c;
12 	int m, n, nalloc;
13 	char *buf;
14 
15 	nalloc = 0;
16 	buf = nil;
17 	for(m=0; ; ){
18 		n = read(fd, &c, 1);
19 		if(n < 0){
20 			fprint(2, "read: error reading %s: %r\n", file);
21 			exits("read error");
22 		}
23 		if(n == 0){
24 			if(m == 0)
25 				status = "eof";
26 			break;
27 		}
28 		if(m == nalloc){
29 			nalloc += 1024;
30 			buf = realloc(buf, nalloc);
31 			if(buf == nil){
32 				fprint(2, "read: malloc error: %r\n");
33 				exits("malloc");
34 			}
35 		}
36 		buf[m++] = c;
37 		if(c == '\n')
38 			break;
39 	}
40 	if(m > 0)
41 		write(1, buf, m);
42 	free(buf);
43 	return m;
44 }
45 
46 void
lines(int fd,char * file)47 lines(int fd, char *file)
48 {
49 	do{
50 		if(line(fd, file) == 0)
51 			break;
52 	}while(multi || --nlines>0);
53 }
54 
55 void
main(int argc,char * argv[])56 main(int argc, char *argv[])
57 {
58 	int i, fd;
59 	char *s;
60 
61 	ARGBEGIN{
62 	case 'm':
63 		multi = 1;
64 		break;
65 	case 'n':
66 		s = ARGF();
67 		if(s){
68 			nlines = atoi(s);
69 			break;
70 		}
71 		/* fall through */
72 	default:
73 		fprint(2, "usage: read [-m] [-n nlines] [files...]\n");
74 		exits("usage");
75 	}ARGEND
76 
77 	if(argc == 0)
78 		lines(0, "<stdin>");
79 	else
80 		for(i=0; i<argc; i++){
81 			fd = open(argv[i], OREAD);
82 			if(fd < 0){
83 				fprint(2, "read: can't open %s: %r\n", argv[i]);
84 				exits("open");
85 			}
86 			lines(fd, argv[i]);
87 			close(fd);
88 		}
89 
90 	exits(status);
91 }
92