1*0Sstevel@tonic-gate /* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ 2*0Sstevel@tonic-gate /* Changes: Removed mktemp */ 3*0Sstevel@tonic-gate 4*0Sstevel@tonic-gate /* 5*0Sstevel@tonic-gate * Copyright (c) 1987, 1993 6*0Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 7*0Sstevel@tonic-gate * 8*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 9*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 10*0Sstevel@tonic-gate * are met: 11*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 12*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 13*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 14*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 15*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 16*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 17*0Sstevel@tonic-gate * must display the following acknowledgement: 18*0Sstevel@tonic-gate * This product includes software developed by the University of 19*0Sstevel@tonic-gate * California, Berkeley and its contributors. 20*0Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 21*0Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 22*0Sstevel@tonic-gate * without specific prior written permission. 23*0Sstevel@tonic-gate * 24*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34*0Sstevel@tonic-gate * SUCH DAMAGE. 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #include "includes.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #ifndef HAVE_MKDTEMP 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 42*0Sstevel@tonic-gate static char rcsid[] = "$OpenBSD: mktemp.c,v 1.16 2002/05/27 18:20:45 millert Exp $"; 43*0Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #ifdef HAVE_CYGWIN 46*0Sstevel@tonic-gate #define open binary_open 47*0Sstevel@tonic-gate extern int binary_open(); 48*0Sstevel@tonic-gate #endif 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate static int _gettemp(char *, int *, int, int); 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate int 53*0Sstevel@tonic-gate mkstemps(path, slen) 54*0Sstevel@tonic-gate char *path; 55*0Sstevel@tonic-gate int slen; 56*0Sstevel@tonic-gate { 57*0Sstevel@tonic-gate int fd; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate return (_gettemp(path, &fd, 0, slen) ? fd : -1); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate int 63*0Sstevel@tonic-gate mkstemp(path) 64*0Sstevel@tonic-gate char *path; 65*0Sstevel@tonic-gate { 66*0Sstevel@tonic-gate int fd; 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate return (_gettemp(path, &fd, 0, 0) ? fd : -1); 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate char * 72*0Sstevel@tonic-gate mkdtemp(path) 73*0Sstevel@tonic-gate char *path; 74*0Sstevel@tonic-gate { 75*0Sstevel@tonic-gate return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate static int 79*0Sstevel@tonic-gate _gettemp(path, doopen, domkdir, slen) 80*0Sstevel@tonic-gate char *path; 81*0Sstevel@tonic-gate register int *doopen; 82*0Sstevel@tonic-gate int domkdir; 83*0Sstevel@tonic-gate int slen; 84*0Sstevel@tonic-gate { 85*0Sstevel@tonic-gate register char *start, *trv, *suffp; 86*0Sstevel@tonic-gate struct stat sbuf; 87*0Sstevel@tonic-gate int rval; 88*0Sstevel@tonic-gate pid_t pid; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate if (doopen && domkdir) { 91*0Sstevel@tonic-gate errno = EINVAL; 92*0Sstevel@tonic-gate return(0); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate for (trv = path; *trv; ++trv) 96*0Sstevel@tonic-gate ; 97*0Sstevel@tonic-gate trv -= slen; 98*0Sstevel@tonic-gate suffp = trv; 99*0Sstevel@tonic-gate --trv; 100*0Sstevel@tonic-gate if (trv < path) { 101*0Sstevel@tonic-gate errno = EINVAL; 102*0Sstevel@tonic-gate return (0); 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate pid = getpid(); 105*0Sstevel@tonic-gate while (trv >= path && *trv == 'X' && pid != 0) { 106*0Sstevel@tonic-gate *trv-- = (pid % 10) + '0'; 107*0Sstevel@tonic-gate pid /= 10; 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate while (trv >= path && *trv == 'X') { 110*0Sstevel@tonic-gate char c; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate pid = (arc4random() & 0xffff) % (26+26); 113*0Sstevel@tonic-gate if (pid < 26) 114*0Sstevel@tonic-gate c = pid + 'A'; 115*0Sstevel@tonic-gate else 116*0Sstevel@tonic-gate c = (pid - 26) + 'a'; 117*0Sstevel@tonic-gate *trv-- = c; 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate start = trv + 1; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* 122*0Sstevel@tonic-gate * check the target directory; if you have six X's and it 123*0Sstevel@tonic-gate * doesn't exist this runs for a *very* long time. 124*0Sstevel@tonic-gate */ 125*0Sstevel@tonic-gate if (doopen || domkdir) { 126*0Sstevel@tonic-gate for (;; --trv) { 127*0Sstevel@tonic-gate if (trv <= path) 128*0Sstevel@tonic-gate break; 129*0Sstevel@tonic-gate if (*trv == '/') { 130*0Sstevel@tonic-gate *trv = '\0'; 131*0Sstevel@tonic-gate rval = stat(path, &sbuf); 132*0Sstevel@tonic-gate *trv = '/'; 133*0Sstevel@tonic-gate if (rval != 0) 134*0Sstevel@tonic-gate return(0); 135*0Sstevel@tonic-gate if (!S_ISDIR(sbuf.st_mode)) { 136*0Sstevel@tonic-gate errno = ENOTDIR; 137*0Sstevel@tonic-gate return(0); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate break; 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate for (;;) { 145*0Sstevel@tonic-gate if (doopen) { 146*0Sstevel@tonic-gate if ((*doopen = 147*0Sstevel@tonic-gate open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 148*0Sstevel@tonic-gate return(1); 149*0Sstevel@tonic-gate if (errno != EEXIST) 150*0Sstevel@tonic-gate return(0); 151*0Sstevel@tonic-gate } else if (domkdir) { 152*0Sstevel@tonic-gate if (mkdir(path, 0700) == 0) 153*0Sstevel@tonic-gate return(1); 154*0Sstevel@tonic-gate if (errno != EEXIST) 155*0Sstevel@tonic-gate return(0); 156*0Sstevel@tonic-gate } else if (lstat(path, &sbuf)) 157*0Sstevel@tonic-gate return(errno == ENOENT ? 1 : 0); 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate /* tricky little algorithm for backward compatibility */ 160*0Sstevel@tonic-gate for (trv = start;;) { 161*0Sstevel@tonic-gate if (!*trv) 162*0Sstevel@tonic-gate return (0); 163*0Sstevel@tonic-gate if (*trv == 'Z') { 164*0Sstevel@tonic-gate if (trv == suffp) 165*0Sstevel@tonic-gate return (0); 166*0Sstevel@tonic-gate *trv++ = 'a'; 167*0Sstevel@tonic-gate } else { 168*0Sstevel@tonic-gate if (isdigit(*trv)) 169*0Sstevel@tonic-gate *trv = 'a'; 170*0Sstevel@tonic-gate else if (*trv == 'z') /* inc from z to A */ 171*0Sstevel@tonic-gate *trv = 'A'; 172*0Sstevel@tonic-gate else { 173*0Sstevel@tonic-gate if (trv == suffp) 174*0Sstevel@tonic-gate return (0); 175*0Sstevel@tonic-gate ++*trv; 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate break; 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate /*NOTREACHED*/ 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate #endif /* !HAVE_MKDTEMP */ 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 187