commit 3dba660db67ecad95e584481b719e6bf58e6debe
parent 6399b226b0ea5620ffe39ca9fb9dcfbde262d13d
Author: ukai <ukai>
Date: Wed, 15 Jan 2003 16:11:43 +0000
[w3m-dev 03640] Re: cleanup (don't close connection of news server)
* anchor.c (_put_ahchor_news): always conv_str
(_put_anchor_all): always conv_str
* etc.c (close_all_fds): deleted
(close_all_fds_except): added, except fd=f is left open
* file.c (guess_filename): added
(UFhalfclose): added
(convertLine): cleanup_line if not raw mode
check uf
(readHeader): always convertLine
(loadGeneralFile): rewrite
(loadGopherDir): return Str, args change to ParsedURL and code
rewrite
(saveBuffer): always conv_str
(_doFileCopy): close_all_fds
(doFileSave): close_all_fds_except
(uncompress_stream): dup, close_all_fds_except
* form.c (form_fputs_decode): always conv_str
(input_textarea): convertLine
* frame.c (createFrameFile): convertLine
* ftp.c (loadFTPDir): arg code
rewrite
(readFTPDir): convertLine
* html.h (UFfileno): added
* image.c (loadImage): close_all_fds
* indep.h (RAW_MODE): added
* local.c (loadLocalDir): return Str
(dirBuffer): rewrite
(localcgi_popen_r): close_all_fds
* main.c (main): check SCM_LOCAL
print err_msg
* news.c (news_command): args cmd and arg
(news_quit): news_command
(openNewsStream): news_command
(readNewsgroup): deleted
(loadNewsgroup): added
(closeNews): added
* proto.h (loadGopherDir): update
(conv_str): define for no JP_CHARSET
(readFTPDir): deleted
(loadFTPDir): added
(readNewsgroup): deleted
(loadNewsgroup): added
(dirBuffer): deleted
(loadLocalDir): added
(close_all_fds): defined by close_all_fds_except
(close_all_fds_except): added
From: Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
Diffstat:
M | ChangeLog | | | 50 | ++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | anchor.c | | | 10 | ++-------- |
M | etc.c | | | 8 | +++++--- |
M | file.c | | | 289 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
M | form.c | | | 9 | ++------- |
M | frame.c | | | 21 | ++++++--------------- |
M | ftp.c | | | 32 | +++++++++++++++++++++----------- |
M | html.h | | | 1 | + |
M | image.c | | | 1 | + |
M | indep.h | | | 7 | ++++--- |
M | local.c | | | 39 | +++++++++++++++++++-------------------- |
M | main.c | | | 9 | +++++++-- |
M | news.c | | | 71 | ++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
M | proto.h | | | 14 | +++++++++----- |
14 files changed, 301 insertions(+), 260 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,5 +1,55 @@
2003-01-16 Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
+ * [w3m-dev 03640] Re: cleanup (don't close connection of news server)
+ * anchor.c (_put_ahchor_news): always conv_str
+ (_put_anchor_all): always conv_str
+ * etc.c (close_all_fds): deleted
+ (close_all_fds_except): added, except fd=f is left open
+ * file.c (guess_filename): added
+ (UFhalfclose): added
+ (convertLine): cleanup_line if not raw mode
+ check uf
+ (readHeader): always convertLine
+ (loadGeneralFile): rewrite
+ (loadGopherDir): return Str, args change to ParsedURL and code
+ rewrite
+ (saveBuffer): always conv_str
+ (_doFileCopy): close_all_fds
+ (doFileSave): close_all_fds_except
+ (uncompress_stream): dup, close_all_fds_except
+ * form.c (form_fputs_decode): always conv_str
+ (input_textarea): convertLine
+ * frame.c (createFrameFile): convertLine
+ * ftp.c (loadFTPDir): arg code
+ rewrite
+ (readFTPDir): convertLine
+ * html.h (UFfileno): added
+ * image.c (loadImage): close_all_fds
+ * indep.h (RAW_MODE): added
+ * local.c (loadLocalDir): return Str
+ (dirBuffer): rewrite
+ (localcgi_popen_r): close_all_fds
+ * main.c (main): check SCM_LOCAL
+ print err_msg
+ * news.c (news_command): args cmd and arg
+ (news_quit): news_command
+ (openNewsStream): news_command
+ (readNewsgroup): deleted
+ (loadNewsgroup): added
+ (closeNews): added
+ * proto.h (loadGopherDir): update
+ (conv_str): define for no JP_CHARSET
+ (readFTPDir): deleted
+ (loadFTPDir): added
+ (readNewsgroup): deleted
+ (loadNewsgroup): added
+ (dirBuffer): deleted
+ (loadLocalDir): added
+ (close_all_fds): defined by close_all_fds_except
+ (close_all_fds_except): added
+
+2003-01-16 Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
+
* [w3m-dev 03639] Re: smb.cgi
* Bonus/2ch.cgi: change password handling
* Bonus/README: update
diff --git a/anchor.c b/anchor.c
@@ -198,10 +198,7 @@ _put_anchor_news(Buffer *buf, char *p1, char *p2, int line, int pos)
if (*(p2 - 1) == '>')
p2--;
}
- tmp = Strnew_charp_n(p1, p2 - p1);
-#ifdef JP_CHARSET
- tmp = conv_str(tmp, InnerCode, buf->document_code);
-#endif
+ tmp = conv_str(Strnew_charp_n(p1, p2 - p1), InnerCode, buf->document_code);
tmp = Sprintf("news:%s", file_quote(tmp->ptr));
return registerHref(buf, tmp->ptr, NULL, NO_REFERER, NULL, '\0', line,
pos);
@@ -213,10 +210,7 @@ _put_anchor_all(Buffer *buf, char *p1, char *p2, int line, int pos)
{
Str tmp;
- tmp = Strnew_charp_n(p1, p2 - p1);
-#ifdef JP_CHARSET
- tmp = conv_str(tmp, InnerCode, buf->document_code);
-#endif
+ tmp = conv_str(Strnew_charp_n(p1, p2 - p1), InnerCode, buf->document_code);
return registerHref(buf, url_quote(tmp->ptr), NULL, NO_REFERER, NULL,
'\0', line, pos);
}
diff --git a/etc.c b/etc.c
@@ -1306,7 +1306,7 @@ reset_signals(void)
#endif
void
-close_all_fds(int i)
+close_all_fds_except(int i, int f)
{
switch (i) { /* fall through */
case 0:
@@ -1317,8 +1317,10 @@ close_all_fds(int i)
dup2(open("/dev/null", O_WRONLY), 2);
}
/* close all other file descriptors (socket, ...) */
- for (i = 3; i < FOPEN_MAX; i++)
- close(i);
+ for (i = 3; i < FOPEN_MAX; i++) {
+ if (i != f)
+ close(i);
+ }
}
#ifdef HAVE_SETPGRP
diff --git a/file.c b/file.c
@@ -28,6 +28,7 @@
static int frame_source = 0;
+static char *guess_filename(char *file);
static int _MoveFile(char *path1, char *path2);
static void uncompress_stream(URLFile *uf, char **src);
static FILE *lessopen_stream(char *path);
@@ -193,6 +194,25 @@ KeyAbort(SIGNAL_ARG)
SIGNAL_RETURN;
}
+static void
+UFhalfclose(URLFile *f)
+{
+ switch (f->scheme) {
+ case SCM_FTP:
+ closeFTP();
+ break;
+#ifdef USE_NNTP
+ case SCM_NEWS:
+ case SCM_NNTP:
+ closeFTP();
+ break;
+#endif
+ default:
+ UFclose(f);
+ break;
+ }
+}
+
int
currentLn(Buffer *buf)
{
@@ -455,9 +475,10 @@ convertLine(URLFile *uf, Str line, char *code, int mode)
line = conv_str(line, *code, InnerCode);
}
#endif /* JP_CHARSET */
- cleanup_line(line, mode);
+ if (mode != RAW_MODE)
+ cleanup_line(line, mode);
#ifdef USE_NNTP
- if (uf->scheme == SCM_NEWS)
+ if (uf && uf->scheme == SCM_NEWS)
Strchop(line);
#endif /* USE_NNTP */
return line;
@@ -560,9 +581,7 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)
Str lineBuf2 = NULL;
Str tmp;
TextList *headerlist;
-#ifdef JP_CHARSET
- char code = DocumentCode, ic;
-#endif
+ char code;
FILE *src = NULL;
headerlist = newBuf->document_header = newTextList();
@@ -581,6 +600,9 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)
if (src)
newBuf->header_source = tmpf->ptr;
}
+#ifdef JP_CHARSET
+ code = DocumentCode;
+#endif
while ((tmp = StrmyUFgets(uf))->length) {
#ifdef USE_NNTP
if (uf->scheme == SCM_NEWS && tmp->ptr[0] == '.')
@@ -616,13 +638,7 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)
/* header line is continued */
continue;
lineBuf2 = decodeMIME(lineBuf2->ptr);
-#ifdef JP_CHARSET
- if ((ic = checkShiftCode(lineBuf2, code)) != '\0') {
- if (UseAutoDetect)
- code = ic;
- lineBuf2 = conv_str(lineBuf2, code, InnerCode);
- }
-#endif /* JP_CHARSET */
+ lineBuf2 = convertLine(NULL, lineBuf2, &code, RAW_MODE);
/* separated with line and stored */
tmp = Strnew_size(lineBuf2->length);
for (p = lineBuf2->ptr; *p; p = q) {
@@ -1503,6 +1519,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
unsigned char status = HTST_NORMAL;
URLOption url_option;
Str tmp;
+ Str volatile page = NULL;
+ char code = '\0';
HRequest hr;
ParsedURL *volatile auth_pu;
@@ -1524,34 +1542,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
content_charset = '\0';
#endif
if (f.stream == NULL) {
- /* openURL failure: it means either (1) the requested URL is a directory name
- * on an FTP server, or (2) is a local directory name.
- */
switch (f.scheme) {
- case SCM_FTPDIR:
- {
- Str ftpdir = readFTPDir(&pu);
- if (ftpdir && ftpdir->length > 0) {
- FILE *src;
- tmp = tmpfname(TMPF_SRC, ".html");
- src = fopen(tmp->ptr, "w");
- if (src) {
- Strfputs(ftpdir, src);
- fclose(src);
- }
- b = loadHTMLString(ftpdir);
- if (b) {
- if (b->currentURL.host == NULL
- && b->currentURL.file == NULL)
- copyParsedURL(&b->currentURL, &pu);
- b->real_scheme = pu.scheme;
- if (src)
- b->sourcefile = tmp->ptr;
- }
- return b;
- }
- }
- break;
case SCM_LOCAL:
{
struct stat st;
@@ -1572,42 +1563,24 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
return b;
}
else {
- b = dirBuffer(pu.real_file);
- if (b == NULL)
- return NULL;
- t = "text/html";
- b->real_scheme = pu.scheme;
- goto loaded;
+ page = loadLocalDir(pu.real_file);
+ t = "local:directory";
+#ifdef JP_CHARSET
+ code = SystemCode;
+#endif
}
- }
- }
- break;
+ }
+ }
+ break;
+ case SCM_FTPDIR:
+ page = loadFTPDir(&pu, &code);
+ t = "ftp:directory";
+ break;
#ifdef USE_NNTP
case SCM_NEWS_GROUP:
- {
- Str group = readNewsgroup(&pu);
- if (group && group->length > 0) {
- FILE *src;
- tmp = tmpfname(TMPF_SRC, ".html");
- src = fopen(tmp->ptr, "w");
- if (src) {
- Strfputs(group, src);
- fclose(src);
- }
- b = loadHTMLString(group);
- if (b) {
- b->real_type = "news:group";
- if (b->currentURL.host == NULL
- && b->currentURL.file == NULL)
- copyParsedURL(&b->currentURL, &pu);
- b->real_scheme = pu.scheme;
- if (src)
- b->sourcefile = tmp->ptr;
- }
- return b;
- }
- }
- break;
+ page = loadNewsgroup(&pu, &code);
+ t = "news:group";
+ break;
#endif
case SCM_UNKNOWN:
#ifdef USE_EXTERNAL_URI_LOADER
@@ -1623,6 +1596,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
parsedURL2Str(&pu)->ptr)->ptr, FALSE);
break;
}
+ if (page && page->length > 0)
+ goto page_loaded;
return NULL;
}
@@ -1812,11 +1787,13 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
t = "text/plain";
break;
case '1':
- t = "gopher:directory";
- break;
case 'm':
+ page = loadGopherDir(&f, &pu, &code);
t = "gopher:directory";
- break;
+ if (fmInitialized)
+ term_raw();
+ signal(SIGINT, prevtrap);
+ goto page_loaded;
case 's':
t = "audio/basic";
break;
@@ -1906,12 +1883,52 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
if (f.guess_type)
t = f.guess_type;
}
+
+ page_loaded:
+ if (page) {
+ FILE *src;
+ tmp = tmpfname(TMPF_SRC, ".html");
+ src = fopen(tmp->ptr, "w");
+ if (src) {
+ Strfputs(conv_str(page, InnerCode, code), src);
+ fclose(src);
+ }
+ if (do_download) {
+ char *file;
+ if (!src)
+ return NULL;
+ file = guess_filename(pu.file);
+#ifdef USE_GOPHER
+ if (f.scheme == SCM_GOPHER)
+ file = Sprintf("%s.html", file)->ptr;
+#endif
+#ifdef USE_NNTP
+ if (f.scheme == SCM_NEWS_GROUP)
+ file = Sprintf("%s.html", file)->ptr;
+#endif
+ doFileMove(tmp->ptr, file);
+ return NO_BUFFER;
+ }
+ b = loadHTMLString(page);
+ if (b) {
+ copyParsedURL(&b->currentURL, &pu);
+ b->real_scheme = pu.scheme;
+ b->real_type = t;
+ if (src)
+ b->sourcefile = tmp->ptr;
+#ifdef JP_CHARSET
+ b->document_code = code;
+#endif
+ }
+ return b;
+ }
+
+ if (real_type == NULL)
+ real_type = t;
if (SkipHeader) {
t_buf = newBuffer(INIT_BUFFER_WIDTH);
readHeader(&f, t_buf, TRUE, NULL);
}
- if (real_type == NULL)
- real_type = t;
proc = loadBuffer;
#ifdef USE_IMAGE
cur_baseURL = New(ParsedURL);
@@ -1921,7 +1938,6 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
current_content_length = 0;
if ((p = checkHeader(t_buf, "Content-Length:")) != NULL)
current_content_length = strtoclen(p);
-
if (do_download) {
/* download only */
char *file;
@@ -1938,8 +1954,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
}
else
file = guess_save_name(t_buf, pu.file);
- if (doFileSave(f, file) == 0 && f.scheme == SCM_FTP)
- closeFTP();
+ if (doFileSave(f, file) == 0)
+ UFhalfclose(&f);
else
UFclose(&f);
return NO_BUFFER;
@@ -1986,11 +2002,6 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
!(w3m_dump & ~DUMP_FRAME) && !strncasecmp(t, "image/", 6))
proc = loadImageBuffer;
#endif
-#ifdef USE_GOPHER
- else if (!strcasecmp(t, "gopher:directory")) {
- proc = loadGopherDir;
- }
-#endif /* USE_GOPHER */
else if (w3m_backend) ;
else if (!(w3m_dump & ~DUMP_FRAME) || is_dump_text_type(t)) {
if (!do_download && doExternal(f,
@@ -2021,9 +2032,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
else {
if (DecodeCTE && IStype(f.stream) != IST_ENCODED)
f.stream = newEncodedStream(f.stream, f.encoding);
- if (doFileSave(f, guess_save_name(t_buf, pu.file)) == 0 &&
- f.scheme == SCM_FTP)
- closeFTP();
+ if (doFileSave(f, guess_save_name(t_buf, pu.file)) == 0)
+ UFhalfclose(&f);
else
UFclose(&f);
}
@@ -2047,7 +2057,6 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
if (b) {
b->real_scheme = f.scheme;
b->real_type = real_type;
- loaded:
if (b->currentURL.host == NULL && b->currentURL.file == NULL)
copyParsedURL(&b->currentURL, &pu);
if (!strcasecmp(t, "text/html"))
@@ -2060,10 +2069,6 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
else if (proc == loadImageBuffer)
b->type = "text/html";
#endif
-#ifdef USE_GOPHER
- else if (proc == loadGopherDir)
- b->type = "text/html";
-#endif
else
b->type = "text/plain";
if (pu.label) {
@@ -6558,8 +6563,6 @@ loadHTMLString(Str page)
URLFile f;
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
Buffer *newBuf;
- Str tmp;
- FILE *volatile src = NULL;
newBuf = newBuffer(INIT_BUFFER_WIDTH);
if (SETJMP(AbortLoading) != 0) {
@@ -6574,15 +6577,7 @@ loadHTMLString(Str page)
term_cbreak();
init_stream(&f, SCM_LOCAL, newStrStream(page));
-
- if (w3m_dump & DUMP_FRAME) {
- tmp = tmpfname(TMPF_SRC, ".html");
- src = fopen(tmp->ptr, "w");
- if (src)
- newBuf->sourcefile = tmp->ptr;
- }
-
- loadHTMLstream(&f, newBuf, src, TRUE);
+ loadHTMLstream(&f, newBuf, NULL, TRUE);
if (fmInitialized)
term_raw();
@@ -6597,9 +6592,6 @@ loadHTMLString(Str page)
newBuf->real_type = newBuf->type;
if (n_textarea)
formResetBuffer(newBuf, newBuf->formitem);
- if (src)
- fclose(src);
-
return newBuf;
}
@@ -6608,19 +6600,21 @@ loadHTMLString(Str page)
/*
* loadGopherDir: get gopher directory
*/
-Buffer *
-loadGopherDir(URLFile *uf, Buffer *volatile newBuf)
+Str
+loadGopherDir(URLFile *uf, ParsedURL *pu, char *code)
{
- Str tmp, lbuf, name, file, host, port;
- char code = CODE_ASCII;
- char *p, *q;
- FILE *src;
- URLFile f;
+ Str volatile tmp;
+ Str lbuf, name, file, host, port;
+ char *volatile p, *volatile q;
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
- if (newBuf == NULL)
- newBuf = newBuffer(INIT_BUFFER_WIDTH);
- tmp = Strnew_charp("<pre>\n");
+ tmp = parsedURL2Str(pu);
+ p = html_quote(tmp->ptr);
+ tmp = convertLine(NULL, Strnew_charp(file_unquote(tmp->ptr)), code, NULL);
+ q = html_quote(tmp->ptr);
+ tmp = Strnew_m_charp("<html>\n<head>\n<base href=\"", p, "\">\n<title>", q,
+ "</title>\n</head>\n<body>\n<h1>Index of ", q,
+ "</h1>\n<table>\n", NULL);
if (SETJMP(AbortLoading) != 0)
goto gopher_end;
@@ -6629,13 +6623,7 @@ loadGopherDir(URLFile *uf, Buffer *volatile newBuf)
term_cbreak();
#ifdef JP_CHARSET
- if (newBuf->document_code != '\0')
- code = newBuf->document_code;
- else if (content_charset != '\0' && UseContentCharset)
- code = content_charset;
- else
- code = DocumentCode;
- content_charset = '\0';
+ *code = DocumentCode;
#endif
while (1) {
if (lbuf = StrUFgets(uf), lbuf->length == 0)
@@ -6643,7 +6631,7 @@ loadGopherDir(URLFile *uf, Buffer *volatile newBuf)
if (lbuf->ptr[0] == '.' &&
(lbuf->ptr[1] == '\n' || lbuf->ptr[1] == '\r'))
break;
- lbuf = convertLine(uf, lbuf, &code, HTML_MODE);
+ lbuf = convertLine(uf, lbuf, code, HTML_MODE);
p = lbuf->ptr;
for (q = p; *q && *q != '\t'; q++) ;
name = Strnew_charp_n(p, q - p);
@@ -6665,22 +6653,22 @@ loadGopherDir(URLFile *uf, Buffer *volatile newBuf)
switch (name->ptr[0]) {
case '0':
- p = "[text file] ";
+ p = "[text file]";
break;
case '1':
- p = "[directory] ";
+ p = "[directory]";
break;
case 'm':
- p = "[message] ";
+ p = "[message]";
break;
case 's':
- p = "[sound] ";
+ p = "[sound]";
break;
case 'g':
- p = "[gif] ";
+ p = "[gif]";
break;
case 'h':
- p = "[HTML] ";
+ p = "[HTML]";
break;
default:
p = "[unsupported]";
@@ -6688,9 +6676,9 @@ loadGopherDir(URLFile *uf, Buffer *volatile newBuf)
}
q = Strnew_m_charp("gopher://", host->ptr, ":", port->ptr,
"/", file->ptr, NULL)->ptr;
- Strcat_m_charp(tmp, "<a href=\"",
- html_quote(url_quote_conv(q, code)),
- "\">", p, html_quote(name->ptr + 1), "</a>\n", NULL);
+ Strcat_m_charp(tmp, "<tr valign=top><td>", p, "<td><a href=\"",
+ html_quote(url_quote_conv(q, *code)),
+ "\">", html_quote(name->ptr + 1), "</a>\n", NULL);
}
gopher_end:
@@ -6698,25 +6686,8 @@ loadGopherDir(URLFile *uf, Buffer *volatile newBuf)
term_raw();
signal(SIGINT, prevtrap);
- Strcat_charp(tmp, "</pre>\n");
-
- file = tmpfname(TMPF_SRC, ".html");
- src = fopen(file->ptr, "w");
- newBuf->sourcefile = file->ptr;
-
- init_stream(&f, SCM_LOCAL, newStrStream(tmp));
- loadHTMLstream(&f, newBuf, src, TRUE);
- if (src)
- fclose(src);
-
-#ifdef JP_CHARSET
- newBuf->document_code = code;
-#endif /* JP_CHARSET */
- newBuf->topLine = newBuf->firstLine;
- newBuf->lastLine = newBuf->currentLine;
- newBuf->currentLine = newBuf->firstLine;
-
- return newBuf;
+ Strcat_charp(tmp, "</table>\n</body>\n</html>\n");
+ return tmp;
}
#endif /* USE_GOPHER */
@@ -6946,10 +6917,7 @@ saveBuffer(Buffer *buf, FILE * f)
else
#endif
tmp = Strnew_charp_n(l->lineBuf, l->len);
-#ifdef JP_CHARSET
- tmp = conv_str(tmp, InnerCode, DisplayCode);
-#endif
- Strfputs(tmp, f);
+ Strfputs(conv_str(tmp, InnerCode, DisplayCode), f);
if (Strlastchar(tmp) != '\n')
putc('\n', f);
}
@@ -7520,6 +7488,7 @@ _doFileCopy(char *tmpf, char *defstr, int download)
signal(SIGINT, SIG_IGN);
SETPGRP();
close_tty();
+ close_all_fds(2);
QuietMessage = TRUE;
fmInitialized = FALSE;
if (!_MoveFile(tmpf, p) && PreserveTimestamp && !is_pipe &&
@@ -7626,6 +7595,7 @@ doFileSave(URLFile uf, char *defstr)
signal(SIGINT, SIG_IGN);
SETPGRP();
close_tty();
+ close_all_fds_except(2, UFfileno(&uf));
QuietMessage = TRUE;
fmInitialized = FALSE;
if (!save2tmp(uf, p) && PreserveTimestamp && uf.modtime != -1)
@@ -7788,6 +7758,9 @@ uncompress_stream(URLFile *uf, char **src)
QuietMessage = TRUE;
fmInitialized = FALSE;
close(fd1[0]);
+ dup2(fd1[1], 1);
+ dup2(fd1[1], 2);
+ close_all_fds_except(-1, UFfileno(uf));
if (tmpf) {
#ifdef USE_BINMODE_STREAM
int tmpfd = open(tmpf, O_RDONLY | O_BINARY);
@@ -7825,8 +7798,6 @@ uncompress_stream(URLFile *uf, char **src)
close(fd2[1]);
dup2(fd2[0], 0);
}
- dup2(fd1[1], 1);
- dup2(fd1[1], 2);
execlp(expand_cmd, expand_name, NULL);
exit(0);
}
diff --git a/form.c b/form.c
@@ -447,11 +447,7 @@ form_fputs_decode(Str s, FILE * f)
break;
}
}
-#ifdef JP_CHARSET
fputs(conv_str(z, InnerCode, DisplayCode)->ptr, f);
-#else /* not JP_CHARSET */
- fputs(z->ptr, f);
-#endif /* not JP_CHARSET */
}
@@ -462,7 +458,7 @@ input_textarea(FormItemList *fi)
Str tmp;
FILE *f;
#ifdef JP_CHARSET
- char code = DisplayCode, ic;
+ char code = DisplayCode;
#endif
f = fopen(tmpf, "w");
@@ -497,8 +493,7 @@ input_textarea(FormItemList *fi)
Strcat_charp(tmp, "\r\n");
}
#ifdef JP_CHARSET
- if ((ic = checkShiftCode(tmp, code)) != '\0')
- tmp = conv_str(tmp, (code = ic), InnerCode);
+ tmp = convertLine(NULL, tmp, &code, RAW_MODE);
#endif /* not JP_CHARSET */
Strcat(fi->value, tmp);
}
diff --git a/frame.c b/frame.c
@@ -410,8 +410,9 @@ createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
{
int r, c, t_stack;
URLFile f2;
+ char code;
#ifdef JP_CHARSET
- char code, ic, charset[2];
+ char charset[2];
#endif /* JP_CHARSET */
char *d_target, *p_target, *s_target, *t_target;
ParsedURL *currentURL, base;
@@ -530,20 +531,15 @@ createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
t_target = "_blank";
d_target = TargetSelf ? s_target : t_target;
#ifdef JP_CHARSET
- code = '\0';
-#endif /* JP_CHARSET */
+ code = DocumentCode;
+#endif
t_stack = 0;
if (frame.body->type &&
!strcasecmp(frame.body->type, "text/plain")) {
Str tmp;
fprintf(f1, "<pre>\n");
while ((tmp = StrmyUFgets(&f2))->length) {
-#ifdef JP_CHARSET
- if ((ic = checkShiftCode(tmp, code)) != '\0')
- tmp = conv_str(tmp, (code = ic), InnerCode);
-
-#endif /* JP_CHARSET */
- cleanup_line(tmp, HTML_MODE);
+ tmp = convertLine(NULL, tmp, &code, HTML_MODE);
fprintf(f1, "%s", html_quote(tmp->ptr));
}
fprintf(f1, "</pre>\n");
@@ -560,12 +556,7 @@ createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
Str tmp = StrmyUFgets(&f2);
if (tmp->length == 0)
break;
-#ifdef JP_CHARSET
- if ((ic = checkShiftCode(tmp, code)) != '\0')
- tmp = conv_str(tmp, (code = ic), InnerCode);
-
-#endif /* JP_CHARSET */
- cleanup_line(tmp, HTML_MODE);
+ tmp = convertLine(NULL, tmp, &code, HTML_MODE);
p = tmp->ptr;
}
read_token(tok, &p, &status, 1, status != R_ST_NORMAL);
diff --git a/ftp.c b/ftp.c
@@ -411,15 +411,18 @@ openFTPStream(ParsedURL *pu, URLFile *uf)
}
Str
-readFTPDir(ParsedURL *pu)
+loadFTPDir(ParsedURL *pu, char *code)
{
Str FTPDIRtmp;
Str tmp;
int status, sv_type;
- char *realpathname, *fn;
+ char *realpathname, *fn, *q;
char **flist;
int i, nfile, nfile_max = 100;
+#ifdef JP_CHARSET
+ *code = DocumentCode;
+#endif
if (current_ftp.data == NULL)
return NULL;
tmp = ftp_command(¤t_ftp, "SYST", NULL, &status);
@@ -453,13 +456,16 @@ readFTPDir(ParsedURL *pu)
if (Strlastchar(tmp) != '/')
Strcat_char(tmp, '/');
fn = html_quote(tmp->ptr);
- FTPDIRtmp = Strnew_m_charp("<html><head><title>", fn,
- "</title></head><body><h1>Index of ", fn,
+ tmp = convertLine(NULL, Strnew_charp(file_unquote(tmp->ptr)), code, NULL);
+ q = html_quote(tmp->ptr);
+ FTPDIRtmp = Strnew_m_charp("<html>\n<head>\n<base href=\"", fn,
+ "\">\n<title>", q,
+ "</title>\n</head>\n<body>\n<h1>Index of ", q,
"</h1>\n", NULL);
if (sv_type == UNIXLIKE_SERVER)
- Strcat_charp(FTPDIRtmp, "<pre>");
+ Strcat_charp(FTPDIRtmp, "<pre>\n");
else
- Strcat_charp(FTPDIRtmp, "<ul><li>");
+ Strcat_charp(FTPDIRtmp, "<ul>\n<li>");
Strcat_charp(FTPDIRtmp, "<a href=\"..\">[Upper Directory]</a>\n");
flist = New_N(char *, nfile_max);
@@ -519,8 +525,9 @@ readFTPDir(ParsedURL *pu)
}
date++;
len = strlen(fn);
+ tmp = convertLine(NULL, Strnew_charp(fn), code, NULL);
Strcat_m_charp(FTPDIRtmp, "<a href=\"", html_quote(file_quote(fn)),
- "\">", html_quote(fn), NULL);
+ "\">", html_quote(tmp->ptr), NULL);
if (ftype == FTPDIR_LINK) {
Strcat_charp(FTPDIRtmp, "@");
len++;
@@ -536,7 +543,7 @@ readFTPDir(ParsedURL *pu)
}
Strcat_m_charp(FTPDIRtmp, date, "\n", NULL);
}
- Strcat_charp(FTPDIRtmp, "</pre></body></html>\n");
+ Strcat_charp(FTPDIRtmp, "</pre>\n");
}
else {
while (tmp = Strfgets(current_ftp.data), tmp->length > 0) {
@@ -550,12 +557,15 @@ readFTPDir(ParsedURL *pu)
qsort(flist, nfile, sizeof(char *), strCmp);
for (i = 0; i < nfile; i++) {
fn = flist[i];
+ tmp = convertLine(NULL, Strnew_charp(fn), code, NULL);
Strcat_m_charp(FTPDIRtmp, "<li><a href=\"",
- html_quote(file_quote(fn)), "\">", html_quote(fn),
- "</a>\n", NULL);
+ html_quote(file_quote(fn)), "\">",
+ html_quote(tmp->ptr), "</a>\n", NULL);
}
- Strcat_charp(FTPDIRtmp, "</ul></body></html>\n");
+ Strcat_charp(FTPDIRtmp, "</ul>\n");
}
+ Strcat_charp(FTPDIRtmp, "</body>\n</html>\n");
+
closeFTPdata(current_ftp.data);
return FTPDIRtmp;
}
diff --git a/html.h b/html.h
@@ -15,6 +15,7 @@
#define UFundogetc(f) ISundogetc((f)->stream)
#define UFread(f,buf,len) ISread((f)->stream,buf,len)
#define UFclose(f) (void)(ISclose((f)->stream) == 0 && ((f)->stream = NULL))
+#define UFfileno(f) ISfileno((f)->stream)
struct cmdtable {
char *cmdname;
diff --git a/image.c b/image.c
@@ -456,6 +456,7 @@ loadImage(int flag)
reset_signals();
signal(SIGINT, SIG_IGN);
close_tty();
+ close_all_fds(2);
QuietMessage = TRUE;
fmInitialized = FALSE;
image_source = cache->file;
diff --git a/indep.h b/indep.h
@@ -12,9 +12,10 @@
#define FALSE 0
#endif /* FALSE */
-#define PAGER_MODE 0
-#define HTML_MODE 1
-#define HEADER_MODE 2
+#define RAW_MODE 0
+#define PAGER_MODE 1
+#define HTML_MODE 2
+#define HEADER_MODE 3
extern clen_t strtoclen(const char *s);
extern char *conv_entity(int ch);
diff --git a/local.c b/local.c
@@ -34,8 +34,8 @@ setLocalCookie()
set_environ("LOCAL_COOKIE", Local_cookie->ptr);
}
-Buffer *
-dirBuffer(char *dname)
+Str
+loadLocalDir(char *dname)
{
Str tmp;
DIR *d;
@@ -53,17 +53,18 @@ dirBuffer(char *dname)
int i, l, nrow = 0, n = 0, maxlen = 0;
int nfile, nfile_max = 100;
Str dirname;
- Buffer *buf;
d = opendir(dname);
if (d == NULL)
return NULL;
dirname = Strnew_charp(dname);
+ if (Strlastchar(dirname) != '/')
+ Strcat_char(dirname, '/');
qdir = html_quote(Str_conv_from_system(dirname)->ptr);
- tmp =
- Sprintf
- ("<title>Directory list of %s</title><h1>Directory list of %s</h1>\n",
- qdir, qdir);
+ tmp = Strnew_m_charp("<HTML>\n<HEAD>\n<BASE HREF=\"file://", qdir,
+ "\">\n<TITLE>Directory list of ", qdir,
+ "</TITLE>\n</HEAD>\n<BODY>\n<H1>Directory list of ",
+ qdir, "</H1>\n", NULL);
flist = New_N(char *, nfile_max);
nfile = 0;
while ((dir = readdir(d)) != NULL) {
@@ -86,7 +87,7 @@ dirBuffer(char *dname)
l = 1;
nrow = (n + l - 1) / l;
n = 1;
- Strcat_charp(tmp, "<TABLE CELLPADDING=0><TR VALIGN=TOP>\n");
+ Strcat_charp(tmp, "<TABLE CELLPADDING=0>\n<TR VALIGN=TOP>\n");
}
qsort((void *)flist, nfile, sizeof(char *), strCmp);
for (i = 0; i < nfile; i++) {
@@ -108,22 +109,23 @@ dirBuffer(char *dname)
Strcat_charp(tmp, "<TD><NOBR>");
}
else {
- if (S_ISDIR(st.st_mode))
- Strcat_charp(tmp, "[DIR] ");
#ifdef HAVE_LSTAT
- else if (S_ISLNK(lst.st_mode))
+ if (S_ISLNK(lst.st_mode))
Strcat_charp(tmp, "[LINK] ");
+ else
#endif /* HAVE_LSTAT */
+ if (S_ISDIR(st.st_mode))
+ Strcat_charp(tmp, "[DIR] ");
else
Strcat_charp(tmp, "[FILE] ");
}
- Strcat_m_charp(tmp, "<A HREF=\"", file_to_url(fbuf->ptr), NULL);
+ Strcat_m_charp(tmp, "<A HREF=\"", html_quote(file_quote(p)), NULL);
if (S_ISDIR(st.st_mode))
Strcat_char(tmp, '/');
Strcat_m_charp(tmp, "\">", html_quote(conv_from_system(p)), NULL);
if (S_ISDIR(st.st_mode))
Strcat_char(tmp, '/');
- Strcat_charp(tmp, "</a>");
+ Strcat_charp(tmp, "</A>");
if (multicolList) {
if (n++ == nrow) {
Strcat_charp(tmp, "</NOBR></TD>\n");
@@ -149,15 +151,11 @@ dirBuffer(char *dname)
}
}
if (multicolList) {
- Strcat_charp(tmp, "</TR></TABLE>\n");
+ Strcat_charp(tmp, "</TR>\n</TABLE>\n");
}
+ Strcat_charp(tmp, "</BODY>\n</HTML>\n");
- buf = loadHTMLString(tmp);
-#ifdef JP_CHARSET
- if (buf)
- buf->document_code = SystemCode;
-#endif
- return buf;
+ return tmp;
}
static int
@@ -364,6 +362,7 @@ localcgi_popen_r(FILE ** p_fp)
close(fd[1]);
close(fd[0]);
+ close_all_fds(2);
}
else {
close(fd[1]);
diff --git a/main.c b/main.c
@@ -889,7 +889,8 @@ main(int argc, char **argv, char **envp)
else if (newbuf == NO_BUFFER)
continue;
if (newbuf->pagerSource ||
- (newbuf->currentURL.file && strcmp(newbuf->currentURL.file, "-")))
+ (newbuf->real_scheme == SCM_LOCAL && newbuf->header_source &&
+ newbuf->currentURL.file && strcmp(newbuf->currentURL.file, "-")))
newbuf->search_header = search_header;
if (CurrentTab == NULL) {
FirstTab = LastTab = CurrentTab = newTab();
@@ -928,6 +929,8 @@ main(int argc, char **argv, char **envp)
}
}
if (w3m_dump) {
+ if (err_msg->length)
+ fprintf(stderr, "%s", err_msg->ptr);
#ifdef USE_COOKIE
save_cookies();
#endif /* USE_COOKIE */
@@ -4409,7 +4412,9 @@ vwSrc(void)
return;
}
}
- else if (Currentbuf->real_scheme == SCM_LOCAL) {
+ else if (Currentbuf->real_scheme == SCM_LOCAL &&
+ !(Currentbuf->real_type &&
+ !strcasecmp(Currentbuf->real_type, "local:directory"))) {
fn = Currentbuf->filename;
}
else {
diff --git a/news.c b/news.c
@@ -33,14 +33,18 @@ KeyAbort(SIGNAL_ARG)
}
static Str
-news_command(News * news, char *command, int *status)
+news_command(News * news, char *cmd, char *arg, int *status)
{
Str tmp;
if (!news->host)
return NULL;
- if (command) {
- fprintf(news->wf, "%s\r\n", command);
+ if (cmd) {
+ if (arg)
+ tmp = Sprintf("%s %s\r\n", cmd, arg);
+ else
+ tmp = Sprintf("%s\r\n", cmd);
+ fwrite(tmp->ptr, tmp->length, sizeof(char), news->wf);
fflush(news->wf);
}
if (!status)
@@ -82,11 +86,11 @@ news_open(News * news)
if (!news->rf || !news->wf)
goto open_err;
IStype(news->rf) |= IST_UNCLOSE;
- news_command(news, NULL, &status);
+ news_command(news, NULL, NULL, &status);
if (status != 200 && status != 201)
goto open_err;
if (news->mode) {
- news_command(news, Sprintf("MODE %s", news->mode)->ptr, &status);
+ news_command(news, "MODE", news->mode, &status);
if (status != 200 && status != 201)
goto open_err;
}
@@ -99,7 +103,7 @@ news_open(News * news)
static void
news_quit(News * news)
{
- news_command(news, "QUIT", NULL);
+ news_command(news, "QUIT", NULL, NULL);
news_close(news);
}
@@ -257,8 +261,8 @@ openNewsStream(ParsedURL *pu)
mode = NULL;
if (current_news.host) {
if (!strcmp(current_news.host, host) && current_news.port == port) {
- tmp = Sprintf("MODE %s", mode ? mode : "READER");
- tmp = news_command(¤t_news, tmp->ptr, &status);
+ tmp = news_command(¤t_news, "MODE", mode ? mode : "READER",
+ &status);
if (status != 200 && status != 201)
news_close(¤t_news);
}
@@ -283,17 +287,15 @@ openNewsStream(ParsedURL *pu)
}
else { /* <newsgroup>/<message-id or article-number> */
*p++ = '\0';
- news_command(¤t_news, Sprintf("GROUP %s", group)->ptr,
- &status);
+ news_command(¤t_news, "GROUP", group, &status);
if (status != 211)
return NULL;
}
if (strchr(p, '@')) /* <message-id> */
- news_command(¤t_news, Sprintf("ARTICLE <%s>", p)->ptr,
+ news_command(¤t_news, "ARTICLE", Sprintf("<%s>", p)->ptr,
&status);
else /* <article-number> */
- news_command(¤t_news, Sprintf("ARTICLE %s", p)->ptr,
- &status);
+ news_command(¤t_news, "ARTICLE", p, &status);
if (status != 220)
return NULL;
return current_news.rf;
@@ -302,7 +304,7 @@ openNewsStream(ParsedURL *pu)
}
Str
-readNewsgroup(ParsedURL *pu)
+loadNewsgroup(ParsedURL *pu, char *code)
{
volatile Str page;
Str tmp;
@@ -312,11 +314,13 @@ readNewsgroup(ParsedURL *pu)
char *volatile scheme, *volatile group, *volatile list;
int status, i, first, last;
volatile int flag = 0, start = 0, end = 0;
- char code = '\0';
MySignalHandler(*volatile trap) (SIGNAL_ARG) = NULL;
if (current_news.host == NULL || !pu->file || *pu->file == '\0')
return NULL;
+#ifdef JP_CHARSET
+ *code = DocumentCode;
+#endif
group = allocStr(pu->file, -1);
if (pu->scheme == SCM_NNTP_GROUP)
scheme = "/";
@@ -332,12 +336,15 @@ readNewsgroup(ParsedURL *pu)
}
qgroup = html_quote(group);
group = file_unquote(group);
- page = Sprintf("<title>Newsgroup: %s</title>\n\
-<h1>Newsgroup: %s</h1>\n<hr>\n", qgroup, qgroup);
+ page = Strnew_m_charp("<html>\n<head>\n<base href=\"",
+ parsedURL2Str(pu)->ptr, "\">\n<title>Newsgroup: ",
+ qgroup, "</title>\n</head>\n<body>\n<h1>Newsgroup: ",
+ qgroup, "</h1>\n<hr>\n", NULL);
if (SETJMP(AbortLoading) != 0) {
news_close(¤t_news);
- Strcat_charp(page, "</table><p>Transfer Interrupted!\n");
+ Strcat_charp(page,
+ "</table>\n<p>Transfer Interrupted!\n");
goto news_end;
}
trap = signal(SIGINT, KeyAbort);
@@ -345,7 +352,7 @@ readNewsgroup(ParsedURL *pu)
term_cbreak();
tmp =
- news_command(¤t_news, Sprintf("GROUP %s", group)->ptr, &status);
+ news_command(¤t_news, "GROUP", group, &status);
if (status != 211)
goto news_list;
if (sscanf(tmp->ptr, "%d %d %d %d", &status, &i, &first, &last) != 4)
@@ -369,8 +376,11 @@ readNewsgroup(ParsedURL *pu)
if (end - start > MaxNewsMessage - 1)
start = end - MaxNewsMessage + 1;
}
- page = Sprintf("<title>Newsgroup: %s %d-%d</title>\n\
-<h1>Newsgroup: %s %d-%d</h1>\n<hr>\n", qgroup, start, end, qgroup, start, end);
+ page = Sprintf("<html>\n<head>\n<base href=\"%s\">\n\
+<title>Newsgroup: %s %d-%d</title>\n\
+</head>\n<body>\n<h1>Newsgroup: %s %d-%d</h1>\n<hr>\n",
+ parsedURL2Str(pu)->ptr, qgroup, start, end, qgroup, start,
+ end);
if (start > first) {
i = start - MaxNewsMessage;
if (i < first)
@@ -380,7 +390,7 @@ readNewsgroup(ParsedURL *pu)
}
Strcat_charp(page, "<table>\n");
- news_command(¤t_news, Sprintf("XOVER %d-%d", start, end)->ptr,
+ news_command(¤t_news, "XOVER", Sprintf("%d-%d", start, end)->ptr,
&status);
if (status == 224) {
f.scheme = SCM_NEWS;
@@ -407,8 +417,8 @@ readNewsgroup(ParsedURL *pu)
if (!(q = strchr(p, '>')) && !(q = strchr(p, '\t')))
continue;
*q = '\0';
- s = convertLine(&f, decodeMIME(s), &code, HEADER_MODE)->ptr;
- n = convertLine(&f, decodeMIME(n), &code, HEADER_MODE)->ptr;
+ s = convertLine(&f, decodeMIME(s), code, HEADER_MODE)->ptr;
+ n = convertLine(&f, decodeMIME(n), code, HEADER_MODE)->ptr;
add_news_message(page, i, t, n, s, p, scheme,
pu->scheme == SCM_NNTP_GROUP ? qgroup : NULL);
}
@@ -417,7 +427,7 @@ readNewsgroup(ParsedURL *pu)
init_stream(&f, SCM_NEWS, current_news.rf);
buf = newBuffer(INIT_BUFFER_WIDTH);
for (i = start; i <= end && i <= last; i++) {
- news_command(¤t_news, Sprintf("HEAD %d", i)->ptr, &status);
+ news_command(¤t_news, "HEAD", Sprintf("%d", i)->ptr, &status);
if (status != 221)
continue;
readHeader(&f, buf, FALSE, NULL);
@@ -449,10 +459,10 @@ readNewsgroup(ParsedURL *pu)
flag = 1;
news_list:
- tmp = Sprintf("LIST ACTIVE %s", group);
+ tmp = Sprintf("ACTIVE %s", group);
if (!strchr(group, '*'))
Strcat_charp(tmp, ".*");
- news_command(¤t_news, tmp->ptr, &status);
+ news_command(¤t_news, "LIST", tmp->ptr, &status);
if (status != 215)
goto news_end;
while (1) {
@@ -481,6 +491,7 @@ readNewsgroup(ParsedURL *pu)
Strcat_charp(page, "</table>\n");
news_end:
+ Strcat_charp(page, "</body>\n</html>\n");
if (fmInitialized)
term_raw();
signal(SIGINT, trap);
@@ -488,6 +499,12 @@ readNewsgroup(ParsedURL *pu)
}
void
+closeNews(void)
+{
+ news_close(¤t_news);
+}
+
+void
disconnectNews(void)
{
news_quit(¤t_news);
diff --git a/proto.h b/proto.h
@@ -218,7 +218,7 @@ extern void loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src,
int internal);
extern Buffer *loadHTMLString(Str page);
#ifdef USE_GOPHER
-extern Buffer *loadGopherDir(URLFile *uf, Buffer *newBuf);
+extern Str loadGopherDir(URLFile *uf, ParsedURL *pu, char *code);
#endif /* USE_GOPHER */
extern Buffer *loadBuffer(URLFile *uf, Buffer *newBuf);
#ifdef USE_IMAGE
@@ -477,6 +477,8 @@ extern char checkShiftCode(Str buf, unsigned char hint);
extern char str_to_code(char *str);
extern char *code_to_str(char code);
extern void put_sjis(Str os, unsigned char ub, unsigned char lb);
+#else
+#define conv_str(is, fc, tc) (is)
#endif /* JP_CHARSET */
extern void initMimeTypes();
extern void free_ssl_ctx();
@@ -506,12 +508,13 @@ extern char *guessContentType(char *filename);
extern TextList *make_domain_list(char *domain_list);
extern int check_no_proxy(char *domain);
extern InputStream openFTPStream(ParsedURL *pu, URLFile *uf);
-extern Str readFTPDir(ParsedURL *pu);
+extern Str loadFTPDir(ParsedURL *pu, char *code);
extern void closeFTP(void);
extern void disconnectFTP(void);
#ifdef USE_NNTP
extern InputStream openNewsStream(ParsedURL *pu);
-extern Str readNewsgroup(ParsedURL *pu);
+extern Str loadNewsgroup(ParsedURL *pu, char *code);
+extern void closeNews(void);
extern void disconnectNews(void);
#endif
extern AnchorList *putAnchor(AnchorList *al, char *url, char *target,
@@ -569,7 +572,7 @@ extern char *auxbinFile(char *base);
extern char *libFile(char *base);
extern char *helpFile(char *base);
extern void setLocalCookie(void);
-extern Buffer *dirBuffer(char *dirname);
+extern Str loadLocalDir(char *dirname);
extern void set_environ(char *var, char *value);
extern FILE *localcgi_post(char *, char *, FormList *, char *);
extern FILE *localcgi_get(char *, char *, char *);
@@ -585,7 +588,8 @@ extern char *last_modified(Buffer *buf);
extern Str romanNumeral(int n);
extern Str romanAlphabet(int n);
extern void reset_signals(void);
-extern void close_all_fds(int i);
+extern void close_all_fds_except(int i, int f);
+#define close_all_fds(i) close_all_fds_except(i, -1)
#ifdef HAVE_SETPGRP
extern void myExec(char *command);
#endif