130888Sbostic /* 230888Sbostic * Copyright (c) 1987 Regents of the University of California. 332701Sbostic * All rights reserved. 432701Sbostic * 542625Sbostic * %sccs.include.redist.c% 630888Sbostic */ 730888Sbostic 826570Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*46611Sbostic static char sccsid[] = "@(#)mktemp.c 5.10 (Berkeley) 02/24/91"; 1034436Sbostic #endif /* LIBC_SCCS and not lint */ 1113260Sroot 1230888Sbostic #include <sys/types.h> 1332155Sbostic #include <sys/stat.h> 14*46611Sbostic #include <fcntl.h> 1532155Sbostic #include <errno.h> 1630888Sbostic #include <stdio.h> 1730888Sbostic 18*46611Sbostic static int _gettemp(); 19*46611Sbostic 2039307Sbostic mkstemp(path) 2139307Sbostic char *path; 2230888Sbostic { 2339307Sbostic int fd; 2430888Sbostic 2539307Sbostic return (_gettemp(path, &fd) ? fd : -1); 2630888Sbostic } 2730888Sbostic 2813260Sroot char * 2939307Sbostic mktemp(path) 3039307Sbostic char *path; 3113260Sroot { 3239307Sbostic return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); 3330888Sbostic } 3413260Sroot 3530888Sbostic static 3639307Sbostic _gettemp(path, doopen) 3739307Sbostic char *path; 3839307Sbostic register int *doopen; 3930888Sbostic { 4039307Sbostic extern int errno; 4139307Sbostic register char *start, *trv; 4239307Sbostic struct stat sbuf; 4339307Sbostic u_int pid; 4430888Sbostic 4513260Sroot pid = getpid(); 4639307Sbostic for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ 4730888Sbostic while (*--trv == 'X') { 4830888Sbostic *trv = (pid % 10) + '0'; 4913260Sroot pid /= 10; 5013260Sroot } 5130888Sbostic 5230888Sbostic /* 5339307Sbostic * check the target directory; if you have six X's and it 5439307Sbostic * doesn't exist this runs for a *very* long time. 5530888Sbostic */ 5639307Sbostic for (start = trv + 1;; --trv) { 5739307Sbostic if (trv <= path) 5839307Sbostic break; 5939307Sbostic if (*trv == '/') { 6039307Sbostic *trv = '\0'; 6139307Sbostic if (stat(path, &sbuf)) 6239307Sbostic return(0); 6339307Sbostic if (!S_ISDIR(sbuf.st_mode)) { 6439307Sbostic errno = ENOTDIR; 6539307Sbostic return(0); 6639307Sbostic } 6739307Sbostic *trv = '/'; 6839307Sbostic break; 6939307Sbostic } 7013260Sroot } 7130888Sbostic 7230888Sbostic for (;;) { 7332155Sbostic if (doopen) { 7439307Sbostic if ((*doopen = 7539307Sbostic open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 7639307Sbostic return(1); 7739307Sbostic if (errno != EEXIST) 7839307Sbostic return(0); 7932155Sbostic } 8039307Sbostic else if (stat(path, &sbuf)) 8139307Sbostic return(errno == ENOENT ? 1 : 0); 8232155Sbostic 8330888Sbostic /* tricky little algorithm for backward compatibility */ 8430888Sbostic for (trv = start;;) { 8530888Sbostic if (!*trv) 8639307Sbostic return(0); 8730888Sbostic if (*trv == 'z') 8830888Sbostic *trv++ = 'a'; 8930888Sbostic else { 9030888Sbostic if (isdigit(*trv)) 9130888Sbostic *trv = 'a'; 9230888Sbostic else 9330888Sbostic ++*trv; 9430888Sbostic break; 9530888Sbostic } 9630888Sbostic } 9730888Sbostic } 9830888Sbostic /*NOTREACHED*/ 9913260Sroot } 100