#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "posix.h"
#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "nonposix.h"
#ifndef HAVE_MKSTEMP_PROTO
extern "C" {
extern int mkstemp (char *);
}
#endif
#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
#define TMPDIR_ENVVAR "TMPDIR"
#ifdef P_tmpdir
# define DEFAULT_TMPDIR P_tmpdir
#else
# define DEFAULT_TMPDIR "/tmp"
#endif
#ifdef __MSDOS__
#define TMPFILE_PREFIX ""
#else
#define TMPFILE_PREFIX "groff"
#endif
char *xtmptemplate(char *postfix)
{
const char *dir = getenv(GROFF_TMPDIR_ENVVAR);
int postlen = 0;
if (postfix)
postlen = strlen(postfix);
if (!dir) {
dir = getenv(TMPDIR_ENVVAR);
if (!dir)
dir = DEFAULT_TMPDIR;
}
size_t dir_len = strlen(dir);
const char *dir_end = dir + dir_len - 1;
int needs_slash = strchr(DIR_SEPS, *dir_end) == NULL;
char *templ = new char[strlen(dir) + needs_slash
+ sizeof(TMPFILE_PREFIX) - 1 + 6 + 1 + postlen];
strcpy(templ, dir);
if (needs_slash)
strcat(templ, "/");
strcat(templ, TMPFILE_PREFIX);
if (postlen > 0)
strcat(templ, postfix);
strcat(templ, "XXXXXX");
return( templ );
}
static struct xtmpfile_list {
struct xtmpfile_list *next;
char fname[1];
} *xtmpfiles_to_delete;
static void remove_tmp_files()
{
struct xtmpfile_list *p = xtmpfiles_to_delete;
while (p) {
if (unlink(p->fname) < 0)
error("cannot unlink `%1': %2", p->fname, strerror(errno));
struct xtmpfile_list *old = p;
p = p->next;
free(old);
}
}
static void add_tmp_file(const char *name)
{
if (xtmpfiles_to_delete == NULL)
atexit(remove_tmp_files);
struct xtmpfile_list *p
= (struct xtmpfile_list *)malloc(sizeof(struct xtmpfile_list)
+ strlen (name));
if (p == NULL) {
error("cannot unlink `%1': %2", name, strerror(errno));
return;
}
p->next = xtmpfiles_to_delete;
strcpy(p->fname, name);
xtmpfiles_to_delete = p;
}
FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
{
char *templ = xtmptemplate(postfix);
#ifdef HAVE_MKSTEMP
errno = 0;
int fd = mkstemp(templ);
if (fd < 0)
fatal("cannot create temporary file: %1", strerror(errno));
errno = 0;
FILE *fp = fdopen(fd, FOPEN_RWB); if (!fp)
fatal("fdopen: %1", strerror(errno));
#else
if (!mktemp(templ) || !templ[0])
fatal("cannot create file name for temporary file");
errno = 0;
FILE *fp = fopen(templ, FOPEN_RWB);
if (!fp)
fatal("cannot open `%1': %2", templ, strerror(errno));
#endif
if (do_unlink)
add_tmp_file(templ);
if ((namep != 0) && ((*namep) != 0))
*namep = templ;
else
a_delete templ;
return fp;
}