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