xref: /plan9/sys/src/cmd/webfs/plumb.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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
21 plumbinit(void)
22 {
23 	plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
24 	plumbwebfd = plumbopen("web", OREAD|OCEXEC);
25 }
26 
27 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
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
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
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
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/tiff", "tiff" },
105 	{ "text/html", "html" },
106 	{ "text/plain", "txt" },
107 	{ "text/xml", "xml" },
108 };
109 
110 void
111 replumb(Client *c)
112 {
113 	int i;
114 	Plumbmsg *m;
115 	char name[128], *ctype, *ext, *p;
116 
117 	if(!c->plumbed)
118 		return;
119 	m = emalloc(sizeof(Plumbmsg));
120 	m->src = "webfs";
121 	m->dst = nil;
122 	m->wdir = "/";
123 	m->type = "text";
124 	m->attr = nil;
125 	addattr(m, "url", c->url->url);
126 	ctype = c->contenttype;
127 	ext = nil;
128 	if(ctype != nil) {
129 		addattr(m, "content-type", ctype);
130 		for(i = 0; i < nelem(ctypes); i++) {
131 			if(strcmp(ctype, ctypes[i].ctype) == 0) {
132 				ext = ctypes[i].ext;
133 				break;
134 			}
135 		}
136 	}
137 	if(ext == nil) {
138 		p = strrchr(c->url->url, '/');
139 		if(p != nil)
140 			p = strrchr(p+1, '.');
141 		if(p != nil && strlen(p) <= 5)
142 			ext = p+1;
143 		else
144 			ext = "txt";		/* punt */
145 	}
146 	c->ext = ext;
147 if(0)fprint(2, "content type %s -> extension .%s\n", ctype, ext);
148 	m->ndata = snprint(name, sizeof name, "/mnt/web/%d/body.%s", c->num, ext);
149 	m->data = estrdup(name);
150 	proccreate(plumbsendproc, m, STACK);	/* separate proc to avoid a deadlock */
151 }
152 
153 static void
154 plumbsendproc(void *x)
155 {
156 	Plumbmsg *m;
157 
158 	m = x;
159 	plumbsend(plumbsendfd, m);
160 	freeattrs(m);
161 	free(m->data);
162 	free(m);
163 }
164