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 fa325e9b 2020-01-10 cross * a caveat: if you run more than one gs, only the last
5 fa325e9b 2020-01-10 cross * 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 05a4d855 2007-03-26 devnull #include <thread.h>
11 24c02865 2005-01-04 devnull #include <bio.h>
12 05a4d855 2007-03-26 devnull #include <cursor.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 05a4d855 2007-03-26 devnull void
41 05a4d855 2007-03-26 devnull spawnreader(void *cp)
42 24c02865 2005-01-04 devnull {
43 05a4d855 2007-03-26 devnull int n, fd, pfd[2];
44 05a4d855 2007-03-26 devnull char buf[1024];
45 24c02865 2005-01-04 devnull
46 05a4d855 2007-03-26 devnull recv(cp, &fd);
47 24c02865 2005-01-04 devnull
48 05a4d855 2007-03-26 devnull if(pipe(pfd)<0)
49 05a4d855 2007-03-26 devnull wexits("pipe failed");
50 24c02865 2005-01-04 devnull
51 05a4d855 2007-03-26 devnull send(cp, &pfd[1]);
52 24c02865 2005-01-04 devnull
53 05a4d855 2007-03-26 devnull while((n=read(pfd[0], buf, sizeof buf)) > 0) {
54 05a4d855 2007-03-26 devnull write(1, buf, n);
55 05a4d855 2007-03-26 devnull write(fd, buf, n);
56 24c02865 2005-01-04 devnull }
57 24c02865 2005-01-04 devnull
58 05a4d855 2007-03-26 devnull close(pfd[0]);
59 05a4d855 2007-03-26 devnull threadexits(0);
60 24c02865 2005-01-04 devnull }
61 24c02865 2005-01-04 devnull
62 24c02865 2005-01-04 devnull void
63 05a4d855 2007-03-26 devnull spawnmonitor(void *cp)
64 24c02865 2005-01-04 devnull {
65 24c02865 2005-01-04 devnull char buf[4096];
66 24c02865 2005-01-04 devnull char *xbuf;
67 05a4d855 2007-03-26 devnull int fd;
68 24c02865 2005-01-04 devnull int n;
69 24c02865 2005-01-04 devnull int out;
70 24c02865 2005-01-04 devnull int first;
71 24c02865 2005-01-04 devnull
72 05a4d855 2007-03-26 devnull recv(cp, &fd);
73 24c02865 2005-01-04 devnull
74 05a4d855 2007-03-26 devnull out = open("/dev/tty", OWRITE);
75 24c02865 2005-01-04 devnull if(out < 0)
76 24c02865 2005-01-04 devnull out = 2;
77 24c02865 2005-01-04 devnull
78 24c02865 2005-01-04 devnull xbuf = buf; /* for ease of acid */
79 24c02865 2005-01-04 devnull first = 1;
80 24c02865 2005-01-04 devnull while((n = read(fd, xbuf, sizeof buf)) > 0){
81 24c02865 2005-01-04 devnull if(first){
82 24c02865 2005-01-04 devnull first = 0;
83 24c02865 2005-01-04 devnull fprint(2, "Ghostscript Error:\n");
84 24c02865 2005-01-04 devnull }
85 24c02865 2005-01-04 devnull write(out, xbuf, n);
86 24c02865 2005-01-04 devnull alarm(500);
87 24c02865 2005-01-04 devnull }
88 05a4d855 2007-03-26 devnull threadexits(0);
89 24c02865 2005-01-04 devnull }
90 24c02865 2005-01-04 devnull
91 fa325e9b 2020-01-10 cross int
92 17157e4a 2006-03-20 devnull spawngs(GSInfo *g, char *safer)
93 24c02865 2005-01-04 devnull {
94 05a4d855 2007-03-26 devnull Channel *cp;
95 24c02865 2005-01-04 devnull char *args[16];
96 24c02865 2005-01-04 devnull char tb[32], gb[32];
97 24c02865 2005-01-04 devnull int i, nargs;
98 24c02865 2005-01-04 devnull int devnull;
99 05a4d855 2007-03-26 devnull int stdinp[2];
100 05a4d855 2007-03-26 devnull int stdoutp[2];
101 24c02865 2005-01-04 devnull int dataout[2];
102 24c02865 2005-01-04 devnull int errout[2];
103 24c02865 2005-01-04 devnull
104 24c02865 2005-01-04 devnull /*
105 24c02865 2005-01-04 devnull * spawn gs
106 24c02865 2005-01-04 devnull *
107 24c02865 2005-01-04 devnull * gs's standard input is fed from stdinout.
108 24c02865 2005-01-04 devnull * gs output written to fd-2 (i.e. output we generate intentionally) is fed to stdinout.
109 24c02865 2005-01-04 devnull * gs output written to fd 1 (i.e. ouptut gs generates on error) is fed to errout.
110 24c02865 2005-01-04 devnull * gs data output is written to fd 3, which is dataout.
111 24c02865 2005-01-04 devnull */
112 05a4d855 2007-03-26 devnull if(pipe(stdinp)<0 || pipe(stdoutp)<0 || pipe(dataout)<0 || pipe(errout)<0)
113 24c02865 2005-01-04 devnull return -1;
114 24c02865 2005-01-04 devnull
115 24c02865 2005-01-04 devnull nargs = 0;
116 24c02865 2005-01-04 devnull args[nargs++] = "gs";
117 24c02865 2005-01-04 devnull args[nargs++] = "-dNOPAUSE";
118 0e52c796 2009-05-26 jg args[nargs++] = "-dNOPROMPT";
119 05a4d855 2007-03-26 devnull args[nargs++] = "-dDELAYSAFER";
120 0e52c796 2009-05-26 jg args[nargs++] = "-dQUIET";
121 05a4d855 2007-03-26 devnull args[nargs++] = "-sDEVICE=bmp16m";
122 05a4d855 2007-03-26 devnull args[nargs++] = "-sOutputFile=/dev/fd/3";
123 24c02865 2005-01-04 devnull args[nargs++] = "-r100";
124 24c02865 2005-01-04 devnull sprint(tb, "-dTextAlphaBits=%d", textbits);
125 24c02865 2005-01-04 devnull sprint(gb, "-dGraphicsAlphaBits=%d", gfxbits);
126 24c02865 2005-01-04 devnull if(textbits)
127 24c02865 2005-01-04 devnull args[nargs++] = tb;
128 24c02865 2005-01-04 devnull if(gfxbits)
129 24c02865 2005-01-04 devnull args[nargs++] = gb;
130 24c02865 2005-01-04 devnull args[nargs] = nil;
131 24c02865 2005-01-04 devnull
132 24c02865 2005-01-04 devnull gspid = fork();
133 24c02865 2005-01-04 devnull if(gspid == 0) {
134 05a4d855 2007-03-26 devnull close(stdinp[1]);
135 05a4d855 2007-03-26 devnull close(stdoutp[0]);
136 05a4d855 2007-03-26 devnull close(dataout[0]);
137 05a4d855 2007-03-26 devnull close(errout[0]);
138 24c02865 2005-01-04 devnull
139 24c02865 2005-01-04 devnull /*
140 24c02865 2005-01-04 devnull * Horrible problem: we want to dup fd's 0-4 below,
141 24c02865 2005-01-04 devnull * but some of the source fd's might have those small numbers.
142 24c02865 2005-01-04 devnull * So we need to reallocate those. In order to not step on
143 24c02865 2005-01-04 devnull * anything else, we'll dup the fd's to higher ones using
144 24c02865 2005-01-04 devnull * dup(x, -1), but we need to use up the lower ones first.
145 24c02865 2005-01-04 devnull */
146 24c02865 2005-01-04 devnull while((devnull = open("/dev/null", ORDWR)) < 5)
147 24c02865 2005-01-04 devnull ;
148 24c02865 2005-01-04 devnull
149 05a4d855 2007-03-26 devnull stdinp[0] = dup(stdinp[0], -1);
150 05a4d855 2007-03-26 devnull stdoutp[1] = dup(stdoutp[1], -1);
151 05a4d855 2007-03-26 devnull errout[1] = dup(errout[1], -1);
152 05a4d855 2007-03-26 devnull dataout[1] = dup(dataout[1], -1);
153 24c02865 2005-01-04 devnull
154 05a4d855 2007-03-26 devnull dup(stdinp[0], 0);
155 05a4d855 2007-03-26 devnull dup(errout[1], 1);
156 0e52c796 2009-05-26 jg dup(devnull, 2); /* never anything useful */
157 05a4d855 2007-03-26 devnull dup(dataout[1], 3);
158 05a4d855 2007-03-26 devnull dup(stdoutp[1], 4);
159 24c02865 2005-01-04 devnull for(i=5; i<20; i++)
160 24c02865 2005-01-04 devnull close(i);
161 05a4d855 2007-03-26 devnull execvp("gs", args);
162 24c02865 2005-01-04 devnull wexits("exec");
163 24c02865 2005-01-04 devnull }
164 05a4d855 2007-03-26 devnull close(stdinp[0]);
165 05a4d855 2007-03-26 devnull close(stdoutp[1]);
166 05a4d855 2007-03-26 devnull close(errout[1]);
167 05a4d855 2007-03-26 devnull close(dataout[1]);
168 24c02865 2005-01-04 devnull atexit(killgs);
169 24c02865 2005-01-04 devnull
170 05a4d855 2007-03-26 devnull cp = chancreate(sizeof(int), 0);
171 05a4d855 2007-03-26 devnull if(teegs) {
172 05a4d855 2007-03-26 devnull proccreate(spawnreader, cp, mainstacksize);
173 05a4d855 2007-03-26 devnull send(cp, &stdoutp[0]);
174 05a4d855 2007-03-26 devnull recv(cp, &stdoutp[0]);
175 05a4d855 2007-03-26 devnull }
176 24c02865 2005-01-04 devnull
177 05a4d855 2007-03-26 devnull gsfd = g->gsfd = stdinp[1];
178 24c02865 2005-01-04 devnull g->gspid = gspid;
179 05a4d855 2007-03-26 devnull g->g.fd = dataout[0];
180 05a4d855 2007-03-26 devnull g->g.name = "gs pipe";
181 05a4d855 2007-03-26 devnull g->g.type = Ibmp;
182 24c02865 2005-01-04 devnull
183 05a4d855 2007-03-26 devnull proccreate(spawnmonitor, cp, mainstacksize);
184 05a4d855 2007-03-26 devnull send(cp, &errout[0]);
185 05a4d855 2007-03-26 devnull chanfree(cp);
186 24c02865 2005-01-04 devnull
187 05a4d855 2007-03-26 devnull Binit(&g->gsrd, stdoutp[0], OREAD);
188 047fd921 2019-02-25 rsc
189 047fd921 2019-02-25 rsc gscmd(g, "/PAGEDIDSHOWPAGE false def\n");
190 047fd921 2019-02-25 rsc gscmd(g, "/showpage { /PAGEDIDSHOWPAGE true def showpage } bind def\n");
191 047fd921 2019-02-25 rsc gscmd(g, "/PAGEFLUSH { PAGEDIDSHOWPAGE not {showpage} if /PAGEDIDSHOWPAGE false def } def\n");
192 05a4d855 2007-03-26 devnull
193 05a4d855 2007-03-26 devnull gscmd(g, "/PAGEOUT (/dev/fd/4) (w) file def\n");
194 05a4d855 2007-03-26 devnull if(!strcmp(safer, "-dSAFER"))
195 05a4d855 2007-03-26 devnull gscmd(g, ".setsafe\n");
196 24c02865 2005-01-04 devnull gscmd(g, "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n");
197 24c02865 2005-01-04 devnull waitgs(g);
198 24c02865 2005-01-04 devnull
199 24c02865 2005-01-04 devnull return 0;
200 24c02865 2005-01-04 devnull }
201 24c02865 2005-01-04 devnull
202 24c02865 2005-01-04 devnull int
203 24c02865 2005-01-04 devnull gscmd(GSInfo *gs, char *fmt, ...)
204 24c02865 2005-01-04 devnull {
205 24c02865 2005-01-04 devnull char buf[1024];
206 24c02865 2005-01-04 devnull int n;
207 24c02865 2005-01-04 devnull
208 24c02865 2005-01-04 devnull va_list v;
209 24c02865 2005-01-04 devnull va_start(v, fmt);
210 24c02865 2005-01-04 devnull n = vseprint(buf, buf+sizeof buf, fmt, v) - buf;
211 24c02865 2005-01-04 devnull if(n <= 0)
212 24c02865 2005-01-04 devnull return n;
213 24c02865 2005-01-04 devnull
214 24c02865 2005-01-04 devnull if(chatty) {
215 24c02865 2005-01-04 devnull fprint(2, "cmd: ");
216 24c02865 2005-01-04 devnull write(2, buf, n);
217 24c02865 2005-01-04 devnull }
218 24c02865 2005-01-04 devnull
219 24c02865 2005-01-04 devnull if(write(gs->gsfd, buf, n) != 0)
220 24c02865 2005-01-04 devnull return -1;
221 24c02865 2005-01-04 devnull
222 24c02865 2005-01-04 devnull return n;
223 24c02865 2005-01-04 devnull }
224 24c02865 2005-01-04 devnull
225 24c02865 2005-01-04 devnull /*
226 24c02865 2005-01-04 devnull * set the dimensions of the bitmap we expect to get back from GS.
227 24c02865 2005-01-04 devnull */
228 24c02865 2005-01-04 devnull void
229 24c02865 2005-01-04 devnull setdim(GSInfo *gs, Rectangle bbox, int ppi, int landscape)
230 24c02865 2005-01-04 devnull {
231 24c02865 2005-01-04 devnull Rectangle pbox;
232 24c02865 2005-01-04 devnull
233 24c02865 2005-01-04 devnull if(chatty)
234 24c02865 2005-01-04 devnull fprint(2, "setdim: bbox=%R\n", bbox);
235 24c02865 2005-01-04 devnull
236 24c02865 2005-01-04 devnull if(ppi)
237 24c02865 2005-01-04 devnull gs->ppi = ppi;
238 24c02865 2005-01-04 devnull
239 24c02865 2005-01-04 devnull gscmd(gs, "mark\n");
240 24c02865 2005-01-04 devnull if(ppi)
241 24c02865 2005-01-04 devnull gscmd(gs, "/HWResolution [%d %d]\n", ppi, ppi);
242 24c02865 2005-01-04 devnull
243 24c02865 2005-01-04 devnull if(!Dx(bbox))
244 24c02865 2005-01-04 devnull bbox = Rect(0, 0, 612, 792); /* 8½×11 */
245 24c02865 2005-01-04 devnull
246 05a4d855 2007-03-26 devnull switch(landscape){
247 05a4d855 2007-03-26 devnull case 0:
248 24c02865 2005-01-04 devnull pbox = bbox;
249 05a4d855 2007-03-26 devnull break;
250 05a4d855 2007-03-26 devnull default:
251 05a4d855 2007-03-26 devnull pbox = Rect(bbox.min.y, bbox.min.x, bbox.max.y, bbox.max.x);
252 05a4d855 2007-03-26 devnull break;
253 05a4d855 2007-03-26 devnull }
254 24c02865 2005-01-04 devnull gscmd(gs, "/PageSize [%d %d]\n", Dx(pbox), Dy(pbox));
255 24c02865 2005-01-04 devnull gscmd(gs, "/Margins [%d %d]\n", -pbox.min.x, -pbox.min.y);
256 24c02865 2005-01-04 devnull gscmd(gs, "currentdevice putdeviceprops pop\n");
257 24c02865 2005-01-04 devnull gscmd(gs, "/#copies 1 store\n");
258 24c02865 2005-01-04 devnull
259 24c02865 2005-01-04 devnull if(!eqpt(bbox.min, ZP))
260 24c02865 2005-01-04 devnull gscmd(gs, "%d %d translate\n", -bbox.min.x, -bbox.min.y);
261 24c02865 2005-01-04 devnull
262 24c02865 2005-01-04 devnull switch(landscape){
263 24c02865 2005-01-04 devnull case 0:
264 24c02865 2005-01-04 devnull break;
265 24c02865 2005-01-04 devnull case 1:
266 24c02865 2005-01-04 devnull gscmd(gs, "%d 0 translate\n", Dy(bbox));
267 24c02865 2005-01-04 devnull gscmd(gs, "90 rotate\n");
268 24c02865 2005-01-04 devnull break;
269 24c02865 2005-01-04 devnull }
270 24c02865 2005-01-04 devnull
271 24c02865 2005-01-04 devnull waitgs(gs);
272 24c02865 2005-01-04 devnull }
273 24c02865 2005-01-04 devnull
274 24c02865 2005-01-04 devnull void
275 24c02865 2005-01-04 devnull waitgs(GSInfo *gs)
276 24c02865 2005-01-04 devnull {
277 24c02865 2005-01-04 devnull /* we figure out that gs is done by telling it to
278 24c02865 2005-01-04 devnull * print something and waiting until it does.
279 24c02865 2005-01-04 devnull */
280 24c02865 2005-01-04 devnull char *p;
281 24c02865 2005-01-04 devnull Biobuf *b = &gs->gsrd;
282 24c02865 2005-01-04 devnull uchar buf[1024];
283 24c02865 2005-01-04 devnull int n;
284 24c02865 2005-01-04 devnull
285 05a4d855 2007-03-26 devnull // gscmd(gs, "(\\n**bstack\\n) print flush\n");
286 05a4d855 2007-03-26 devnull // gscmd(gs, "stack flush\n");
287 05a4d855 2007-03-26 devnull // gscmd(gs, "(**estack\\n) print flush\n");
288 05a4d855 2007-03-26 devnull gscmd(gs, "(\\n//GO.SYSIN DD\\n) PAGE==\n");
289 24c02865 2005-01-04 devnull
290 24c02865 2005-01-04 devnull alarm(300*1000);
291 24c02865 2005-01-04 devnull for(;;) {
292 24c02865 2005-01-04 devnull p = Brdline(b, '\n');
293 24c02865 2005-01-04 devnull if(p == nil) {
294 24c02865 2005-01-04 devnull n = Bbuffered(b);
295 24c02865 2005-01-04 devnull if(n <= 0)
296 24c02865 2005-01-04 devnull break;
297 24c02865 2005-01-04 devnull if(n > sizeof buf)
298 24c02865 2005-01-04 devnull n = sizeof buf;
299 24c02865 2005-01-04 devnull Bread(b, buf, n);
300 24c02865 2005-01-04 devnull continue;
301 24c02865 2005-01-04 devnull }
302 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = 0;
303 24c02865 2005-01-04 devnull if(chatty) fprint(2, "p: ");
304 24c02865 2005-01-04 devnull if(chatty) write(2, p, Blinelen(b)-1);
305 24c02865 2005-01-04 devnull if(chatty) fprint(2, "\n");
306 24c02865 2005-01-04 devnull if(strstr(p, "Error:")) {
307 24c02865 2005-01-04 devnull alarm(0);
308 24c02865 2005-01-04 devnull fprint(2, "ghostscript error: %s\n", p);
309 24c02865 2005-01-04 devnull wexits("gs error");
310 24c02865 2005-01-04 devnull }
311 24c02865 2005-01-04 devnull
312 24c02865 2005-01-04 devnull if(strstr(p, "//GO.SYSIN DD")) {
313 24c02865 2005-01-04 devnull break;
314 24c02865 2005-01-04 devnull }
315 24c02865 2005-01-04 devnull }
316 24c02865 2005-01-04 devnull alarm(0);
317 24c02865 2005-01-04 devnull }