1 /*
2 * Copyright (c) 1987, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 06/04/93";
10 #endif /* LIBC_SCCS and not lint */
11
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 #include <stdio.h>
17 #include <ctype.h>
18
19 static int _gettemp();
20
mkstemp(path)21 mkstemp(path)
22 char *path;
23 {
24 int fd;
25
26 return (_gettemp(path, &fd) ? fd : -1);
27 }
28
29 char *
mktemp(path)30 mktemp(path)
31 char *path;
32 {
33 return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
34 }
35
36 static
_gettemp(path,doopen)37 _gettemp(path, doopen)
38 char *path;
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 for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
48 while (*--trv == 'X') {
49 *trv = (pid % 10) + '0';
50 pid /= 10;
51 }
52
53 /*
54 * check the target directory; if you have six X's and it
55 * doesn't exist this runs for a *very* long time.
56 */
57 for (start = trv + 1;; --trv) {
58 if (trv <= path)
59 break;
60 if (*trv == '/') {
61 *trv = '\0';
62 if (stat(path, &sbuf))
63 return(0);
64 if (!S_ISDIR(sbuf.st_mode)) {
65 errno = ENOTDIR;
66 return(0);
67 }
68 *trv = '/';
69 break;
70 }
71 }
72
73 for (;;) {
74 if (doopen) {
75 if ((*doopen =
76 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
77 return(1);
78 if (errno != EEXIST)
79 return(0);
80 }
81 else if (stat(path, &sbuf))
82 return(errno == ENOENT ? 1 : 0);
83
84 /* tricky little algorithm for backward compatibility */
85 for (trv = start;;) {
86 if (!*trv)
87 return(0);
88 if (*trv == 'z')
89 *trv++ = 'a';
90 else {
91 if (isdigit(*trv))
92 *trv = 'a';
93 else
94 ++*trv;
95 break;
96 }
97 }
98 }
99 /*NOTREACHED*/
100 }
101