1 /* $OpenBSD: mktemp.c,v 1.20 2013/08/06 21:56:51 landry Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997, 2001-2003, 2013 5 * Todd C. Miller <Todd.Miller@courtesan.com> 6 * 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. 10 * 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. 18 */ 19 20 #include <err.h> 21 #include <paths.h> 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 __dead void usage(void); 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; 33 34 int 35 main(int argc, char *argv[]) 36 { 37 int ch, fd, uflag = 0, tflag = 0, makedir = 0; 38 char *cp, *template, *tempfile, *prefix = _PATH_TMP; 39 size_t len; 40 41 while ((ch = getopt(argc, argv, "dp:qtu")) != -1) 42 switch(ch) { 43 case 'd': 44 makedir = 1; 45 break; 46 case 'p': 47 prefix = optarg; 48 tflag = 1; 49 break; 50 case 'q': 51 quiet = 1; 52 break; 53 case 't': 54 tflag = 1; 55 break; 56 case 'u': 57 uflag = 1; 58 break; 59 default: 60 usage(); 61 } 62 63 /* If no template specified use a default one (implies -t mode) */ 64 switch (argc - optind) { 65 case 1: 66 template = argv[optind]; 67 break; 68 case 0: 69 template = "tmp.XXXXXXXXXX"; 70 tflag = 1; 71 break; 72 default: 73 usage(); 74 } 75 76 len = strlen(template); 77 if (len < 6 || strcmp(&template[len - 6], "XXXXXX")) { 78 fatalx("insufficient number of Xs in template `%s'", 79 template); 80 } 81 if (tflag) { 82 if (strchr(template, '/')) { 83 fatalx("template must not contain directory " 84 "separators in -t mode"); 85 } 86 87 cp = getenv("TMPDIR"); 88 if (cp != NULL && *cp != '\0') 89 prefix = cp; 90 len = strlen(prefix); 91 while (len != 0 && prefix[len - 1] == '/') 92 len--; 93 94 if (asprintf(&tempfile, "%.*s/%s", (int)len, prefix, template) < 0) 95 tempfile = NULL; 96 } else 97 tempfile = strdup(template); 98 99 if (tempfile == NULL) 100 fatalx("cannot allocate memory"); 101 102 if (makedir) { 103 if (mkdtemp(tempfile) == NULL) 104 fatal("cannot make temp dir %s", tempfile); 105 if (uflag) 106 (void)rmdir(tempfile); 107 } else { 108 if ((fd = mkstemp(tempfile)) < 0) 109 fatal("cannot make temp file %s", tempfile); 110 (void)close(fd); 111 if (uflag) 112 (void)unlink(tempfile); 113 } 114 115 (void)puts(tempfile); 116 free(tempfile); 117 118 exit(EXIT_SUCCESS); 119 } 120 121 __dead void 122 fatal(const char *fmt, ...) 123 { 124 if (!quiet) { 125 va_list ap; 126 127 va_start(ap, fmt); 128 vwarn(fmt, ap); 129 va_end(ap); 130 } 131 exit(EXIT_FAILURE); 132 } 133 134 __dead void 135 fatalx(const char *fmt, ...) 136 { 137 if (!quiet) { 138 va_list ap; 139 140 va_start(ap, fmt); 141 vwarnx(fmt, ap); 142 va_end(ap); 143 } 144 exit(EXIT_FAILURE); 145 } 146 147 __dead void 148 usage(void) 149 { 150 extern char *__progname; 151 152 (void)fprintf(stderr, 153 "usage: %s [-dqtu] [-p directory] [template]\n", __progname); 154 exit(EXIT_FAILURE); 155 } 156