xref: /plan9/sys/src/cmd/fossil/9srv.c (revision 5e96a66c77eb9140492ca53f857cbbf108e128ed)
1*5e96a66cSDavid du Colombier #include "stdinc.h"
2*5e96a66cSDavid du Colombier 
3*5e96a66cSDavid du Colombier #include "9.h"
4*5e96a66cSDavid du Colombier 
5*5e96a66cSDavid du Colombier typedef struct Srv Srv;
6*5e96a66cSDavid du Colombier typedef struct Srv {
7*5e96a66cSDavid du Colombier 	int	fd;
8*5e96a66cSDavid du Colombier 	int	srvfd;
9*5e96a66cSDavid du Colombier 	char*	service;
10*5e96a66cSDavid du Colombier 	char*	mntpnt;
11*5e96a66cSDavid du Colombier 
12*5e96a66cSDavid du Colombier 	Srv*	next;
13*5e96a66cSDavid du Colombier 	Srv*	prev;
14*5e96a66cSDavid du Colombier } Srv;
15*5e96a66cSDavid du Colombier 
16*5e96a66cSDavid du Colombier static struct {
17*5e96a66cSDavid du Colombier 	VtLock*	lock;
18*5e96a66cSDavid du Colombier 
19*5e96a66cSDavid du Colombier 	Srv*	head;
20*5e96a66cSDavid du Colombier 	Srv*	tail;
21*5e96a66cSDavid du Colombier } sbox;
22*5e96a66cSDavid du Colombier 
23*5e96a66cSDavid du Colombier static int
24*5e96a66cSDavid du Colombier srvFd(char* name, int mode, int fd)
25*5e96a66cSDavid du Colombier {
26*5e96a66cSDavid du Colombier 	int n, srvfd;
27*5e96a66cSDavid du Colombier 	char buf[10], srv[VtMaxStringSize];
28*5e96a66cSDavid du Colombier 
29*5e96a66cSDavid du Colombier 	/*
30*5e96a66cSDavid du Colombier 	 * Drop a file descriptor with given name and mode into /srv.
31*5e96a66cSDavid du Colombier 	 * Create with ORCLOSE and don't close srvfd so it will be removed
32*5e96a66cSDavid du Colombier 	 * automatically on process exit.
33*5e96a66cSDavid du Colombier 	 */
34*5e96a66cSDavid du Colombier 	snprint(srv, sizeof(srv), "/srv/%s", name);
35*5e96a66cSDavid du Colombier 	if((srvfd = create(srv, ORCLOSE|OWRITE, mode)) < 0){
36*5e96a66cSDavid du Colombier 		snprint(srv, sizeof(srv), "#s/%s", name);
37*5e96a66cSDavid du Colombier 		if((srvfd = create(srv, ORCLOSE|OWRITE, mode)) < 0){
38*5e96a66cSDavid du Colombier 			vtSetError("create %s: %r", srv);
39*5e96a66cSDavid du Colombier 			return -1;
40*5e96a66cSDavid du Colombier 		}
41*5e96a66cSDavid du Colombier 	}
42*5e96a66cSDavid du Colombier 
43*5e96a66cSDavid du Colombier 	n = snprint(buf, sizeof(buf), "%d", fd);
44*5e96a66cSDavid du Colombier 	if(write(srvfd, buf, n) < 0){
45*5e96a66cSDavid du Colombier 		close(srvfd);
46*5e96a66cSDavid du Colombier 		vtSetError("write %s: %r", srv);
47*5e96a66cSDavid du Colombier 		return -1;
48*5e96a66cSDavid du Colombier 	}
49*5e96a66cSDavid du Colombier 
50*5e96a66cSDavid du Colombier 	return srvfd;
51*5e96a66cSDavid du Colombier }
52*5e96a66cSDavid du Colombier 
53*5e96a66cSDavid du Colombier static void
54*5e96a66cSDavid du Colombier srvFree(Srv* srv)
55*5e96a66cSDavid du Colombier {
56*5e96a66cSDavid du Colombier 	if(srv->prev != nil)
57*5e96a66cSDavid du Colombier 		srv->prev->next = srv->next;
58*5e96a66cSDavid du Colombier 	else
59*5e96a66cSDavid du Colombier 		sbox.head = srv->next;
60*5e96a66cSDavid du Colombier 	if(srv->next != nil)
61*5e96a66cSDavid du Colombier 		srv->next->prev = srv->prev;
62*5e96a66cSDavid du Colombier 	else
63*5e96a66cSDavid du Colombier 		sbox.tail = srv->prev;
64*5e96a66cSDavid du Colombier 
65*5e96a66cSDavid du Colombier 	if(srv->srvfd != -1)
66*5e96a66cSDavid du Colombier 		close(srv->srvfd);
67*5e96a66cSDavid du Colombier 	vtMemFree(srv->service);
68*5e96a66cSDavid du Colombier 	vtMemFree(srv->mntpnt);
69*5e96a66cSDavid du Colombier 	vtMemFree(srv);
70*5e96a66cSDavid du Colombier }
71*5e96a66cSDavid du Colombier 
72*5e96a66cSDavid du Colombier static Srv*
73*5e96a66cSDavid du Colombier srvAlloc(char* service, int mode, int fd)
74*5e96a66cSDavid du Colombier {
75*5e96a66cSDavid du Colombier 	Srv *srv;
76*5e96a66cSDavid du Colombier 	int srvfd;
77*5e96a66cSDavid du Colombier 
78*5e96a66cSDavid du Colombier 	vtLock(sbox.lock);
79*5e96a66cSDavid du Colombier 	for(srv = sbox.head; srv != nil; srv = srv->next){
80*5e96a66cSDavid du Colombier 		if(strcmp(srv->service, service) != 0)
81*5e96a66cSDavid du Colombier 			continue;
82*5e96a66cSDavid du Colombier 		vtSetError("srv: already serving '%s'", service);
83*5e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
84*5e96a66cSDavid du Colombier 		return nil;
85*5e96a66cSDavid du Colombier 	}
86*5e96a66cSDavid du Colombier 
87*5e96a66cSDavid du Colombier 	if((srvfd = srvFd(service, mode, fd)) < 0){
88*5e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
89*5e96a66cSDavid du Colombier 		return nil;
90*5e96a66cSDavid du Colombier 	}
91*5e96a66cSDavid du Colombier 	close(fd);
92*5e96a66cSDavid du Colombier 
93*5e96a66cSDavid du Colombier 	srv = vtMemAllocZ(sizeof(Srv));
94*5e96a66cSDavid du Colombier 	srv->srvfd = srvfd;
95*5e96a66cSDavid du Colombier 	srv->service = vtStrDup(service);
96*5e96a66cSDavid du Colombier 
97*5e96a66cSDavid du Colombier 	if(sbox.tail != nil){
98*5e96a66cSDavid du Colombier 		srv->prev = sbox.tail;
99*5e96a66cSDavid du Colombier 		sbox.tail->next = srv;
100*5e96a66cSDavid du Colombier 	}
101*5e96a66cSDavid du Colombier 	else{
102*5e96a66cSDavid du Colombier 		sbox.head = srv;
103*5e96a66cSDavid du Colombier 		srv->prev = nil;
104*5e96a66cSDavid du Colombier 	}
105*5e96a66cSDavid du Colombier 	sbox.tail = srv;
106*5e96a66cSDavid du Colombier 	vtUnlock(sbox.lock);
107*5e96a66cSDavid du Colombier 
108*5e96a66cSDavid du Colombier 	return srv;
109*5e96a66cSDavid du Colombier }
110*5e96a66cSDavid du Colombier 
111*5e96a66cSDavid du Colombier static int
112*5e96a66cSDavid du Colombier cmdSrv(int argc, char* argv[])
113*5e96a66cSDavid du Colombier {
114*5e96a66cSDavid du Colombier 	Srv *srv;
115*5e96a66cSDavid du Colombier 	int dflag, fd[2], mode, pflag, r;
116*5e96a66cSDavid du Colombier 	char *usage = "usage: srv [-dp] [service]";
117*5e96a66cSDavid du Colombier 
118*5e96a66cSDavid du Colombier 	dflag = pflag = 0;
119*5e96a66cSDavid du Colombier 	mode = 0666;
120*5e96a66cSDavid du Colombier 
121*5e96a66cSDavid du Colombier 	ARGBEGIN{
122*5e96a66cSDavid du Colombier 	default:
123*5e96a66cSDavid du Colombier 		return cliError(usage);
124*5e96a66cSDavid du Colombier 	case 'd':
125*5e96a66cSDavid du Colombier 		dflag = 1;
126*5e96a66cSDavid du Colombier 		break;
127*5e96a66cSDavid du Colombier 	case 'p':
128*5e96a66cSDavid du Colombier 		pflag = 1;
129*5e96a66cSDavid du Colombier 		mode = 0600;
130*5e96a66cSDavid du Colombier 		break;
131*5e96a66cSDavid du Colombier 	}ARGEND
132*5e96a66cSDavid du Colombier 
133*5e96a66cSDavid du Colombier 	switch(argc){
134*5e96a66cSDavid du Colombier 	default:
135*5e96a66cSDavid du Colombier 		return cliError(usage);
136*5e96a66cSDavid du Colombier 	case 0:
137*5e96a66cSDavid du Colombier 		vtRLock(sbox.lock);
138*5e96a66cSDavid du Colombier 		for(srv = sbox.head; srv != nil; srv = srv->next)
139*5e96a66cSDavid du Colombier 			consPrint("\t%s\t%d\n", srv->service, srv->srvfd);
140*5e96a66cSDavid du Colombier 		vtRUnlock(sbox.lock);
141*5e96a66cSDavid du Colombier 
142*5e96a66cSDavid du Colombier 		return 1;
143*5e96a66cSDavid du Colombier 	case 1:
144*5e96a66cSDavid du Colombier 		if(!dflag)
145*5e96a66cSDavid du Colombier 			break;
146*5e96a66cSDavid du Colombier 
147*5e96a66cSDavid du Colombier 		vtLock(sbox.lock);
148*5e96a66cSDavid du Colombier 		for(srv = sbox.head; srv != nil; srv = srv->next){
149*5e96a66cSDavid du Colombier 			if(strcmp(srv->service, argv[0]) != 0)
150*5e96a66cSDavid du Colombier 				continue;
151*5e96a66cSDavid du Colombier 			srvFree(srv);
152*5e96a66cSDavid du Colombier 			break;
153*5e96a66cSDavid du Colombier 		}
154*5e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
155*5e96a66cSDavid du Colombier 
156*5e96a66cSDavid du Colombier 		if(srv == nil){
157*5e96a66cSDavid du Colombier 			vtSetError("srv: '%s' not found", argv[0]);
158*5e96a66cSDavid du Colombier 			return 0;
159*5e96a66cSDavid du Colombier 		}
160*5e96a66cSDavid du Colombier 
161*5e96a66cSDavid du Colombier 		return 1;
162*5e96a66cSDavid du Colombier 	}
163*5e96a66cSDavid du Colombier 
164*5e96a66cSDavid du Colombier 	if(pipe(fd) < 0){
165*5e96a66cSDavid du Colombier 		vtSetError("srv pipe: %r");
166*5e96a66cSDavid du Colombier 		return 0;
167*5e96a66cSDavid du Colombier 	}
168*5e96a66cSDavid du Colombier 	if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){
169*5e96a66cSDavid du Colombier 		close(fd[0]); close(fd[1]);
170*5e96a66cSDavid du Colombier 		return 0;
171*5e96a66cSDavid du Colombier 	}
172*5e96a66cSDavid du Colombier 
173*5e96a66cSDavid du Colombier 	if(pflag)
174*5e96a66cSDavid du Colombier 		r = consOpen(fd[1], srv->srvfd, -1);
175*5e96a66cSDavid du Colombier 	else
176*5e96a66cSDavid du Colombier 		r = (conAlloc(fd[1], argv[0]) != nil);
177*5e96a66cSDavid du Colombier 	if(r == 0){
178*5e96a66cSDavid du Colombier 		close(fd[1]);
179*5e96a66cSDavid du Colombier 		vtLock(sbox.lock);
180*5e96a66cSDavid du Colombier 		srvFree(srv);
181*5e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
182*5e96a66cSDavid du Colombier 	}
183*5e96a66cSDavid du Colombier 
184*5e96a66cSDavid du Colombier 	return r;
185*5e96a66cSDavid du Colombier }
186*5e96a66cSDavid du Colombier 
187*5e96a66cSDavid du Colombier int
188*5e96a66cSDavid du Colombier srvInit(void)
189*5e96a66cSDavid du Colombier {
190*5e96a66cSDavid du Colombier 	sbox.lock = vtLockAlloc();
191*5e96a66cSDavid du Colombier 
192*5e96a66cSDavid du Colombier 	cliAddCmd("srv", cmdSrv);
193*5e96a66cSDavid du Colombier 
194*5e96a66cSDavid du Colombier 	return 1;
195*5e96a66cSDavid du Colombier }
196