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 this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific written prior permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #if defined(LIBC_SCCS) && !defined(lint) 14 static char sccsid[] = "@(#)mktemp.c 5.5 (Berkeley) 11/30/87"; 15 #endif LIBC_SCCS and not lint 16 17 #include <sys/types.h> 18 #include <sys/file.h> 19 #include <sys/stat.h> 20 #include <errno.h> 21 #include <stdio.h> 22 #include <ctype.h> 23 24 #define YES 1 25 #define NO 0 26 27 mkstemp(as) 28 char *as; 29 { 30 int fd; 31 32 return (_gettemp(as, &fd) ? fd : -1); 33 } 34 35 char * 36 mktemp(as) 37 char *as; 38 { 39 return(_gettemp(as, (int *)NULL) ? as : (char *)NULL); 40 } 41 42 static 43 _gettemp(as, doopen) 44 char *as; 45 register int *doopen; 46 { 47 extern int errno; 48 register char *start, *trv; 49 struct stat sbuf; 50 u_int pid; 51 52 pid = getpid(); 53 54 /* extra X's get set to 0's */ 55 for (trv = as; *trv; ++trv); 56 while (*--trv == 'X') { 57 *trv = (pid % 10) + '0'; 58 pid /= 10; 59 } 60 61 /* 62 * check for write permission on target directory; if you have 63 * six X's and you can't write the directory, this will run for 64 * a *very* long time. 65 */ 66 for (start = ++trv; trv > as && *trv != '/'; --trv); 67 if (*trv == '/') { 68 *trv = '\0'; 69 if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) 70 return(NO); 71 *trv = '/'; 72 } 73 else if (stat(".", &sbuf) == -1) 74 return(NO); 75 76 for (;;) { 77 if (doopen) { 78 if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 79 return(YES); 80 if (errno != EEXIST) 81 return(NO); 82 } 83 else if (stat(as, &sbuf)) 84 return(errno == ENOENT ? YES : NO); 85 86 /* tricky little algorithm for backward compatibility */ 87 for (trv = start;;) { 88 if (!*trv) 89 return(NO); 90 if (*trv == 'z') 91 *trv++ = 'a'; 92 else { 93 if (isdigit(*trv)) 94 *trv = 'a'; 95 else 96 ++*trv; 97 break; 98 } 99 } 100 } 101 /*NOTREACHED*/ 102 } 103