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 48d4eaae7aSPhilippe Charnier #ifndef lint 49d4eaae7aSPhilippe Charnier static const char rcsid[] = 50d4eaae7aSPhilippe Charnier "$FreeBSD$"; 51d4eaae7aSPhilippe Charnier #endif /* not lint */ 52d4eaae7aSPhilippe Charnier 53*1a7ac2bdSAlfonso Gregory static void usage(void) __dead2; 544ca332d5SPeter Wemm 55cfc57d7dSKyle Evans static const struct option long_opts[] = { 56cfc57d7dSKyle Evans {"directory", no_argument, NULL, 'd'}, 57ac6f924eSKyle Evans {"tmpdir", optional_argument, NULL, 'p'}, 58cfc57d7dSKyle Evans {"quiet", no_argument, NULL, 'q'}, 59cfc57d7dSKyle Evans {"dry-run", no_argument, NULL, 'u'}, 60cfc57d7dSKyle Evans {NULL, no_argument, NULL, 0}, 61cfc57d7dSKyle Evans }; 62cfc57d7dSKyle Evans 634ca332d5SPeter Wemm int 644ca332d5SPeter Wemm main(int argc, char **argv) 654ca332d5SPeter Wemm { 664ca332d5SPeter Wemm int c, fd, ret; 67ac6f924eSKyle Evans const char *prefix, *tmpdir; 684ca332d5SPeter Wemm char *name; 694ca332d5SPeter Wemm int dflag, qflag, tflag, uflag; 70ac6f924eSKyle Evans bool prefer_tmpdir; 714ca332d5SPeter Wemm 724ca332d5SPeter Wemm ret = dflag = qflag = tflag = uflag = 0; 73ac6f924eSKyle Evans prefer_tmpdir = true; 74d4eaae7aSPhilippe Charnier prefix = "mktemp"; 754ca332d5SPeter Wemm name = NULL; 76ac6f924eSKyle Evans tmpdir = NULL; 774ca332d5SPeter Wemm 78ac6f924eSKyle Evans while ((c = getopt_long(argc, argv, "dp:qt:u", long_opts, NULL)) != -1) 794ca332d5SPeter Wemm switch (c) { 804ca332d5SPeter Wemm case 'd': 814ca332d5SPeter Wemm dflag++; 824ca332d5SPeter Wemm break; 834ca332d5SPeter Wemm 84ac6f924eSKyle Evans case 'p': 85ac6f924eSKyle Evans tmpdir = optarg; 86ac6f924eSKyle Evans if (tmpdir == NULL || *tmpdir == '\0') 87ac6f924eSKyle Evans tmpdir = getenv("TMPDIR"); 88d22f0363SKyle Evans 89d22f0363SKyle Evans /* 90d22f0363SKyle Evans * We've already done the necessary environment 91d22f0363SKyle Evans * fallback, skip the later one. 92d22f0363SKyle Evans */ 93d22f0363SKyle Evans prefer_tmpdir = false; 94ac6f924eSKyle Evans break; 95ac6f924eSKyle Evans 964ca332d5SPeter Wemm case 'q': 974ca332d5SPeter Wemm qflag++; 984ca332d5SPeter Wemm break; 994ca332d5SPeter Wemm 1004ca332d5SPeter Wemm case 't': 1014ca332d5SPeter Wemm prefix = optarg; 1024ca332d5SPeter Wemm tflag++; 1034ca332d5SPeter Wemm break; 1044ca332d5SPeter Wemm 1054ca332d5SPeter Wemm case 'u': 1064ca332d5SPeter Wemm uflag++; 1074ca332d5SPeter Wemm break; 1084ca332d5SPeter Wemm 1094ca332d5SPeter Wemm default: 110d4eaae7aSPhilippe Charnier usage(); 1114ca332d5SPeter Wemm } 1124ca332d5SPeter Wemm 1134ca332d5SPeter Wemm argc -= optind; 1144ca332d5SPeter Wemm argv += optind; 1154ca332d5SPeter Wemm 1168e0079a0SEitan Adler if (!tflag && argc < 1) { 1178e0079a0SEitan Adler tflag = 1; 1188e0079a0SEitan Adler prefix = "tmp"; 119ac6f924eSKyle Evans 120ac6f924eSKyle Evans /* 121ac6f924eSKyle Evans * For this implied -t mode, we actually want to swap the usual 122ac6f924eSKyle Evans * order of precedence: -p, then TMPDIR, then /tmp. 123ac6f924eSKyle Evans */ 124ac6f924eSKyle Evans prefer_tmpdir = false; 1258e0079a0SEitan Adler } 1268e0079a0SEitan Adler 1274ca332d5SPeter Wemm if (tflag) { 128ac6f924eSKyle Evans const char *envtmp; 129a6346c02SKyle Evans size_t len; 130ac6f924eSKyle Evans 131ac6f924eSKyle Evans envtmp = NULL; 132ac6f924eSKyle Evans 133ac6f924eSKyle Evans /* 134ac6f924eSKyle Evans * $TMPDIR preferred over `-p` if specified, for compatibility. 135ac6f924eSKyle Evans */ 136ac6f924eSKyle Evans if (prefer_tmpdir || tmpdir == NULL) 137ac6f924eSKyle Evans envtmp = getenv("TMPDIR"); 138ac6f924eSKyle Evans if (envtmp != NULL) 139ac6f924eSKyle Evans tmpdir = envtmp; 1404ca332d5SPeter Wemm if (tmpdir == NULL) 141a6346c02SKyle Evans tmpdir = _PATH_TMP; 142a6346c02SKyle Evans len = strlen(tmpdir); 143a6346c02SKyle Evans if (len > 0 && tmpdir[len - 1] == '/') 144a6346c02SKyle Evans asprintf(&name, "%s%s.XXXXXXXXXX", tmpdir, prefix); 1454ca332d5SPeter Wemm else 14698839c40SWolfram Schneider asprintf(&name, "%s/%s.XXXXXXXXXX", tmpdir, prefix); 1474ca332d5SPeter Wemm /* if this fails, the program is in big trouble already */ 1484ca332d5SPeter Wemm if (name == NULL) { 1494ca332d5SPeter Wemm if (qflag) 1504ca332d5SPeter Wemm return (1); 1514ca332d5SPeter Wemm else 152d4eaae7aSPhilippe Charnier errx(1, "cannot generate template"); 1534ca332d5SPeter Wemm } 1544ca332d5SPeter Wemm } 1554ca332d5SPeter Wemm 1564ca332d5SPeter Wemm /* generate all requested files */ 1574ca332d5SPeter Wemm while (name != NULL || argc > 0) { 1584ca332d5SPeter Wemm if (name == NULL) { 159ac6f924eSKyle Evans if (!tflag && tmpdir != NULL) 160ac6f924eSKyle Evans asprintf(&name, "%s/%s", tmpdir, argv[0]); 161ac6f924eSKyle Evans else 1624ca332d5SPeter Wemm name = strdup(argv[0]); 163ac6f924eSKyle Evans if (name == NULL) 164ac6f924eSKyle Evans err(1, "%s", argv[0]); 1654ca332d5SPeter Wemm argv++; 1664ca332d5SPeter Wemm argc--; 1674ca332d5SPeter Wemm } 1684ca332d5SPeter Wemm 1694ca332d5SPeter Wemm if (dflag) { 1704ca332d5SPeter Wemm if (mkdtemp(name) == NULL) { 1714ca332d5SPeter Wemm ret = 1; 1724ca332d5SPeter Wemm if (!qflag) 1734ca332d5SPeter Wemm warn("mkdtemp failed on %s", name); 1744ca332d5SPeter Wemm } else { 1754ca332d5SPeter Wemm printf("%s\n", name); 1764ca332d5SPeter Wemm if (uflag) 1774ca332d5SPeter Wemm rmdir(name); 1784ca332d5SPeter Wemm } 1794ca332d5SPeter Wemm } else { 1804ca332d5SPeter Wemm fd = mkstemp(name); 1814ca332d5SPeter Wemm if (fd < 0) { 1824ca332d5SPeter Wemm ret = 1; 1834ca332d5SPeter Wemm if (!qflag) 1844ca332d5SPeter Wemm warn("mkstemp failed on %s", name); 1854ca332d5SPeter Wemm } else { 1864ca332d5SPeter Wemm close(fd); 1874ca332d5SPeter Wemm if (uflag) 1884ca332d5SPeter Wemm unlink(name); 1894ca332d5SPeter Wemm printf("%s\n", name); 1904ca332d5SPeter Wemm } 1914ca332d5SPeter Wemm } 1924ca332d5SPeter Wemm if (name) 1934ca332d5SPeter Wemm free(name); 1944ca332d5SPeter Wemm name = NULL; 1954ca332d5SPeter Wemm } 1964ca332d5SPeter Wemm return (ret); 1974ca332d5SPeter Wemm } 198d4eaae7aSPhilippe Charnier 199d4eaae7aSPhilippe Charnier static void 2007d0d4ebcSXin LI usage(void) 201d4eaae7aSPhilippe Charnier { 202d4eaae7aSPhilippe Charnier fprintf(stderr, 203ac6f924eSKyle Evans "usage: mktemp [-d] [-p tmpdir] [-q] [-t prefix] [-u] template " 204ac6f924eSKyle Evans "...\n"); 205c0206f33SAlexander Langer fprintf(stderr, 206ac6f924eSKyle Evans " mktemp [-d] [-p tmpdir] [-q] [-u] -t prefix \n"); 207d4eaae7aSPhilippe Charnier exit (1); 208d4eaae7aSPhilippe Charnier } 209