Annotation of src/usr.bin/mktemp/mktemp.c, Revision 1.26
1.26 ! millert 1: /* $OpenBSD: mktemp.c,v 1.25 2019/06/28 05:35:34 deraadt Exp $ */
1.1 millert 2:
3: /*
1.16 millert 4: * Copyright (c) 1996, 1997, 2001-2003, 2013
1.23 millert 5: * Todd C. Miller <millert@openbsd.org>
1.1 millert 6: *
1.11 millert 7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
1.1 millert 10: *
1.13 millert 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 millert 18: */
19:
1.19 millert 20: #include <err.h>
1.6 millert 21: #include <paths.h>
1.19 millert 22: #include <stdarg.h>
1.1 millert 23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <string.h>
26: #include <unistd.h>
27:
1.8 millert 28: __dead void usage(void);
1.19 millert 29: __dead void fatal(const char *, ...) __attribute__((__format__(printf, 1, 2)));
30: __dead void fatalx(const char *, ...) __attribute__((__format__(printf, 1, 2)));
31:
32: static int quiet;
1.1 millert 33:
34: int
1.12 deraadt 35: main(int argc, char *argv[])
1.1 millert 36: {
1.19 millert 37: int ch, fd, uflag = 0, tflag = 0, makedir = 0;
1.26 ! millert 38: char *base, *cp, *template, *tempfile, *prefix = _PATH_TMP;
! 39: size_t len, suffixlen = 0;
1.21 deraadt 40:
1.22 deraadt 41: if (pledge("stdio rpath wpath cpath", NULL) == -1)
42: err(1, "pledge");
1.1 millert 43:
1.6 millert 44: while ((ch = getopt(argc, argv, "dp:qtu")) != -1)
45: switch(ch) {
1.3 millert 46: case 'd':
47: makedir = 1;
1.1 millert 48: break;
1.6 millert 49: case 'p':
50: prefix = optarg;
51: tflag = 1;
52: break;
1.1 millert 53: case 'q':
1.7 millert 54: quiet = 1;
1.1 millert 55: break;
1.6 millert 56: case 't':
57: tflag = 1;
58: break;
1.3 millert 59: case 'u':
60: uflag = 1;
61: break;
1.1 millert 62: default:
63: usage();
64: }
65:
1.7 millert 66: /* If no template specified use a default one (implies -t mode) */
67: switch (argc - optind) {
68: case 1:
69: template = argv[optind];
70: break;
71: case 0:
72: template = "tmp.XXXXXXXXXX";
73: tflag = 1;
74: break;
75: default:
1.1 millert 76: usage();
1.7 millert 77: }
1.1 millert 78:
1.26 ! millert 79: base = strrchr(template, '/');
! 80: if (base != NULL)
! 81: base++;
! 82: else
! 83: base = template;
! 84: len = strlen(base);
! 85: if (len > 0 && base[len - 1] != 'X') {
! 86: /* Check for suffix, e.g. /tmp/XXXXXX.foo in last component. */
! 87: for (suffixlen = 0; suffixlen < len; suffixlen++) {
! 88: if (base[len - suffixlen - 1] == 'X')
! 89: break;
! 90: }
! 91: }
! 92: if (len - suffixlen < 6 ||
! 93: strncmp(&base[len - suffixlen - 6], "XXXXXX", 6)) {
1.20 landry 94: fatalx("insufficient number of Xs in template `%s'",
95: template);
96: }
1.6 millert 97: if (tflag) {
1.26 ! millert 98: if (base != template) {
1.19 millert 99: fatalx("template must not contain directory "
100: "separators in -t mode");
1.6 millert 101: }
102:
103: cp = getenv("TMPDIR");
104: if (cp != NULL && *cp != '\0')
105: prefix = cp;
1.16 millert 106: len = strlen(prefix);
107: while (len != 0 && prefix[len - 1] == '/')
108: len--;
1.6 millert 109:
1.24 deraadt 110: if (asprintf(&tempfile, "%.*s/%s", (int)len, prefix, template) == -1)
1.10 millert 111: tempfile = NULL;
1.20 landry 112: } else
1.9 millert 113: tempfile = strdup(template);
1.20 landry 114:
1.19 millert 115: if (tempfile == NULL)
116: fatalx("cannot allocate memory");
1.1 millert 117:
1.3 millert 118: if (makedir) {
1.26 ! millert 119: if (mkdtemps(tempfile, suffixlen) == NULL)
1.19 millert 120: fatal("cannot make temp dir %s", tempfile);
1.3 millert 121: if (uflag)
1.7 millert 122: (void)rmdir(tempfile);
1.3 millert 123: } else {
1.26 ! millert 124: if ((fd = mkstemps(tempfile, suffixlen)) == -1)
1.19 millert 125: fatal("cannot make temp file %s", tempfile);
1.7 millert 126: (void)close(fd);
1.3 millert 127: if (uflag)
1.7 millert 128: (void)unlink(tempfile);
1.1 millert 129: }
130:
1.7 millert 131: (void)puts(tempfile);
132: free(tempfile);
1.1 millert 133:
1.26 ! millert 134: return EXIT_SUCCESS;
1.19 millert 135: }
136:
137: __dead void
138: fatal(const char *fmt, ...)
139: {
140: if (!quiet) {
141: va_list ap;
142:
143: va_start(ap, fmt);
144: vwarn(fmt, ap);
145: va_end(ap);
146: }
147: exit(EXIT_FAILURE);
148: }
149:
150: __dead void
151: fatalx(const char *fmt, ...)
152: {
153: if (!quiet) {
154: va_list ap;
155:
156: va_start(ap, fmt);
157: vwarnx(fmt, ap);
158: va_end(ap);
159: }
160: exit(EXIT_FAILURE);
1.7 millert 161: }
162:
163: __dead void
1.12 deraadt 164: usage(void)
1.7 millert 165: {
166: extern char *__progname;
167:
168: (void)fprintf(stderr,
1.14 sobrado 169: "usage: %s [-dqtu] [-p directory] [template]\n", __progname);
1.19 millert 170: exit(EXIT_FAILURE);
1.1 millert 171: }