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