130888Sbostic /* 230888Sbostic * Copyright (c) 1987 Regents of the University of California. 332701Sbostic * All rights reserved. 432701Sbostic * 532701Sbostic * Redistribution and use in source and binary forms are permitted 6*34821Sbostic * provided that the above copyright notice and this paragraph are 7*34821Sbostic * duplicated in all such forms and that any documentation, 8*34821Sbostic * advertising materials, and other materials related to such 9*34821Sbostic * distribution and use acknowledge that the software was developed 10*34821Sbostic * by the University of California, Berkeley. The name of the 11*34821Sbostic * University may not be used to endorse or promote products derived 12*34821Sbostic * from this software without specific prior written permission. 13*34821Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34821Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34821Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1630888Sbostic */ 1730888Sbostic 1826570Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*34821Sbostic static char sccsid[] = "@(#)mktemp.c 5.7 (Berkeley) 06/27/88"; 2034436Sbostic #endif /* LIBC_SCCS and not lint */ 2113260Sroot 2230888Sbostic #include <sys/types.h> 2330888Sbostic #include <sys/file.h> 2432155Sbostic #include <sys/stat.h> 2532155Sbostic #include <errno.h> 2630888Sbostic #include <stdio.h> 2730888Sbostic #include <ctype.h> 2830888Sbostic 2930888Sbostic #define YES 1 3030888Sbostic #define NO 0 3130888Sbostic 3230888Sbostic mkstemp(as) 3330888Sbostic char *as; 3430888Sbostic { 3530888Sbostic int fd; 3630888Sbostic 3730888Sbostic return (_gettemp(as, &fd) ? fd : -1); 3830888Sbostic } 3930888Sbostic 4013260Sroot char * 4113260Sroot mktemp(as) 4230888Sbostic char *as; 4313260Sroot { 4430888Sbostic return(_gettemp(as, (int *)NULL) ? as : (char *)NULL); 4530888Sbostic } 4613260Sroot 4730888Sbostic static 4830888Sbostic _gettemp(as, doopen) 4930888Sbostic char *as; 5030888Sbostic register int *doopen; 5130888Sbostic { 5232155Sbostic extern int errno; 5330888Sbostic register char *start, *trv; 5432155Sbostic struct stat sbuf; 5530888Sbostic u_int pid; 5630888Sbostic 5713260Sroot pid = getpid(); 5830888Sbostic 5930888Sbostic /* extra X's get set to 0's */ 6032155Sbostic for (trv = as; *trv; ++trv); 6130888Sbostic while (*--trv == 'X') { 6230888Sbostic *trv = (pid % 10) + '0'; 6313260Sroot pid /= 10; 6413260Sroot } 6530888Sbostic 6630888Sbostic /* 6730888Sbostic * check for write permission on target directory; if you have 6830888Sbostic * six X's and you can't write the directory, this will run for 6930888Sbostic * a *very* long time. 7030888Sbostic */ 7132155Sbostic for (start = ++trv; trv > as && *trv != '/'; --trv); 7230888Sbostic if (*trv == '/') { 7330888Sbostic *trv = '\0'; 7432155Sbostic if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) 7530888Sbostic return(NO); 7632155Sbostic *trv = '/'; 7713260Sroot } 7832155Sbostic else if (stat(".", &sbuf) == -1) 7930888Sbostic return(NO); 8030888Sbostic 8130888Sbostic for (;;) { 8232155Sbostic if (doopen) { 8332155Sbostic if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 8430888Sbostic return(YES); 8532155Sbostic if (errno != EEXIST) 8632155Sbostic return(NO); 8732155Sbostic } 8832155Sbostic else if (stat(as, &sbuf)) 8932155Sbostic return(errno == ENOENT ? YES : NO); 9032155Sbostic 9130888Sbostic /* tricky little algorithm for backward compatibility */ 9230888Sbostic for (trv = start;;) { 9330888Sbostic if (!*trv) 9430888Sbostic return(NO); 9530888Sbostic if (*trv == 'z') 9630888Sbostic *trv++ = 'a'; 9730888Sbostic else { 9830888Sbostic if (isdigit(*trv)) 9930888Sbostic *trv = 'a'; 10030888Sbostic else 10130888Sbostic ++*trv; 10230888Sbostic break; 10330888Sbostic } 10430888Sbostic } 10530888Sbostic } 10630888Sbostic /*NOTREACHED*/ 10713260Sroot } 108