2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 // Solaris 2.5.1 has these functions,
34 // but its stdlib.h fails to declare them.
39 // If this is set, create temporary files there
40 #define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
41 // otherwise if this is set, create temporary files there
42 #define TMPDIR_ENVVAR "TMPDIR"
43 // otherwise if P_tmpdir is defined, create temporary files there
45 # define DEFAULT_TMPDIR P_tmpdir
47 // otherwise create temporary files here.
48 # define DEFAULT_TMPDIR "/tmp"
50 // Use this as the prefix for temporary filenames.
51 #define TMPFILE_PREFIX "groff"
54 * Generate a temporary name template with a postfix
55 * immediately after the TMPFILE_PREFIX.
56 * It uses the groff preferences for a temporary directory.
57 * Note that no file name is either created or opened,
58 * only the *template* is returned.
61 char *xtmptemplate(char *postfix
)
63 const char *dir
= getenv(GROFF_TMPDIR_ENVVAR
);
67 postlen
= strlen(postfix
);
70 dir
= getenv(TMPDIR_ENVVAR
);
75 size_t dir_len
= strlen(dir
);
76 const char *dir_end
= dir
+ dir_len
- 1;
77 int needs_slash
= strchr(DIR_SEPS
, *dir_end
) == NULL
;
78 char *templ
= new char[strlen(dir
) + needs_slash
79 + sizeof(TMPFILE_PREFIX
) - 1 + 6 + 1 + postlen
];
83 strcat(templ
, TMPFILE_PREFIX
);
85 strcat(templ
, postfix
);
86 strcat(templ
, "XXXXXX");
91 // The trick with unlinking the temporary file while it is still in
92 // use is not portable, it will fail on MS-DOS and most MS-Windows
93 // filesystems. So it cannot be used on non-Posix systems.
94 // Instead, we maintain a list of files to be deleted on exit, and
95 // register an atexit function that will remove them all in one go.
96 // This should be portable to all platforms.
98 static struct xtmpfile_list
{
99 struct xtmpfile_list
*next
;
101 } *xtmpfiles_to_delete
;
103 static void remove_tmp_files(void)
105 struct xtmpfile_list
*p
= xtmpfiles_to_delete
;
109 if (unlink(p
->fname
) < 0)
110 error("cannot unlink `%1': %2", p
->fname
, strerror(errno
));
112 struct xtmpfile_list
*old
= p
;
118 static void add_tmp_file(const char *name
)
120 if (xtmpfiles_to_delete
== NULL
)
121 atexit(remove_tmp_files
);
123 char *fname
= new char[FILENAME_MAX
];
124 struct xtmpfile_list
*p
125 = (struct xtmpfile_list
*)malloc(sizeof(struct xtmpfile_list
));
128 error("cannot unlink `%1': %2", name
, strerror(errno
));
131 p
->next
= xtmpfiles_to_delete
;
132 p
->fname
= strcpy(fname
, name
);
133 xtmpfiles_to_delete
= p
;
136 // Open a temporary file and with fatal error on failure.
140 FILE *xtmpfile(char **namep
, char *postfix
, int do_unlink
)
142 char *templ
= xtmptemplate(postfix
);
146 int fd
= mkstemp(templ
);
148 fatal("cannot create temporary file: %1", strerror(errno
));
150 FILE *fp
= fdopen(fd
, FOPEN_RWB
); // many callers of xtmpfile use binary I/O
152 fatal("fdopen: %1", strerror(errno
));
153 #else /* not HAVE_MKSTEMP */
154 if (!mktemp(templ
) || !templ
[0])
155 fatal("cannot create file name for temporary file");
157 FILE *fp
= fopen(templ
, FOPEN_RWB
);
159 fatal("cannot open `%1': %2", templ
, strerror(errno
));
160 #endif /* not HAVE_MKSTEMP */
163 if ((namep
!= 0) && ((*namep
) != 0)) {
173 // FIXME: does MSVC have mktemp or mkstemp? If so, it should now
174 // use the version above, as it no longer removes an open file.
175 // The version below will NOT work with grohtml, since grohtml
176 // wants to know the name of the file opened by xtmpfile!!
178 // If you're not running Unix, the following will do:
179 FILE *xtmpfile(char **namep
, char *postfix
, int do_unlink
)
181 FILE *fp
= tmpfile();
183 fatal("couldn't create temporary file");
187 #endif /* _MSC_VER */