_fdinfo.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #define _BSDTIME_EXTENSION
  2. #include "lib.h"
  3. #include <sys/stat.h>
  4. #include <stdlib.h>
  5. #include "sys9.h"
  6. #include <string.h>
  7. extern int errno;
  8. Fdinfo _fdinfo[OPEN_MAX];
  9. /*
  10. called from _envsetup, either with the value of the environment
  11. variable _fdinfo (from s to se-1), or with s==0 if there was no _fdinfo
  12. */
  13. static void
  14. defaultfdinit(void)
  15. {
  16. int i;
  17. Fdinfo *fi;
  18. for(i = 0; i <= 2; i++) {
  19. fi = &_fdinfo[i];
  20. fi->flags = FD_ISOPEN;
  21. fi->oflags = (i == 0)? O_RDONLY : O_WRONLY;
  22. if(_isatty(i))
  23. fi->flags |= FD_ISTTY;
  24. }
  25. }
  26. static int
  27. readprocfdinit(void)
  28. {
  29. /* construct info from /proc/$pid/fd */
  30. char buf[8192];
  31. Fdinfo *fi;
  32. int fd, pfd, pid, n, tot, m;
  33. char *s, *nexts;
  34. memset(buf, 0, sizeof buf);
  35. pfd = _OPEN("#c/pid", 0);
  36. if(pfd < 0)
  37. return -1;
  38. if(_PREAD(pfd, buf, 100, 0) < 0){
  39. _CLOSE(pfd);
  40. return -1;
  41. }
  42. _CLOSE(pfd);
  43. pid = strtoul(buf, 0, 10);
  44. strcpy(buf, "#p/");
  45. _ultoa(buf+3, pid);
  46. strcat(buf, "/fd");
  47. pfd = _OPEN(buf, 0);
  48. if(pfd < 0)
  49. return -1;
  50. memset(buf, 0, sizeof buf);
  51. tot = 0;
  52. for(;;){
  53. n = _PREAD(pfd, buf+tot, sizeof buf-tot, tot);
  54. if(n <= 0)
  55. break;
  56. tot += n;
  57. }
  58. _CLOSE(pfd);
  59. if(n < 0)
  60. return -1;
  61. buf[sizeof buf-1] = '\0';
  62. s = strchr(buf, '\n'); /* skip current directory */
  63. if(s == 0)
  64. return -1;
  65. s++;
  66. m = 0;
  67. for(; s && *s; s=nexts){
  68. nexts = strchr(s, '\n');
  69. if(nexts)
  70. *nexts++ = '\0';
  71. errno = 0;
  72. fd = strtoul(s, &s, 10);
  73. if(errno != 0)
  74. return -1;
  75. if(fd >= OPEN_MAX)
  76. continue;
  77. if(fd == pfd)
  78. continue;
  79. fi = &_fdinfo[fd];
  80. fi->flags = FD_ISOPEN;
  81. while(*s == ' ' || *s == '\t')
  82. s++;
  83. if(*s == 'r'){
  84. m |= 1;
  85. s++;
  86. }
  87. if(*s == 'w'){
  88. m |= 2;
  89. }
  90. if(m==1)
  91. fi->oflags = O_RDONLY;
  92. else if(m==2)
  93. fi->oflags = O_WRONLY;
  94. else
  95. fi->oflags = O_RDWR;
  96. if(strlen(s) >= 9 && strcmp(s+strlen(s)-9, "/dev/cons") == 0)
  97. fi->flags |= FD_ISTTY;
  98. }
  99. return 0;
  100. }
  101. static void
  102. sfdinit(int usedproc, char *s, char *se)
  103. {
  104. int i;
  105. Fdinfo *fi;
  106. unsigned long fd, fl, ofl;
  107. char *e;
  108. struct stat sbuf;
  109. while(s < se){
  110. fd = strtoul(s, &e, 10);
  111. if(s == e)
  112. break;
  113. s = e;
  114. fl = strtoul(s, &e, 10);
  115. if(s == e)
  116. break;
  117. s = e;
  118. ofl = strtoul(s, &e, 10);
  119. if(s == e)
  120. break;
  121. s = e;
  122. if(fd < OPEN_MAX){
  123. fi = &_fdinfo[fd];
  124. if(usedproc && !(fi->flags&FD_ISOPEN))
  125. continue; /* should probably ignore all of $_fdinit */
  126. fi->flags = fl;
  127. fi->oflags = ofl;
  128. if(_isatty(fd))
  129. fi->flags |= FD_ISTTY;
  130. }
  131. }
  132. }
  133. void
  134. _fdinit(char *s, char *se)
  135. {
  136. int i, usedproc;
  137. Fdinfo *fi;
  138. struct stat sbuf;
  139. usedproc = 0;
  140. if(readprocfdinit() == 0)
  141. usedproc = 1;
  142. else
  143. _WRITE(2, "FAILED\n", 7);
  144. if(s)
  145. sfdinit(usedproc, s, se);
  146. if(!s && !usedproc)
  147. defaultfdinit();
  148. for(i = 0; i < OPEN_MAX; i++) {
  149. fi = &_fdinfo[i];
  150. if(fi->flags&FD_ISOPEN){
  151. if(fstat(i, &sbuf) >= 0) {
  152. fi->uid = sbuf.st_uid;
  153. fi->gid = sbuf.st_gid;
  154. }
  155. }
  156. }
  157. }