1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #if defined(LIBC_SCCS) && !defined(lint) 8 static char sccsid[] = "@(#)mktemp.c 5.4 (Berkeley) 09/14/87"; 9 #endif LIBC_SCCS and not lint 10 11 #include <sys/types.h> 12 #include <sys/file.h> 13 #include <sys/stat.h> 14 #include <errno.h> 15 #include <stdio.h> 16 #include <ctype.h> 17 18 #define YES 1 19 #define NO 0 20 21 mkstemp(as) 22 char *as; 23 { 24 int fd; 25 26 return (_gettemp(as, &fd) ? fd : -1); 27 } 28 29 char * 30 mktemp(as) 31 char *as; 32 { 33 return(_gettemp(as, (int *)NULL) ? as : (char *)NULL); 34 } 35 36 static 37 _gettemp(as, doopen) 38 char *as; 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 48 /* extra X's get set to 0's */ 49 for (trv = as; *trv; ++trv); 50 while (*--trv == 'X') { 51 *trv = (pid % 10) + '0'; 52 pid /= 10; 53 } 54 55 /* 56 * check for write permission on target directory; if you have 57 * six X's and you can't write the directory, this will run for 58 * a *very* long time. 59 */ 60 for (start = ++trv; trv > as && *trv != '/'; --trv); 61 if (*trv == '/') { 62 *trv = '\0'; 63 if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) 64 return(NO); 65 *trv = '/'; 66 } 67 else if (stat(".", &sbuf) == -1) 68 return(NO); 69 70 for (;;) { 71 if (doopen) { 72 if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 73 return(YES); 74 if (errno != EEXIST) 75 return(NO); 76 } 77 else if (stat(as, &sbuf)) 78 return(errno == ENOENT ? YES : NO); 79 80 /* tricky little algorithm for backward compatibility */ 81 for (trv = start;;) { 82 if (!*trv) 83 return(NO); 84 if (*trv == 'z') 85 *trv++ = 'a'; 86 else { 87 if (isdigit(*trv)) 88 *trv = 'a'; 89 else 90 ++*trv; 91 break; 92 } 93 } 94 } 95 /*NOTREACHED*/ 96 } 97