1 /* output-pstoedit.c: utility routines for libpstoedit.so functions
2
3 Copyright (C) 2002 Masatake YAMATO
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 as published by the Free Software Foundation; either version 2.1 of
8 the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 USA. */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif /* Def: HAVE_CONFIG_H */
23
24 /* This module uses a temporary file to pass a file to libpstoedit
25 Which functions should I use to create tmpfile?
26 -------------------------------------------------------------------
27 Function || Security | Availability
28 ---------++------------+-------------------------------------------
29 mktemp || risky | BSD 4.3
30 mkstemp || no problem | BSD 4.3
31 tempnam || risky | SVID 2, BSD 4.3
32 tmpfile || no problem | SVID 3, POSIX, BSD 4.3, ISO 9899, SUSv2
33 tmpnam || risky | SVID 2, POSIX, BSD 4.3, ISO 9899
34 -------------------------------------------------------------------
35 tmpfile returns file pointer, not file name
36
37 mkstemp is the best in the security aspect, however it is not portable.
38 (Read http://groups.yahoo.com/group/autotrace/message/369) */
39
40 #include "output-pstoedit.h"
41 #include "output-p2e.h"
42 #include "filename.h"
43 #include "xstd.h"
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <errno.h>
49
50 #define BO_DEBUG 0
51 #define TMPDIR "/tmp/"
52
53 /* #define OUTPUT_PSTOEDIT_DEBUG */
54
55 static char ** pstoedit_suffix_table = NULL;
56 static void pstoedit_suffix_table_init (void);
57 static at_string pstoedit_suffix_table_lookup_deep (const at_string suffix);
58 static at_bool pstoedit_suffix_table_lookup_shallow (const void * suffix);
59 static const at_string get_symbolicname(const at_string suffix);
60
61 static int output_pstoedit_writer (const at_string suffix,
62 FILE* file, at_string name,
63 int llx, int lly, int urx, int ury,
64 at_output_opts_type * opts,
65 at_spline_list_array_type shape,
66 at_msg_func msg_func,
67 at_address msg_data);
68
69 static void remove_temporary_file (const at_string tmpfile_name);
70 static FILE * make_temporary_file(char *template, char * mode);
71
72 static void
pstoedit_suffix_table_init(void)73 pstoedit_suffix_table_init (void)
74 {
75 struct DriverDescription_S* dd_start, *dd_tmp;
76
77 if (pstoedit_suffix_table != NULL)
78 return;
79
80 pstoedit_checkversion(pstoeditdllversion);
81 dd_start = getPstoeditDriverInfo_plainC();
82 if (dd_start)
83 {
84 dd_tmp = dd_start;
85 while (dd_tmp->symbolicname)
86 dd_tmp++;
87 XMALLOC(pstoedit_suffix_table, sizeof(char *) * 2 * (dd_tmp - dd_start) + 1);
88
89 #if defined (OUTPUT_PSTOEDIT_DEBUG) && defined(__GNUC__)
90 fprintf(stderr, "OUTPUT PSTOEDIT BACKEND DEBUG(%s)\n", __FUNCTION__);
91 #endif /* Def: OUTPUT_PSTOEDIT_DEBUG */
92 dd_tmp = dd_start;
93 while (dd_tmp->symbolicname)
94 {
95 #ifdef OUTPUT_PSTOEDIT_DEBUG
96 fprintf(stderr, "[symbolicname: %d]%s\n", (dd_tmp - dd_start), dd_tmp->symbolicname);
97 fprintf(stderr, "[ suffix: %d]%s\n", (dd_tmp - dd_start), dd_tmp->suffix);
98 #endif /* Def: OUTPUT_PSTOEDIT_DEBUG */
99 pstoedit_suffix_table[2 * (dd_tmp - dd_start)] = strdup(dd_tmp->symbolicname);
100 pstoedit_suffix_table[2 * (dd_tmp - dd_start) + 1] = strdup(dd_tmp->suffix);
101 dd_tmp++;
102 }
103 pstoedit_suffix_table[2 * (dd_tmp - dd_start)] = NULL;
104 free(dd_start);
105 }
106 else
107 {
108 XMALLOC(pstoedit_suffix_table, sizeof(char *));
109 pstoedit_suffix_table[0] = NULL;
110 }
111 }
112
113 static at_string
pstoedit_suffix_table_lookup_deep(const at_string suffix)114 pstoedit_suffix_table_lookup_deep (const at_string suffix)
115 {
116 char ** tmp;
117
118 if (pstoedit_suffix_table == NULL)
119 pstoedit_suffix_table_init();
120
121 #if defined (OUTPUT_PSTOEDIT_DEBUG) && defined(__GNUC__)
122 fprintf(stderr, "OUTPUT PSTOEDIT BACKEND DEBUG(%s)\n", __FUNCTION__);
123 #endif /* Def: OUTPUT_PSTOEDIT_DEBUG */
124
125 for (tmp = pstoedit_suffix_table; *tmp != NULL; tmp++)
126 {
127 #ifdef OUTPUT_PSTOEDIT_DEBUG
128 fprintf(stderr, "%s\n", *tmp);
129 #endif /* Def: OUTPUT_PSTOEDIT_DEBUG */
130
131 if (0 == strcmp(suffix, *tmp))
132 return * tmp;
133 }
134 return NULL;
135 }
136
137 static at_bool
pstoedit_suffix_table_lookup_shallow(const void * suffix)138 pstoedit_suffix_table_lookup_shallow (const void * suffix)
139 {
140 char ** tmp;
141
142 if (pstoedit_suffix_table == NULL)
143 pstoedit_suffix_table_init();
144
145 for (tmp = pstoedit_suffix_table; *tmp != NULL; tmp++)
146 if (*tmp == suffix)
147 return true;
148 return false;
149 }
150
151 at_output_write_func
output_pstoedit_get_writer(const at_string suffix)152 output_pstoedit_get_writer(const at_string suffix)
153 {
154 return (at_output_write_func)pstoedit_suffix_table_lookup_deep (suffix);
155 }
156
157 at_bool
output_pstoedit_is_writer(at_output_write_func writer)158 output_pstoedit_is_writer (at_output_write_func writer)
159 {
160 return pstoedit_suffix_table_lookup_shallow(writer);
161 }
162
163 int
output_pstoedit_invoke_writer(at_output_write_func writer,FILE * file,at_string name,int llx,int lly,int urx,int ury,at_output_opts_type * opts,at_spline_list_array_type shape,at_msg_func msg_func,at_address msg_data)164 output_pstoedit_invoke_writer (at_output_write_func writer,
165 FILE* file, at_string name,
166 int llx, int lly, int urx, int ury,
167 at_output_opts_type * opts,
168 at_spline_list_array_type shape,
169 at_msg_func msg_func,
170 at_address msg_data)
171 {
172 return output_pstoedit_writer((const at_string) writer,
173 file, name,
174 llx, lly, urx, ury,
175 opts,
176 shape,
177 msg_func, msg_data);
178
179 }
180
181 /* This output routine uses two temporary files to keep the
182 both the command line syntax of autotrace and the
183 pstoedit API.
184
185 shape -> bo file(tmpfile_name_p2e)
186 -> specified formatted file(tmpfile_name_pstoedit)
187 -> file */
188 static int
output_pstoedit_writer(const at_string suffix,FILE * file,at_string name,int llx,int lly,int urx,int ury,at_output_opts_type * opts,at_spline_list_array_type shape,at_msg_func msg_func,at_address msg_data)189 output_pstoedit_writer (const at_string suffix,
190 FILE* file, at_string name,
191 int llx, int lly, int urx, int ury,
192 at_output_opts_type * opts,
193 at_spline_list_array_type shape,
194 at_msg_func msg_func,
195 at_address msg_data)
196 {
197 char tmpfile_name_p2e[] = TMPDIR "at-bo-" "XXXXXX";
198 char tmpfile_name_pstoedit[] = TMPDIR "at-fo-" "XXXXXX";
199 char * symbolicname;
200 FILE * tmpfile;
201 int result = 0;
202 int c;
203
204 int argc;
205 #define CMD_INDEX 0
206 #define SYMBOLICNAME_FLAG_INDEX 1
207 #define SYMBOLICNAME_VAL_INDEX 2
208 #define BO_FLAG_INDEX 3
209 #define INPUT_INDEX 4
210 #define OUTPUT_INDEX 5
211 char * argv[] = {"pstoedit", "-f", 0, "-bo", 0, 0};
212
213 argc = sizeof(argv) / sizeof(char *);
214
215 if (false == pstoedit_suffix_table_lookup_shallow(suffix))
216 {
217 if (msg_func)
218 msg_func ("Suffix for pstoedit backend driver is wrong",
219 AT_MSG_WARNING, msg_data);
220 return -1;
221 }
222
223 symbolicname = get_symbolicname(suffix);
224 if (!symbolicname)
225 {
226 if (msg_func)
227 msg_func ("Symbolicname for pstoedit backend driver is wrong",
228 AT_MSG_WARNING, msg_data);
229 return -1;
230 }
231
232 tmpfile = make_temporary_file(tmpfile_name_p2e, "w");
233 if (NULL == tmpfile)
234 {
235 result = -1;
236 goto remove_tmp_p2e;
237 }
238
239 /*
240 * shape -> bo file
241 */
242 output_p2e_writer(tmpfile, tmpfile_name_p2e,
243 llx, lly, urx, ury, opts,
244 shape, msg_func, msg_data);
245 fclose(tmpfile);
246
247 tmpfile = make_temporary_file(tmpfile_name_pstoedit, "r");
248 if (NULL == tmpfile)
249 {
250 result = -1;
251 goto remove_tmp_pstoedit;
252 }
253
254 /*
255 * bo file -> specified formatted file
256 */
257 argv[SYMBOLICNAME_VAL_INDEX] = symbolicname;
258 argv[INPUT_INDEX] = tmpfile_name_p2e;
259 argv[OUTPUT_INDEX] = tmpfile_name_pstoedit;
260 pstoedit_plainC(argc, argv, NULL);
261
262 /*
263 * specified formatted file(tmpfile_name_pstoedit) -> file
264 */
265 /* fseek(tmpfile, 0, SEEK_SET); */
266 while (EOF != (c = fgetc(tmpfile)))
267 fputc(c, file);
268 fclose(tmpfile);
269
270 remove_tmp_pstoedit:
271 remove_temporary_file(tmpfile_name_pstoedit);
272 remove_tmp_p2e:
273 remove_temporary_file(tmpfile_name_p2e);
274 free(symbolicname);
275 return result;
276 }
277
278 at_bool
output_pstoedit_is_unusable_writer(const at_string name)279 output_pstoedit_is_unusable_writer(const at_string name)
280 {
281 if (0 == strcmp(name, "sam")
282 || 0 == strcmp(name, "dbg")
283 || 0 == strcmp(name, "gs")
284 || 0 == strcmp(name, "psf")
285 || 0 == strcmp(name, "fps")
286 || 0 == strcmp(name, "ps")
287 || 0 == strcmp(name, "spsc")
288 || 0 == strcmp(name, "debug")
289 || 0 == strcmp(name, "dump")
290 || 0 == strcmp(name, "ps2as"))
291 return true;
292 else
293 return false;
294 }
295
296 /* get_symbolicname --- Return symbolicname associated with SUFFIX
297 If SUFFIX itself a symbolicname, just return SUFFIX.
298 If SUFFIX doesn't have any associated symbolicname and
299 it is not a suffix registered in pstoedit, reutrn NULL. */
300 static const at_string
get_symbolicname(const at_string suffix)301 get_symbolicname(const at_string suffix)
302 {
303 at_string symbolicname = NULL;
304 struct DriverDescription_S* dd_start, * dd_tmp;
305
306 if (!suffix)
307 return NULL;
308
309 dd_start = getPstoeditDriverInfo_plainC();
310 if (dd_start)
311 {
312 dd_tmp = dd_start;
313 while (dd_tmp->symbolicname)
314 {
315 if (0 == strcmp(dd_tmp->suffix, suffix))
316 {
317 symbolicname = strdup(dd_tmp->symbolicname);
318 break;
319 }
320 else if (0 == strcmp(dd_tmp->symbolicname, suffix))
321 {
322 symbolicname = strdup(suffix);
323 break;
324 }
325 else
326 dd_tmp++;
327 }
328 free (dd_start);
329 }
330 return symbolicname;
331 }
332
333 /* make_temporary_file --- Make a temporary file */
334 static FILE *
make_temporary_file(char * template,char * mode)335 make_temporary_file(char *template, char * mode)
336 {
337 #ifdef HAVE_MKSTEMP
338 /* #warning "To make temporary file, mkstemp will be used." */
339 int tmpfd;
340 tmpfd = mkstemp(template);
341 if (tmpfd < 0)
342 return NULL;
343 return fdopen(tmpfd, mode);
344 #else
345 /* #warning "To make temporary file, tmpnam will be used." */
346 char * tmpname;
347 tmpname = tmpnam(template);
348 if (template == NULL)
349 return NULL;
350 return fopen(tmpname, mode);
351 #endif /* HAVE_MKSTEMP */
352 }
353
354 static void
remove_temporary_file(const at_string tmpfile_name)355 remove_temporary_file (const at_string tmpfile_name)
356 {
357 #if BO_DEBUG == 0
358 remove (tmpfile_name);
359 #else
360 fprintf(stderr, "tmp file name: %s\n", tmpfile_name);
361 #endif /* Not BO_DEBUG == 0 */
362 }
363