RdFToI.c revision a966c04f
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/* $XFree86$ */
35
36/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
37
38#ifdef HAVE_CONFIG_H
39#include <config.h>
40#endif
41#include "XpmI.h"
42#ifndef NO_ZPIPE
43#include <fcntl.h>
44#include <errno.h>
45#include <sys/types.h>
46#include <sys/wait.h>
47#else
48#ifdef FOR_MSW
49#include <fcntl.h>
50#endif
51#endif
52
53LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata));
54LFUNC(xpmDataClose, void, (xpmData *mdata));
55
56#ifndef CXPMPROG
57int
58XpmReadFileToImage(display, filename,
59		   image_return, shapeimage_return, attributes)
60    Display *display;
61    char *filename;
62    XImage **image_return;
63    XImage **shapeimage_return;
64    XpmAttributes *attributes;
65{
66    XpmImage image;
67    XpmInfo info;
68    int ErrorStatus;
69    xpmData mdata;
70
71    xpmInitXpmImage(&image);
72    xpmInitXpmInfo(&info);
73
74    /* open file to read */
75    if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
76	return (ErrorStatus);
77
78    /* create the XImage from the XpmData */
79    if (attributes) {
80	xpmInitAttributes(attributes);
81	xpmSetInfoMask(&info, attributes);
82	ErrorStatus = xpmParseDataAndCreate(display, &mdata,
83					    image_return, shapeimage_return,
84					    &image, &info, attributes);
85    } else
86	ErrorStatus = xpmParseDataAndCreate(display, &mdata,
87					    image_return, shapeimage_return,
88					    &image, NULL, attributes);
89    if (attributes) {
90	if (ErrorStatus >= 0)		/* no fatal error */
91	    xpmSetAttributes(attributes, &image, &info);
92	XpmFreeXpmInfo(&info);
93    }
94
95    xpmDataClose(&mdata);
96    /* free the XpmImage */
97    XpmFreeXpmImage(&image);
98
99    return (ErrorStatus);
100}
101
102int
103XpmReadFileToXpmImage(filename, image, info)
104    char *filename;
105    XpmImage *image;
106    XpmInfo *info;
107{
108    xpmData mdata;
109    int ErrorStatus;
110
111    /* init returned values */
112    xpmInitXpmImage(image);
113    xpmInitXpmInfo(info);
114
115    /* open file to read */
116    if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
117	return (ErrorStatus);
118
119    /* create the XpmImage from the XpmData */
120    ErrorStatus = xpmParseData(&mdata, image, info);
121
122    xpmDataClose(&mdata);
123
124    return (ErrorStatus);
125}
126#endif /* CXPMPROG */
127
128#ifndef NO_ZPIPE
129/* Do not depend on errno after read_through */
130FILE*
131xpmPipeThrough(fd, cmd, arg1, mode)
132    int fd;
133    const char* cmd;
134    const char* arg1;
135    const char* mode;
136{
137    FILE* fp;
138    int status, fds[2], in = 0, out = 1;
139    pid_t pid;
140    if ( 'w' == *mode )
141	out = 0, in = 1;
142    if ( pipe(fds) < 0 )
143	return NULL;
144    pid = fork();
145    if ( pid < 0 )
146	goto fail1;
147    if ( 0 == pid )
148    {
149	close(fds[in]);
150	if ( dup2(fds[out], out) < 0 )
151	    goto err;
152	close(fds[out]);
153	if ( dup2(fd, in) < 0 )
154	    goto err;
155	close(fd);
156	pid = fork();
157	if ( pid < 0 )
158	    goto err;
159	if ( 0 == pid )
160	{
161	    execlp(cmd, cmd, arg1, (char *)NULL);
162	    perror(cmd);
163	    goto err;
164	}
165	_exit(0);
166    err:
167	_exit(1);
168    }
169    close(fds[out]);
170    /* calling process: wait for first child */
171    while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
172	;
173    if ( WIFSIGNALED(status) ||
174	 (WIFEXITED(status) && WEXITSTATUS(status) != 0) )
175	goto fail2;
176    fp = fdopen(fds[in], mode);
177    if ( !fp )
178	goto fail2;
179    close(fd); /* still open in 2nd child */
180    return fp;
181fail1:
182    close(fds[out]);
183fail2:
184    close(fds[in]);
185    return NULL;
186}
187#endif
188
189/*
190 * open the given file to be read as an xpmData which is returned.
191 */
192static int
193OpenReadFile(filename, mdata)
194    char *filename;
195    xpmData *mdata;
196{
197    if (!filename) {
198	mdata->stream.file = (stdin);
199	mdata->type = XPMFILE;
200    } else {
201	int fd = open(filename, O_RDONLY);
202#if defined(NO_ZPIPE)
203	if ( fd < 0 )
204	    return XpmOpenFailed;
205#else
206	const char* ext = NULL;
207	if ( fd >= 0 )
208	    ext = strrchr(filename, '.');
209#ifdef STAT_ZFILE /* searching for z-files if the given name not found */
210	else
211	{
212	    size_t len = strlen(filename);
213	    char *compressfile = (char *) XpmMalloc(len + 4);
214	    if ( !compressfile )
215		return (XpmNoMemory);
216	    strcpy(compressfile, filename);
217	    strcpy(compressfile + len, ext = ".Z");
218	    fd = open(compressfile, O_RDONLY);
219	    if ( fd < 0 )
220	    {
221		strcpy(compressfile + len, ext = ".gz");
222		fd = open(compressfile, O_RDONLY);
223		if ( fd < 0 )
224		{
225		    XpmFree(compressfile);
226		    return XpmOpenFailed;
227		}
228	    }
229	    XpmFree(compressfile);
230	}
231#endif
232	if ( ext && !strcmp(ext, ".Z") )
233	{
234	    mdata->type = XPMPIPE;
235	    mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r");
236	}
237	else if ( ext && !strcmp(ext, ".gz") )
238	{
239	    mdata->type = XPMPIPE;
240	    mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r");
241	}
242	else
243#endif /* z-files */
244	{
245	    mdata->type = XPMFILE;
246	    mdata->stream.file = fdopen(fd, "r");
247	}
248	if (!mdata->stream.file)
249	{
250	    close(fd);
251	    return (XpmOpenFailed);
252	}
253    }
254    mdata->CommentLength = 0;
255#ifdef CXPMPROG
256    mdata->lineNum = 0;
257    mdata->charNum = 0;
258#endif
259    return (XpmSuccess);
260}
261
262/*
263 * close the file related to the xpmData if any
264 */
265static void
266xpmDataClose(mdata)
267    xpmData *mdata;
268{
269    if (mdata->stream.file != (stdin))
270	fclose(mdata->stream.file);
271}
272