/*
* Copyright (C) 1989-95 GROUPE BULL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of GROUPE BULL shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from GROUPE BULL.
*/
/*****************************************************************************\
* RdFToI.c: *
* *
* XPM library *
* Parse an XPM file and create the image and possibly its mask *
* *
* Developed by Arnaud Le Hors *
\*****************************************************************************/
/* $XFree86$ */
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "XpmI.h"
#ifndef NO_ZPIPE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#else
#ifdef FOR_MSW
#include <fcntl.h>
#endif
#endif
LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata));
LFUNC(xpmDataClose, void, (xpmData *mdata));
#ifndef CXPMPROG
int
XpmReadFileToImage(display, filename,
image_return, shapeimage_return, attributes)
Display *display;
char *filename;
XImage **image_return;
XImage **shapeimage_return;
XpmAttributes *attributes;
{
XpmImage image;
XpmInfo info;
int ErrorStatus;
xpmData mdata;
xpmInitXpmImage(&image);
xpmInitXpmInfo(&info);
/* open file to read */
if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
return (ErrorStatus);
/* create the XImage from the XpmData */
if (attributes) {
xpmInitAttributes(attributes);
xpmSetInfoMask(&info, attributes);
ErrorStatus = xpmParseDataAndCreate(display, &mdata,
image_return, shapeimage_return,
&image, &info, attributes);
} else
ErrorStatus = xpmParseDataAndCreate(display, &mdata,
image_return, shapeimage_return,
&image, NULL, attributes);
if (attributes) {
if (ErrorStatus >= 0) /* no fatal error */
xpmSetAttributes(attributes, &image, &info);
XpmFreeXpmInfo(&info);
}
xpmDataClose(&mdata);
/* free the XpmImage */
XpmFreeXpmImage(&image);
return (ErrorStatus);
}
int
XpmReadFileToXpmImage(filename, image, info)
char *filename;
XpmImage *image;
XpmInfo *info;
{
xpmData mdata;
int ErrorStatus;
/* init returned values */
xpmInitXpmImage(image);
xpmInitXpmInfo(info);
/* open file to read */
if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
return (ErrorStatus);
/* create the XpmImage from the XpmData */
ErrorStatus = xpmParseData(&mdata, image, info);
xpmDataClose(&mdata);
return (ErrorStatus);
}
#endif /* CXPMPROG */
#ifndef NO_ZPIPE
/* Do not depend on errno after read_through */
FILE*
xpmPipeThrough(fd, cmd, arg1, mode)
int fd;
const char* cmd;
const char* arg1;
const char* mode;
{
FILE* fp;
int status, fds[2], in = 0, out = 1;
pid_t pid;
if ( 'w' == *mode )
out = 0, in = 1;
if ( pipe(fds) < 0 )
return NULL;
pid = fork();
if ( pid < 0 )
goto fail1;
if ( 0 == pid )
{
close(fds[in]);
if ( dup2(fds[out], out) < 0 )
goto err;
close(fds[out]);
if ( dup2(fd, in) < 0 )
goto err;
close(fd);
pid = fork();
if ( pid < 0 )
goto err;
if ( 0 == pid )
{
execlp(cmd, cmd, arg1, (char *)NULL);
perror(cmd);
goto err;
}
_exit(0);
err:
_exit(1);
}
close(fds[out]);
/* calling process: wait for first child */
while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
;
if ( WIFSIGNALED(status) ||
(WIFEXITED(status) && WEXITSTATUS(status) != 0) )
goto fail2;
fp = fdopen(fds[in], mode);
if ( !fp )
goto fail2;
close(fd); /* still open in 2nd child */
return fp;
fail1:
close(fds[out]);
fail2:
close(fds[in]);
return NULL;
}
#endif
/*
* open the given file to be read as an xpmData which is returned.
*/
static int
OpenReadFile(filename, mdata)
char *filename;
xpmData *mdata;
{
if (!filename) {
mdata->stream.file = (stdin);
mdata->type = XPMFILE;
} else {
int fd = open(filename, O_RDONLY);
#if defined(NO_ZPIPE)
if ( fd < 0 )
return XpmOpenFailed;
#else
const char* ext = NULL;
if ( fd >= 0 )
ext = strrchr(filename, '.');
#ifdef STAT_ZFILE /* searching for z-files if the given name not found */
else
{
size_t len = strlen(filename);
char *compressfile = (char *) XpmMalloc(len + 4);
if ( !compressfile )
return (XpmNoMemory);
strcpy(compressfile, filename);
strcpy(compressfile + len, ext = ".Z");
fd = open(compressfile, O_RDONLY);
if ( fd < 0 )
{
strcpy(compressfile + len, ext = ".gz");
fd = open(compressfile, O_RDONLY);
if ( fd < 0 )
{
XpmFree(compressfile);
return XpmOpenFailed;
}
}
XpmFree(compressfile);
}
#endif
if ( ext && !strcmp(ext, ".Z") )
{
mdata->type = XPMPIPE;
mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r");
}
else if ( ext && !strcmp(ext, ".gz") )
{
mdata->type = XPMPIPE;
mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r");
}
else
#endif /* z-files */
{
mdata->type = XPMFILE;
mdata->stream.file = fdopen(fd, "r");
}
if (!mdata->stream.file)
{
close(fd);
return (XpmOpenFailed);
}
}
mdata->CommentLength = 0;
#ifdef CXPMPROG
mdata->lineNum = 0;
mdata->charNum = 0;
#endif
return (XpmSuccess);
}
/*
* close the file related to the xpmData if any
*/
static void
xpmDataClose(mdata)
xpmData *mdata;
{
if (mdata->stream.file != (stdin))
fclose(mdata->stream.file);
}