$NetBSD: patch-ae,v 1.7 2009/05/17 22:04:11 dholland Exp $

Fix insecure-temp-files. Replaces older nonworking patch with similar
intent. XXX inadequately tested, lack of time.

Upstream: sent upstream by obache@: http://sourceforge.net/tracker/?func=detail&atid=406763&aid=2537314&group_id=32880

--- src/types.c.orig	2008-07-09 15:51:26.000000000 -0400
+++ src/types.c	2009-05-17 17:55:28.000000000 -0400
@@ -28,6 +28,12 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#ifdef __sun /* paths.h missing in solaris */
+#define _PATH_TMP "/tmp/"
+#else
+#include <paths.h>
+#endif
+
 #include <stddef.h>
 
 #include "strutil.h"
@@ -345,14 +351,18 @@ static FType * match_file(GList *list, D
 void typ_identify_end(MainInfo *min, const gchar *path)
 {
 	const GList	*here;
-	gchar		buf[MAXNAMLEN + 2], *temp_name;
+	gchar		buf[MAXNAMLEN + 2];
 	gint		fd[2], len, status;
 	pid_t		file_pid;
 	FType		*type;
+	char		tempnamebuf[64];
+	int		tempfd;
 
 	if(file_list == NULL)
 		return;
-	if((temp_name = tmpnam(NULL)) == NULL)
+	strcpy(tempnamebuf, _PATH_TMP "gentoo.XXXXXX");
+	tempfd = mkstemp(tempnamebuf);
+	if (tempfd < 0)
 		return;
 	if(pipe(fd) != 0)
 		return;
@@ -360,20 +370,16 @@ void typ_identify_end(MainInfo *min, con
 	file_pid = fork();
 	if(file_pid == 0)
 	{
-		guint	bits = 0U;
-
-		if(close(STDIN_FILENO) == 0)
-		{
-			if(dup(fd[STDIN_FILENO]) == STDIN_FILENO)
-				bits |= (close(fd[STDIN_FILENO]) == 0);
-		}
-		if(close(STDOUT_FILENO) == 0)
-		{
-			if(open(temp_name, O_CREAT | O_RDWR, S_IRWXU) == STDOUT_FILENO)
-				bits |= (close(fd[STDOUT_FILENO]) == 0) << 1;
-		}
-		if(bits == 3U && chdir(path) == 0)
-			execlp("file", "file", "-f", "-", NULL);
+		if (dup2(fd[0], STDIN_FILENO) < 0)
+			_exit(EXIT_FAILURE);
+		if (dup2(tempfd, STDOUT_FILENO) < 0)
+			_exit(EXIT_FAILURE);
+		close(fd[0]);
+		close(fd[1]);
+		close(tempfd);
+		if (chdir(path) < 0)
+			_exit(EXIT_FAILURE);
+		execlp("file", "file", "-f", "-", NULL);
 		_exit(EXIT_FAILURE);
 	}
 	else if(file_pid < 0)
@@ -382,21 +388,21 @@ void typ_identify_end(MainInfo *min, con
 		return;
 	}
 	/* We don't need the input part of the pipe, so close it. */
-	close(fd[STDIN_FILENO]);
+	close(fd[0]);
 	/* Now, we have file listening on pipe, so write all filenames to it. */
 	for(here = file_list; here != NULL; here = g_list_next(here))
 	{
 		len = g_snprintf(buf, sizeof buf, "%s\n", DP_SEL_NAME(here));
-		write(fd[STDOUT_FILENO], buf, len);
+		write(fd[1], buf, len);
 	}
-	close(fd[STDOUT_FILENO]);
+	close(fd[1]);
 	waitpid(file_pid, &status, 0);
 
 	if(WIFEXITED(status))
 	{
 		FILE	*in;
 
-		if((in = fopen(temp_name, "rt")) != NULL)
+		if((in = fdopen(tempfd, "rt")) != NULL)
 		{
 			const gchar	*fout;
 			gchar		line[MAXNAMLEN + 256];
@@ -412,10 +418,14 @@ void typ_identify_end(MainInfo *min, con
 			}
 			fclose(in);
 		}
+		else
+			close(tempfd);
 	}
+	else
+		close(tempfd);
 	g_list_free(file_list);
 	file_list = NULL;
-	remove(temp_name);
+	remove(tempnamebuf);
 }
 
 /* ----------------------------------------------------------------------------------------- */
