Home | History | Annotate | Download | only in stdio
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1988 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31 
     32 #pragma weak _tempnam = tempnam
     33 
     34 #include "lint.h"
     35 #include <mtlib.h>
     36 #include <sys/types.h>
     37 #include <stdio.h>
     38 #include <string.h>
     39 #include <stdlib.h>
     40 #include <thread.h>
     41 #include <synch.h>
     42 #include <unistd.h>
     43 #include <sys/stat.h>
     44 
     45 #define	max(A, B) (((A) < (B))?(B):(A))
     46 
     47 static char *pcopy(char *, const char *);
     48 
     49 static char seed[] = "AAA";
     50 
     51 static mutex_t seed_lk = DEFAULTMUTEX;
     52 
     53 char *
     54 tempnam(const char *dir,	/* use this directory please (if non-NULL) */
     55 	const char *pfx)	/* use this (if non-NULL) as filename prefix */
     56 {
     57 	char *p, *q, *tdir;
     58 	size_t x = 0, y = 0, z;
     59 	struct stat64 statbuf;
     60 
     61 	z = sizeof (P_tmpdir) - 1;
     62 	if ((tdir = getenv("TMPDIR")) != NULL) {
     63 		x = strlen(tdir);
     64 	}
     65 	if (dir != NULL) {
     66 		if (stat64(dir, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
     67 			y = strlen(dir);
     68 	}
     69 	if ((p = malloc(max(max(x, y), z)+16)) == NULL)
     70 		return (NULL);
     71 	if (x > 0 && access(pcopy(p, tdir), (W_OK | X_OK)) == 0)
     72 		goto OK;
     73 	if (y > 0 && access(pcopy(p, dir), (W_OK | X_OK)) == 0)
     74 		goto OK;
     75 	if (access(pcopy(p, P_tmpdir), (W_OK | X_OK)) == 0)
     76 		goto OK;
     77 	if (access(pcopy(p, "/tmp"), (W_OK | X_OK)) != 0) {
     78 		free(p);
     79 		return (NULL);
     80 	}
     81 OK:
     82 	(void) strcat(p, "/");
     83 	if (pfx) {
     84 		*(p+strlen(p)+5) = '\0';
     85 		(void) strncat(p, pfx, 5);
     86 	}
     87 	lmutex_lock(&seed_lk);
     88 	(void) strcat(p, seed);
     89 	(void) strcat(p, "XXXXXX");
     90 	q = seed;
     91 	while (*q == 'Z')
     92 		*q++ = 'A';
     93 	if (*q != '\0')
     94 		++*q;
     95 	lmutex_unlock(&seed_lk);
     96 	if (*mktemp(p) == '\0') {
     97 		free(p);
     98 		return (NULL);
     99 	}
    100 	return (p);
    101 }
    102 
    103 static char *
    104 pcopy(char *space, const char *arg)
    105 {
    106 	char *p;
    107 
    108 	if (arg) {
    109 		(void) strcpy(space, arg);
    110 		p = space-1+strlen(space);
    111 		while ((p >= space) && (*p == '/'))
    112 			*p-- = '\0';
    113 	}
    114 	return (space);
    115 }
    116