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