summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/plan9/_envsetup.c
blob: 58ed0534203c1bbb2460deb265f98d7e2a34e4a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "lib.h"
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "sys9.h"
#include "dir.h"

/*
 * Called before main to initialize environ.
 * Some plan9 environment variables
 * have 0 bytes in them (notably $path);
 * we change them to 1's (and execve changes back)
 *
 * Also, register the note handler.
 */

char **environ;
int *_errnoloc;
unsigned long _clock;
static void fdsetup(char *, char *);
static void sigsetup(char *, char *);

enum {
	Envhunk=7000,
};

void
_envsetup(void)
{
	int dfd;
	int n, nd, m, i, j, f;
	int psize, cnt;
	int nohandle;
	int fdinited;
	char *ps, *p;
	char **pp;
	Dir *d9, *d9a;

	ps = 0;
	psize = 0;
	nohandle = 0;
	fdinited = 0;
	cnt = 0;
	dfd = _OPEN("/env", OREAD);
	if(dfd < 0)
		goto done;
	psize = Envhunk;
	ps = p = malloc(psize);
	nd = _dirreadall(dfd, &d9a);
	_CLOSE(dfd);
	for(j=0; j<nd; j++){
		d9 = &d9a[j];
		n = strlen(d9->name);
		m = d9->length;
		i = p - ps;
		if(i+n+5+m+1 > psize) {
			psize += (n+m+6 < Envhunk)? Envhunk : n+m+6;
			ps = realloc(ps, psize);
			p = ps + i;
		}
		strcpy(p, "/env/");
		memcpy(p+5, d9->name, n+1);
		f = _OPEN(p, OREAD);
		memset(p, 0, n+6);
		memcpy(p, d9->name, n);
		p[n] = '=';
		if(f < 0 || _READ(f, p+n+1, m) != m)
			m = 0;
		_CLOSE(f);
		if(p[n+m] == 0)
			m--;
		for(i=0; i<m; i++)
			if(p[n+1+i] == 0)
				p[n+1+i] = 1;
		p[n+1+m] = 0;
		if(strcmp(d9->name, "_fdinfo") == 0) {
			_fdinit(p+n+1, p+n+1+m);
			fdinited = 1;
		} else if(strcmp(d9->name, "_sighdlr") == 0)
			sigsetup(p+n+1, p+n+1+m);
		else if(strcmp(d9->name, "nohandle") == 0)
			nohandle = 1;
		p += n+m+2;
		cnt++;
	}
	free(d9a);
	if(!fdinited)
		_fdinit(0, 0);
done:
	environ = pp = malloc((1+cnt)*sizeof(char *));
	p = ps;
	for(i = 0; i < cnt; i++) {
		*pp++ = p;
		p = memchr(p, 0, ps+psize-p);
		if (!p)
			break;
		p++;
	}
	*pp = 0;
	if(!nohandle)
		_NOTIFY(_notehandler);
}

static void
sigsetup(char *s, char *se)
{
	int sig;
	char *e;

	while(s < se){
		sig = strtoul(s, &e, 10);
		if(s == e)
			break;
		s = e;
		if(sig <= MAXSIG)
			_sighdlr[sig] = SIG_IGN;
	}
}