xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 42625)
130888Sbostic /*
230888Sbostic  * Copyright (c) 1987 Regents of the University of California.
332701Sbostic  * All rights reserved.
432701Sbostic  *
5*42625Sbostic  * %sccs.include.redist.c%
630888Sbostic  */
730888Sbostic 
826570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*42625Sbostic static char sccsid[] = "@(#)mktemp.c	5.9 (Berkeley) 06/01/90";
1034436Sbostic #endif /* LIBC_SCCS and not lint */
1113260Sroot 
1230888Sbostic #include <sys/types.h>
1330888Sbostic #include <sys/file.h>
1432155Sbostic #include <sys/stat.h>
1532155Sbostic #include <errno.h>
1630888Sbostic #include <stdio.h>
1730888Sbostic #include <ctype.h>
1830888Sbostic 
1939307Sbostic mkstemp(path)
2039307Sbostic 	char *path;
2130888Sbostic {
2239307Sbostic 	int fd;
2330888Sbostic 
2439307Sbostic 	return (_gettemp(path, &fd) ? fd : -1);
2530888Sbostic }
2630888Sbostic 
2713260Sroot char *
2839307Sbostic mktemp(path)
2939307Sbostic 	char *path;
3013260Sroot {
3139307Sbostic 	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
3230888Sbostic }
3313260Sroot 
3430888Sbostic static
3539307Sbostic _gettemp(path, doopen)
3639307Sbostic 	char *path;
3739307Sbostic 	register int *doopen;
3830888Sbostic {
3939307Sbostic 	extern int errno;
4039307Sbostic 	register char *start, *trv;
4139307Sbostic 	struct stat sbuf;
4239307Sbostic 	u_int pid;
4330888Sbostic 
4413260Sroot 	pid = getpid();
4539307Sbostic 	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
4630888Sbostic 	while (*--trv == 'X') {
4730888Sbostic 		*trv = (pid % 10) + '0';
4813260Sroot 		pid /= 10;
4913260Sroot 	}
5030888Sbostic 
5130888Sbostic 	/*
5239307Sbostic 	 * check the target directory; if you have six X's and it
5339307Sbostic 	 * doesn't exist this runs for a *very* long time.
5430888Sbostic 	 */
5539307Sbostic 	for (start = trv + 1;; --trv) {
5639307Sbostic 		if (trv <= path)
5739307Sbostic 			break;
5839307Sbostic 		if (*trv == '/') {
5939307Sbostic 			*trv = '\0';
6039307Sbostic 			if (stat(path, &sbuf))
6139307Sbostic 				return(0);
6239307Sbostic 			if (!S_ISDIR(sbuf.st_mode)) {
6339307Sbostic 				errno = ENOTDIR;
6439307Sbostic 				return(0);
6539307Sbostic 			}
6639307Sbostic 			*trv = '/';
6739307Sbostic 			break;
6839307Sbostic 		}
6913260Sroot 	}
7030888Sbostic 
7130888Sbostic 	for (;;) {
7232155Sbostic 		if (doopen) {
7339307Sbostic 			if ((*doopen =
7439307Sbostic 			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
7539307Sbostic 				return(1);
7639307Sbostic 			if (errno != EEXIST)
7739307Sbostic 				return(0);
7832155Sbostic 		}
7939307Sbostic 		else if (stat(path, &sbuf))
8039307Sbostic 			return(errno == ENOENT ? 1 : 0);
8132155Sbostic 
8230888Sbostic 		/* tricky little algorithm for backward compatibility */
8330888Sbostic 		for (trv = start;;) {
8430888Sbostic 			if (!*trv)
8539307Sbostic 				return(0);
8630888Sbostic 			if (*trv == 'z')
8730888Sbostic 				*trv++ = 'a';
8830888Sbostic 			else {
8930888Sbostic 				if (isdigit(*trv))
9030888Sbostic 					*trv = 'a';
9130888Sbostic 				else
9230888Sbostic 					++*trv;
9330888Sbostic 				break;
9430888Sbostic 			}
9530888Sbostic 		}
9630888Sbostic 	}
9730888Sbostic 	/*NOTREACHED*/
9813260Sroot }
99