Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions doc/README.mailcap
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
On mailcap support

(11/07/2000) Okabe Katsuya
okabek@guitar.ocn.ne.jp
(translated from Japanese)

* Starting with the 10/6/2000 version, w3m follows the mailcap fields
`nametemplate', `needsterminal', `copiousoutput', `edit' (see RFC-1524).
Also, starting with the 10/26/2000 version, the path of mailcap and
mime.types may be set from the option settings panel.

* In mailcap, the %s is replaced with the path name passed to the external
command, and %t is replaced with the file's content type.

* When a mailcap entry contains a test=command field, the file will only be
opened if the test command returns true. e.g. if you write

image/gif; xv '%s'; test=test "$DISPLAY"

then xv will only be launched if the DISPLAY environment variable is set.

* When a mailcap entry contains the `copiousoutput' field, the external
command's output is read into a new buffer.
e.g.

application/x-troff-man;/usr/bin/nroff -mandoc;copiousoutput

For the most part, this functionality can substitute all uses of LESSOPEN.
Therefore, usage of LESSOPEN has been made optional.

w3m has an extension called `x-htmloutput'. Just like `copiousoutput',
this reads the command's output into the buffer. The difference is that
`x-htmloutput' renders the output as HTML. For interoperability with other
browsers, it may be best to place entries not containing x-htmloutput before
entries that do contain the flag.

* nametemplate= specifies the extension of files passed to the external
command.
Normally, when a temporary file is created, the file extension present
in the URL is used. This can be changed using the nametemplate= field.
e.g.

application/x-dvi;xdvi '%s';test=test -n "$DISPLAY";nametemplate=%s.dvi

* For the meaning of the `needsterminal' and `edit' fields, please consult
RFC 1524.
106 changes: 79 additions & 27 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
#endif
HRequest hr;
ParsedURL *volatile auth_pu;
int needs_halfclose = FALSE;

tpath = path;
prevtrap = NULL;
Expand Down Expand Up @@ -2283,11 +2284,14 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
#endif
frame_source = flag & RG_FRAME_SRC;
if (proc == DO_EXTERNAL) {
b = doExternal(f, t, t_buf);
b = doExternal(f, t, t_buf, &needs_halfclose);
} else {
b = loadSomething(&f, proc, t_buf);
}
UFclose(&f);
if (needs_halfclose)
UFhalfclose(&f);
else
UFclose(&f);
frame_source = 0;
if (b && b != NO_BUFFER) {
b->real_scheme = f.scheme;
Expand Down Expand Up @@ -7999,6 +8003,7 @@ openGeneralPagerBuffer(InputStream stream)
char *t = "text/plain";
Buffer *t_buf = NULL;
URLFile uf;
int needs_halfclose = FALSE;

init_stream(&uf, SCM_UNKNOWN, stream);

Expand Down Expand Up @@ -8043,8 +8048,11 @@ openGeneralPagerBuffer(InputStream stream)
#endif
else {
if (searchExtViewer(t)) {
buf = doExternal(uf, t, t_buf);
UFclose(&uf);
buf = doExternal(uf, t, t_buf, &needs_halfclose);
if (needs_halfclose)
UFhalfclose(&uf);
else
UFclose(&uf);
if (buf == NULL || buf == NO_BUFFER)
return buf;
}
Expand Down Expand Up @@ -8185,21 +8193,15 @@ getNextPage(Buffer *buf, int plen)
return last;
}

int
save2tmp(URLFile uf, char *tmpf)
static int
save2file(URLFile uf, FILE *ff)
{
FILE *ff;
clen_t linelen = 0, trbyte = 0;
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
static JMP_BUF env_bak;
volatile int retval = 0;
char *volatile buf = NULL;

ff = fopen(tmpf, "wb");
if (ff == NULL) {
/* fclose(f); */
return -1;
}
bcopy(AbortLoading, env_bak, sizeof(JMP_BUF));
if (SETJMP(AbortLoading) != 0) {
goto _end;
Expand Down Expand Up @@ -8248,19 +8250,35 @@ save2tmp(URLFile uf, char *tmpf)
bcopy(env_bak, AbortLoading, sizeof(JMP_BUF));
TRAP_OFF;
xfree(buf);
fclose(ff);
current_content_length = 0;
return retval;
}

int
save2tmp(URLFile uf, char *tmpf)
{
FILE *ff;
int r;

ff = fopen(tmpf, "wb");
if (ff == NULL) {
/* fclose(f); */
return -1;
}
r = save2file(uf, ff);
fclose(ff);
return r;
}

Buffer *
doExternal(URLFile uf, char *type, Buffer *defaultbuf)
doExternal(URLFile uf, char *type, Buffer *defaultbuf, int *needs_halfclose)
{
Str tmpf, command;
struct mailcap *mcap;
int mc_stat;
int mc_stat, err, background;
Buffer *buf = NULL;
char *header, *src = NULL, *ext = uf.ext;
FILE *ff;

if (!(mcap = searchExtViewer(type)))
return NULL;
Expand All @@ -8279,7 +8297,8 @@ doExternal(URLFile uf, char *type, Buffer *defaultbuf)
header = conv_to_system(header);
command = unquote_mailcap(mcap->viewer, type, tmpf->ptr, header, &mc_stat);
#ifndef __EMX__
if (!(mc_stat & MCSTAT_REPNAME)) {
if (!(mc_stat & MCSTAT_REPNAME) &&
(mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT))) {
Str tmp = Sprintf("(%s) < %s", command->ptr, shell_quote(tmpf->ptr));
command = tmp;
}
Expand All @@ -8291,18 +8310,35 @@ doExternal(URLFile uf, char *type, Buffer *defaultbuf)
flush_tty();
if (!fork()) {
setup_child(FALSE, 0, UFfileno(&uf));
if (save2tmp(uf, tmpf->ptr) < 0)
exit(1);
UFclose(&uf);
myExec(command->ptr);
if (mc_stat & MCSTAT_REPNAME) {
if (save2tmp(uf, tmpf->ptr) < 0)
exit(1);
UFclose(&uf);
myExec(command->ptr);
}
else {
/* no file name needed; we can pipe directly */
if (!(ff = popen(command->ptr, "w")))
exit(1);
err = save2file(uf, ff);
pclose(ff);
/* we are in a child process, we can close uf. */
UFclose(&uf);
exit(-err); /* exit child process */
}
}
if (needs_halfclose)
*needs_halfclose = TRUE;
return NO_BUFFER;
}
else
#endif
{
if (save2tmp(uf, tmpf->ptr) < 0) {
return NULL;
if ((mc_stat & MCSTAT_REPNAME) ||
(mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT))) {
if (save2tmp(uf, tmpf->ptr) < 0) {
return NULL;
}
}
}
if (mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT)) {
Expand Down Expand Up @@ -8332,16 +8368,30 @@ doExternal(URLFile uf, char *type, Buffer *defaultbuf)
}
}
else {
if (mcap->flags & MAILCAP_NEEDSTERMINAL || !BackgroundExtViewer) {
background = !(mcap->flags & MAILCAP_NEEDSTERMINAL) &&
BackgroundExtViewer;
if (!background)
fmTerm();
mySystem(command->ptr, 0);
if (mc_stat & MCSTAT_REPNAME) {
/* saved already */
mySystem(command->ptr, background);
}
else {
/* either:
* foreground, so we can save2file directly.
* OR background but no setpgrp, in which case we can't do better.
*/
if (!(ff = popen(command->ptr, "w")))
return NULL;
err = save2file(uf, ff);
pclose(ff);
/* do *not* close uf, it will be closed later. */
}
if (!background) {
fmInit();
if (CurrentTab && Currentbuf)
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
else {
mySystem(command->ptr, 1);
}
buf = NO_BUFFER;
}
if (buf && buf != NO_BUFFER) {
Expand All @@ -8351,6 +8401,8 @@ doExternal(URLFile uf, char *type, Buffer *defaultbuf)
buf->edit = mcap->edit;
buf->mailcap = mcap;
}
if (needs_halfclose)
*needs_halfclose = FALSE;
return buf;
}

Expand Down
3 changes: 2 additions & 1 deletion proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ extern Buffer *openPagerBuffer(InputStream stream, Buffer *buf);
extern Buffer *openGeneralPagerBuffer(InputStream stream);
extern Line *getNextPage(Buffer *buf, int plen);
extern int save2tmp(URLFile uf, char *tmpf);
extern Buffer *doExternal(URLFile uf, char *type, Buffer *defaultbuf);
extern Buffer *doExternal(URLFile uf, char *type, Buffer *defaultbuf,
int *needs_halfclose);
extern int _doFileCopy(char *tmpf, char *defstr, int download);
#define doFileCopy(tmpf, defstr) _doFileCopy(tmpf, defstr, FALSE);
extern int doFileMove(char *tmpf, char *defstr);
Expand Down