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