1a966c04fSmrg/*
2a966c04fSmrg * Copyright (C) 1989-95 GROUPE BULL
3a966c04fSmrg *
4a966c04fSmrg * Permission is hereby granted, free of charge, to any person obtaining a copy
5a966c04fSmrg * of this software and associated documentation files (the "Software"), to
6a966c04fSmrg * deal in the Software without restriction, including without limitation the
7a966c04fSmrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8a966c04fSmrg * sell copies of the Software, and to permit persons to whom the Software is
9a966c04fSmrg * furnished to do so, subject to the following conditions:
10a966c04fSmrg *
11a966c04fSmrg * The above copyright notice and this permission notice shall be included in
12a966c04fSmrg * all copies or substantial portions of the Software.
13a966c04fSmrg *
14a966c04fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15a966c04fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16a966c04fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17a966c04fSmrg * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18a966c04fSmrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19a966c04fSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20a966c04fSmrg *
21a966c04fSmrg * Except as contained in this notice, the name of GROUPE BULL shall not be
22a966c04fSmrg * used in advertising or otherwise to promote the sale, use or other dealings
23a966c04fSmrg * in this Software without prior written authorization from GROUPE BULL.
24a966c04fSmrg */
25a966c04fSmrg
26a966c04fSmrg/*****************************************************************************\
27a966c04fSmrg*  RdFToI.c:                                                                  *
28a966c04fSmrg*                                                                             *
29a966c04fSmrg*  XPM library                                                                *
30a966c04fSmrg*  Parse an XPM file and create the image and possibly its mask               *
31a966c04fSmrg*                                                                             *
32a966c04fSmrg*  Developed by Arnaud Le Hors                                                *
33a966c04fSmrg\*****************************************************************************/
34a966c04fSmrg
35a966c04fSmrg/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
36a966c04fSmrg
37a966c04fSmrg#ifdef HAVE_CONFIG_H
38a966c04fSmrg#include <config.h>
39a966c04fSmrg#endif
40a966c04fSmrg#include "XpmI.h"
41a966c04fSmrg#ifndef NO_ZPIPE
42a966c04fSmrg#include <fcntl.h>
43a966c04fSmrg#include <errno.h>
44a966c04fSmrg#include <sys/types.h>
45a966c04fSmrg#include <sys/wait.h>
461c235774Smrg#include <unistd.h>
47a966c04fSmrg#else
48a966c04fSmrg#ifdef FOR_MSW
49a966c04fSmrg#include <fcntl.h>
50a966c04fSmrg#endif
51a966c04fSmrg#endif
52a966c04fSmrg
53ac92798bSmrgLFUNC(OpenReadFile, int, (const char *filename, xpmData *mdata));
54a966c04fSmrgLFUNC(xpmDataClose, void, (xpmData *mdata));
55a966c04fSmrg
5652dc082bSmrgHFUNC(xpmPipeThrough, FILE*, (int fd,
572e2dd055Smrg			     const char *cmd,
582e2dd055Smrg			     const char *arg1,
592e2dd055Smrg			     const char *mode));
602e2dd055Smrg
61a966c04fSmrg#ifndef CXPMPROG
62a966c04fSmrgint
632e2dd055SmrgXpmReadFileToImage(
642e2dd055Smrg    Display		 *display,
65ac92798bSmrg    const char		 *filename,
662e2dd055Smrg    XImage		**image_return,
672e2dd055Smrg    XImage		**shapeimage_return,
682e2dd055Smrg    XpmAttributes	 *attributes)
69a966c04fSmrg{
70a966c04fSmrg    XpmImage image;
71a966c04fSmrg    XpmInfo info;
72a966c04fSmrg    int ErrorStatus;
73a966c04fSmrg    xpmData mdata;
74a966c04fSmrg
75a966c04fSmrg    xpmInitXpmImage(&image);
76a966c04fSmrg    xpmInitXpmInfo(&info);
77a966c04fSmrg
78a966c04fSmrg    /* open file to read */
79a966c04fSmrg    if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
80a966c04fSmrg	return (ErrorStatus);
81a966c04fSmrg
82a966c04fSmrg    /* create the XImage from the XpmData */
83a966c04fSmrg    if (attributes) {
84a966c04fSmrg	xpmInitAttributes(attributes);
85a966c04fSmrg	xpmSetInfoMask(&info, attributes);
86a966c04fSmrg	ErrorStatus = xpmParseDataAndCreate(display, &mdata,
87a966c04fSmrg					    image_return, shapeimage_return,
88a966c04fSmrg					    &image, &info, attributes);
89a966c04fSmrg    } else
90a966c04fSmrg	ErrorStatus = xpmParseDataAndCreate(display, &mdata,
91a966c04fSmrg					    image_return, shapeimage_return,
92a966c04fSmrg					    &image, NULL, attributes);
93a966c04fSmrg    if (attributes) {
94a966c04fSmrg	if (ErrorStatus >= 0)		/* no fatal error */
95a966c04fSmrg	    xpmSetAttributes(attributes, &image, &info);
96a966c04fSmrg	XpmFreeXpmInfo(&info);
97a966c04fSmrg    }
98a966c04fSmrg
99a966c04fSmrg    xpmDataClose(&mdata);
100a966c04fSmrg    /* free the XpmImage */
101a966c04fSmrg    XpmFreeXpmImage(&image);
102a966c04fSmrg
103a966c04fSmrg    return (ErrorStatus);
104a966c04fSmrg}
105a966c04fSmrg
106a966c04fSmrgint
1072e2dd055SmrgXpmReadFileToXpmImage(
108ac92798bSmrg    const char	*filename,
1092e2dd055Smrg    XpmImage	*image,
1102e2dd055Smrg    XpmInfo	*info)
111a966c04fSmrg{
112a966c04fSmrg    xpmData mdata;
113a966c04fSmrg    int ErrorStatus;
114a966c04fSmrg
115a966c04fSmrg    /* init returned values */
116a966c04fSmrg    xpmInitXpmImage(image);
117a966c04fSmrg    xpmInitXpmInfo(info);
118a966c04fSmrg
119a966c04fSmrg    /* open file to read */
120a966c04fSmrg    if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
121a966c04fSmrg	return (ErrorStatus);
122a966c04fSmrg
123a966c04fSmrg    /* create the XpmImage from the XpmData */
124a966c04fSmrg    ErrorStatus = xpmParseData(&mdata, image, info);
125a966c04fSmrg
126a966c04fSmrg    xpmDataClose(&mdata);
127a966c04fSmrg
128a966c04fSmrg    return (ErrorStatus);
129a966c04fSmrg}
130a966c04fSmrg#endif /* CXPMPROG */
131a966c04fSmrg
132a966c04fSmrg#ifndef NO_ZPIPE
133a966c04fSmrg/* Do not depend on errno after read_through */
134a966c04fSmrgFILE*
1352e2dd055SmrgxpmPipeThrough(
1362e2dd055Smrg    int		 fd,
1372e2dd055Smrg    const char	*cmd,
1382e2dd055Smrg    const char	*arg1,
1392e2dd055Smrg    const char	*mode)
140a966c04fSmrg{
141a966c04fSmrg    FILE* fp;
142a966c04fSmrg    int status, fds[2], in = 0, out = 1;
143a966c04fSmrg    pid_t pid;
144a966c04fSmrg    if ( 'w' == *mode )
145a966c04fSmrg	out = 0, in = 1;
146a966c04fSmrg    if ( pipe(fds) < 0 )
147a966c04fSmrg	return NULL;
148a966c04fSmrg    pid = fork();
149a966c04fSmrg    if ( pid < 0 )
150a966c04fSmrg	goto fail1;
151a966c04fSmrg    if ( 0 == pid )
152a966c04fSmrg    {
153a966c04fSmrg	close(fds[in]);
154a966c04fSmrg	if ( dup2(fds[out], out) < 0 )
155a966c04fSmrg	    goto err;
156a966c04fSmrg	close(fds[out]);
157a966c04fSmrg	if ( dup2(fd, in) < 0 )
158a966c04fSmrg	    goto err;
159a966c04fSmrg	close(fd);
160a966c04fSmrg	pid = fork();
161a966c04fSmrg	if ( pid < 0 )
162a966c04fSmrg	    goto err;
163a966c04fSmrg	if ( 0 == pid )
164a966c04fSmrg	{
1651c235774Smrg#ifdef HAVE_CLOSEFROM
1661c235774Smrg	    closefrom(3);
1671c235774Smrg#elif defined(HAVE_CLOSE_RANGE)
1681c235774Smrg# ifdef CLOSE_RANGE_UNSHARE
1691c235774Smrg#  define close_range_flags CLOSE_RANGE_UNSHARE
1701c235774Smrg# else
1711c235774Smrg#  define close_range_flags 0
1721c235774Smrg#endif
1731c235774Smrg	    close_range(3, ~0U, close_range_flags);
1741c235774Smrg#endif
1751c235774Smrg	    execl(cmd, cmd, arg1, (char *)NULL);
176a966c04fSmrg	    perror(cmd);
177a966c04fSmrg	    goto err;
178a966c04fSmrg	}
179a966c04fSmrg	_exit(0);
180a966c04fSmrg    err:
181a966c04fSmrg	_exit(1);
182a966c04fSmrg    }
183a966c04fSmrg    close(fds[out]);
184a966c04fSmrg    /* calling process: wait for first child */
185a966c04fSmrg    while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
186a966c04fSmrg	;
187a966c04fSmrg    if ( WIFSIGNALED(status) ||
188a966c04fSmrg	 (WIFEXITED(status) && WEXITSTATUS(status) != 0) )
189a966c04fSmrg	goto fail2;
190a966c04fSmrg    fp = fdopen(fds[in], mode);
191a966c04fSmrg    if ( !fp )
192a966c04fSmrg	goto fail2;
193a966c04fSmrg    close(fd); /* still open in 2nd child */
194a966c04fSmrg    return fp;
195a966c04fSmrgfail1:
196a966c04fSmrg    close(fds[out]);
197a966c04fSmrgfail2:
198a966c04fSmrg    close(fds[in]);
199a966c04fSmrg    return NULL;
200a966c04fSmrg}
201a966c04fSmrg#endif
202a966c04fSmrg
203a966c04fSmrg/*
204a966c04fSmrg * open the given file to be read as an xpmData which is returned.
205a966c04fSmrg */
206a966c04fSmrgstatic int
2072e2dd055SmrgOpenReadFile(
208ac92798bSmrg    const char	*filename,
2092e2dd055Smrg    xpmData	*mdata)
210a966c04fSmrg{
211a966c04fSmrg    if (!filename) {
212a966c04fSmrg	mdata->stream.file = (stdin);
213a966c04fSmrg	mdata->type = XPMFILE;
214a966c04fSmrg    } else {
21552dc082bSmrg	int fd = open(filename, O_RDONLY | O_CLOEXEC);
216a966c04fSmrg#if defined(NO_ZPIPE)
217a966c04fSmrg	if ( fd < 0 )
218a966c04fSmrg	    return XpmOpenFailed;
219a966c04fSmrg#else
220a966c04fSmrg	const char* ext = NULL;
221a966c04fSmrg	if ( fd >= 0 )
222a966c04fSmrg	    ext = strrchr(filename, '.');
223a966c04fSmrg#ifdef STAT_ZFILE /* searching for z-files if the given name not found */
224a966c04fSmrg	else
225a966c04fSmrg	{
226a966c04fSmrg	    size_t len = strlen(filename);
227a966c04fSmrg	    char *compressfile = (char *) XpmMalloc(len + 4);
228a966c04fSmrg	    if ( !compressfile )
229a966c04fSmrg		return (XpmNoMemory);
230a966c04fSmrg	    strcpy(compressfile, filename);
231a966c04fSmrg	    strcpy(compressfile + len, ext = ".Z");
23252dc082bSmrg	    fd = open(compressfile, O_RDONLY | O_CLOEXEC);
233a966c04fSmrg	    if ( fd < 0 )
234a966c04fSmrg	    {
235a966c04fSmrg		strcpy(compressfile + len, ext = ".gz");
23652dc082bSmrg		fd = open(compressfile, O_RDONLY | O_CLOEXEC);
237a966c04fSmrg		if ( fd < 0 )
238a966c04fSmrg		{
239a966c04fSmrg		    XpmFree(compressfile);
240a966c04fSmrg		    return XpmOpenFailed;
241a966c04fSmrg		}
242a966c04fSmrg	    }
243a966c04fSmrg	    XpmFree(compressfile);
244a966c04fSmrg	}
245a966c04fSmrg#endif
246a966c04fSmrg	if ( ext && !strcmp(ext, ".Z") )
247a966c04fSmrg	{
248a966c04fSmrg	    mdata->type = XPMPIPE;
24974835918Smrg#ifdef XPM_PATH_UNCOMPRESS
2501c235774Smrg	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_UNCOMPRESS, "-c", "r");
25174835918Smrg#else
25274835918Smrg	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-dqc", "r");
25374835918Smrg#endif
254a966c04fSmrg	}
255a966c04fSmrg	else if ( ext && !strcmp(ext, ".gz") )
256a966c04fSmrg	{
257a966c04fSmrg	    mdata->type = XPMPIPE;
2581c235774Smrg	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-dqc", "r");
259a966c04fSmrg	}
260a966c04fSmrg	else
261a966c04fSmrg#endif /* z-files */
262a966c04fSmrg	{
263a966c04fSmrg	    mdata->type = XPMFILE;
264a966c04fSmrg	    mdata->stream.file = fdopen(fd, "r");
265a966c04fSmrg	}
266a966c04fSmrg	if (!mdata->stream.file)
267a966c04fSmrg	{
268a966c04fSmrg	    close(fd);
269a966c04fSmrg	    return (XpmOpenFailed);
270a966c04fSmrg	}
271a966c04fSmrg    }
272a966c04fSmrg    mdata->CommentLength = 0;
273a966c04fSmrg#ifdef CXPMPROG
274a966c04fSmrg    mdata->lineNum = 0;
275a966c04fSmrg    mdata->charNum = 0;
276a966c04fSmrg#endif
277a966c04fSmrg    return (XpmSuccess);
278a966c04fSmrg}
279a966c04fSmrg
280a966c04fSmrg/*
281a966c04fSmrg * close the file related to the xpmData if any
282a966c04fSmrg */
283a966c04fSmrgstatic void
2842e2dd055SmrgxpmDataClose(xpmData *mdata)
285a966c04fSmrg{
286a966c04fSmrg    if (mdata->stream.file != (stdin))
287a966c04fSmrg	fclose(mdata->stream.file);
288a966c04fSmrg}
289