xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 32701)
130888Sbostic /*
230888Sbostic  * Copyright (c) 1987 Regents of the University of California.
3*32701Sbostic  * All rights reserved.
4*32701Sbostic  *
5*32701Sbostic  * Redistribution and use in source and binary forms are permitted
6*32701Sbostic  * provided that this notice is preserved and that due credit is given
7*32701Sbostic  * to the University of California at Berkeley. The name of the University
8*32701Sbostic  * may not be used to endorse or promote products derived from this
9*32701Sbostic  * software without specific written prior permission. This software
10*32701Sbostic  * is provided ``as is'' without express or implied warranty.
1130888Sbostic  */
1230888Sbostic 
1326570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
14*32701Sbostic static char sccsid[] = "@(#)mktemp.c	5.5 (Berkeley) 11/30/87";
1526570Sdonn #endif LIBC_SCCS and not lint
1613260Sroot 
1730888Sbostic #include <sys/types.h>
1830888Sbostic #include <sys/file.h>
1932155Sbostic #include <sys/stat.h>
2032155Sbostic #include <errno.h>
2130888Sbostic #include <stdio.h>
2230888Sbostic #include <ctype.h>
2330888Sbostic 
2430888Sbostic #define	YES	1
2530888Sbostic #define	NO	0
2630888Sbostic 
2730888Sbostic mkstemp(as)
2830888Sbostic 	char	*as;
2930888Sbostic {
3030888Sbostic 	int	fd;
3130888Sbostic 
3230888Sbostic 	return (_gettemp(as, &fd) ? fd : -1);
3330888Sbostic }
3430888Sbostic 
3513260Sroot char *
3613260Sroot mktemp(as)
3730888Sbostic 	char	*as;
3813260Sroot {
3930888Sbostic 	return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
4030888Sbostic }
4113260Sroot 
4230888Sbostic static
4330888Sbostic _gettemp(as, doopen)
4430888Sbostic 	char	*as;
4530888Sbostic 	register int	*doopen;
4630888Sbostic {
4732155Sbostic 	extern int	errno;
4830888Sbostic 	register char	*start, *trv;
4932155Sbostic 	struct stat	sbuf;
5030888Sbostic 	u_int	pid;
5130888Sbostic 
5213260Sroot 	pid = getpid();
5330888Sbostic 
5430888Sbostic 	/* extra X's get set to 0's */
5532155Sbostic 	for (trv = as; *trv; ++trv);
5630888Sbostic 	while (*--trv == 'X') {
5730888Sbostic 		*trv = (pid % 10) + '0';
5813260Sroot 		pid /= 10;
5913260Sroot 	}
6030888Sbostic 
6130888Sbostic 	/*
6230888Sbostic 	 * check for write permission on target directory; if you have
6330888Sbostic 	 * six X's and you can't write the directory, this will run for
6430888Sbostic 	 * a *very* long time.
6530888Sbostic 	 */
6632155Sbostic 	for (start = ++trv; trv > as && *trv != '/'; --trv);
6730888Sbostic 	if (*trv == '/') {
6830888Sbostic 		*trv = '\0';
6932155Sbostic 		if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR))
7030888Sbostic 			return(NO);
7132155Sbostic 		*trv = '/';
7213260Sroot 	}
7332155Sbostic 	else if (stat(".", &sbuf) == -1)
7430888Sbostic 		return(NO);
7530888Sbostic 
7630888Sbostic 	for (;;) {
7732155Sbostic 		if (doopen) {
7832155Sbostic 		    if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
7930888Sbostic 			return(YES);
8032155Sbostic 		    if (errno != EEXIST)
8132155Sbostic 			return(NO);
8232155Sbostic 		}
8332155Sbostic 		else if (stat(as, &sbuf))
8432155Sbostic 			return(errno == ENOENT ? YES : NO);
8532155Sbostic 
8630888Sbostic 		/* tricky little algorithm for backward compatibility */
8730888Sbostic 		for (trv = start;;) {
8830888Sbostic 			if (!*trv)
8930888Sbostic 				return(NO);
9030888Sbostic 			if (*trv == 'z')
9130888Sbostic 				*trv++ = 'a';
9230888Sbostic 			else {
9330888Sbostic 				if (isdigit(*trv))
9430888Sbostic 					*trv = 'a';
9530888Sbostic 				else
9630888Sbostic 					++*trv;
9730888Sbostic 				break;
9830888Sbostic 			}
9930888Sbostic 		}
10030888Sbostic 	}
10130888Sbostic 	/*NOTREACHED*/
10213260Sroot }
103