xref: /freebsd/usr.bin/mktemp/mktemp.c (revision 4ca332d5bff412fef921f5440d01b94c5eb301d6)
14ca332d5SPeter Wemm /*-
24ca332d5SPeter Wemm  * Copyright (c) 1994, 1995, 1996, 1998 Peter Wemm <peter@netplex.com.au>
34ca332d5SPeter Wemm  * All rights reserved.
44ca332d5SPeter Wemm  *
54ca332d5SPeter Wemm  * Redistribution and use in source and binary forms, with or without
64ca332d5SPeter Wemm  * modification, are permitted provided that the following conditions
74ca332d5SPeter Wemm  * are met:
84ca332d5SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
94ca332d5SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
104ca332d5SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
114ca332d5SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
124ca332d5SPeter Wemm  *    documentation and/or other materials provided with the distribution.
134ca332d5SPeter Wemm  *
144ca332d5SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154ca332d5SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164ca332d5SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174ca332d5SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184ca332d5SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194ca332d5SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204ca332d5SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214ca332d5SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224ca332d5SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234ca332d5SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244ca332d5SPeter Wemm  * SUCH DAMAGE.
254ca332d5SPeter Wemm  *
264ca332d5SPeter Wemm  * $FreeBSD$
274ca332d5SPeter Wemm  */
284ca332d5SPeter Wemm 
294ca332d5SPeter Wemm /*
304ca332d5SPeter Wemm  * This program was originally written long ago, originally for a non
314ca332d5SPeter Wemm  * BSD-like OS without mkstemp().  It's been modified over the years
324ca332d5SPeter Wemm  * to use mkstemp() rather than the original O_CREAT|O_EXCL/fstat/lstat
334ca332d5SPeter Wemm  * etc style hacks.
344ca332d5SPeter Wemm  * A cleanup, misc options and mkdtemp() calls were added to try and work
354ca332d5SPeter Wemm  * more like the OpenBSD version - which was first to publish the interface.
364ca332d5SPeter Wemm  */
374ca332d5SPeter Wemm 
384ca332d5SPeter Wemm #include <sys/types.h>
394ca332d5SPeter Wemm #include <stdio.h>
404ca332d5SPeter Wemm #include <stdlib.h>
414ca332d5SPeter Wemm #include <unistd.h>
424ca332d5SPeter Wemm #include <paths.h>
434ca332d5SPeter Wemm #include <err.h>
444ca332d5SPeter Wemm #include <string.h>
454ca332d5SPeter Wemm 
464ca332d5SPeter Wemm int
474ca332d5SPeter Wemm main(int argc, char **argv)
484ca332d5SPeter Wemm {
494ca332d5SPeter Wemm 	int c, fd, ret;
504ca332d5SPeter Wemm 	char *usage = "[-d] [-q] [-t prefix] [-u] [template ...]";
514ca332d5SPeter Wemm 	char *tmpdir, *prefix;
524ca332d5SPeter Wemm 	char *prog;
534ca332d5SPeter Wemm 	char *name;
544ca332d5SPeter Wemm 	int dflag, qflag, tflag, uflag;
554ca332d5SPeter Wemm 
564ca332d5SPeter Wemm 	ret = dflag = qflag = tflag = uflag = 0;
574ca332d5SPeter Wemm 	name = NULL;
584ca332d5SPeter Wemm 	prog = argv[0];		/* XXX basename(argv[0]) */
594ca332d5SPeter Wemm 
604ca332d5SPeter Wemm 	while ((c = getopt(argc, argv, "dqt:u")) != -1)
614ca332d5SPeter Wemm 		switch (c) {
624ca332d5SPeter Wemm 		case 'd':
634ca332d5SPeter Wemm 			dflag++;
644ca332d5SPeter Wemm 			break;
654ca332d5SPeter Wemm 
664ca332d5SPeter Wemm 		case 'q':
674ca332d5SPeter Wemm 			qflag++;
684ca332d5SPeter Wemm 			break;
694ca332d5SPeter Wemm 
704ca332d5SPeter Wemm 		case 't':
714ca332d5SPeter Wemm 			prefix = optarg;
724ca332d5SPeter Wemm 			tflag++;
734ca332d5SPeter Wemm 			break;
744ca332d5SPeter Wemm 
754ca332d5SPeter Wemm 		case 'u':
764ca332d5SPeter Wemm 			uflag++;
774ca332d5SPeter Wemm 			break;
784ca332d5SPeter Wemm 
794ca332d5SPeter Wemm 		default:
804ca332d5SPeter Wemm 			fprintf(stderr, "Usage: %s %s\n", prog, usage);
814ca332d5SPeter Wemm 			return (1);
824ca332d5SPeter Wemm 		}
834ca332d5SPeter Wemm 
844ca332d5SPeter Wemm 	argc -= optind;
854ca332d5SPeter Wemm 	argv += optind;
864ca332d5SPeter Wemm 
874ca332d5SPeter Wemm 	if (tflag) {
884ca332d5SPeter Wemm 		tmpdir = getenv("TMPDIR");
894ca332d5SPeter Wemm 		if (prefix == NULL)
904ca332d5SPeter Wemm 			prefix = "mktemp";	/* shouldn't happen, but.. */
914ca332d5SPeter Wemm 		if (tmpdir == NULL)
924ca332d5SPeter Wemm 			asprintf(&name, "%s%s.XXXXXXXX", _PATH_TMP, prefix);
934ca332d5SPeter Wemm 		else
944ca332d5SPeter Wemm 			asprintf(&name, "%s/%s.XXXXXXXX", tmpdir, prefix);
954ca332d5SPeter Wemm 		/* if this fails, the program is in big trouble already */
964ca332d5SPeter Wemm 		if (name == NULL) {
974ca332d5SPeter Wemm 			if (qflag)
984ca332d5SPeter Wemm 				return (1);
994ca332d5SPeter Wemm 			else
1004ca332d5SPeter Wemm 				err(1, "cannot generate template");
1014ca332d5SPeter Wemm 		}
1024ca332d5SPeter Wemm 	} else if (argc < 1) {
1034ca332d5SPeter Wemm 		fprintf(stderr, "Usage: %s %s\n", prog, usage);
1044ca332d5SPeter Wemm 		return (1);
1054ca332d5SPeter Wemm 	}
1064ca332d5SPeter Wemm 
1074ca332d5SPeter Wemm 	/* generate all requested files */
1084ca332d5SPeter Wemm 	while (name != NULL || argc > 0) {
1094ca332d5SPeter Wemm 		if (name == NULL) {
1104ca332d5SPeter Wemm 			name = strdup(argv[0]);
1114ca332d5SPeter Wemm 			argv++;
1124ca332d5SPeter Wemm 			argc--;
1134ca332d5SPeter Wemm 		}
1144ca332d5SPeter Wemm 
1154ca332d5SPeter Wemm 		if (dflag) {
1164ca332d5SPeter Wemm 			if (mkdtemp(name) == NULL) {
1174ca332d5SPeter Wemm 				ret = 1;
1184ca332d5SPeter Wemm 				if (!qflag)
1194ca332d5SPeter Wemm 					warn("mkdtemp failed on %s", name);
1204ca332d5SPeter Wemm 			} else {
1214ca332d5SPeter Wemm 				printf("%s\n", name);
1224ca332d5SPeter Wemm 				if (uflag)
1234ca332d5SPeter Wemm 					rmdir(name);
1244ca332d5SPeter Wemm 			}
1254ca332d5SPeter Wemm 		} else {
1264ca332d5SPeter Wemm 			fd = mkstemp(name);
1274ca332d5SPeter Wemm 			if (fd < 0) {
1284ca332d5SPeter Wemm 				ret = 1;
1294ca332d5SPeter Wemm 				if (!qflag)
1304ca332d5SPeter Wemm 					warn("mkstemp failed on %s", name);
1314ca332d5SPeter Wemm 			} else {
1324ca332d5SPeter Wemm 				close(fd);
1334ca332d5SPeter Wemm 				if (uflag)
1344ca332d5SPeter Wemm 					unlink(name);
1354ca332d5SPeter Wemm 				printf("%s\n", name);
1364ca332d5SPeter Wemm 			}
1374ca332d5SPeter Wemm 		}
1384ca332d5SPeter Wemm 		if (name)
1394ca332d5SPeter Wemm 			free(name);
1404ca332d5SPeter Wemm 		name = NULL;
1414ca332d5SPeter Wemm 	}
1424ca332d5SPeter Wemm 	return (ret);
1434ca332d5SPeter Wemm }
144