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