Blame


1 24c02865 2005-01-04 devnull /*
2 24c02865 2005-01-04 devnull * gs interface for page.
3 24c02865 2005-01-04 devnull * ps.c and pdf.c both use these routines.
4 24c02865 2005-01-04 devnull * a caveat: if you run more than one gs, only the last
5 24c02865 2005-01-04 devnull * one gets killed by killgs
6 24c02865 2005-01-04 devnull */
7 24c02865 2005-01-04 devnull #include <u.h>
8 24c02865 2005-01-04 devnull #include <libc.h>
9 24c02865 2005-01-04 devnull #include <draw.h>
10 24c02865 2005-01-04 devnull #include <event.h>
11 24c02865 2005-01-04 devnull #include <bio.h>
12 24c02865 2005-01-04 devnull #include "page.h"
13 24c02865 2005-01-04 devnull
14 24c02865 2005-01-04 devnull static int gspid; /* globals for atexit */
15 24c02865 2005-01-04 devnull static int gsfd;
16 24c02865 2005-01-04 devnull static void killgs(void);
17 24c02865 2005-01-04 devnull
18 24c02865 2005-01-04 devnull static void
19 24c02865 2005-01-04 devnull killgs(void)
20 24c02865 2005-01-04 devnull {
21 24c02865 2005-01-04 devnull char tmpfile[100];
22 24c02865 2005-01-04 devnull
23 24c02865 2005-01-04 devnull close(gsfd);
24 24c02865 2005-01-04 devnull postnote(PNGROUP, getpid(), "die");
25 24c02865 2005-01-04 devnull
26 24c02865 2005-01-04 devnull /*
27 24c02865 2005-01-04 devnull * from ghostscript's use.txt:
28 24c02865 2005-01-04 devnull * ``Ghostscript currently doesn't do a very good job of deleting temporary
29 24c02865 2005-01-04 devnull * files when it exits; you may have to delete them manually from time to
30 24c02865 2005-01-04 devnull * time.''
31 24c02865 2005-01-04 devnull */
32 24c02865 2005-01-04 devnull sprint(tmpfile, "/tmp/gs_%.5da", (gspid+300000)%100000);
33 24c02865 2005-01-04 devnull if(chatty) fprint(2, "remove %s...\n", tmpfile);
34 24c02865 2005-01-04 devnull remove(tmpfile);
35 24c02865 2005-01-04 devnull sleep(100);
36 24c02865 2005-01-04 devnull postnote(PNPROC, gspid, "die yankee pig dog");
37 24c02865 2005-01-04 devnull }
38 24c02865 2005-01-04 devnull
39 24c02865 2005-01-04 devnull int
40 24c02865 2005-01-04 devnull spawnwriter(GSInfo *g, Biobuf *b)
41 24c02865 2005-01-04 devnull {
42 24c02865 2005-01-04 devnull char buf[4096];
43 24c02865 2005-01-04 devnull int n;
44 24c02865 2005-01-04 devnull int fd;
45 24c02865 2005-01-04 devnull
46 24c02865 2005-01-04 devnull switch(fork()){
47 24c02865 2005-01-04 devnull case -1: return -1;
48 24c02865 2005-01-04 devnull case 0: break;
49 24c02865 2005-01-04 devnull default: return 0;
50 24c02865 2005-01-04 devnull }
51 24c02865 2005-01-04 devnull
52 24c02865 2005-01-04 devnull Bseek(b, 0, 0);
53 24c02865 2005-01-04 devnull fd = g->gsfd;
54 24c02865 2005-01-04 devnull while((n = Bread(b, buf, sizeof buf)) > 0)
55 24c02865 2005-01-04 devnull write(fd, buf, n);
56 24c02865 2005-01-04 devnull fprint(fd, "(/fd/3) (w) file dup (THIS IS NOT AN INFERNO BITMAP\\n) writestring flushfile\n");
57 24c02865 2005-01-04 devnull _exits(0);
58 24c02865 2005-01-04 devnull return -1;
59 24c02865 2005-01-04 devnull }
60 24c02865 2005-01-04 devnull
61 24c02865 2005-01-04 devnull int
62 24c02865 2005-01-04 devnull spawnreader(int fd)
63 24c02865 2005-01-04 devnull {
64 24c02865 2005-01-04 devnull int n, pfd[2];
65 24c02865 2005-01-04 devnull char buf[1024];
66 24c02865 2005-01-04 devnull
67 24c02865 2005-01-04 devnull if(pipe(pfd)<0)
68 24c02865 2005-01-04 devnull return -1;
69 24c02865 2005-01-04 devnull switch(fork()){
70 24c02865 2005-01-04 devnull case -1:
71 24c02865 2005-01-04 devnull return -1;
72 24c02865 2005-01-04 devnull case 0:
73 24c02865 2005-01-04 devnull break;
74 24c02865 2005-01-04 devnull default:
75 24c02865 2005-01-04 devnull close(pfd[0]);
76 24c02865 2005-01-04 devnull return pfd[1];
77 24c02865 2005-01-04 devnull }
78 24c02865 2005-01-04 devnull
79 24c02865 2005-01-04 devnull close(pfd[1]);
80 24c02865 2005-01-04 devnull switch(fork()){
81 24c02865 2005-01-04 devnull case -1:
82 24c02865 2005-01-04 devnull wexits("fork failed");
83 24c02865 2005-01-04 devnull case 0:
84 24c02865 2005-01-04 devnull while((n=read(fd, buf, sizeof buf)) > 0) {
85 24c02865 2005-01-04 devnull write(1, buf, n);
86 24c02865 2005-01-04 devnull write(pfd[0], buf, n);
87 24c02865 2005-01-04 devnull }
88 24c02865 2005-01-04 devnull break;
89 24c02865 2005-01-04 devnull default:
90 24c02865 2005-01-04 devnull while((n=read(pfd[0], buf, sizeof buf)) > 0) {
91 24c02865 2005-01-04 devnull write(1, buf, n);
92 24c02865 2005-01-04 devnull write(fd, buf, n);
93 24c02865 2005-01-04 devnull }
94 24c02865 2005-01-04 devnull break;
95 24c02865 2005-01-04 devnull }
96 24c02865 2005-01-04 devnull postnote(PNGROUP, getpid(), "i'm die-ing");
97 24c02865 2005-01-04 devnull _exits(0);
98 24c02865 2005-01-04 devnull return -1;
99 24c02865 2005-01-04 devnull }
100 24c02865 2005-01-04 devnull
101 24c02865 2005-01-04 devnull void
102 24c02865 2005-01-04 devnull spawnmonitor(int fd)
103 24c02865 2005-01-04 devnull {
104 24c02865 2005-01-04 devnull char buf[4096];
105 24c02865 2005-01-04 devnull char *xbuf;
106 24c02865 2005-01-04 devnull int n;
107 24c02865 2005-01-04 devnull int out;
108 24c02865 2005-01-04 devnull int first;
109 24c02865 2005-01-04 devnull
110 24c02865 2005-01-04 devnull switch(rfork(RFFDG|RFNOTEG|RFPROC)){
111 24c02865 2005-01-04 devnull case -1:
112 24c02865 2005-01-04 devnull default:
113 24c02865 2005-01-04 devnull return;
114 24c02865 2005-01-04 devnull
115 24c02865 2005-01-04 devnull case 0:
116 24c02865 2005-01-04 devnull break;
117 24c02865 2005-01-04 devnull }
118 24c02865 2005-01-04 devnull
119 24c02865 2005-01-04 devnull out = open("/dev/cons", OWRITE);
120 24c02865 2005-01-04 devnull if(out < 0)
121 24c02865 2005-01-04 devnull out = 2;
122 24c02865 2005-01-04 devnull
123 24c02865 2005-01-04 devnull xbuf = buf; /* for ease of acid */
124 24c02865 2005-01-04 devnull first = 1;
125 24c02865 2005-01-04 devnull while((n = read(fd, xbuf, sizeof buf)) > 0){
126 24c02865 2005-01-04 devnull if(first){
127 24c02865 2005-01-04 devnull first = 0;
128 24c02865 2005-01-04 devnull fprint(2, "Ghostscript Error:\n");
129 24c02865 2005-01-04 devnull }
130 24c02865 2005-01-04 devnull write(out, xbuf, n);
131 24c02865 2005-01-04 devnull alarm(500);
132 24c02865 2005-01-04 devnull }
133 24c02865 2005-01-04 devnull _exits(0);
134 24c02865 2005-01-04 devnull }
135 24c02865 2005-01-04 devnull
136 24c02865 2005-01-04 devnull int
137 24c02865 2005-01-04 devnull spawngs(GSInfo *g)
138 24c02865 2005-01-04 devnull {
139 24c02865 2005-01-04 devnull char *args[16];
140 24c02865 2005-01-04 devnull char tb[32], gb[32];
141 24c02865 2005-01-04 devnull int i, nargs;
142 24c02865 2005-01-04 devnull int devnull;
143 24c02865 2005-01-04 devnull int stdinout[2];
144 24c02865 2005-01-04 devnull int dataout[2];
145 24c02865 2005-01-04 devnull int errout[2];
146 24c02865 2005-01-04 devnull
147 24c02865 2005-01-04 devnull /*
148 24c02865 2005-01-04 devnull * spawn gs
149 24c02865 2005-01-04 devnull *
150 24c02865 2005-01-04 devnull * gs's standard input is fed from stdinout.
151 24c02865 2005-01-04 devnull * gs output written to fd-2 (i.e. output we generate intentionally) is fed to stdinout.
152 24c02865 2005-01-04 devnull * gs output written to fd 1 (i.e. ouptut gs generates on error) is fed to errout.
153 24c02865 2005-01-04 devnull * gs data output is written to fd 3, which is dataout.
154 24c02865 2005-01-04 devnull */
155 24c02865 2005-01-04 devnull if(pipe(stdinout) < 0 || pipe(dataout)<0 || pipe(errout)<0)
156 24c02865 2005-01-04 devnull return -1;
157 24c02865 2005-01-04 devnull
158 24c02865 2005-01-04 devnull nargs = 0;
159 24c02865 2005-01-04 devnull args[nargs++] = "gs";
160 24c02865 2005-01-04 devnull args[nargs++] = "-dNOPAUSE";
161 24c02865 2005-01-04 devnull args[nargs++] = "-dSAFER";
162 24c02865 2005-01-04 devnull args[nargs++] = "-sDEVICE=plan9";
163 24c02865 2005-01-04 devnull args[nargs++] = "-sOutputFile=/fd/3";
164 24c02865 2005-01-04 devnull args[nargs++] = "-dQUIET";
165 24c02865 2005-01-04 devnull args[nargs++] = "-r100";
166 24c02865 2005-01-04 devnull sprint(tb, "-dTextAlphaBits=%d", textbits);
167 24c02865 2005-01-04 devnull sprint(gb, "-dGraphicsAlphaBits=%d", gfxbits);
168 24c02865 2005-01-04 devnull if(textbits)
169 24c02865 2005-01-04 devnull args[nargs++] = tb;
170 24c02865 2005-01-04 devnull if(gfxbits)
171 24c02865 2005-01-04 devnull args[nargs++] = gb;
172 24c02865 2005-01-04 devnull args[nargs++] = "-";
173 24c02865 2005-01-04 devnull args[nargs] = nil;
174 24c02865 2005-01-04 devnull
175 24c02865 2005-01-04 devnull gspid = fork();
176 24c02865 2005-01-04 devnull if(gspid == 0) {
177 24c02865 2005-01-04 devnull close(stdinout[1]);
178 24c02865 2005-01-04 devnull close(dataout[1]);
179 24c02865 2005-01-04 devnull close(errout[1]);
180 24c02865 2005-01-04 devnull
181 24c02865 2005-01-04 devnull /*
182 24c02865 2005-01-04 devnull * Horrible problem: we want to dup fd's 0-4 below,
183 24c02865 2005-01-04 devnull * but some of the source fd's might have those small numbers.
184 24c02865 2005-01-04 devnull * So we need to reallocate those. In order to not step on
185 24c02865 2005-01-04 devnull * anything else, we'll dup the fd's to higher ones using
186 24c02865 2005-01-04 devnull * dup(x, -1), but we need to use up the lower ones first.
187 24c02865 2005-01-04 devnull */
188 24c02865 2005-01-04 devnull while((devnull = open("/dev/null", ORDWR)) < 5)
189 24c02865 2005-01-04 devnull ;
190 24c02865 2005-01-04 devnull
191 24c02865 2005-01-04 devnull stdinout[0] = dup(stdinout[0], -1);
192 24c02865 2005-01-04 devnull errout[0] = dup(errout[0], -1);
193 24c02865 2005-01-04 devnull dataout[0] = dup(dataout[0], -1);
194 24c02865 2005-01-04 devnull
195 24c02865 2005-01-04 devnull dup(stdinout[0], 0);
196 24c02865 2005-01-04 devnull dup(errout[0], 1);
197 24c02865 2005-01-04 devnull dup(devnull, 2); /* never anything useful */
198 24c02865 2005-01-04 devnull dup(dataout[0], 3);
199 24c02865 2005-01-04 devnull dup(stdinout[0], 4);
200 24c02865 2005-01-04 devnull for(i=5; i<20; i++)
201 24c02865 2005-01-04 devnull close(i);
202 24c02865 2005-01-04 devnull exec("/bin/gs", args);
203 24c02865 2005-01-04 devnull wexits("exec");
204 24c02865 2005-01-04 devnull }
205 24c02865 2005-01-04 devnull close(stdinout[0]);
206 24c02865 2005-01-04 devnull close(errout[0]);
207 24c02865 2005-01-04 devnull close(dataout[0]);
208 24c02865 2005-01-04 devnull atexit(killgs);
209 24c02865 2005-01-04 devnull
210 24c02865 2005-01-04 devnull if(teegs)
211 24c02865 2005-01-04 devnull stdinout[1] = spawnreader(stdinout[1]);
212 24c02865 2005-01-04 devnull
213 24c02865 2005-01-04 devnull gsfd = g->gsfd = stdinout[1];
214 24c02865 2005-01-04 devnull g->gsdfd = dataout[1];
215 24c02865 2005-01-04 devnull g->gspid = gspid;
216 24c02865 2005-01-04 devnull
217 24c02865 2005-01-04 devnull spawnmonitor(errout[1]);
218 24c02865 2005-01-04 devnull Binit(&g->gsrd, g->gsfd, OREAD);
219 24c02865 2005-01-04 devnull
220 24c02865 2005-01-04 devnull gscmd(g, "/PAGEOUT (/fd/4) (w) file def\n");
221 24c02865 2005-01-04 devnull gscmd(g, "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n");
222 24c02865 2005-01-04 devnull waitgs(g);
223 24c02865 2005-01-04 devnull
224 24c02865 2005-01-04 devnull return 0;
225 24c02865 2005-01-04 devnull }
226 24c02865 2005-01-04 devnull
227 24c02865 2005-01-04 devnull int
228 24c02865 2005-01-04 devnull gscmd(GSInfo *gs, char *fmt, ...)
229 24c02865 2005-01-04 devnull {
230 24c02865 2005-01-04 devnull char buf[1024];
231 24c02865 2005-01-04 devnull int n;
232 24c02865 2005-01-04 devnull
233 24c02865 2005-01-04 devnull va_list v;
234 24c02865 2005-01-04 devnull va_start(v, fmt);
235 24c02865 2005-01-04 devnull n = vseprint(buf, buf+sizeof buf, fmt, v) - buf;
236 24c02865 2005-01-04 devnull if(n <= 0)
237 24c02865 2005-01-04 devnull return n;
238 24c02865 2005-01-04 devnull
239 24c02865 2005-01-04 devnull if(chatty) {
240 24c02865 2005-01-04 devnull fprint(2, "cmd: ");
241 24c02865 2005-01-04 devnull write(2, buf, n);
242 24c02865 2005-01-04 devnull }
243 24c02865 2005-01-04 devnull
244 24c02865 2005-01-04 devnull if(write(gs->gsfd, buf, n) != 0)
245 24c02865 2005-01-04 devnull return -1;
246 24c02865 2005-01-04 devnull
247 24c02865 2005-01-04 devnull return n;
248 24c02865 2005-01-04 devnull }
249 24c02865 2005-01-04 devnull
250 24c02865 2005-01-04 devnull /*
251 24c02865 2005-01-04 devnull * set the dimensions of the bitmap we expect to get back from GS.
252 24c02865 2005-01-04 devnull */
253 24c02865 2005-01-04 devnull void
254 24c02865 2005-01-04 devnull setdim(GSInfo *gs, Rectangle bbox, int ppi, int landscape)
255 24c02865 2005-01-04 devnull {
256 24c02865 2005-01-04 devnull Rectangle pbox;
257 24c02865 2005-01-04 devnull
258 24c02865 2005-01-04 devnull if(chatty)
259 24c02865 2005-01-04 devnull fprint(2, "setdim: bbox=%R\n", bbox);
260 24c02865 2005-01-04 devnull
261 24c02865 2005-01-04 devnull if(ppi)
262 24c02865 2005-01-04 devnull gs->ppi = ppi;
263 24c02865 2005-01-04 devnull
264 24c02865 2005-01-04 devnull gscmd(gs, "mark\n");
265 24c02865 2005-01-04 devnull if(ppi)
266 24c02865 2005-01-04 devnull gscmd(gs, "/HWResolution [%d %d]\n", ppi, ppi);
267 24c02865 2005-01-04 devnull
268 24c02865 2005-01-04 devnull if(!Dx(bbox))
269 24c02865 2005-01-04 devnull bbox = Rect(0, 0, 612, 792); /* 8½×11 */
270 24c02865 2005-01-04 devnull
271 24c02865 2005-01-04 devnull switch(landscape){
272 24c02865 2005-01-04 devnull case 0:
273 24c02865 2005-01-04 devnull pbox = bbox;
274 24c02865 2005-01-04 devnull break;
275 24c02865 2005-01-04 devnull case 1:
276 24c02865 2005-01-04 devnull pbox = Rect(bbox.min.y, bbox.min.x, bbox.max.y, bbox.max.x);
277 24c02865 2005-01-04 devnull break;
278 24c02865 2005-01-04 devnull }
279 24c02865 2005-01-04 devnull gscmd(gs, "/PageSize [%d %d]\n", Dx(pbox), Dy(pbox));
280 24c02865 2005-01-04 devnull gscmd(gs, "/Margins [%d %d]\n", -pbox.min.x, -pbox.min.y);
281 24c02865 2005-01-04 devnull gscmd(gs, "currentdevice putdeviceprops pop\n");
282 24c02865 2005-01-04 devnull gscmd(gs, "/#copies 1 store\n");
283 24c02865 2005-01-04 devnull
284 24c02865 2005-01-04 devnull if(!eqpt(bbox.min, ZP))
285 24c02865 2005-01-04 devnull gscmd(gs, "%d %d translate\n", -bbox.min.x, -bbox.min.y);
286 24c02865 2005-01-04 devnull
287 24c02865 2005-01-04 devnull switch(landscape){
288 24c02865 2005-01-04 devnull case 0:
289 24c02865 2005-01-04 devnull break;
290 24c02865 2005-01-04 devnull case 1:
291 24c02865 2005-01-04 devnull gscmd(gs, "%d 0 translate\n", Dy(bbox));
292 24c02865 2005-01-04 devnull gscmd(gs, "90 rotate\n");
293 24c02865 2005-01-04 devnull break;
294 24c02865 2005-01-04 devnull }
295 24c02865 2005-01-04 devnull
296 24c02865 2005-01-04 devnull waitgs(gs);
297 24c02865 2005-01-04 devnull }
298 24c02865 2005-01-04 devnull
299 24c02865 2005-01-04 devnull void
300 24c02865 2005-01-04 devnull waitgs(GSInfo *gs)
301 24c02865 2005-01-04 devnull {
302 24c02865 2005-01-04 devnull /* we figure out that gs is done by telling it to
303 24c02865 2005-01-04 devnull * print something and waiting until it does.
304 24c02865 2005-01-04 devnull */
305 24c02865 2005-01-04 devnull char *p;
306 24c02865 2005-01-04 devnull Biobuf *b = &gs->gsrd;
307 24c02865 2005-01-04 devnull uchar buf[1024];
308 24c02865 2005-01-04 devnull int n;
309 24c02865 2005-01-04 devnull
310 24c02865 2005-01-04 devnull // gscmd(gs, "(\\n**bstack\\n) print flush\n");
311 24c02865 2005-01-04 devnull // gscmd(gs, "stack flush\n");
312 24c02865 2005-01-04 devnull // gscmd(gs, "(**estack\\n) print flush\n");
313 24c02865 2005-01-04 devnull gscmd(gs, "(\\n//GO.SYSIN DD\\n) PAGE==\n");
314 24c02865 2005-01-04 devnull
315 24c02865 2005-01-04 devnull alarm(300*1000);
316 24c02865 2005-01-04 devnull for(;;) {
317 24c02865 2005-01-04 devnull p = Brdline(b, '\n');
318 24c02865 2005-01-04 devnull if(p == nil) {
319 24c02865 2005-01-04 devnull n = Bbuffered(b);
320 24c02865 2005-01-04 devnull if(n <= 0)
321 24c02865 2005-01-04 devnull break;
322 24c02865 2005-01-04 devnull if(n > sizeof buf)
323 24c02865 2005-01-04 devnull n = sizeof buf;
324 24c02865 2005-01-04 devnull Bread(b, buf, n);
325 24c02865 2005-01-04 devnull continue;
326 24c02865 2005-01-04 devnull }
327 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = 0;
328 24c02865 2005-01-04 devnull if(chatty) fprint(2, "p: ");
329 24c02865 2005-01-04 devnull if(chatty) write(2, p, Blinelen(b)-1);
330 24c02865 2005-01-04 devnull if(chatty) fprint(2, "\n");
331 24c02865 2005-01-04 devnull if(strstr(p, "Error:")) {
332 24c02865 2005-01-04 devnull alarm(0);
333 24c02865 2005-01-04 devnull fprint(2, "ghostscript error: %s\n", p);
334 24c02865 2005-01-04 devnull wexits("gs error");
335 24c02865 2005-01-04 devnull }
336 24c02865 2005-01-04 devnull
337 24c02865 2005-01-04 devnull if(strstr(p, "//GO.SYSIN DD")) {
338 24c02865 2005-01-04 devnull break;
339 24c02865 2005-01-04 devnull }
340 24c02865 2005-01-04 devnull }
341 24c02865 2005-01-04 devnull alarm(0);
342 24c02865 2005-01-04 devnull }