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*54995Sbostic static char sccsid[] = "@(#)mktemp.c 5.11 (Berkeley) 07/12/92"; 1034436Sbostic #endif /* LIBC_SCCS and not lint */ 1113260Sroot 1230888Sbostic #include <sys/types.h> 1332155Sbostic #include <sys/stat.h> 1446611Sbostic #include <fcntl.h> 1532155Sbostic #include <errno.h> 1630888Sbostic #include <stdio.h> 17*54995Sbostic #include <ctype.h> 1830888Sbostic 1946611Sbostic static int _gettemp(); 2046611Sbostic 2139307Sbostic mkstemp(path) 2239307Sbostic char *path; 2330888Sbostic { 2439307Sbostic int fd; 2530888Sbostic 2639307Sbostic return (_gettemp(path, &fd) ? fd : -1); 2730888Sbostic } 2830888Sbostic 2913260Sroot char * 3039307Sbostic mktemp(path) 3139307Sbostic char *path; 3213260Sroot { 3339307Sbostic return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); 3430888Sbostic } 3513260Sroot 3630888Sbostic static 3739307Sbostic _gettemp(path, doopen) 3839307Sbostic char *path; 3939307Sbostic register int *doopen; 4030888Sbostic { 4139307Sbostic extern int errno; 4239307Sbostic register char *start, *trv; 4339307Sbostic struct stat sbuf; 4439307Sbostic u_int pid; 4530888Sbostic 4613260Sroot pid = getpid(); 4739307Sbostic for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ 4830888Sbostic while (*--trv == 'X') { 4930888Sbostic *trv = (pid % 10) + '0'; 5013260Sroot pid /= 10; 5113260Sroot } 5230888Sbostic 5330888Sbostic /* 5439307Sbostic * check the target directory; if you have six X's and it 5539307Sbostic * doesn't exist this runs for a *very* long time. 5630888Sbostic */ 5739307Sbostic for (start = trv + 1;; --trv) { 5839307Sbostic if (trv <= path) 5939307Sbostic break; 6039307Sbostic if (*trv == '/') { 6139307Sbostic *trv = '\0'; 6239307Sbostic if (stat(path, &sbuf)) 6339307Sbostic return(0); 6439307Sbostic if (!S_ISDIR(sbuf.st_mode)) { 6539307Sbostic errno = ENOTDIR; 6639307Sbostic return(0); 6739307Sbostic } 6839307Sbostic *trv = '/'; 6939307Sbostic break; 7039307Sbostic } 7113260Sroot } 7230888Sbostic 7330888Sbostic for (;;) { 7432155Sbostic if (doopen) { 7539307Sbostic if ((*doopen = 7639307Sbostic open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 7739307Sbostic return(1); 7839307Sbostic if (errno != EEXIST) 7939307Sbostic return(0); 8032155Sbostic } 8139307Sbostic else if (stat(path, &sbuf)) 8239307Sbostic return(errno == ENOENT ? 1 : 0); 8332155Sbostic 8430888Sbostic /* tricky little algorithm for backward compatibility */ 8530888Sbostic for (trv = start;;) { 8630888Sbostic if (!*trv) 8739307Sbostic return(0); 8830888Sbostic if (*trv == 'z') 8930888Sbostic *trv++ = 'a'; 9030888Sbostic else { 9130888Sbostic if (isdigit(*trv)) 9230888Sbostic *trv = 'a'; 9330888Sbostic else 9430888Sbostic ++*trv; 9530888Sbostic break; 9630888Sbostic } 9730888Sbostic } 9830888Sbostic } 9930888Sbostic /*NOTREACHED*/ 10013260Sroot } 101