From lodea@angmar.mel.vet.com.au  Tue Feb 22 21:08:20 2000
Return-Path: <lodea@angmar.mel.vet.com.au>
Received: from angmar.mel.vet.com.au (angmar.mel.vet.com.au [203.103.154.62])
	by hub.freebsd.org (Postfix) with ESMTP id 4EF3737B89C
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 22 Feb 2000 21:08:17 -0800 (PST)
	(envelope-from lodea@angmar.mel.vet.com.au)
Received: (from lodea@localhost)
	by angmar.mel.vet.com.au (8.9.3/8.9.3) id QAA09369;
	Wed, 23 Feb 2000 16:08:12 +1100 (EST)
Message-Id: <200002230508.QAA09369@angmar.mel.vet.com.au>
Date: Wed, 23 Feb 2000 16:08:12 +1100 (EST)
From: lodea@angmar.mel.vet.com.au
Reply-To: lodea@vet.com.au
To: FreeBSD-gnats-submit@freebsd.org
Subject: tmpfile(3) should respect TMPDIR env variable
X-Send-Pr-Version: 3.2

>Number:         16924
>Category:       bin
>Synopsis:       tmpfile(3) ignores TMPDIR and always uses /tmp
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    mikeh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Feb 22 21:10:01 PST 2000
>Closed-Date:    Thu Aug 16 09:24:27 PDT 2001
>Last-Modified:  Thu Aug 16 09:24:41 PDT 2001
>Originator:     Lachlan O'Dea
>Release:        FreeBSD 3.3-STABLE i386
>Organization:
Computer Associates
>Environment:

FreeBSD angmar.mel.vet.com.au 3.3-STABLE FreeBSD 3.3-STABLE #4: Wed Dec  1 20:06:43 EST 1999     lodea@angmar.mel.vet.com.au:/usr/src/sys/compile/ANGMAR  i386

>Description:

Others may disagree, but I think it would be nice if the tmpfile(3)
function would use the TMPDIR environment variable if it is present.
Currently it is hard-coded to use /tmp.

My reason for doing this is that the Cyrus deliver program uses
tmpfile to store the email that it is delivering. I don't really
want to make my MFS /tmp big enough to hold the largest email
messages I expect to receive.

I can't see any problems caused by this change.

>How-To-Repeat:

Set TMPDIR to /var/tmp. Use tmpfile(3) to create a temporary file, then
write 50 Mb of data to it. Chances are pretty good your /tmp will run
out of space.

>Fix:
	
Here's a patch which might be satisfactory. If TMPDIR is not set, it
reverts to current behaviour. Please let me know if you like the
idea but not the patch.


Index: tmpfile.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/tmpfile.c,v
retrieving revision 1.4
diff -u -r1.4 tmpfile.c
--- tmpfile.c	2000/01/27 23:06:46	1.4
+++ tmpfile.c	2000/02/23 04:26:46
@@ -47,6 +47,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <paths.h>
+#include <stdlib.h>
 
 FILE *
 tmpfile()
@@ -55,10 +56,24 @@
 	FILE *fp;
 	int fd, sverrno;
 #define	TRAILER	"tmp.XXXXXX"
-	char buf[sizeof(_PATH_TMP) + sizeof(TRAILER)];
+	char *buf;
+	char *envtmpdir;
+	int envtmpdirlen;
 
-	(void)memcpy(buf, _PATH_TMP, sizeof(_PATH_TMP) - 1);
-	(void)memcpy(buf + sizeof(_PATH_TMP) - 1, TRAILER, sizeof(TRAILER));
+	if ((envtmpdir = getenv("TMPDIR")) != NULL)
+	{
+		envtmpdirlen = strlen(envtmpdir);
+		buf = malloc(envtmpdirlen + 1 + sizeof(TRAILER));
+		(void)memcpy(buf, envtmpdir, envtmpdirlen);
+		buf[envtmpdirlen] = '/';
+		(void)memcpy(buf + envtmpdirlen + 1, TRAILER, sizeof(TRAILER));
+	}
+	else
+	{
+		buf = malloc(sizeof(_PATH_TMP) + sizeof(TRAILER) - 1);
+		(void)memcpy(buf, _PATH_TMP, sizeof(_PATH_TMP) - 1);
+		(void)memcpy(buf + sizeof(_PATH_TMP) - 1, TRAILER, sizeof(TRAILER));
+	}
 
 	sigfillset(&set);
 	(void)sigprocmask(SIG_BLOCK, &set, &oset);
@@ -66,6 +81,8 @@
 	fd = mkstemp(buf);
 	if (fd != -1)
 		(void)unlink(buf);
+
+	free(buf);
 
 	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
 



>Release-Note:
>Audit-Trail:

From: Daniel Hagan <dhagan@cs.vt.edu>
To: freebsd-gnats-submit@FreeBSD.org, lodea@vet.com.au
Cc:  
Subject: Re: bin/16924: tmpfile(3) ignores TMPDIR and always uses /tmp
Date: Wed, 05 Apr 2000 21:54:37 -0400

 You need to do error checking on your calls to malloc.  Other than that, I
 think it looks ok on an initial reading.  (I'm certainly not an expert on
 libc though.)
 
 Daniel
 
 

From: "Lachlan O'Dea" <lodea@vet.com.au>
To: Daniel Hagan <dhagan@cs.vt.edu>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/16924: tmpfile(3) ignores TMPDIR and always uses /tmp
Date: Thu, 6 Apr 2000 14:03:55 +1000

 On Wed, Apr 05, 2000 at 09:54:37PM -0400, Daniel Hagan wrote:
 > You need to do error checking on your calls to malloc.  Other than that, I
 > think it looks ok on an initial reading.  (I'm certainly not an expert on
 > libc though.)
 
 Thanks for looking at this. I wanted to include error checking, but I
 wasn't sure of what action to take if an error occurred. I remember
 finding some other malloc calls in libc that didn't check for errors, so
 I just left it alone. If anyone can point me to an example of how to
 handle this, I'd appreciate it.
 

From: Sheldon Hearn <sheldonh@uunet.co.za>
To: Mike Heffner <spock@techfour.net>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/16924: tmpfile(3) ignores TMPDIR and always uses /tmp 
Date: Thu, 06 Apr 2000 15:41:20 +0200

 On Thu, 06 Apr 2000 09:28:55 -0400, Mike Heffner wrote:
 
 > I assume you mean the part of malloc setting ENOMEM. Is there a case
 > where it wouldn't set ENOMEM? According to the manpage, this is how
 > malloc(3) should behave.
 
 Bleh, please ignore that.  I don't know what I've been smoking, but I'm
 actually the guy who modified the malloc(3) manual page to specifically
 state that it _does_ set errno! :-)
 
 The problem is that the C standard doesn't specify that malloc() sets
 errno.  We should probably mention in malloc(3)'s STANDARDS section that
 setting errno from malloc() is mandated by the standard and that other
 implementations can not be relied on to do so.
 
 Ciao,
 Sheldon.
 

From: Daniel Hagan <dhagan@cs.vt.edu>
To: "Lachlan O'Dea" <lodea@vet.com.au>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/16924: tmpfile(3) ignores TMPDIR and always uses /tmp
Date: Thu, 6 Apr 2000 09:56:33 -0400 (EDT)

 On Thu, 6 Apr 2000, Lachlan O'Dea wrote:
 
 > Thanks for looking at this. I wanted to include error checking, but I
 > wasn't sure of what action to take if an error occurred. I remember
 > finding some other malloc calls in libc that didn't check for errors, so
 > I just left it alone. If anyone can point me to an example of how to
 > handle this, I'd appreciate it.
 
 From the information given in the man page for tmpfile(3), it would appear
 that the correct way to handle a malloc failure would be to return null
 and leave errno set to whatever value malloc(3) put there.  See the RETURN
 VALUES and ERRORS section of the tmpfile(3) manpage.
 
 The original code is incorrect anyway since it doesn't handle malloc
 errors.
 
 Daniel
 
 -- 
 Daniel Hagan                                             Computer Science CSE
 dhagan@cs.vt.edu                                http://www.cs.vt.edu/~dhagan/
 
 

From: "Lachlan O'Dea" <lodea@vet.com.au>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/16924: tmpfile(3) ignores TMPDIR and always uses /tmp
Date: Mon, 10 Apr 2000 20:44:54 +1000

 On Thu, Apr 06, 2000 at 09:56:33AM -0400, Daniel Hagan wrote:
 
 > The original code is incorrect anyway since it doesn't handle malloc
 > errors.
 
 So based on the discussion, all I have to do is return NULL if malloc
 returns NULL. The attached diff does this. I also added a paragraph to
 the man page.
 
 I didn't add anything to the ERRORS section, as it states that errno can
 be set to any of the errors returned by fdopen(3), which in turn can set
 errno to any value specified by malloc(3).
 
 Index: tmpfile.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/tmpfile.c,v
 retrieving revision 1.4
 diff -u -r1.4 tmpfile.c
 --- tmpfile.c	2000/01/27 23:06:46	1.4
 +++ tmpfile.c	2000/04/10 10:34:49
 @@ -47,6 +47,7 @@
  #include <stdio.h>
  #include <string.h>
  #include <paths.h>
 +#include <stdlib.h>
  
  FILE *
  tmpfile()
 @@ -55,10 +56,28 @@
  	FILE *fp;
  	int fd, sverrno;
  #define	TRAILER	"tmp.XXXXXX"
 -	char buf[sizeof(_PATH_TMP) + sizeof(TRAILER)];
 +	char *buf;
 +	char *envtmpdir;
 +	int envtmpdirlen;
  
 -	(void)memcpy(buf, _PATH_TMP, sizeof(_PATH_TMP) - 1);
 -	(void)memcpy(buf + sizeof(_PATH_TMP) - 1, TRAILER, sizeof(TRAILER));
 +	if ((envtmpdir = getenv("TMPDIR")) != NULL)
 +	{
 +		envtmpdirlen = strlen(envtmpdir);
 +		buf = malloc(envtmpdirlen + 1 + sizeof(TRAILER));
 +		if (buf == NULL)
 +			return NULL;
 +		(void)memcpy(buf, envtmpdir, envtmpdirlen);
 +		buf[envtmpdirlen] = '/';
 +		(void)memcpy(buf + envtmpdirlen + 1, TRAILER, sizeof(TRAILER));
 +	}
 +	else
 +	{
 +		buf = malloc(sizeof(_PATH_TMP) + sizeof(TRAILER) - 1);
 +		if (buf == NULL)
 +			return NULL;
 +		(void)memcpy(buf, _PATH_TMP, sizeof(_PATH_TMP) - 1);
 +		(void)memcpy(buf + sizeof(_PATH_TMP) - 1, TRAILER, sizeof(TRAILER));
 +	}
  
  	sigfillset(&set);
  	(void)sigprocmask(SIG_BLOCK, &set, &oset);
 @@ -66,6 +85,8 @@
  	fd = mkstemp(buf);
  	if (fd != -1)
  		(void)unlink(buf);
 +
 +	free(buf);
  
  	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
  
 Index: tmpnam.3
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/tmpnam.3,v
 retrieving revision 1.5
 diff -u -r1.5 tmpnam.3
 --- tmpnam.3	2000/01/09 08:54:03	1.5
 +++ tmpnam.3	2000/04/10 10:34:50
 @@ -66,6 +66,16 @@
  The file is opened with the access value
  .Ql w+ .
  .Pp
 +The file is initially created in the directory specified by the environment
 +variable
 +.Ev TMPDIR
 +(if set), or
 +.Pa /tmp
 +by default.
 +As the file is immediately unlinked, the only effect of
 +.Ev TMPDIR
 +is to specify which partition the file is created on.
 +.Pp
  The
  .Fn tmpnam
  function
 
State-Changed-From-To: open->analyzed 
State-Changed-By: mikeh 
State-Changed-When: Fri Jul 6 21:09:45 PDT 2001 
State-Changed-Why:  
Comitted to current, MFC in 2 weeks. 


Responsible-Changed-From-To: freebsd-bugs->	 mikeh 
Responsible-Changed-By: mikeh 
Responsible-Changed-When: Fri Jul 6 21:09:45 PDT 2001 
Responsible-Changed-Why:  
Might as well since I committed the fix ;) 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=16924 
State-Changed-From-To: analyzed->closed 
State-Changed-By: mikeh 
State-Changed-When: Thu Aug 16 09:24:27 PDT 2001 
State-Changed-Why:  
Fix MFC'd. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=16924 
>Unformatted:
