1 /* alephbis.c: C routines to support external OCPs
2 * based on omegabis.c from the Omega project
3
4 This file is part of the Aleph project
5
6 Copyright (C) 1994--2001, 2014 John Plaice and Yannis Haralambous
7 Copyright (C) 2002 Behdad Esfahbod
8 Copyright (C) 2002, 2005, 2006 Roozbeh Pournader
9 Copyright (C) 2004 the Aleph team
10
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
20
21 You should have received a copy of the GNU Library General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25 #define EXTERN extern
26 #include "alephd.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <string.h>
31 #undef read
32
33 #if 1
34
35 void
runexternalocp(string external_ocp_name)36 runexternalocp (string external_ocp_name)
37 {
38 char *in_file_name;
39 char *out_file_name;
40 FILE *in_file;
41 FILE *out_file;
42 char command_line[400];
43 int i;
44 unsigned c;
45 int c_in;
46 #ifdef WIN32
47 const char *tempenv;
48
49 #define null_string(s) ((s == NULL) || (*s == '\0'))
50
51 tempenv = getenv("TMPDIR");
52 if (null_string(tempenv))
53 tempenv = getenv("TEMP");
54 if (null_string(tempenv))
55 tempenv = getenv("TMP");
56 if (null_string(tempenv))
57 tempenv = "c:/tmp"; /* "/tmp" is not good if we are on a CD-ROM */
58 in_file_name = concat(tempenv, "/__aleph__in__XXXXXX");
59 mktemp(in_file_name);
60 in_file = fopen(in_file_name, FOPEN_WBIN_MODE);
61 #else
62 #if HAVE_MKSTEMP
63 int in_file_fd;
64 int out_file_fd;
65
66 in_file_name = xstrdup("/tmp/__aleph__in__XXXXXX");
67 in_file_fd = mkstemp(in_file_name);
68 in_file = fdopen(in_file_fd, FOPEN_WBIN_MODE);
69 #else
70 #if HAVE_MKTEMP
71 in_file_name = xstrdup("/tmp/__aleph__in__XXXXXX");
72 mktemp(in_file_name);
73 #else
74 in_file_name = xstrdup(tmpnam(NULL));
75 #endif /* HAVE_MKTEMP */
76 in_file = fopen(in_file_name, FOPEN_WBIN_MODE);
77 #endif /* HAVE_MKSTEMP */
78
79 #endif /* WIN32 */
80
81 if (in_file == NULL)
82 fprintf(stderr, "aleph: error opening file: %s\n", strerror(errno));
83
84 for (i=1; i<=otpinputend; i++) {
85 c = otpinputbuf[i];
86 if (c>0xffff) {
87 fprintf(stderr, "aleph: 31-bit chars not supported, goodbye.\n");
88 exit(1);
89 }
90 if (c<0x80) {
91 fputc(c & 0x7f, in_file);
92 } else if (c<0x800) {
93 fputc(0xc0 | ((c>>6) & 0x1f), in_file);
94 fputc(0x80 | (c & 0x3f), in_file);
95 } else if (c<0x10000) {
96 fputc(0xe0 | ((c>>12) & 0xf), in_file);
97 fputc(0x80 | ((c>>6) & 0x3f), in_file);
98 fputc(0x80 | (c & 0x3f), in_file);
99 } else if (c<0x200000) {
100 fputc(0xf0 | ((c>>18) & 0x7), in_file);
101 fputc(0x80 | ((c>>12) & 0x3f), in_file);
102 fputc(0x80 | ((c>>6) & 0x3f), in_file);
103 fputc(0x80 | (c & 0x3f), in_file);
104 } else if (c<0x4000000) {
105 fputc(0xf8 | ((c>>24) & 0x3), in_file);
106 fputc(0x80 | ((c>>18) & 0x3f), in_file);
107 fputc(0x80 | ((c>>12) & 0x3f), in_file);
108 fputc(0x80 | ((c>>6) & 0x3f), in_file);
109 fputc(0x80 | (c & 0x3f), in_file);
110 } else { /* c>=0x4000000 */
111 fputc(0xfc | ((c>>30) & 0x1), in_file);
112 fputc(0x80 | ((c>>24) & 0x3f), in_file);
113 fputc(0x80 | ((c>>18) & 0x3f), in_file);
114 fputc(0x80 | ((c>>12) & 0x3f), in_file);
115 fputc(0x80 | ((c>>6) & 0x3f), in_file);
116 fputc(0x80 | (c & 0x3f), in_file);
117 }
118 }
119 fclose(in_file);
120
121 #define advance_cin do { if ((c_in = fgetc(out_file)) == -1) { \
122 fprintf(stderr, "File contains bad char\n"); \
123 goto end_of_while; \
124 } } while (0)
125
126 #ifdef WIN32
127 out_file_name = concat(tempenv, "/__aleph__out__XXXXXX");
128 mktemp(out_file_name);
129 out_file = fopen(out_file_name, FOPEN_RBIN_MODE);
130 #else
131
132 #if HAVE_MKSTEMP
133 out_file_name = xstrdup("/tmp/__aleph__out__XXXXXX");
134 out_file_fd = mkstemp(out_file_name);
135 out_file = fdopen(out_file_fd, FOPEN_RBIN_MODE);
136 #else
137 #if HAVE_MKTEMP
138 out_file_name = xstrdup("/tmp/__aleph__out__XXXXXX");
139 mktemp(out_file_name);
140 #else
141 out_file_name = xstrdup(tmpnam(NULL));
142 #endif /* HAVE_MKTEMP */
143 out_file = fopen(out_file_name, FOPEN_RBIN_MODE);
144 #endif /* HAVE_MKSTEMP */
145
146 #endif /* WIN32 */
147
148 if (out_file == NULL)
149 fprintf(stderr, "aleph: error opening file: %s\n", strerror(errno));
150
151 if (strlen(external_ocp_name+1) + strlen(in_file_name)
152 + strlen(out_file_name) + 15 > sizeof(command_line)) { /* random 15 */
153 fprintf(stderr, "aleph: command line would be too long (%d): %s %s %s\n",
154 (int) sizeof(command_line),
155 external_ocp_name+1, in_file_name, out_file_name);
156 exit(1);
157 }
158
159 if (strchr(external_ocp_name+1, '\'')) {
160 fprintf(stderr, "aleph: single quote not allowed in ocp name: %s\n",
161 external_ocp_name+1);
162 exit(1);
163 }
164 if (strchr(in_file_name, '\'')) {
165 fprintf(stderr, "aleph: single quote not allowed in in file name: %s\n",
166 in_file_name);
167 exit(1);
168 }
169 if (strchr(out_file_name, '\'')) {
170 fprintf(stderr, "aleph: single quote not allowed in out file name: %s\n",
171 out_file_name);
172 exit(1);
173 }
174
175 /* ok, we've done some basic safety checks. */
176 sprintf(command_line, "'%s' <'%s' >'%s'\n",
177 external_ocp_name+1, in_file_name, out_file_name);
178 system(command_line);
179 otpoutputend = 0;
180 otpoutputbuf[otpoutputend] = 0;
181 while ((c_in = fgetc(out_file)) != -1) {
182 if (c_in<0x80) {
183 c = c_in & 0x7f;
184 } else if (c_in<0xe0) {
185 c = (c_in & 0x1f) << 6;
186 advance_cin;
187 c |= c_in & 0x3f;
188 } else if (c_in<=0xf0) {
189 c = (c_in & 0xf) << 12;
190 advance_cin;
191 c |= (c_in & 0x3f) << 6;
192 advance_cin;
193 c |= c_in & 0x3f;
194 } else if (c_in<0xf8) {
195 c = (c_in & 0x7) << 18;
196 advance_cin;
197 c |= (c_in & 0x3f) << 12;
198 advance_cin;
199 c |= (c_in & 0x3f) << 6;
200 advance_cin;
201 c |= c_in & 0x3f;
202 } else if (c_in<0xfc) {
203 c = (c_in & 0x3) << 24;
204 advance_cin;
205 c |= (c_in & 0x3f) << 18;
206 advance_cin;
207 c |= (c_in & 0x3f) << 12;
208 advance_cin;
209 c |= (c_in & 0x3f) << 6;
210 advance_cin;
211 c |= c_in & 0x3f;
212 } else { /* c>=0xfc */
213 c = (c_in & 0x1) << 30;
214 advance_cin;
215 c |= (c_in & 0x3f) << 24;
216 advance_cin;
217 c |= (c_in & 0x3f) << 18;
218 advance_cin;
219 c |= (c_in & 0x3f) << 12;
220 advance_cin;
221 c |= (c_in & 0x3f) << 6;
222 advance_cin;
223 c |= c_in & 0x3f;
224 }
225 otpoutputbuf[++otpoutputend] = c;
226 }
227
228 end_of_while:
229 fclose(out_file);
230 remove(in_file_name);
231 remove(out_file_name);
232 free(in_file_name);
233 free(out_file_name);
234 }
235
236 #else /* 0 */
237
238 void
runexternalocp(string external_ocp_name)239 runexternalocp (string external_ocp_name)
240 {
241 int outpipes[2], inpipes[2];
242 char *outbuf;
243 char *inbuf;
244 int n;
245 int chars_read_in, chars_to_go_out;
246 int myerrno;
247
248 #ifdef WIN32
249 STARTUPINFO si;
250 PROCESS_INFORMATION pi;
251 HANDLE hIn, hOut, hPipeIn, hPipeOut;
252 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
253 DWORD ret = 0;
254
255 /* Make pipes to send data from the parent to the child. The parent
256 writes to outpipes[0], and the child reads from outpipes[1]. */
257 _pipe (outpipes, 0, _O_BINARY);
258 /* Make pipes to send data from the child to the parent. The child
259 writes to inpipes[0], and the parent reads from inpipes[1]. */
260 _pipe (inpipes, 0, _O_BINARY);
261
262 ZeroMemory( &si, sizeof(STARTUPINFO) );
263 si.cb = sizeof(STARTUPINFO);
264 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
265 si.wShowWindow = SW_SHOW;
266 si.hStdInput = _get_osfhandle(outpipes[0]);
267 si.hStdOutput = _get_osfhandle(inpipes[1]);
268 si.hStdError = _get_osfhandle(_fileno(stderr));
269
270 /* Close unnecessary pipes. */
271 close (outpipes[1]);
272 close (inpipes[0]);
273
274 if (CreateProcess(external_ocp_name+1,
275 NULL, /* Use lpApplicationName */
276 NULL,
277 NULL,
278 TRUE, /* bInheritHandles */
279 0,
280 NULL,
281 NULL,
282 &si,
283 &pi) == 0) {
284 fprintf(stderr, "Failed to create process for %s (Error %d).\n", external_ocp_name+1, GetLastError());
285 return;
286 }
287
288 #else /* ! WIN32 */
289
290 /* Make pipes to send data from the parent to the child. The parent
291 writes to outpipes[0], and the child reads from outpipes[1]. */
292 pipe (outpipes);
293 /* Make pipes to send data from the child to the parent. The child
294 writes to inpipes[0], and the parent reads from inpipes[1]. */
295 pipe (inpipes);
296
297 /* For a child process. */
298 if (fork () == 0)
299 {
300 /* This part is executed by the child process. It translates
301 lower case letters to upper case. */
302
303 char *prog = external_ocp_name+1;
304 char *args[] = {external_ocp_name+1, NULL};
305
306 /* Close unnecessary pipes. They are for the parent. */
307 close (outpipes[1]);
308 close (inpipes[0]);
309
310 /* Connect pipes to stdin and stdout. */
311 dup2 (outpipes[0], 0);
312 dup2 (inpipes[1], 1);
313
314 /* Overlays a new process image on an old process. */
315 execv (prog, args);
316
317 /* We should never reach here. */
318 }
319 else
320 {
321 /* Close unnecessary pipes. They are for the child. */
322 close (outpipes[0]);
323 close (inpipes[1]);
324
325 #endif /* WIN32 */
326
327 /* Here is the interesting part */
328 outbuf = ((char *) otpinputbuf)+2;
329 inbuf = ((char *) otpoutputbuf)+2;
330 chars_to_go_out = 2*otpinputend;
331 chars_read_in = 0;
332 while ((n = write (outpipes[1], outbuf, chars_to_go_out))>0) {
333 fprintf(stderr, "Wrote (1) %d characters\n", n);
334 outbuf+=n;
335 chars_to_go_out-=n;
336 if (chars_to_go_out==0) goto done_writing;
337 /*
338 n = read (inpipes[0], inbuf, 1024);
339 fprintf(stderr, "Read (1) %d characters\n", n);
340 inbuf+=n;
341 chars_read_in+=n;
342 */
343 }
344 fprintf(stderr, "Wrote (2) %d characters\n", n);
345
346 done_writing:
347 close (outpipes[1]);
348 while ((n = read (inpipes[0], inbuf, 1024)) > 0) {
349 fprintf(stderr, "Read (2) %d characters\n", n);
350 inbuf+=n;
351 chars_read_in+=n;
352 }
353 fprintf(stderr, "Read (3) %d characters\n", n);
354 otpoutputend = chars_read_in / 2;
355
356 close (inpipes[0]);
357 #ifndef WIN32
358 }
359 #endif
360 }
361
362 #endif /* 0 */
363