Home | History | Annotate | Line # | Download | only in src
      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 (at) 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 #endif
     48 
     49 LFUNC(OpenReadFile, int, (const char *filename, xpmData *mdata));
     50 LFUNC(xpmDataClose, void, (xpmData *mdata));
     51 
     52 HFUNC(xpmPipeThrough, FILE*, (int fd,
     53 			     const char *cmd,
     54 			     const char *arg1,
     55 			     const char *mode));
     56 
     57 #ifndef CXPMPROG
     58 int
     59 XpmReadFileToImage(
     60     Display		 *display,
     61     const 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 
    102 int
    103 XpmReadFileToXpmImage(
    104     const 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 */
    130 FILE*
    131 xpmPipeThrough(
    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 #ifdef HAVE_CLOSEFROM
    162 	    closefrom(3);
    163 #elif defined(HAVE_CLOSE_RANGE)
    164 # ifdef CLOSE_RANGE_UNSHARE
    165 #  define close_range_flags CLOSE_RANGE_UNSHARE
    166 # else
    167 #  define close_range_flags 0
    168 #endif
    169 	    close_range(3, ~0U, close_range_flags);
    170 #endif
    171 	    execl(cmd, cmd, arg1, (char *)NULL);
    172 	    perror(cmd);
    173 	    goto err;
    174 	}
    175 	_exit(0);
    176     err:
    177 	_exit(1);
    178     }
    179     close(fds[out]);
    180     /* calling process: wait for first child */
    181     while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
    182 	;
    183     if ( WIFSIGNALED(status) ||
    184 	 (WIFEXITED(status) && WEXITSTATUS(status) != 0) )
    185 	goto fail2;
    186     fp = fdopen(fds[in], mode);
    187     if ( !fp )
    188 	goto fail2;
    189     close(fd); /* still open in 2nd child */
    190     return fp;
    191 fail1:
    192     close(fds[out]);
    193 fail2:
    194     close(fds[in]);
    195     return NULL;
    196 }
    197 #endif
    198 
    199 /*
    200  * open the given file to be read as an xpmData which is returned.
    201  */
    202 static int
    203 OpenReadFile(
    204     const char	*filename,
    205     xpmData	*mdata)
    206 {
    207     if (!filename) {
    208 	mdata->stream.file = (stdin);
    209 	mdata->type = XPMFILE;
    210     } else {
    211 	int fd = open(filename, O_RDONLY | O_CLOEXEC);
    212 #if defined(NO_ZPIPE)
    213 	if ( fd < 0 )
    214 	    return XpmOpenFailed;
    215 #else
    216 	const char* ext = NULL;
    217 	if ( fd >= 0 )
    218 	    ext = strrchr(filename, '.');
    219 #ifdef STAT_ZFILE /* searching for z-files if the given name not found */
    220 	else
    221 	{
    222 	    size_t len = strlen(filename);
    223 	    char *compressfile = (char *) XpmMalloc(len + 4);
    224 	    if ( !compressfile )
    225 		return (XpmNoMemory);
    226 	    strcpy(compressfile, filename);
    227 	    strcpy(compressfile + len, ext = ".Z");
    228 	    fd = open(compressfile, O_RDONLY | O_CLOEXEC);
    229 	    if ( fd < 0 )
    230 	    {
    231 		strcpy(compressfile + len, ext = ".gz");
    232 		fd = open(compressfile, O_RDONLY | O_CLOEXEC);
    233 		if ( fd < 0 )
    234 		{
    235 		    XpmFree(compressfile);
    236 		    return XpmOpenFailed;
    237 		}
    238 	    }
    239 	    XpmFree(compressfile);
    240 	}
    241 #endif
    242 	if ( ext && !strcmp(ext, ".Z") )
    243 	{
    244 	    mdata->type = XPMPIPE;
    245 #ifdef XPM_PATH_UNCOMPRESS
    246 	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_UNCOMPRESS, "-c", "r");
    247 #else
    248 	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-dqc", "r");
    249 #endif
    250 	}
    251 	else if ( ext && !strcmp(ext, ".gz") )
    252 	{
    253 	    mdata->type = XPMPIPE;
    254 	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-dqc", "r");
    255 	}
    256 	else
    257 #endif /* z-files */
    258 	{
    259 	    mdata->type = XPMFILE;
    260 	    mdata->stream.file = fdopen(fd, "r");
    261 	}
    262 	if (!mdata->stream.file)
    263 	{
    264 	    close(fd);
    265 	    return (XpmOpenFailed);
    266 	}
    267     }
    268     mdata->CommentLength = 0;
    269 #ifdef CXPMPROG
    270     mdata->lineNum = 0;
    271     mdata->charNum = 0;
    272 #endif
    273     return (XpmSuccess);
    274 }
    275 
    276 /*
    277  * close the file related to the xpmData if any
    278  */
    279 static void
    280 xpmDataClose(xpmData *mdata)
    281 {
    282     if (mdata->stream.file != (stdin))
    283 	fclose(mdata->stream.file);
    284 }
    285