130888Sbostic /* 230888Sbostic * Copyright (c) 1987 Regents of the University of California. 330888Sbostic * All rights reserved. The Berkeley software License Agreement 430888Sbostic * specifies the terms and conditions for redistribution. 530888Sbostic */ 630888Sbostic 726570Sdonn #if defined(LIBC_SCCS) && !defined(lint) 8*32155Sbostic static char sccsid[] = "@(#)mktemp.c 5.4 (Berkeley) 09/14/87"; 926570Sdonn #endif LIBC_SCCS and not lint 1013260Sroot 1130888Sbostic #include <sys/types.h> 1230888Sbostic #include <sys/file.h> 13*32155Sbostic #include <sys/stat.h> 14*32155Sbostic #include <errno.h> 1530888Sbostic #include <stdio.h> 1630888Sbostic #include <ctype.h> 1730888Sbostic 1830888Sbostic #define YES 1 1930888Sbostic #define NO 0 2030888Sbostic 2130888Sbostic mkstemp(as) 2230888Sbostic char *as; 2330888Sbostic { 2430888Sbostic int fd; 2530888Sbostic 2630888Sbostic return (_gettemp(as, &fd) ? fd : -1); 2730888Sbostic } 2830888Sbostic 2913260Sroot char * 3013260Sroot mktemp(as) 3130888Sbostic char *as; 3213260Sroot { 3330888Sbostic return(_gettemp(as, (int *)NULL) ? as : (char *)NULL); 3430888Sbostic } 3513260Sroot 3630888Sbostic static 3730888Sbostic _gettemp(as, doopen) 3830888Sbostic char *as; 3930888Sbostic register int *doopen; 4030888Sbostic { 41*32155Sbostic extern int errno; 4230888Sbostic register char *start, *trv; 43*32155Sbostic struct stat sbuf; 4430888Sbostic u_int pid; 4530888Sbostic 4613260Sroot pid = getpid(); 4730888Sbostic 4830888Sbostic /* extra X's get set to 0's */ 49*32155Sbostic for (trv = as; *trv; ++trv); 5030888Sbostic while (*--trv == 'X') { 5130888Sbostic *trv = (pid % 10) + '0'; 5213260Sroot pid /= 10; 5313260Sroot } 5430888Sbostic 5530888Sbostic /* 5630888Sbostic * check for write permission on target directory; if you have 5730888Sbostic * six X's and you can't write the directory, this will run for 5830888Sbostic * a *very* long time. 5930888Sbostic */ 60*32155Sbostic for (start = ++trv; trv > as && *trv != '/'; --trv); 6130888Sbostic if (*trv == '/') { 6230888Sbostic *trv = '\0'; 63*32155Sbostic if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) 6430888Sbostic return(NO); 65*32155Sbostic *trv = '/'; 6613260Sroot } 67*32155Sbostic else if (stat(".", &sbuf) == -1) 6830888Sbostic return(NO); 6930888Sbostic 7030888Sbostic for (;;) { 71*32155Sbostic if (doopen) { 72*32155Sbostic if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 7330888Sbostic return(YES); 74*32155Sbostic if (errno != EEXIST) 75*32155Sbostic return(NO); 76*32155Sbostic } 77*32155Sbostic else if (stat(as, &sbuf)) 78*32155Sbostic return(errno == ENOENT ? YES : NO); 79*32155Sbostic 8030888Sbostic /* tricky little algorithm for backward compatibility */ 8130888Sbostic for (trv = start;;) { 8230888Sbostic if (!*trv) 8330888Sbostic return(NO); 8430888Sbostic if (*trv == 'z') 8530888Sbostic *trv++ = 'a'; 8630888Sbostic else { 8730888Sbostic if (isdigit(*trv)) 8830888Sbostic *trv = 'a'; 8930888Sbostic else 9030888Sbostic ++*trv; 9130888Sbostic break; 9230888Sbostic } 9330888Sbostic } 9430888Sbostic } 9530888Sbostic /*NOTREACHED*/ 9613260Sroot } 97