read.c 1.2 KB

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