xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/_envsetup.c (revision 1936bb650459bace06c38a45b60888b47e5cd459)
1 #include "lib.h"
2 #include <stdlib.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <dirent.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <signal.h>
9 #include "sys9.h"
10 #include "dir.h"
11 
12 /*
13  * Called before main to initialize environ.
14  * Some plan9 environment variables
15  * have 0 bytes in them (notably $path);
16  * we change them to 1's (and execve changes back)
17  *
18  * Also, register the note handler.
19  */
20 
21 char **environ;
22 int errno;
23 unsigned long _clock;
24 
25 static void fdsetup(char *, char *);
26 static void sigsetup(char *, char *);
27 
28 enum {
29 	Envhunk=7000,
30 };
31 
32 void
33 _envsetup(void)
34 {
35 	int dfd, fdinited, n, nd, m, i, j, f, nohandle, psize, cnt;
36 	char *ps, *p;
37 	char **pp;
38 	char name[NAME_MAX+5];
39 	Dir *d9, *d9a;
40 	struct dirent *de;
41 	static char **emptyenvp = 0;
42 
43 	environ = emptyenvp;		/* pessimism */
44 	nohandle = 0;
45 	fdinited = 0;
46 	cnt = 0;
47 	strcpy(name, "#e");
48 	dfd = _OPEN(name, 0);
49 	if(dfd < 0)
50 		return;
51 	name[2] = '/';
52 	ps = p = malloc(Envhunk);
53 	if(p == 0)
54 		return;
55 	psize = Envhunk;
56 	nd = _dirreadall(dfd, &d9a);
57 	_CLOSE(dfd);
58 	for(j=0; j<nd; j++){
59 		d9 = &d9a[j];
60 		n = strlen(d9->name);
61 		if(n >= sizeof name - 4)
62 			continue;	/* shouldn't be possible */
63 		m = d9->length;
64 		i = p - ps;
65 		if(i+n+1+m+1 > psize) {
66 			psize += (n+m+2 < Envhunk)? Envhunk : n+m+2;
67 			ps = realloc(ps, psize);
68 			if (ps == 0) {
69 				free(d9a);
70 				return;
71 			}
72 			p = ps + i;
73 		}
74 		memcpy(p, d9->name, n);
75 		p[n] = '=';
76 		strcpy(name+3, d9->name);
77 		f = _OPEN(name, O_RDONLY);
78 		if(f < 0 || _READ(f, p+n+1, m) != m)
79 			m = 0;
80 		_CLOSE(f);
81 		if(p[n+m] == 0)
82 			m--;
83 		for(i=0; i<m; i++)
84 			if(p[n+1+i] == 0)
85 				p[n+1+i] = 1;
86 		p[n+1+m] = 0;
87 		if(strcmp(d9->name, "_fdinfo") == 0) {
88 			_fdinit(p+n+1, p+n+1+m);
89 			fdinited = 1;
90 		} else if(strcmp(d9->name, "_sighdlr") == 0)
91 			sigsetup(p+n+1, p+n+1+m);
92 		else if(strcmp(d9->name, "nohandle") == 0)
93 			nohandle = 1;
94 		p += n+m+2;
95 		cnt++;
96 	}
97 	free(d9a);
98 	if(!fdinited)
99 		_fdinit(0, 0);
100 	pp = malloc((1+cnt)*sizeof(char *));
101 	if (pp == 0)
102 		return;
103 	environ = pp;
104 	p = ps;
105 	for(i = 0; i < cnt; i++) {
106 		*pp++ = p;
107 		p = memchr(p, 0, ps+psize-p);
108 		if (!p)
109 			break;
110 		p++;
111 	}
112 	*pp = 0;
113 	if(!nohandle)
114 		_NOTIFY(_notehandler);
115 }
116 
117 static void
118 sigsetup(char *s, char *se)
119 {
120 	int i, sig;
121 	char *e;
122 
123 	while(s < se){
124 		sig = strtoul(s, &e, 10);
125 		if(s == e)
126 			break;
127 		s = e;
128 		if(sig <= MAXSIG)
129 			_sighdlr[sig] = SIG_IGN;
130 	}
131 }
132