xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 32155)
130888Sbostic /*
230888Sbostic  * Copyright (c) 1987 Regents of the University of California.
330888Sbostic  * All rights reserved.  The Berkeley software License Agreement
430888Sbostic  * specifies the terms and conditions for redistribution.
530888Sbostic  */
630888Sbostic 
726570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
8*32155Sbostic static char sccsid[] = "@(#)mktemp.c	5.4 (Berkeley) 09/14/87";
926570Sdonn #endif LIBC_SCCS and not lint
1013260Sroot 
1130888Sbostic #include <sys/types.h>
1230888Sbostic #include <sys/file.h>
13*32155Sbostic #include <sys/stat.h>
14*32155Sbostic #include <errno.h>
1530888Sbostic #include <stdio.h>
1630888Sbostic #include <ctype.h>
1730888Sbostic 
1830888Sbostic #define	YES	1
1930888Sbostic #define	NO	0
2030888Sbostic 
2130888Sbostic mkstemp(as)
2230888Sbostic 	char	*as;
2330888Sbostic {
2430888Sbostic 	int	fd;
2530888Sbostic 
2630888Sbostic 	return (_gettemp(as, &fd) ? fd : -1);
2730888Sbostic }
2830888Sbostic 
2913260Sroot char *
3013260Sroot mktemp(as)
3130888Sbostic 	char	*as;
3213260Sroot {
3330888Sbostic 	return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
3430888Sbostic }
3513260Sroot 
3630888Sbostic static
3730888Sbostic _gettemp(as, doopen)
3830888Sbostic 	char	*as;
3930888Sbostic 	register int	*doopen;
4030888Sbostic {
41*32155Sbostic 	extern int	errno;
4230888Sbostic 	register char	*start, *trv;
43*32155Sbostic 	struct stat	sbuf;
4430888Sbostic 	u_int	pid;
4530888Sbostic 
4613260Sroot 	pid = getpid();
4730888Sbostic 
4830888Sbostic 	/* extra X's get set to 0's */
49*32155Sbostic 	for (trv = as; *trv; ++trv);
5030888Sbostic 	while (*--trv == 'X') {
5130888Sbostic 		*trv = (pid % 10) + '0';
5213260Sroot 		pid /= 10;
5313260Sroot 	}
5430888Sbostic 
5530888Sbostic 	/*
5630888Sbostic 	 * check for write permission on target directory; if you have
5730888Sbostic 	 * six X's and you can't write the directory, this will run for
5830888Sbostic 	 * a *very* long time.
5930888Sbostic 	 */
60*32155Sbostic 	for (start = ++trv; trv > as && *trv != '/'; --trv);
6130888Sbostic 	if (*trv == '/') {
6230888Sbostic 		*trv = '\0';
63*32155Sbostic 		if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR))
6430888Sbostic 			return(NO);
65*32155Sbostic 		*trv = '/';
6613260Sroot 	}
67*32155Sbostic 	else if (stat(".", &sbuf) == -1)
6830888Sbostic 		return(NO);
6930888Sbostic 
7030888Sbostic 	for (;;) {
71*32155Sbostic 		if (doopen) {
72*32155Sbostic 		    if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
7330888Sbostic 			return(YES);
74*32155Sbostic 		    if (errno != EEXIST)
75*32155Sbostic 			return(NO);
76*32155Sbostic 		}
77*32155Sbostic 		else if (stat(as, &sbuf))
78*32155Sbostic 			return(errno == ENOENT ? YES : NO);
79*32155Sbostic 
8030888Sbostic 		/* tricky little algorithm for backward compatibility */
8130888Sbostic 		for (trv = start;;) {
8230888Sbostic 			if (!*trv)
8330888Sbostic 				return(NO);
8430888Sbostic 			if (*trv == 'z')
8530888Sbostic 				*trv++ = 'a';
8630888Sbostic 			else {
8730888Sbostic 				if (isdigit(*trv))
8830888Sbostic 					*trv = 'a';
8930888Sbostic 				else
9030888Sbostic 					++*trv;
9130888Sbostic 				break;
9230888Sbostic 			}
9330888Sbostic 		}
9430888Sbostic 	}
9530888Sbostic 	/*NOTREACHED*/
9613260Sroot }
97