xref: /original-bsd/lib/libc/stdio/mktemp.c (revision 8a1064d0)
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.3 (Berkeley) 04/10/87";
9 #endif LIBC_SCCS and not lint
10 
11 #include <sys/types.h>
12 #include <sys/file.h>
13 #include <stdio.h>
14 #include <ctype.h>
15 
16 #define	YES	1
17 #define	NO	0
18 
19 mkstemp(as)
20 	char	*as;
21 {
22 	int	fd;
23 
24 	return (_gettemp(as, &fd) ? fd : -1);
25 }
26 
27 char *
28 mktemp(as)
29 	char	*as;
30 {
31 	return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
32 }
33 
34 static
35 _gettemp(as, doopen)
36 	char	*as;
37 	register int	*doopen;
38 {
39 	register char	*start, *trv;
40 	u_int	pid;
41 	char	savech;
42 
43 	pid = getpid();
44 
45 	/* extra X's get set to 0's */
46 	for (trv = as;*trv;++trv);
47 	while (*--trv == 'X') {
48 		*trv = (pid % 10) + '0';
49 		pid /= 10;
50 	}
51 
52 	/*
53 	 * check for write permission on target directory; if you have
54 	 * six X's and you can't write the directory, this will run for
55 	 * a *very* long time.
56 	 */
57 	for (start = ++trv;trv > as && *trv != '/';--trv);
58 	if (*trv == '/') {
59 		savech = *++trv;
60 		*trv = '\0';
61 		if (access(as, W_OK))
62 			return(NO);
63 		*trv = savech;
64 	}
65 	else if (access(".", W_OK))
66 		return(NO);
67 
68 	for (;;) {
69 		if (doopen
70 		    && (*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) != -1
71 		    || access(as, F_OK))
72 			return(YES);
73 		/* tricky little algorithm for backward compatibility */
74 		for (trv = start;;) {
75 			if (!*trv)
76 				return(NO);
77 			if (*trv == 'z')
78 				*trv++ = 'a';
79 			else {
80 				if (isdigit(*trv))
81 					*trv = 'a';
82 				else
83 					++*trv;
84 				break;
85 			}
86 		}
87 	}
88 	/*NOTREACHED*/
89 }
90