xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 39307)
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
634821Sbostic  * provided that the above copyright notice and this paragraph are
734821Sbostic  * duplicated in all such forms and that any documentation,
834821Sbostic  * advertising materials, and other materials related to such
934821Sbostic  * distribution and use acknowledge that the software was developed
1034821Sbostic  * by the University of California, Berkeley.  The name of the
1134821Sbostic  * University may not be used to endorse or promote products derived
1234821Sbostic  * from this software without specific prior written permission.
1334821Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434821Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534821Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1630888Sbostic  */
1730888Sbostic 
1826570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
19*39307Sbostic static char sccsid[] = "@(#)mktemp.c	5.8 (Berkeley) 10/16/89";
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 
29*39307Sbostic mkstemp(path)
30*39307Sbostic 	char *path;
3130888Sbostic {
32*39307Sbostic 	int fd;
3330888Sbostic 
34*39307Sbostic 	return (_gettemp(path, &fd) ? fd : -1);
3530888Sbostic }
3630888Sbostic 
3713260Sroot char *
38*39307Sbostic mktemp(path)
39*39307Sbostic 	char *path;
4013260Sroot {
41*39307Sbostic 	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
4230888Sbostic }
4313260Sroot 
4430888Sbostic static
45*39307Sbostic _gettemp(path, doopen)
46*39307Sbostic 	char *path;
47*39307Sbostic 	register int *doopen;
4830888Sbostic {
49*39307Sbostic 	extern int errno;
50*39307Sbostic 	register char *start, *trv;
51*39307Sbostic 	struct stat sbuf;
52*39307Sbostic 	u_int pid;
5330888Sbostic 
5413260Sroot 	pid = getpid();
55*39307Sbostic 	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
5630888Sbostic 	while (*--trv == 'X') {
5730888Sbostic 		*trv = (pid % 10) + '0';
5813260Sroot 		pid /= 10;
5913260Sroot 	}
6030888Sbostic 
6130888Sbostic 	/*
62*39307Sbostic 	 * check the target directory; if you have six X's and it
63*39307Sbostic 	 * doesn't exist this runs for a *very* long time.
6430888Sbostic 	 */
65*39307Sbostic 	for (start = trv + 1;; --trv) {
66*39307Sbostic 		if (trv <= path)
67*39307Sbostic 			break;
68*39307Sbostic 		if (*trv == '/') {
69*39307Sbostic 			*trv = '\0';
70*39307Sbostic 			if (stat(path, &sbuf))
71*39307Sbostic 				return(0);
72*39307Sbostic 			if (!S_ISDIR(sbuf.st_mode)) {
73*39307Sbostic 				errno = ENOTDIR;
74*39307Sbostic 				return(0);
75*39307Sbostic 			}
76*39307Sbostic 			*trv = '/';
77*39307Sbostic 			break;
78*39307Sbostic 		}
7913260Sroot 	}
8030888Sbostic 
8130888Sbostic 	for (;;) {
8232155Sbostic 		if (doopen) {
83*39307Sbostic 			if ((*doopen =
84*39307Sbostic 			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
85*39307Sbostic 				return(1);
86*39307Sbostic 			if (errno != EEXIST)
87*39307Sbostic 				return(0);
8832155Sbostic 		}
89*39307Sbostic 		else if (stat(path, &sbuf))
90*39307Sbostic 			return(errno == ENOENT ? 1 : 0);
9132155Sbostic 
9230888Sbostic 		/* tricky little algorithm for backward compatibility */
9330888Sbostic 		for (trv = start;;) {
9430888Sbostic 			if (!*trv)
95*39307Sbostic 				return(0);
9630888Sbostic 			if (*trv == 'z')
9730888Sbostic 				*trv++ = 'a';
9830888Sbostic 			else {
9930888Sbostic 				if (isdigit(*trv))
10030888Sbostic 					*trv = 'a';
10130888Sbostic 				else
10230888Sbostic 					++*trv;
10330888Sbostic 				break;
10430888Sbostic 			}
10530888Sbostic 		}
10630888Sbostic 	}
10730888Sbostic 	/*NOTREACHED*/
10813260Sroot }
109