RdFToI.c revision 52dc082b
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 56HFUNC(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 | O_CLOEXEC); 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 | O_CLOEXEC); 233 if ( fd < 0 ) 234 { 235 strcpy(compressfile + len, ext = ".gz"); 236 fd = open(compressfile, O_RDONLY | O_CLOEXEC); 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