xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 32155)
1 /*
2  * Copyright (c) 1987 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #if defined(LIBC_SCCS) && !defined(lint)
8 static char sccsid[] = "@(#)mktemp.c	5.4 (Berkeley) 09/14/87";
9 #endif LIBC_SCCS and not lint
10 
11 #include <sys/types.h>
12 #include <sys/file.h>
13 #include <sys/stat.h>
14 #include <errno.h>
15 #include <stdio.h>
16 #include <ctype.h>
17 
18 #define	YES	1
19 #define	NO	0
20 
21 mkstemp(as)
22 	char	*as;
23 {
24 	int	fd;
25 
26 	return (_gettemp(as, &fd) ? fd : -1);
27 }
28 
29 char *
30 mktemp(as)
31 	char	*as;
32 {
33 	return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
34 }
35 
36 static
37 _gettemp(as, doopen)
38 	char	*as;
39 	register int	*doopen;
40 {
41 	extern int	errno;
42 	register char	*start, *trv;
43 	struct stat	sbuf;
44 	u_int	pid;
45 
46 	pid = getpid();
47 
48 	/* extra X's get set to 0's */
49 	for (trv = as; *trv; ++trv);
50 	while (*--trv == 'X') {
51 		*trv = (pid % 10) + '0';
52 		pid /= 10;
53 	}
54 
55 	/*
56 	 * check for write permission on target directory; if you have
57 	 * six X's and you can't write the directory, this will run for
58 	 * a *very* long time.
59 	 */
60 	for (start = ++trv; trv > as && *trv != '/'; --trv);
61 	if (*trv == '/') {
62 		*trv = '\0';
63 		if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR))
64 			return(NO);
65 		*trv = '/';
66 	}
67 	else if (stat(".", &sbuf) == -1)
68 		return(NO);
69 
70 	for (;;) {
71 		if (doopen) {
72 		    if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
73 			return(YES);
74 		    if (errno != EEXIST)
75 			return(NO);
76 		}
77 		else if (stat(as, &sbuf))
78 			return(errno == ENOENT ? YES : NO);
79 
80 		/* tricky little algorithm for backward compatibility */
81 		for (trv = start;;) {
82 			if (!*trv)
83 				return(NO);
84 			if (*trv == 'z')
85 				*trv++ = 'a';
86 			else {
87 				if (isdigit(*trv))
88 					*trv = 'a';
89 				else
90 					++*trv;
91 				break;
92 			}
93 		}
94 	}
95 	/*NOTREACHED*/
96 }
97