xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 34821)
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
6*34821Sbostic  * provided that the above copyright notice and this paragraph are
7*34821Sbostic  * duplicated in all such forms and that any documentation,
8*34821Sbostic  * advertising materials, and other materials related to such
9*34821Sbostic  * distribution and use acknowledge that the software was developed
10*34821Sbostic  * by the University of California, Berkeley.  The name of the
11*34821Sbostic  * University may not be used to endorse or promote products derived
12*34821Sbostic  * from this software without specific prior written permission.
13*34821Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*34821Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*34821Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1630888Sbostic  */
1730888Sbostic 
1826570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
19*34821Sbostic static char sccsid[] = "@(#)mktemp.c	5.7 (Berkeley) 06/27/88";
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 
2930888Sbostic #define	YES	1
3030888Sbostic #define	NO	0
3130888Sbostic 
3230888Sbostic mkstemp(as)
3330888Sbostic 	char	*as;
3430888Sbostic {
3530888Sbostic 	int	fd;
3630888Sbostic 
3730888Sbostic 	return (_gettemp(as, &fd) ? fd : -1);
3830888Sbostic }
3930888Sbostic 
4013260Sroot char *
4113260Sroot mktemp(as)
4230888Sbostic 	char	*as;
4313260Sroot {
4430888Sbostic 	return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
4530888Sbostic }
4613260Sroot 
4730888Sbostic static
4830888Sbostic _gettemp(as, doopen)
4930888Sbostic 	char	*as;
5030888Sbostic 	register int	*doopen;
5130888Sbostic {
5232155Sbostic 	extern int	errno;
5330888Sbostic 	register char	*start, *trv;
5432155Sbostic 	struct stat	sbuf;
5530888Sbostic 	u_int	pid;
5630888Sbostic 
5713260Sroot 	pid = getpid();
5830888Sbostic 
5930888Sbostic 	/* extra X's get set to 0's */
6032155Sbostic 	for (trv = as; *trv; ++trv);
6130888Sbostic 	while (*--trv == 'X') {
6230888Sbostic 		*trv = (pid % 10) + '0';
6313260Sroot 		pid /= 10;
6413260Sroot 	}
6530888Sbostic 
6630888Sbostic 	/*
6730888Sbostic 	 * check for write permission on target directory; if you have
6830888Sbostic 	 * six X's and you can't write the directory, this will run for
6930888Sbostic 	 * a *very* long time.
7030888Sbostic 	 */
7132155Sbostic 	for (start = ++trv; trv > as && *trv != '/'; --trv);
7230888Sbostic 	if (*trv == '/') {
7330888Sbostic 		*trv = '\0';
7432155Sbostic 		if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR))
7530888Sbostic 			return(NO);
7632155Sbostic 		*trv = '/';
7713260Sroot 	}
7832155Sbostic 	else if (stat(".", &sbuf) == -1)
7930888Sbostic 		return(NO);
8030888Sbostic 
8130888Sbostic 	for (;;) {
8232155Sbostic 		if (doopen) {
8332155Sbostic 		    if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
8430888Sbostic 			return(YES);
8532155Sbostic 		    if (errno != EEXIST)
8632155Sbostic 			return(NO);
8732155Sbostic 		}
8832155Sbostic 		else if (stat(as, &sbuf))
8932155Sbostic 			return(errno == ENOENT ? YES : NO);
9032155Sbostic 
9130888Sbostic 		/* tricky little algorithm for backward compatibility */
9230888Sbostic 		for (trv = start;;) {
9330888Sbostic 			if (!*trv)
9430888Sbostic 				return(NO);
9530888Sbostic 			if (*trv == 'z')
9630888Sbostic 				*trv++ = 'a';
9730888Sbostic 			else {
9830888Sbostic 				if (isdigit(*trv))
9930888Sbostic 					*trv = 'a';
10030888Sbostic 				else
10130888Sbostic 					++*trv;
10230888Sbostic 				break;
10330888Sbostic 			}
10430888Sbostic 		}
10530888Sbostic 	}
10630888Sbostic 	/*NOTREACHED*/
10713260Sroot }
108