e56e3f8b6ab65b52c465f640cc1d9e0e409bcfa8
[framework/uifw/xorg/lib/libxpm.git] / src / RdFToI.c
1 /*
2  * Copyright (C) 1989-95 GROUPE BULL
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Except as contained in this notice, the name of GROUPE BULL shall not be
22  * used in advertising or otherwise to promote the sale, use or other dealings
23  * in this Software without prior written authorization from GROUPE BULL.
24  */
25
26 /*****************************************************************************\
27 *  RdFToI.c:                                                                  *
28 *                                                                             *
29 *  XPM library                                                                *
30 *  Parse an XPM file and create the image and possibly its mask               *
31 *                                                                             *
32 *  Developed by Arnaud Le Hors                                                *
33 \*****************************************************************************/
34
35 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40 #include "XpmI.h"
41 #ifndef NO_ZPIPE
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <sys/types.h>
45 #include <sys/wait.h>
46 #else
47 #ifdef FOR_MSW
48 #include <fcntl.h>
49 #endif
50 #endif
51
52 LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata));
53 LFUNC(xpmDataClose, void, (xpmData *mdata));
54
55 FUNC(xpmPipeThrough, FILE*, (int fd,
56                              const char *cmd,
57                              const char *arg1,
58                              const char *mode));
59
60 #ifndef CXPMPROG
61 int
62 XpmReadFileToImage(
63     Display              *display,
64     char                 *filename,
65     XImage              **image_return,
66     XImage              **shapeimage_return,
67     XpmAttributes        *attributes)
68 {
69     XpmImage image;
70     XpmInfo info;
71     int ErrorStatus;
72     xpmData mdata;
73
74     xpmInitXpmImage(&image);
75     xpmInitXpmInfo(&info);
76
77     /* open file to read */
78     if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
79         return (ErrorStatus);
80
81     /* create the XImage from the XpmData */
82     if (attributes) {
83         xpmInitAttributes(attributes);
84         xpmSetInfoMask(&info, attributes);
85         ErrorStatus = xpmParseDataAndCreate(display, &mdata,
86                                             image_return, shapeimage_return,
87                                             &image, &info, attributes);
88     } else
89         ErrorStatus = xpmParseDataAndCreate(display, &mdata,
90                                             image_return, shapeimage_return,
91                                             &image, NULL, attributes);
92     if (attributes) {
93         if (ErrorStatus >= 0)           /* no fatal error */
94             xpmSetAttributes(attributes, &image, &info);
95         XpmFreeXpmInfo(&info);
96     }
97
98     xpmDataClose(&mdata);
99     /* free the XpmImage */
100     XpmFreeXpmImage(&image);
101
102     return (ErrorStatus);
103 }
104
105 int
106 XpmReadFileToXpmImage(
107     char        *filename,
108     XpmImage    *image,
109     XpmInfo     *info)
110 {
111     xpmData mdata;
112     int ErrorStatus;
113
114     /* init returned values */
115     xpmInitXpmImage(image);
116     xpmInitXpmInfo(info);
117
118     /* open file to read */
119     if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
120         return (ErrorStatus);
121
122     /* create the XpmImage from the XpmData */
123     ErrorStatus = xpmParseData(&mdata, image, info);
124
125     xpmDataClose(&mdata);
126
127     return (ErrorStatus);
128 }
129 #endif /* CXPMPROG */
130
131 #ifndef NO_ZPIPE
132 /* Do not depend on errno after read_through */
133 FILE*
134 xpmPipeThrough(
135     int          fd,
136     const char  *cmd,
137     const char  *arg1,
138     const char  *mode)
139 {
140     FILE* fp;
141     int status, fds[2], in = 0, out = 1;
142     pid_t pid;
143     if ( 'w' == *mode )
144         out = 0, in = 1;
145     if ( pipe(fds) < 0 )
146         return NULL;
147     pid = fork();
148     if ( pid < 0 )
149         goto fail1;
150     if ( 0 == pid )
151     {
152         close(fds[in]);
153         if ( dup2(fds[out], out) < 0 )
154             goto err;
155         close(fds[out]);
156         if ( dup2(fd, in) < 0 )
157             goto err;
158         close(fd);
159         pid = fork();
160         if ( pid < 0 )
161             goto err;
162         if ( 0 == pid )
163         {
164             execlp(cmd, cmd, arg1, (char *)NULL);
165             perror(cmd);
166             goto err;
167         }
168         _exit(0);
169     err:
170         _exit(1);
171     }
172     close(fds[out]);
173     /* calling process: wait for first child */
174     while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
175         ;
176     if ( WIFSIGNALED(status) ||
177          (WIFEXITED(status) && WEXITSTATUS(status) != 0) )
178         goto fail2;
179     fp = fdopen(fds[in], mode);
180     if ( !fp )
181         goto fail2;
182     close(fd); /* still open in 2nd child */
183     return fp;
184 fail1:
185     close(fds[out]);
186 fail2:
187     close(fds[in]);
188     return NULL;
189 }
190 #endif
191
192 /*
193  * open the given file to be read as an xpmData which is returned.
194  */
195 static int
196 OpenReadFile(
197     char        *filename,
198     xpmData     *mdata)
199 {
200     if (!filename) {
201         mdata->stream.file = (stdin);
202         mdata->type = XPMFILE;
203     } else {
204         int fd = open(filename, O_RDONLY);
205 #if defined(NO_ZPIPE)
206         if ( fd < 0 )
207             return XpmOpenFailed;
208 #else
209         const char* ext = NULL;
210         if ( fd >= 0 )
211             ext = strrchr(filename, '.');
212 #ifdef STAT_ZFILE /* searching for z-files if the given name not found */
213         else
214         {
215             size_t len = strlen(filename);
216             char *compressfile = (char *) XpmMalloc(len + 4);
217             if ( !compressfile )
218                 return (XpmNoMemory);
219             strcpy(compressfile, filename);
220             strcpy(compressfile + len, ext = ".Z");
221             fd = open(compressfile, O_RDONLY);
222             if ( fd < 0 )
223             {
224                 strcpy(compressfile + len, ext = ".gz");
225                 fd = open(compressfile, O_RDONLY);
226                 if ( fd < 0 )
227                 {
228                     XpmFree(compressfile);
229                     return XpmOpenFailed;
230                 }
231             }
232             XpmFree(compressfile);
233         }
234 #endif
235         if ( ext && !strcmp(ext, ".Z") )
236         {
237             mdata->type = XPMPIPE;
238             mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r");
239         }
240         else if ( ext && !strcmp(ext, ".gz") )
241         {
242             mdata->type = XPMPIPE;
243             mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r");
244         }
245         else
246 #endif /* z-files */
247         {
248             mdata->type = XPMFILE;
249             mdata->stream.file = fdopen(fd, "r");
250         }
251         if (!mdata->stream.file)
252         {
253             close(fd);
254             return (XpmOpenFailed);
255         }
256     }
257     mdata->CommentLength = 0;
258 #ifdef CXPMPROG
259     mdata->lineNum = 0;
260     mdata->charNum = 0;
261 #endif
262     return (XpmSuccess);
263 }
264
265 /*
266  * close the file related to the xpmData if any
267  */
268 static void
269 xpmDataClose(xpmData *mdata)
270 {
271     if (mdata->stream.file != (stdin))
272         fclose(mdata->stream.file);
273 }