14ca332d5SPeter Wemm /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
44ca332d5SPeter Wemm * Copyright (c) 1994, 1995, 1996, 1998 Peter Wemm <peter@netplex.com.au>
54ca332d5SPeter Wemm * All rights reserved.
64ca332d5SPeter Wemm *
74ca332d5SPeter Wemm * Redistribution and use in source and binary forms, with or without
84ca332d5SPeter Wemm * modification, are permitted provided that the following conditions
94ca332d5SPeter Wemm * are met:
104ca332d5SPeter Wemm * 1. Redistributions of source code must retain the above copyright
114ca332d5SPeter Wemm * notice, this list of conditions and the following disclaimer.
124ca332d5SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright
134ca332d5SPeter Wemm * notice, this list of conditions and the following disclaimer in the
144ca332d5SPeter Wemm * documentation and/or other materials provided with the distribution.
154ca332d5SPeter Wemm *
164ca332d5SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
174ca332d5SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
184ca332d5SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
194ca332d5SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
204ca332d5SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
214ca332d5SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
224ca332d5SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
234ca332d5SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
244ca332d5SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
254ca332d5SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
264ca332d5SPeter Wemm * SUCH DAMAGE.
274ca332d5SPeter Wemm *
284ca332d5SPeter Wemm */
294ca332d5SPeter Wemm
304ca332d5SPeter Wemm /*
314ca332d5SPeter Wemm * This program was originally written long ago, originally for a non
324ca332d5SPeter Wemm * BSD-like OS without mkstemp(). It's been modified over the years
334ca332d5SPeter Wemm * to use mkstemp() rather than the original O_CREAT|O_EXCL/fstat/lstat
344ca332d5SPeter Wemm * etc style hacks.
354ca332d5SPeter Wemm * A cleanup, misc options and mkdtemp() calls were added to try and work
364ca332d5SPeter Wemm * more like the OpenBSD version - which was first to publish the interface.
374ca332d5SPeter Wemm */
384ca332d5SPeter Wemm
39d4eaae7aSPhilippe Charnier #include <err.h>
40cfc57d7dSKyle Evans #include <getopt.h>
41d4eaae7aSPhilippe Charnier #include <paths.h>
42ac6f924eSKyle Evans #include <stdbool.h>
434ca332d5SPeter Wemm #include <stdio.h>
444ca332d5SPeter Wemm #include <stdlib.h>
454ca332d5SPeter Wemm #include <string.h>
46d4eaae7aSPhilippe Charnier #include <unistd.h>
47d4eaae7aSPhilippe Charnier
48*1a7ac2bdSAlfonso Gregory static void usage(void) __dead2;
494ca332d5SPeter Wemm
50cfc57d7dSKyle Evans static const struct option long_opts[] = {
51cfc57d7dSKyle Evans {"directory", no_argument, NULL, 'd'},
52ac6f924eSKyle Evans {"tmpdir", optional_argument, NULL, 'p'},
53cfc57d7dSKyle Evans {"quiet", no_argument, NULL, 'q'},
54cfc57d7dSKyle Evans {"dry-run", no_argument, NULL, 'u'},
55cfc57d7dSKyle Evans {NULL, no_argument, NULL, 0},
56cfc57d7dSKyle Evans };
57cfc57d7dSKyle Evans
584ca332d5SPeter Wemm int
main(int argc,char ** argv)594ca332d5SPeter Wemm main(int argc, char **argv)
604ca332d5SPeter Wemm {
614ca332d5SPeter Wemm int c, fd, ret;
62ac6f924eSKyle Evans const char *prefix, *tmpdir;
634ca332d5SPeter Wemm char *name;
644ca332d5SPeter Wemm int dflag, qflag, tflag, uflag;
65ac6f924eSKyle Evans bool prefer_tmpdir;
664ca332d5SPeter Wemm
674ca332d5SPeter Wemm ret = dflag = qflag = tflag = uflag = 0;
68ac6f924eSKyle Evans prefer_tmpdir = true;
69d4eaae7aSPhilippe Charnier prefix = "mktemp";
704ca332d5SPeter Wemm name = NULL;
71ac6f924eSKyle Evans tmpdir = NULL;
724ca332d5SPeter Wemm
73ac6f924eSKyle Evans while ((c = getopt_long(argc, argv, "dp:qt:u", long_opts, NULL)) != -1)
744ca332d5SPeter Wemm switch (c) {
754ca332d5SPeter Wemm case 'd':
764ca332d5SPeter Wemm dflag++;
774ca332d5SPeter Wemm break;
784ca332d5SPeter Wemm
79ac6f924eSKyle Evans case 'p':
80ac6f924eSKyle Evans tmpdir = optarg;
81ac6f924eSKyle Evans if (tmpdir == NULL || *tmpdir == '\0')
82ac6f924eSKyle Evans tmpdir = getenv("TMPDIR");
83d22f0363SKyle Evans
84d22f0363SKyle Evans /*
85d22f0363SKyle Evans * We've already done the necessary environment
86d22f0363SKyle Evans * fallback, skip the later one.
87d22f0363SKyle Evans */
88d22f0363SKyle Evans prefer_tmpdir = false;
89ac6f924eSKyle Evans break;
90ac6f924eSKyle Evans
914ca332d5SPeter Wemm case 'q':
924ca332d5SPeter Wemm qflag++;
934ca332d5SPeter Wemm break;
944ca332d5SPeter Wemm
954ca332d5SPeter Wemm case 't':
964ca332d5SPeter Wemm prefix = optarg;
974ca332d5SPeter Wemm tflag++;
984ca332d5SPeter Wemm break;
994ca332d5SPeter Wemm
1004ca332d5SPeter Wemm case 'u':
1014ca332d5SPeter Wemm uflag++;
1024ca332d5SPeter Wemm break;
1034ca332d5SPeter Wemm
1044ca332d5SPeter Wemm default:
105d4eaae7aSPhilippe Charnier usage();
1064ca332d5SPeter Wemm }
1074ca332d5SPeter Wemm
1084ca332d5SPeter Wemm argc -= optind;
1094ca332d5SPeter Wemm argv += optind;
1104ca332d5SPeter Wemm
1118e0079a0SEitan Adler if (!tflag && argc < 1) {
1128e0079a0SEitan Adler tflag = 1;
1138e0079a0SEitan Adler prefix = "tmp";
114ac6f924eSKyle Evans
115ac6f924eSKyle Evans /*
116ac6f924eSKyle Evans * For this implied -t mode, we actually want to swap the usual
117ac6f924eSKyle Evans * order of precedence: -p, then TMPDIR, then /tmp.
118ac6f924eSKyle Evans */
119ac6f924eSKyle Evans prefer_tmpdir = false;
1208e0079a0SEitan Adler }
1218e0079a0SEitan Adler
1224ca332d5SPeter Wemm if (tflag) {
123ac6f924eSKyle Evans const char *envtmp;
124a6346c02SKyle Evans size_t len;
125ac6f924eSKyle Evans
126ac6f924eSKyle Evans envtmp = NULL;
127ac6f924eSKyle Evans
128ac6f924eSKyle Evans /*
129ac6f924eSKyle Evans * $TMPDIR preferred over `-p` if specified, for compatibility.
130ac6f924eSKyle Evans */
131ac6f924eSKyle Evans if (prefer_tmpdir || tmpdir == NULL)
132ac6f924eSKyle Evans envtmp = getenv("TMPDIR");
133ac6f924eSKyle Evans if (envtmp != NULL)
134ac6f924eSKyle Evans tmpdir = envtmp;
1354ca332d5SPeter Wemm if (tmpdir == NULL)
136a6346c02SKyle Evans tmpdir = _PATH_TMP;
137a6346c02SKyle Evans len = strlen(tmpdir);
138a6346c02SKyle Evans if (len > 0 && tmpdir[len - 1] == '/')
139a6346c02SKyle Evans asprintf(&name, "%s%s.XXXXXXXXXX", tmpdir, prefix);
1404ca332d5SPeter Wemm else
14198839c40SWolfram Schneider asprintf(&name, "%s/%s.XXXXXXXXXX", tmpdir, prefix);
1424ca332d5SPeter Wemm /* if this fails, the program is in big trouble already */
1434ca332d5SPeter Wemm if (name == NULL) {
1444ca332d5SPeter Wemm if (qflag)
1454ca332d5SPeter Wemm return (1);
1464ca332d5SPeter Wemm else
147d4eaae7aSPhilippe Charnier errx(1, "cannot generate template");
1484ca332d5SPeter Wemm }
1494ca332d5SPeter Wemm }
1504ca332d5SPeter Wemm
1514ca332d5SPeter Wemm /* generate all requested files */
1524ca332d5SPeter Wemm while (name != NULL || argc > 0) {
1534ca332d5SPeter Wemm if (name == NULL) {
154ac6f924eSKyle Evans if (!tflag && tmpdir != NULL)
155ac6f924eSKyle Evans asprintf(&name, "%s/%s", tmpdir, argv[0]);
156ac6f924eSKyle Evans else
1574ca332d5SPeter Wemm name = strdup(argv[0]);
158ac6f924eSKyle Evans if (name == NULL)
159ac6f924eSKyle Evans err(1, "%s", argv[0]);
1604ca332d5SPeter Wemm argv++;
1614ca332d5SPeter Wemm argc--;
1624ca332d5SPeter Wemm }
1634ca332d5SPeter Wemm
1644ca332d5SPeter Wemm if (dflag) {
1654ca332d5SPeter Wemm if (mkdtemp(name) == NULL) {
1664ca332d5SPeter Wemm ret = 1;
1674ca332d5SPeter Wemm if (!qflag)
1684ca332d5SPeter Wemm warn("mkdtemp failed on %s", name);
1694ca332d5SPeter Wemm } else {
1704ca332d5SPeter Wemm printf("%s\n", name);
1714ca332d5SPeter Wemm if (uflag)
1724ca332d5SPeter Wemm rmdir(name);
1734ca332d5SPeter Wemm }
1744ca332d5SPeter Wemm } else {
1754ca332d5SPeter Wemm fd = mkstemp(name);
1764ca332d5SPeter Wemm if (fd < 0) {
1774ca332d5SPeter Wemm ret = 1;
1784ca332d5SPeter Wemm if (!qflag)
1794ca332d5SPeter Wemm warn("mkstemp failed on %s", name);
1804ca332d5SPeter Wemm } else {
1814ca332d5SPeter Wemm close(fd);
1824ca332d5SPeter Wemm if (uflag)
1834ca332d5SPeter Wemm unlink(name);
1844ca332d5SPeter Wemm printf("%s\n", name);
1854ca332d5SPeter Wemm }
1864ca332d5SPeter Wemm }
1874ca332d5SPeter Wemm if (name)
1884ca332d5SPeter Wemm free(name);
1894ca332d5SPeter Wemm name = NULL;
1904ca332d5SPeter Wemm }
1914ca332d5SPeter Wemm return (ret);
1924ca332d5SPeter Wemm }
193d4eaae7aSPhilippe Charnier
194d4eaae7aSPhilippe Charnier static void
usage(void)1957d0d4ebcSXin LI usage(void)
196d4eaae7aSPhilippe Charnier {
197d4eaae7aSPhilippe Charnier fprintf(stderr,
198ac6f924eSKyle Evans "usage: mktemp [-d] [-p tmpdir] [-q] [-t prefix] [-u] template "
199ac6f924eSKyle Evans "...\n");
200c0206f33SAlexander Langer fprintf(stderr,
201ac6f924eSKyle Evans " mktemp [-d] [-p tmpdir] [-q] [-u] -t prefix \n");
202d4eaae7aSPhilippe Charnier exit (1);
203d4eaae7aSPhilippe Charnier }
204