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", argv[i]);
    116 				exits("open");
    117 			}
    118 			(*proc)(fd, argv[i]);
    119 			close(fd);
    120 		}
    121 
    122 	exits(status);
    123 }