xref: /plan9/sys/src/cmd/webfs/plumb.c (revision 314a20f0e09eab47511b995e9c2c3983f0567584)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <thread.h>
6 #include <plumb.h>
7 #include <9p.h>
8 
9 #include "dat.h"
10 #include "fns.h"
11 
12 static int		plumbsendfd;
13 static int		plumbwebfd;
14 static Channel	*plumbchan;
15 
16 static void	plumbwebproc(void*);
17 static void	plumbwebthread(void*);
18 static void plumbsendproc(void*);
19 
20 void
plumbinit(void)21 plumbinit(void)
22 {
23 	plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
24 	plumbwebfd = plumbopen("web", OREAD|OCEXEC);
25 }
26 
27 void
plumbstart(void)28 plumbstart(void)
29 {
30 	plumbchan = chancreate(sizeof(Plumbmsg*), 0);
31 	proccreate(plumbwebproc, nil, STACK);
32 	threadcreate(plumbwebthread, nil, STACK);
33 }
34 
35 static void
plumbwebthread(void *)36 plumbwebthread(void*)
37 {
38 	char *base;
39 	Plumbmsg *m;
40 
41 	for(;;){
42 		m = recvp(plumbchan);
43 		if(m == nil)
44 			threadexits(nil);
45 		base = plumblookup(m->attr, "baseurl");
46 		if(base == nil)
47 			base = m->wdir;
48 		plumburl(m->data, base);
49 		plumbfree(m);
50 	}
51 }
52 
53 static void
plumbwebproc(void *)54 plumbwebproc(void*)
55 {
56 	Plumbmsg *m;
57 
58 	for(;;){
59 		m = plumbrecv(plumbwebfd);
60 		sendp(plumbchan, m);
61 		if(m == nil)
62 			threadexits(nil);
63 	}
64 }
65 
66 static void
addattr(Plumbmsg * m,char * name,char * value)67 addattr(Plumbmsg *m, char *name, char *value)
68 {
69 	Plumbattr *a;
70 
71 	a = malloc(sizeof(Plumbattr));
72 	a->name = name;
73 	a->value = value;
74 	a->next = m->attr;
75 	m->attr = a;
76 }
77 
78 static void
freeattrs(Plumbmsg * m)79 freeattrs(Plumbmsg *m)
80 {
81 	Plumbattr *a, *next;
82 
83 	a = m->attr;
84 	while(a != nil) {
85 		next = a->next;
86 		free(a);
87 		a = next;
88 	}
89 }
90 
91 static struct
92 {
93 	char	*ctype;
94 	char	*ext;
95 }
96 ctypes[] =
97 {
98 	{ "application/msword", "doc" },
99 	{ "application/pdf", "pdf" },
100 	{ "application/postscript", "ps" },
101 	{ "application/rtf", "rtf" },
102 	{ "image/gif", "gif" },
103 	{ "image/jpeg", "jpg" },
104 	{ "image/png", "png" },
105 	{ "image/ppm", "ppm" },
106 	{ "image/tiff", "tiff" },
107 	{ "text/html", "html" },
108 	{ "text/plain", "txt" },
109 	{ "text/xml", "xml" },
110 };
111 
112 void
replumb(Client * c)113 replumb(Client *c)
114 {
115 	int i;
116 	Plumbmsg *m;
117 	char name[128], *ctype, *ext, *p;
118 
119 	if(!c->plumbed)
120 		return;
121 	m = emalloc(sizeof(Plumbmsg));
122 	m->src = "webfs";
123 	m->dst = nil;
124 	m->wdir = "/";
125 	m->type = "text";
126 	m->attr = nil;
127 	addattr(m, "url", c->url->url);
128 	ctype = c->contenttype;
129 	ext = nil;
130 	if(ctype != nil) {
131 		addattr(m, "content-type", ctype);
132 		for(i = 0; i < nelem(ctypes); i++) {
133 			if(strcmp(ctype, ctypes[i].ctype) == 0) {
134 				ext = ctypes[i].ext;
135 				break;
136 			}
137 		}
138 	}
139 	if(ext == nil) {
140 		p = strrchr(c->url->url, '/');
141 		if(p != nil)
142 			p = strrchr(p+1, '.');
143 		if(p != nil && strlen(p) <= 5)
144 			ext = p+1;
145 		else
146 			ext = "txt";		/* punt */
147 	}
148 	c->ext = ext;
149 if(0)fprint(2, "content type %s -> extension .%s\n", ctype, ext);
150 	m->ndata = snprint(name, sizeof name, "/mnt/web/%d/body.%s", c->num, ext);
151 	m->data = estrdup(name);
152 	proccreate(plumbsendproc, m, STACK);	/* separate proc to avoid a deadlock */
153 }
154 
155 static void
plumbsendproc(void * x)156 plumbsendproc(void *x)
157 {
158 	Plumbmsg *m;
159 
160 	m = x;
161 	plumbsend(plumbsendfd, m);
162 	freeattrs(m);
163 	free(m->data);
164 	free(m);
165 }
166