130888Sbostic /* 230888Sbostic * Copyright (c) 1987 Regents of the University of California. 332701Sbostic * All rights reserved. 432701Sbostic * 532701Sbostic * Redistribution and use in source and binary forms are permitted 634821Sbostic * provided that the above copyright notice and this paragraph are 734821Sbostic * duplicated in all such forms and that any documentation, 834821Sbostic * advertising materials, and other materials related to such 934821Sbostic * distribution and use acknowledge that the software was developed 1034821Sbostic * by the University of California, Berkeley. The name of the 1134821Sbostic * University may not be used to endorse or promote products derived 1234821Sbostic * from this software without specific prior written permission. 1334821Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434821Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534821Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1630888Sbostic */ 1730888Sbostic 1826570Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*39307Sbostic static char sccsid[] = "@(#)mktemp.c 5.8 (Berkeley) 10/16/89"; 2034436Sbostic #endif /* LIBC_SCCS and not lint */ 2113260Sroot 2230888Sbostic #include <sys/types.h> 2330888Sbostic #include <sys/file.h> 2432155Sbostic #include <sys/stat.h> 2532155Sbostic #include <errno.h> 2630888Sbostic #include <stdio.h> 2730888Sbostic #include <ctype.h> 2830888Sbostic 29*39307Sbostic mkstemp(path) 30*39307Sbostic char *path; 3130888Sbostic { 32*39307Sbostic int fd; 3330888Sbostic 34*39307Sbostic return (_gettemp(path, &fd) ? fd : -1); 3530888Sbostic } 3630888Sbostic 3713260Sroot char * 38*39307Sbostic mktemp(path) 39*39307Sbostic char *path; 4013260Sroot { 41*39307Sbostic return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); 4230888Sbostic } 4313260Sroot 4430888Sbostic static 45*39307Sbostic _gettemp(path, doopen) 46*39307Sbostic char *path; 47*39307Sbostic register int *doopen; 4830888Sbostic { 49*39307Sbostic extern int errno; 50*39307Sbostic register char *start, *trv; 51*39307Sbostic struct stat sbuf; 52*39307Sbostic u_int pid; 5330888Sbostic 5413260Sroot pid = getpid(); 55*39307Sbostic for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ 5630888Sbostic while (*--trv == 'X') { 5730888Sbostic *trv = (pid % 10) + '0'; 5813260Sroot pid /= 10; 5913260Sroot } 6030888Sbostic 6130888Sbostic /* 62*39307Sbostic * check the target directory; if you have six X's and it 63*39307Sbostic * doesn't exist this runs for a *very* long time. 6430888Sbostic */ 65*39307Sbostic for (start = trv + 1;; --trv) { 66*39307Sbostic if (trv <= path) 67*39307Sbostic break; 68*39307Sbostic if (*trv == '/') { 69*39307Sbostic *trv = '\0'; 70*39307Sbostic if (stat(path, &sbuf)) 71*39307Sbostic return(0); 72*39307Sbostic if (!S_ISDIR(sbuf.st_mode)) { 73*39307Sbostic errno = ENOTDIR; 74*39307Sbostic return(0); 75*39307Sbostic } 76*39307Sbostic *trv = '/'; 77*39307Sbostic break; 78*39307Sbostic } 7913260Sroot } 8030888Sbostic 8130888Sbostic for (;;) { 8232155Sbostic if (doopen) { 83*39307Sbostic if ((*doopen = 84*39307Sbostic open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 85*39307Sbostic return(1); 86*39307Sbostic if (errno != EEXIST) 87*39307Sbostic return(0); 8832155Sbostic } 89*39307Sbostic else if (stat(path, &sbuf)) 90*39307Sbostic return(errno == ENOENT ? 1 : 0); 9132155Sbostic 9230888Sbostic /* tricky little algorithm for backward compatibility */ 9330888Sbostic for (trv = start;;) { 9430888Sbostic if (!*trv) 95*39307Sbostic return(0); 9630888Sbostic if (*trv == 'z') 9730888Sbostic *trv++ = 'a'; 9830888Sbostic else { 9930888Sbostic if (isdigit(*trv)) 10030888Sbostic *trv = 'a'; 10130888Sbostic else 10230888Sbostic ++*trv; 10330888Sbostic break; 10430888Sbostic } 10530888Sbostic } 10630888Sbostic } 10730888Sbostic /*NOTREACHED*/ 10813260Sroot } 109