xref: /plan9/sys/src/ape/lib/ap/plan9/_fdinfo.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
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