1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Create unique plain files or directories.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <string.h>
34#include <locale.h>
35
36static void
37usage(void)
38{
39	(void) fprintf(stderr,
40	    gettext("Usage: mktemp [-dqtu] [-p prefix_dir] [template]\n"));
41	exit(1);
42	/* NOTREACHED */
43}
44
45int
46main(int argc, char **argv)
47{
48	int opt;
49	char *prefix = NULL;
50	boolean_t dounlink = B_FALSE;
51	boolean_t domkdir = B_FALSE;
52	boolean_t quiet = B_FALSE;
53	boolean_t usetmpdir = B_FALSE;
54	char template[] = "tmp.XXXXXX";
55	char *tmpl;
56
57	(void) setlocale(LC_ALL, "");
58
59#ifndef TEXT_DOMAIN
60#define	TEXT_DOMAIN "SYS_TEST"
61#endif
62	(void) textdomain(TEXT_DOMAIN);
63
64	opterr = 0;
65
66	while ((opt = getopt(argc, argv, "dqtup:")) != EOF) {
67		switch (opt) {
68		case 'd':
69			domkdir = B_TRUE;
70			break;
71		case 'q':
72			quiet = B_TRUE;
73			break;
74		case 'p':
75			prefix = optarg;
76			/* FALLTHROUGH - -p implies -t */
77		case 't':
78			usetmpdir = B_TRUE;
79			break;
80		case 'u':
81			dounlink = B_TRUE;
82			break;
83		default:
84			usage();
85		}
86	}
87	argc -= optind;
88	argv += optind;
89	switch (argc) {
90	case 0:
91		tmpl = template;
92		usetmpdir = B_TRUE;
93		break;
94	case 1:
95		tmpl = argv[0];
96		break;
97	default:
98		usage();
99	}
100
101	if (usetmpdir) {
102		char *tmp = getenv("TMPDIR");
103		size_t len;
104
105		if (strchr(tmpl, '/') != NULL) {
106			(void) fprintf(stderr,
107			    gettext("mktemp: template argument specified "
108			    "with -t/-p option must not contain '/'"
109			    "\n"));
110			return (1);
111		}
112		/* TMPDIR overrides -p so that scripts will honor $TMPDIR */
113		if (tmp != NULL)
114			prefix = tmp;
115		else if (prefix == NULL)
116			prefix = "/tmp";
117
118		len = snprintf(NULL, 0, "%s/%s", prefix, tmpl) + 1;
119		tmp = malloc(len);
120		if (tmp == NULL) {
121			perror("malloc");
122			return (1);
123		}
124		(void) snprintf(tmp, len, "%s/%s", prefix, tmpl);
125		tmpl = tmp;
126	}
127
128	if (domkdir) {
129		if (mkdtemp(tmpl) == NULL) {
130			if (!quiet) {
131				(void) fprintf(stderr,
132				    gettext("mktemp: failed to create "
133				    "directory: %s\n"), tmpl);
134			}
135			return (1);
136		}
137		if (dounlink)
138			(void) rmdir(tmpl);
139	} else {
140		if (mkstemp(tmpl) < 0) {
141			if (!quiet) {
142				(void) fprintf(stderr,
143				    gettext("mktemp: failed to create file: "
144				    "%s\n"), tmpl);
145			}
146			return (1);
147		}
148		if (dounlink)
149			(void) unlink(tmpl);
150	}
151	(void) puts(tmpl);
152	return (0);
153}
154