1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)mktemp.c 5.11 (Berkeley) 07/12/92"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 #include <fcntl.h> 15 #include <errno.h> 16 #include <stdio.h> 17 #include <ctype.h> 18 19 static int _gettemp(); 20 21 mkstemp(path) 22 char *path; 23 { 24 int fd; 25 26 return (_gettemp(path, &fd) ? fd : -1); 27 } 28 29 char * 30 mktemp(path) 31 char *path; 32 { 33 return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); 34 } 35 36 static 37 _gettemp(path, doopen) 38 char *path; 39 register int *doopen; 40 { 41 extern int errno; 42 register char *start, *trv; 43 struct stat sbuf; 44 u_int pid; 45 46 pid = getpid(); 47 for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ 48 while (*--trv == 'X') { 49 *trv = (pid % 10) + '0'; 50 pid /= 10; 51 } 52 53 /* 54 * check the target directory; if you have six X's and it 55 * doesn't exist this runs for a *very* long time. 56 */ 57 for (start = trv + 1;; --trv) { 58 if (trv <= path) 59 break; 60 if (*trv == '/') { 61 *trv = '\0'; 62 if (stat(path, &sbuf)) 63 return(0); 64 if (!S_ISDIR(sbuf.st_mode)) { 65 errno = ENOTDIR; 66 return(0); 67 } 68 *trv = '/'; 69 break; 70 } 71 } 72 73 for (;;) { 74 if (doopen) { 75 if ((*doopen = 76 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 77 return(1); 78 if (errno != EEXIST) 79 return(0); 80 } 81 else if (stat(path, &sbuf)) 82 return(errno == ENOENT ? 1 : 0); 83 84 /* tricky little algorithm for backward compatibility */ 85 for (trv = start;;) { 86 if (!*trv) 87 return(0); 88 if (*trv == 'z') 89 *trv++ = 'a'; 90 else { 91 if (isdigit(*trv)) 92 *trv = 'a'; 93 else 94 ++*trv; 95 break; 96 } 97 } 98 } 99 /*NOTREACHED*/ 100 } 101