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