130888Sbostic /*
2*61180Sbostic * Copyright (c) 1987, 1993
3*61180Sbostic * The Regents of the University of California. All rights reserved.
432701Sbostic *
542625Sbostic * %sccs.include.redist.c%
630888Sbostic */
730888Sbostic
826570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*61180Sbostic static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 06/04/93";
1034436Sbostic #endif /* LIBC_SCCS and not lint */
1113260Sroot
1230888Sbostic #include <sys/types.h>
1332155Sbostic #include <sys/stat.h>
1446611Sbostic #include <fcntl.h>
1532155Sbostic #include <errno.h>
1630888Sbostic #include <stdio.h>
1754995Sbostic #include <ctype.h>
1830888Sbostic
1946611Sbostic static int _gettemp();
2046611Sbostic
mkstemp(path)2139307Sbostic mkstemp(path)
2239307Sbostic char *path;
2330888Sbostic {
2439307Sbostic int fd;
2530888Sbostic
2639307Sbostic return (_gettemp(path, &fd) ? fd : -1);
2730888Sbostic }
2830888Sbostic
2913260Sroot char *
mktemp(path)3039307Sbostic mktemp(path)
3139307Sbostic char *path;
3213260Sroot {
3339307Sbostic return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
3430888Sbostic }
3513260Sroot
3630888Sbostic static
_gettemp(path,doopen)3739307Sbostic _gettemp(path, doopen)
3839307Sbostic char *path;
3939307Sbostic register int *doopen;
4030888Sbostic {
4139307Sbostic extern int errno;
4239307Sbostic register char *start, *trv;
4339307Sbostic struct stat sbuf;
4439307Sbostic u_int pid;
4530888Sbostic
4613260Sroot pid = getpid();
4739307Sbostic for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
4830888Sbostic while (*--trv == 'X') {
4930888Sbostic *trv = (pid % 10) + '0';
5013260Sroot pid /= 10;
5113260Sroot }
5230888Sbostic
5330888Sbostic /*
5439307Sbostic * check the target directory; if you have six X's and it
5539307Sbostic * doesn't exist this runs for a *very* long time.
5630888Sbostic */
5739307Sbostic for (start = trv + 1;; --trv) {
5839307Sbostic if (trv <= path)
5939307Sbostic break;
6039307Sbostic if (*trv == '/') {
6139307Sbostic *trv = '\0';
6239307Sbostic if (stat(path, &sbuf))
6339307Sbostic return(0);
6439307Sbostic if (!S_ISDIR(sbuf.st_mode)) {
6539307Sbostic errno = ENOTDIR;
6639307Sbostic return(0);
6739307Sbostic }
6839307Sbostic *trv = '/';
6939307Sbostic break;
7039307Sbostic }
7113260Sroot }
7230888Sbostic
7330888Sbostic for (;;) {
7432155Sbostic if (doopen) {
7539307Sbostic if ((*doopen =
7639307Sbostic open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
7739307Sbostic return(1);
7839307Sbostic if (errno != EEXIST)
7939307Sbostic return(0);
8032155Sbostic }
8139307Sbostic else if (stat(path, &sbuf))
8239307Sbostic return(errno == ENOENT ? 1 : 0);
8332155Sbostic
8430888Sbostic /* tricky little algorithm for backward compatibility */
8530888Sbostic for (trv = start;;) {
8630888Sbostic if (!*trv)
8739307Sbostic return(0);
8830888Sbostic if (*trv == 'z')
8930888Sbostic *trv++ = 'a';
9030888Sbostic else {
9130888Sbostic if (isdigit(*trv))
9230888Sbostic *trv = 'a';
9330888Sbostic else
9430888Sbostic ++*trv;
9530888Sbostic break;
9630888Sbostic }
9730888Sbostic }
9830888Sbostic }
9930888Sbostic /*NOTREACHED*/
10013260Sroot }
101