1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)mktemp.c 5.7 (Berkeley) 06/27/88"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/types.h> 23 #include <sys/file.h> 24 #include <sys/stat.h> 25 #include <errno.h> 26 #include <stdio.h> 27 #include <ctype.h> 28 29 #define YES 1 30 #define NO 0 31 32 mkstemp(as) 33 char *as; 34 { 35 int fd; 36 37 return (_gettemp(as, &fd) ? fd : -1); 38 } 39 40 char * 41 mktemp(as) 42 char *as; 43 { 44 return(_gettemp(as, (int *)NULL) ? as : (char *)NULL); 45 } 46 47 static 48 _gettemp(as, doopen) 49 char *as; 50 register int *doopen; 51 { 52 extern int errno; 53 register char *start, *trv; 54 struct stat sbuf; 55 u_int pid; 56 57 pid = getpid(); 58 59 /* extra X's get set to 0's */ 60 for (trv = as; *trv; ++trv); 61 while (*--trv == 'X') { 62 *trv = (pid % 10) + '0'; 63 pid /= 10; 64 } 65 66 /* 67 * check for write permission on target directory; if you have 68 * six X's and you can't write the directory, this will run for 69 * a *very* long time. 70 */ 71 for (start = ++trv; trv > as && *trv != '/'; --trv); 72 if (*trv == '/') { 73 *trv = '\0'; 74 if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) 75 return(NO); 76 *trv = '/'; 77 } 78 else if (stat(".", &sbuf) == -1) 79 return(NO); 80 81 for (;;) { 82 if (doopen) { 83 if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 84 return(YES); 85 if (errno != EEXIST) 86 return(NO); 87 } 88 else if (stat(as, &sbuf)) 89 return(errno == ENOENT ? YES : NO); 90 91 /* tricky little algorithm for backward compatibility */ 92 for (trv = start;;) { 93 if (!*trv) 94 return(NO); 95 if (*trv == 'z') 96 *trv++ = 'a'; 97 else { 98 if (isdigit(*trv)) 99 *trv = 'a'; 100 else 101 ++*trv; 102 break; 103 } 104 } 105 } 106 /*NOTREACHED*/ 107 } 108