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