Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 9/27/83; site hplabs.UUCP Path: utzoo!watmath!clyde!floyd!harpo!seismo!hao!hplabs!kg From: kg@hplabs.UUCP (Ken Greer) Newsgroups: net.unix-wizards Subject: Awk bug+fix Message-ID: <2389@hplabs.UUCP> Date: Thu, 1-Mar-84 16:49:43 EST Article-I.D.: hplabs.2389 Posted: Thu Mar 1 16:49:43 1984 Date-Received: Sun, 4-Mar-84 03:22:23 EST Organization: Hewlett Packard Labs, Palo Alto CA Lines: 91 The following awk bug exists on all version of awk I've looked at which includes 4.1BSD, 4.2BSD, Sys 5 rel. 0, and Sys 5 rel. 2. Ken Greer hplabs!kg kg@HPLABS (CSNET) kg.hplabs@RAND-RELAY (ARPA) The awk script, END { print "First" > "junk" print "cat junk" | "sh" print "Second" > "junk" } demonstrates two (and a half) bugs: 1) When finished, the file junk has two lines in it, not one. The second > is treated like an >>. 2) The pipe on line three is executed after awk exits, not at the time of the call. 2.5) As a result of 1) and 2), the file cat-ed on line three shows two lines, not one. The problem in awk is: 1) A file opened (with > or >>) is not closed after the statement is executed. The file name is remembered and subsequent references to that file name use the same open descriptor. (Efficient but wrong). 2) Pipes are not closed (with pclose). The diff for the fix is: ----------------------- In awk/run.c (procedure redirprint): > = new version 11,16d10 < #define FILENUM 10 < struct < { < FILE *fp; < char *fname; < } files[FILENUM]; 858d851 < register int i; 859a853 > FILE *fp; 863,870d856 < for (i=0; isval, files[i].fname) == 0) < goto doit; < for (i=0; i= FILENUM) < error(FATAL, "too many output files %d", i); 872c858 < files[i].fp = popen(x->sval, "w"); --- > fp = popen(x->sval, "w"); 874c860 < files[i].fp = fopen(x->sval, "a"); --- > fp = fopen(x->sval, "a"); 876,877c862,863 < files[i].fp = fopen(x->sval, "w"); < if (files[i].fp == NULL) --- > fp = fopen(x->sval, "w"); > if (fp == NULL) 879,884c865,869 < files[i].fname = tostring(x->sval); < doit: < fprintf(files[i].fp, "%s", s); < #ifndef gcos < fflush(files[i].fp); /* in case someone is waiting for the output */ < #endif --- > fprintf(fp, "%s", s); > if (a == '|') > pclose(fp); > else > fclose(fp); -- Ken Greer