Date: Mon, 9 Jun 1997 13:58:28 +0300 (IDT) From: Eli Zaretskii To: djgpp-workers AT delorie DOT com Subject: Bug in `popen' Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk There is a bug in `popen': it generates a temporary filename using `tmpnam', but then attaches an extension to the generated name. Therefore, the uniqueness of the name is not guaranteed. Moreover, it only calls `tmpnam' once, and relies on the unique extension to do the rest. But this fails in a nested program when the parent has a `popen' call in progress, and the child also calls `popen': the child will generate the same name, fail to see that it is already used, and overwrite the parent's temp file. Another situation is when you happen to have a file named `dj100000.0' (the first name generated by `popen') in your $TMPDIR. Here's the necessary patch. *** src/libc/posix/stdio/popen.c~0 Thu Jun 13 03:44:36 1996 --- src/libc/posix/stdio/popen.c Mon Jun 9 09:45:04 1997 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /* *************** *** 63,69 **** struct pipe_list { FILE *fp; int fd; ! char *command, mode[10], temp_name[FILENAME_MAX]; struct pipe_list *next; }; --- 64,70 ---- struct pipe_list { FILE *fp; int fd; ! char *command, mode[10], temp_name[L_tmpnam]; struct pipe_list *next; }; *************** FILE * *** 74,84 **** popen (const char *cm, const char *md) /* program name, pipe mode */ { struct pipe_list *l1, *l2; - static char *tn = NULL; /* temporary file basename */ - - if (!tn) - if ((tn = tmpnam(0)) == NULL) - return NULL; /* make new node */ if ((l1 = (struct pipe_list *) malloc (sizeof (struct pipe_list))) == NULL) --- 75,80 ---- *************** popen (const char *cm, const char *md) / *** 108,114 **** /* stick in elements we know already */ strcpy (l1->mode, md); ! sprintf (l1->temp_name, "%s.%d", tn, l1->fd); /* if can save the program name, build temp file */ if ((l1->command = malloc(strlen(cm)+1))) --- 104,111 ---- /* stick in elements we know already */ strcpy (l1->mode, md); ! if (tmpnam (l1->temp_name) == NULL) ! return NULL; /* if can save the program name, build temp file */ if ((l1->command = malloc(strlen(cm)+1)))