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