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 632701Sbostic * provided that this notice is preserved and that due credit is given 732701Sbostic * to the University of California at Berkeley. The name of the University 832701Sbostic * may not be used to endorse or promote products derived from this 932701Sbostic * software without specific written prior permission. This software 1032701Sbostic * is provided ``as is'' without express or implied warranty. 1130888Sbostic */ 1230888Sbostic 1326570Sdonn #if defined(LIBC_SCCS) && !defined(lint) 14*34436Sbostic static char sccsid[] = "@(#)mktemp.c 5.6 (Berkeley) 05/23/88"; 15*34436Sbostic #endif /* LIBC_SCCS and not lint */ 1613260Sroot 1730888Sbostic #include <sys/types.h> 1830888Sbostic #include <sys/file.h> 1932155Sbostic #include <sys/stat.h> 2032155Sbostic #include <errno.h> 2130888Sbostic #include <stdio.h> 2230888Sbostic #include <ctype.h> 2330888Sbostic 2430888Sbostic #define YES 1 2530888Sbostic #define NO 0 2630888Sbostic 2730888Sbostic mkstemp(as) 2830888Sbostic char *as; 2930888Sbostic { 3030888Sbostic int fd; 3130888Sbostic 3230888Sbostic return (_gettemp(as, &fd) ? fd : -1); 3330888Sbostic } 3430888Sbostic 3513260Sroot char * 3613260Sroot mktemp(as) 3730888Sbostic char *as; 3813260Sroot { 3930888Sbostic return(_gettemp(as, (int *)NULL) ? as : (char *)NULL); 4030888Sbostic } 4113260Sroot 4230888Sbostic static 4330888Sbostic _gettemp(as, doopen) 4430888Sbostic char *as; 4530888Sbostic register int *doopen; 4630888Sbostic { 4732155Sbostic extern int errno; 4830888Sbostic register char *start, *trv; 4932155Sbostic struct stat sbuf; 5030888Sbostic u_int pid; 5130888Sbostic 5213260Sroot pid = getpid(); 5330888Sbostic 5430888Sbostic /* extra X's get set to 0's */ 5532155Sbostic for (trv = as; *trv; ++trv); 5630888Sbostic while (*--trv == 'X') { 5730888Sbostic *trv = (pid % 10) + '0'; 5813260Sroot pid /= 10; 5913260Sroot } 6030888Sbostic 6130888Sbostic /* 6230888Sbostic * check for write permission on target directory; if you have 6330888Sbostic * six X's and you can't write the directory, this will run for 6430888Sbostic * a *very* long time. 6530888Sbostic */ 6632155Sbostic for (start = ++trv; trv > as && *trv != '/'; --trv); 6730888Sbostic if (*trv == '/') { 6830888Sbostic *trv = '\0'; 6932155Sbostic if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) 7030888Sbostic return(NO); 7132155Sbostic *trv = '/'; 7213260Sroot } 7332155Sbostic else if (stat(".", &sbuf) == -1) 7430888Sbostic return(NO); 7530888Sbostic 7630888Sbostic for (;;) { 7732155Sbostic if (doopen) { 7832155Sbostic if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 7930888Sbostic return(YES); 8032155Sbostic if (errno != EEXIST) 8132155Sbostic return(NO); 8232155Sbostic } 8332155Sbostic else if (stat(as, &sbuf)) 8432155Sbostic return(errno == ENOENT ? YES : NO); 8532155Sbostic 8630888Sbostic /* tricky little algorithm for backward compatibility */ 8730888Sbostic for (trv = start;;) { 8830888Sbostic if (!*trv) 8930888Sbostic return(NO); 9030888Sbostic if (*trv == 'z') 9130888Sbostic *trv++ = 'a'; 9230888Sbostic else { 9330888Sbostic if (isdigit(*trv)) 9430888Sbostic *trv = 'a'; 9530888Sbostic else 9630888Sbostic ++*trv; 9730888Sbostic break; 9830888Sbostic } 9930888Sbostic } 10030888Sbostic } 10130888Sbostic /*NOTREACHED*/ 10213260Sroot } 103