diff options
| -rw-r--r-- | config.h.in | 4 | ||||
| -rw-r--r-- | file.c | 58 | ||||
| -rw-r--r-- | fm.h | 6 | ||||
| -rw-r--r-- | html.h | 7 | ||||
| -rw-r--r-- | image.c | 33 | ||||
| -rw-r--r-- | indep.c | 105 | ||||
| -rw-r--r-- | indep.h | 23 | ||||
| -rw-r--r-- | istream.c | 234 | ||||
| -rw-r--r-- | istream.h | 13 | ||||
| -rw-r--r-- | local.c | 19 | ||||
| -rw-r--r-- | main.c | 44 | ||||
| -rw-r--r-- | mimehead.c | 61 | ||||
| -rw-r--r-- | proto.h | 5 | 
13 files changed, 436 insertions, 176 deletions
| diff --git a/config.h.in b/config.h.in index 59997b4..a4110ea 100644 --- a/config.h.in +++ b/config.h.in @@ -210,6 +210,10 @@ typedef RETSIGTYPE MySignalHandler;  #define SUPPORT_WIN9X_CONSOLE_MBCS 1  #endif +#if defined(__CYGWIN__) && defined(__x86_64__) +#define DONT_CALL_GC_AFTER_FORK +#endif +  #if defined(__DJGPP__)  #define DEFAULT_TERM	"dosansi"  #else @@ -677,6 +677,7 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)  #endif  		    init_stream(&f, SCM_LOCAL, newStrStream(src));  		    loadHTMLstream(&f, newBuf, NULL, TRUE); +		    UFclose(&f);  		    for (l = newBuf->lastLine; l && l->real_linenumber;  			 l = l->prev)  			l->real_linenumber = 0; @@ -7238,16 +7239,17 @@ loadHTMLString(Str page)      MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;      Buffer *newBuf; +    init_stream(&f, SCM_LOCAL, newStrStream(page)); +      newBuf = newBuffer(INIT_BUFFER_WIDTH);      if (SETJMP(AbortLoading) != 0) {  	TRAP_OFF;  	discardBuffer(newBuf); +	UFclose(&f);  	return NULL;      }      TRAP_ON; -    init_stream(&f, SCM_LOCAL, newStrStream(page)); -  #ifdef USE_M17N      newBuf->document_charset = InnerCharset;  #endif @@ -7257,6 +7259,7 @@ loadHTMLString(Str page)  #endif      TRAP_OFF; +    UFclose(&f);      newBuf->topLine = newBuf->firstLine;      newBuf->lastLine = newBuf->currentLine;      newBuf->currentLine = newBuf->firstLine; @@ -7486,15 +7489,13 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)  	!stat(cache->file, &st))  	goto image_buffer; -    TRAP_ON;      if (IStype(uf->stream) != IST_ENCODED)  	uf->stream = newEncodedStream(uf->stream, uf->encoding); +    TRAP_ON;      if (save2tmp(*uf, cache->file) < 0) { -	UFclose(uf);  	TRAP_OFF;  	return NULL;      } -    UFclose(uf);      TRAP_OFF;      cache->loaded = IMG_FLAG_LOADED; @@ -7514,6 +7515,7 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)      init_stream(&f, SCM_LOCAL, newStrStream(tmp));      loadHTMLstream(&f, newBuf, src, TRUE); +    UFclose(&f);      if (src)  	fclose(src); @@ -7909,6 +7911,8 @@ save2tmp(URLFile uf, char *tmpf)      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) { @@ -7945,25 +7949,25 @@ save2tmp(URLFile uf, char *tmpf)      else  #endif				/* USE_NNTP */      { -	Str buf = Strnew_size(SAVE_BUF_SIZE); -	while (UFread(&uf, buf, SAVE_BUF_SIZE)) { -	    if (Strfputs(buf, ff) != buf->length) { -		bcopy(env_bak, AbortLoading, sizeof(JMP_BUF)); -		TRAP_OFF; -		fclose(ff); -		current_content_length = 0; -		return -2; +	int count; + +	buf = NewWithoutGC_N(char, SAVE_BUF_SIZE); +	while ((count = ISread_n(uf.stream, buf, SAVE_BUF_SIZE)) > 0) { +	    if (fwrite(buf, 1, count, ff) != count) { +		retval = -2; +		goto _end;  	    } -	    linelen += buf->length; +	    linelen += count;  	    showProgress(&linelen, &trbyte);  	}      }    _end:      bcopy(env_bak, AbortLoading, sizeof(JMP_BUF));      TRAP_OFF; +    xfree(buf);      fclose(ff);      current_content_length = 0; -    return 0; +    return retval;  }  Buffer * @@ -8074,7 +8078,8 @@ _MoveFile(char *path1, char *path2)      FILE *f2;      int is_pipe;      clen_t linelen = 0, trbyte = 0; -    Str buf; +    char *buf = NULL; +    int count;      f1 = openIS(path1);      if (f1 == NULL) @@ -8092,12 +8097,13 @@ _MoveFile(char *path1, char *path2)  	return -1;      }      current_content_length = 0; -    buf = Strnew_size(SAVE_BUF_SIZE); -    while (ISread(f1, buf, SAVE_BUF_SIZE)) { -	Strfputs(buf, f2); -	linelen += buf->length; +    buf = NewWithoutGC_N(char, SAVE_BUF_SIZE); +    while ((count = ISread_n(f1, buf, SAVE_BUF_SIZE)) > 0) { +	fwrite(buf, 1, count, f2); +	linelen += count;  	showProgress(&linelen, &trbyte);      } +    xfree(buf);      ISclose(f1);      if (is_pipe)  	pclose(f2); @@ -8456,21 +8462,23 @@ uncompress_stream(URLFile *uf, char **src)  	}  	if (pid2 == 0) {  	    /* child2 */ -	    Str buf = Strnew_size(SAVE_BUF_SIZE); +	    char *buf = NewWithoutGC_N(char, SAVE_BUF_SIZE); +	    int count;  	    FILE *f = NULL;  	    setup_child(TRUE, 2, UFfileno(uf));  	    if (tmpf)  		f = fopen(tmpf, "wb"); -	    while (UFread(uf, buf, SAVE_BUF_SIZE)) { -		if (Strfputs(buf, stdout) < 0) +	    while ((count = ISread_n(uf->stream, buf, SAVE_BUF_SIZE)) > 0) { +		if (fwrite(buf, 1, count, stdout) != count) +		    break; +		if (f && fwrite(buf, 1, count, f) != count)  		    break; -		if (f) -		    Strfputs(buf, f);  	    }  	    UFclose(uf);  	    if (f)  		fclose(f); +	    xfree(buf);  	    exit(0);  	}  	/* child1 */ @@ -76,6 +76,7 @@ typedef int wc_ces;	/* XXX: not used */  #include "textlist.h"  #include "funcname1.h"  #include "terms.h" +#include "istream.h"  #ifndef HAVE_BCOPY  void bcopy(const void *, void *, int); @@ -288,8 +289,6 @@ extern int REV_LB[];  #define inputFilenameHist(p,d,h)	inputLineHist(p,d,IN_FILENAME,h)  #define inputChar(p)		inputLine(p,"",IN_CHAR) -#define free(x)  GC_free(x)	/* let GC do it. */ -  #ifdef __EMX__  #define HAVE_STRCASECMP  #define strcasecmp	stricmp @@ -895,6 +894,9 @@ global char *index_file init(NULL);  global char *CurrentDir;  global int CurrentPid; +#if defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) +global char *MyProgramName init("w3m"); +#endif /* defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) */  /*   * global Buffer *Currentbuf;   * global Buffer *Firstbuf; @@ -1,19 +1,17 @@  /* $Id: html.h,v 1.31 2010/08/14 01:29:40 htrb Exp $ */  #ifndef _HTML_H  #define _HTML_H +#include "config.h"  #ifdef USE_SSL  #include <openssl/bio.h>  #include <openssl/x509.h>  #include <openssl/ssl.h>  #endif				/* USE_SSL */ -#include "istream.h" -  #define StrUFgets(f) StrISgets((f)->stream)  #define StrmyUFgets(f) StrmyISgets((f)->stream)  #define UFgetc(f) ISgetc((f)->stream)  #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) @@ -62,11 +60,12 @@ typedef struct _ParsedURL {      int is_nocache;  } ParsedURL; +union input_stream;  typedef struct {      unsigned char scheme;      char is_cgi;      char encoding; -    InputStream stream; +    union input_stream *stream;      char *ext;      int compression;      int content_encoding; @@ -90,17 +90,18 @@ termImage()  static int  openImgdisplay()  { +    char *cmd; + +    if (!strchr(Imgdisplay, '/')) +	cmd = Strnew_m_charp(w3m_auxbin_dir(), "/", Imgdisplay, NULL)->ptr; +    else +	cmd = Imgdisplay;      Imgdisplay_pid = open_pipe_rw(&Imgdisplay_rf, &Imgdisplay_wf);      if (Imgdisplay_pid < 0)  	goto err0;      if (Imgdisplay_pid == 0) {  	/* child */ -	char *cmd;  	setup_child(FALSE, 2, -1); -	if (!strchr(Imgdisplay, '/')) -	    cmd = Strnew_m_charp(w3m_auxbin_dir(), "/", Imgdisplay, NULL)->ptr; -	else -	    cmd = Imgdisplay;  	myExec(cmd);  	/* XXX: ifdef __EMX__, use start /f ? */      } @@ -333,6 +334,9 @@ loadImage(Buffer *buf, int flag)      struct stat st;      int i, draw = FALSE;      /* int wait_st; */ +#ifdef DONT_CALL_GC_AFTER_FORK +    char *loadargs[7]; +#endif      if (maxLoadImage > MAX_LOAD_IMAGE)  	maxLoadImage = MAX_LOAD_IMAGE; @@ -433,6 +437,24 @@ loadImage(Buffer *buf, int flag)  	image_cache[i] = cache;  	flush_tty(); +#ifdef DONT_CALL_GC_AFTER_FORK +	loadargs[0] = MyProgramName; +	loadargs[1] = "-$$getimage"; +	loadargs[2] = conv_to_system(cache->url); +	loadargs[3] = conv_to_system(parsedURL2Str(cache->current)->ptr); +	loadargs[4] = cache->file; +	loadargs[5] = cache->touch; +	loadargs[6] = NULL; +	if ((cache->pid = fork()) == 0) { +	    setup_child(FALSE, 0, -1); +	    execvp(MyProgramName, loadargs); +	    exit(1); +	} +	else if (cache->pid < 0) { +	    cache->pid = 0; +	    return; +	} +#else /* !DONT_CALL_GC_AFTER_FORK */  	if ((cache->pid = fork()) == 0) {  	    Buffer *b;  	    /* @@ -458,6 +480,7 @@ loadImage(Buffer *buf, int flag)  	    cache->pid = 0;  	    return;  	} +#endif /* !DONT_CALL_GC_AFTER_FORK */      }  } @@ -721,6 +721,111 @@ shell_quote(char *str)      return str;  } +void * +xrealloc(void *ptr, size_t size) +{ +    void *newptr = realloc(ptr, size); +    if (newptr == NULL) { +	fprintf(stderr, "Out of memory\n"); +	exit(-1); +    } +    return newptr; +} + +/* Define this as a separate function in case the free() has + * an incompatible prototype. */ +void +xfree(void *ptr) +{ +    free(ptr); +} + +void * +w3m_GC_realloc_atomic(void *ptr, size_t size) +{ +    return ptr ? GC_REALLOC(ptr, size) : GC_MALLOC_ATOMIC(size); +} + +void +w3m_GC_free(void *ptr) +{ +    GC_FREE(ptr); +} + +void +growbuf_init(struct growbuf *gb) +{ +    gb->ptr = NULL; +    gb->length = 0; +    gb->area_size = 0; +    gb->realloc_proc = &w3m_GC_realloc_atomic; +    gb->free_proc = &w3m_GC_free; +} + +void +growbuf_init_without_GC(struct growbuf *gb) +{ +    gb->ptr = NULL; +    gb->length = 0; +    gb->area_size = 0; +    gb->realloc_proc = &xrealloc; +    gb->free_proc = &xfree; +} + +void +growbuf_clear(struct growbuf *gb) +{ +    (*gb->free_proc) (gb->ptr); +    gb->ptr = NULL; +    gb->length = 0; +    gb->area_size = 0; +} + +Str +growbuf_to_Str(struct growbuf *gb) +{ +    Str s; + +    if (gb->free_proc == &w3m_GC_free) { +	growbuf_reserve(gb, gb->length + 1); +	gb->ptr[gb->length] = '\0'; +	s = New(struct _Str); +	s->ptr = gb->ptr; +	s->length = gb->length; +	s->area_size = gb->area_size; +    } else { +	s = Strnew_charp_n(gb->ptr, gb->length); +	(*gb->free_proc) (gb->ptr); +    } +    gb->ptr = NULL; +    gb->length = 0; +    gb->area_size = 0; +    return s; +} + +void +growbuf_reserve(struct growbuf *gb, int leastarea) +{ +    int newarea; + +    if (gb->area_size < leastarea) { +	newarea = gb->area_size * 3 / 2; +	if (newarea < leastarea) +	    newarea = leastarea; +	newarea += 16; +	gb->ptr = (*gb->realloc_proc) (gb->ptr, newarea); +	gb->area_size = newarea; +    } +} + +void +growbuf_append(struct growbuf *gb, const char *src, int len) +{ +    growbuf_reserve(gb, gb->length + len); +    memcpy(&gb->ptr[gb->length], src, len); +    gb->length += len; +} +  static char *  w3m_dir(const char *name, char *dft)  { @@ -12,6 +12,14 @@  #define FALSE 0  #endif				/* FALSE */ +struct growbuf { +    char *ptr; +    int length; +    int area_size; +    void *(*realloc_proc) (void *, size_t); +    void (*free_proc) (void *); +}; +  #define RAW_MODE	0  #define PAGER_MODE	1  #define HTML_MODE	2 @@ -65,6 +73,18 @@ extern Str Str_url_unquote(Str x, int is_form, int safe);  extern Str Str_form_quote(Str x);  #define Str_form_unquote(x) Str_url_unquote((x), TRUE, FALSE)  extern char *shell_quote(char *str); +#define xmalloc(s) xrealloc(NULL, s) +extern void *xrealloc(void *ptr, size_t size); +extern void xfree(void *ptr); +extern void *w3m_GC_realloc_atomic(void *ptr, size_t size); +extern void w3m_GC_free(void *ptr); +extern void growbuf_init(struct growbuf *gb); +extern void growbuf_init_without_GC(struct growbuf *gb); +extern void growbuf_clear(struct growbuf *gb); +extern Str growbuf_to_Str(struct growbuf *gb); +extern void growbuf_reserve(struct growbuf *gb, int leastarea); +extern void growbuf_append(struct growbuf *gb, const char *src, int len); +#define GROWBUF_ADD_CHAR(gb,ch) ((((gb)->length>=(gb)->area_size)?growbuf_reserve(gb,(gb)->length+1):(void)0),(void)((gb)->ptr[(gb)->length++] = (ch)))  extern char *w3m_auxbin_dir();  extern char *w3m_lib_dir(); @@ -77,5 +97,8 @@ extern char *w3m_help_dir();  #define New_N(type,n)	((type*)GC_MALLOC((n)*sizeof(type)))  #define NewAtom_N(type,n)	((type*)GC_MALLOC_ATOMIC((n)*sizeof(type)))  #define New_Reuse(type,ptr,n)   ((type*)GC_REALLOC((ptr),(n)*sizeof(type))) +#define NewWithoutGC(type)	((type*)xmalloc(sizeof(type))) +#define NewWithoutGC_N(type,n)	((type*)xmalloc((n)*sizeof(type))) +#define NewWithoutGC_Reuse(type,ptr,n)	((type*)xrealloc(ptr,(n)*sizeof(type)))  #endif				/* INDEP_H */ @@ -35,12 +35,14 @@ static int ssl_read(struct ssl_handle *handle, char *buf, int len);  static int ens_read(struct ens_handle *handle, char *buf, int len);  static void ens_close(struct ens_handle *handle); +static void memchop(char *p, int *len); +  static void  do_update(BaseStream base)  {      int len;      base->stream.cur = base->stream.next = 0; -    len = base->read(base->handle, base->stream.buf, base->stream.size); +    len = (*base->read) (base->handle, base->stream.buf, base->stream.size);      if (len <= 0)  	base->iseos = TRUE;      else @@ -66,12 +68,12 @@ init_buffer(BaseStream base, char *buf, int bufsize)      StreamBuffer sb = &base->stream;      sb->size = bufsize;      sb->cur = 0; +    sb->buf = NewWithoutGC_N(uchar, bufsize);      if (buf) { -	sb->buf = (uchar *) buf; +	memcpy(sb->buf, buf, bufsize);  	sb->next = bufsize;      }      else { -	sb->buf = NewAtom_N(uchar, bufsize);  	sb->next = 0;      }      base->iseos = FALSE; @@ -95,10 +97,10 @@ newInputStream(int des)      InputStream stream;      if (des < 0)  	return NULL; -    stream = New(union input_stream); +    stream = NewWithoutGC(union input_stream);      init_base_stream(&stream->base, STREAM_BUF_SIZE);      stream->base.type = IST_BASIC; -    stream->base.handle = New(int); +    stream->base.handle = NewWithoutGC(int);      *(int *)stream->base.handle = des;      stream->base.read = (int (*)())basic_read;      stream->base.close = (void (*)())basic_close; @@ -111,10 +113,10 @@ newFileStream(FILE * f, void (*closep) ())      InputStream stream;      if (f == NULL)  	return NULL; -    stream = New(union input_stream); +    stream = NewWithoutGC(union input_stream);      init_base_stream(&stream->base, STREAM_BUF_SIZE);      stream->file.type = IST_FILE; -    stream->file.handle = New(struct io_file_handle); +    stream->file.handle = NewWithoutGC(struct io_file_handle);      stream->file.handle->f = f;      if (closep)  	stream->file.handle->close = closep; @@ -131,10 +133,10 @@ newStrStream(Str s)      InputStream stream;      if (s == NULL)  	return NULL; -    stream = New(union input_stream); +    stream = NewWithoutGC(union input_stream);      init_str_stream(&stream->base, s);      stream->str.type = IST_STR; -    stream->str.handle = s; +    stream->str.handle = NULL;      stream->str.read = (int (*)())str_read;      stream->str.close = NULL;      return stream; @@ -147,10 +149,10 @@ newSSLStream(SSL * ssl, int sock)      InputStream stream;      if (sock < 0)  	return NULL; -    stream = New(union input_stream); +    stream = NewWithoutGC(union input_stream);      init_base_stream(&stream->base, SSL_BUF_SIZE);      stream->ssl.type = IST_SSL; -    stream->ssl.handle = New(struct ssl_handle); +    stream->ssl.handle = NewWithoutGC(struct ssl_handle);      stream->ssl.handle->ssl = ssl;      stream->ssl.handle->sock = sock;      stream->ssl.read = (int (*)())ssl_read; @@ -166,14 +168,14 @@ newEncodedStream(InputStream is, char encoding)      if (is == NULL || (encoding != ENC_QUOTE && encoding != ENC_BASE64 &&  		       encoding != ENC_UUENCODE))  	return is; -    stream = New(union input_stream); +    stream = NewWithoutGC(union input_stream);      init_base_stream(&stream->base, STREAM_BUF_SIZE);      stream->ens.type = IST_ENCODED; -    stream->ens.handle = New(struct ens_handle); +    stream->ens.handle = NewWithoutGC(struct ens_handle);      stream->ens.handle->is = is;      stream->ens.handle->pos = 0;      stream->ens.handle->encoding = encoding; -    stream->ens.handle->s = NULL; +    growbuf_init_without_GC(&stream->ens.handle->gb);      stream->ens.read = (int (*)())ens_read;      stream->ens.close = (void (*)())ens_close;      return stream; @@ -187,8 +189,10 @@ ISclose(InputStream stream)  	stream->base.type & IST_UNCLOSE)  	return -1;      prevtrap = mySignal(SIGINT, SIG_IGN); -    stream->base.close(stream->base.handle); +    stream->base.close (stream->base.handle);      mySignal(SIGINT, prevtrap); +    xfree(stream->base.stream.buf); +    xfree(stream);      return 0;  } @@ -218,122 +222,97 @@ ISundogetc(InputStream stream)      return -1;  } -#define MARGIN_STR_SIZE 10  Str -StrISgets(InputStream stream) +StrISgets2(InputStream stream, char crnl)  { -    BaseStream base; -    StreamBuffer sb; -    Str s = NULL; -    uchar *p; -    int len; +    struct growbuf gb;      if (stream == NULL) -	return '\0'; -    base = &stream->base; -    sb = &base->stream; - -    while (!base->iseos) { -	if (MUST_BE_UPDATED(base)) { -	    do_update(base); -	} -	else { -	    if ((p = memchr(&sb->buf[sb->cur], '\n', sb->next - sb->cur))) { -		len = p - &sb->buf[sb->cur] + 1; -		if (s == NULL) -		    s = Strnew_size(len); -		Strcat_charp_n(s, (char *)&sb->buf[sb->cur], len); -		sb->cur += len; -		return s; -	    } -	    else { -		if (s == NULL) -		    s = Strnew_size(sb->next - sb->cur + MARGIN_STR_SIZE); -		Strcat_charp_n(s, (char *)&sb->buf[sb->cur], -			       sb->next - sb->cur); -		sb->cur = sb->next; -	    } -	} -    } - -    if (s == NULL) -	return Strnew(); -    return s; +	return NULL; +    growbuf_init(&gb); +    ISgets_to_growbuf(stream, &gb, crnl); +    return growbuf_to_Str(&gb);  } -Str -StrmyISgets(InputStream stream) +void +ISgets_to_growbuf(InputStream stream, struct growbuf *gb, char crnl)  { -    BaseStream base; -    StreamBuffer sb; -    Str s = NULL; -    int i, len; +    BaseStream base = &stream->base; +    StreamBuffer sb = &base->stream; +    int i; -    if (stream == NULL) -	return '\0'; -    base = &stream->base; -    sb = &base->stream; +    gb->length = 0;      while (!base->iseos) {  	if (MUST_BE_UPDATED(base)) {  	    do_update(base); +	    continue;  	} -	else { -	    if (s && Strlastchar(s) == '\r') { -		if (sb->buf[sb->cur] == '\n') -		    Strcat_char(s, (char)sb->buf[sb->cur++]); -		return s; +	if (crnl && gb->length > 0  && gb->ptr[gb->length - 1] == '\r') { +	    if (sb->buf[sb->cur] == '\n') { +		GROWBUF_ADD_CHAR(gb, '\n'); +		++sb->cur;  	    } -	    for (i = sb->cur; -		 i < sb->next && sb->buf[i] != '\n' && sb->buf[i] != '\r'; -		 i++) ; -	    if (i < sb->next) { -		len = i - sb->cur + 1; -		if (s == NULL) -		    s = Strnew_size(len + MARGIN_STR_SIZE); -		Strcat_charp_n(s, (char *)&sb->buf[sb->cur], len); -		sb->cur = i + 1; -		if (sb->buf[i] == '\n') -		    return s; -	    } -	    else { -		if (s == NULL) -		    s = Strnew_size(sb->next - sb->cur + MARGIN_STR_SIZE); -		Strcat_charp_n(s, (char *)&sb->buf[sb->cur], -			       sb->next - sb->cur); -		sb->cur = sb->next; +	    break; +	} +	for (i = sb->cur; i < sb->next; ++i) { +	    if (sb->buf[i] == '\n' || (crnl && sb->buf[i] == '\r')) { +		++i; +		break;  	    }  	} +	growbuf_append(gb, &sb->buf[sb->cur], i - sb->cur); +	sb->cur = i; +	if (gb->length > 0 && gb->ptr[gb->length - 1] == '\n') +	    break;      } -    if (s == NULL) -	return Strnew(); -    return s; +    growbuf_reserve(gb, gb->length + 1); +    gb->ptr[gb->length] = '\0'; +    return;  } +#ifdef unused  int  ISread(InputStream stream, Str buf, int count)  { -    int rest, len; +    int len; + +    if (count + 1 > buf->area_size) { +	char *newptr = GC_MALLOC_ATOMIC(count + 1); +	memcpy(newptr, buf->ptr, buf->length); +	newptr[buf->length] = '\0'; +	buf->ptr = newptr; +	buf->area_size = count + 1; +    } +    len = ISread_n(stream, buf->ptr, count); +    buf->length = (len > 0) ? len : 0; +    buf->ptr[buf->length] = '\0'; +    return (len > 0) ? 1 : 0; +} +#endif + +int +ISread_n(InputStream stream, char *dst, int count) +{ +    int len, l;      BaseStream base; -    if (stream == NULL || (base = &stream->base)->iseos) +    if (stream == NULL || count <= 0) +	return -1; +    if ((base = &stream->base)->iseos)  	return 0; -    len = buffer_read(&base->stream, buf->ptr, count); -    rest = count - len; +    len = buffer_read(&base->stream, dst, count);      if (MUST_BE_UPDATED(base)) { -	len = base->read(base->handle, &buf->ptr[len], rest); -	if (len <= 0) { +	l = (*base->read) (base->handle, &dst[len], count - len); +	if (l <= 0) {  	    base->iseos = TRUE; -	    len = 0; +	} else { +	    len += l;  	} -	rest -= len;      } -    Strtruncate(buf, count - rest); -    if (buf->length > 0) -	return 1; -    return 0; +    return len;  }  int @@ -645,6 +624,7 @@ basic_close(int *handle)  #else      close(*(int *)handle);  #endif +    xfree(handle);  }  static int @@ -661,6 +641,7 @@ static void  file_close(struct io_file_handle *handle)  {      handle->close(handle->f); +    xfree(handle);  }  static int @@ -682,6 +663,7 @@ ssl_close(struct ssl_handle *handle)      close(handle->sock);      if (handle->ssl)  	SSL_free(handle->ssl); +    xfree(handle);  }  static int @@ -717,38 +699,60 @@ static void  ens_close(struct ens_handle *handle)  {      ISclose(handle->is); +    growbuf_clear(&handle->gb); +    xfree(handle);  }  static int  ens_read(struct ens_handle *handle, char *buf, int len)  { -    if (handle->s == NULL || handle->pos == handle->s->length) { +    if (handle->pos == handle->gb.length) {  	char *p; -	handle->s = StrmyISgets(handle->is); -	if (handle->s->length == 0) +	struct growbuf gbtmp; + +	ISgets_to_growbuf(handle->is, &handle->gb, TRUE); +	if (handle->gb.length == 0)  	    return 0; -	cleanup_line(handle->s, PAGER_MODE);  	if (handle->encoding == ENC_BASE64) -	    Strchop(handle->s); +	    memchop(handle->gb.ptr, &handle->gb.length);  	else if (handle->encoding == ENC_UUENCODE) { -	    if (!strncmp(handle->s->ptr, "begin", 5)) -		handle->s = StrmyISgets(handle->is); -	    Strchop(handle->s); +	    if (handle->gb.length >= 5 && +		!strncmp(handle->gb.ptr, "begin", 5)) +		ISgets_to_growbuf(handle->is, &handle->gb, TRUE); +	    memchop(handle->gb.ptr, &handle->gb.length);  	} -	p = handle->s->ptr; +	growbuf_init_without_GC(&gbtmp); +	p = handle->gb.ptr;  	if (handle->encoding == ENC_QUOTE) -	    handle->s = decodeQP(&p); +	    decodeQP_to_growbuf(&gbtmp, &p);  	else if (handle->encoding == ENC_BASE64) -	    handle->s = decodeB(&p); +	    decodeB_to_growbuf(&gbtmp, &p);  	else if (handle->encoding == ENC_UUENCODE) -	    handle->s = decodeU(&p); +	    decodeU_to_growbuf(&gbtmp, &p); +	growbuf_clear(&handle->gb); +	handle->gb = gbtmp;  	handle->pos = 0;      } -    if (len > handle->s->length - handle->pos) -	len = handle->s->length - handle->pos; +    if (len > handle->gb.length - handle->pos) +	len = handle->gb.length - handle->pos; -    bcopy(&handle->s->ptr[handle->pos], buf, len); +    memcpy(buf, &handle->gb.ptr[handle->pos], len);      handle->pos += len;      return len;  } + +static void +memchop(char *p, int *len) +{ +    char *q; + +    for (q = p + *len; q > p; --q) { +	if (q[-1] != '\n' && q[-1] != '\r') +	    break; +    } +    if (q != p + *len) +	*q = '\0'; +    *len = q - p; +    return; +} @@ -2,13 +2,13 @@  #ifndef IO_STREAM_H  #define IO_STREAM_H +#include "indep.h"  #include <stdio.h>  #ifdef USE_SSL  #include <openssl/bio.h>  #include <openssl/x509.h>  #include <openssl/ssl.h>  #endif -#include "Str.h"  #include <sys/types.h>  #include <sys/stat.h>  #include <fcntl.h> @@ -36,7 +36,7 @@ union input_stream;  struct ens_handle {      union input_stream *is; -    Str s; +    struct growbuf gb;      int pos;      char encoding;  }; @@ -119,9 +119,14 @@ extern InputStream newEncodedStream(InputStream is, char encoding);  extern int ISclose(InputStream stream);  extern int ISgetc(InputStream stream);  extern int ISundogetc(InputStream stream); -extern Str StrISgets(InputStream stream); -extern Str StrmyISgets(InputStream stream); +extern Str StrISgets2(InputStream stream, char crnl); +#define StrISgets(stream) StrISgets2(stream, FALSE) +#define StrmyISgets(stream) StrISgets2(stream, TRUE) +void ISgets_to_growbuf(InputStream stream, struct growbuf *gb, char crnl); +#ifdef unused  extern int ISread(InputStream stream, Str buf, int count); +#endif +int ISread_n(InputStream stream, char *dst, int bufsize);  extern int ISfileno(InputStream stream);  extern int ISeos(InputStream stream);  #ifdef USE_SSL @@ -359,6 +359,10 @@ localcgi_post(char *uri, char *qstr, FormList *request, char *referer)      int status;      pid_t pid;      char *file = uri, *name = uri, *path_info = NULL, *tmpf = NULL; +#ifdef HAVE_CHDIR +    char *cgi_dir; +#endif +    char *cgi_basename;  #ifdef __MINGW32_VERSION      return NULL; @@ -373,7 +377,14 @@ localcgi_post(char *uri, char *qstr, FormList *request, char *referer)  	if (!fw)  	    return NULL;      } +    if (qstr) +	uri = Strnew_m_charp(uri, "?", qstr, NULL)->ptr; +#ifdef HAVE_CHDIR +    cgi_dir = mydirname(file); +#endif +    cgi_basename = mybasename(file);      pid = open_pipe_rw(&fr, NULL); +    /* Don't invoke gc after here, or the program might crash in some platforms */      if (pid < 0)  	return NULL;      else if (pid) { @@ -383,8 +394,6 @@ localcgi_post(char *uri, char *qstr, FormList *request, char *referer)      }      setup_child(TRUE, 2, fw ? fileno(fw) : -1); -    if (qstr) -	uri = Strnew_m_charp(uri, "?", qstr, NULL)->ptr;      set_cgi_environ(name, file, uri);      if (path_info)  	set_environ("PATH_INFO", path_info); @@ -415,11 +424,11 @@ localcgi_post(char *uri, char *qstr, FormList *request, char *referer)      }  #ifdef HAVE_CHDIR		/* ifndef __EMX__ ? */ -    chdir(mydirname(file)); +    chdir(cgi_dir);  #endif -    execl(file, mybasename(file), NULL); +    execl(file, cgi_basename, NULL);      fprintf(stderr, "execl(\"%s\", \"%s\", NULL): %s\n", -	    file, mybasename(file), strerror(errno)); +	    file, cgi_basename, strerror(errno));      exit(1);      return NULL;  #endif @@ -11,6 +11,9 @@  #include <sys/wait.h>  #endif  #include <time.h> +#if defined(__CYGWIN__) && defined(USE_BINMODE_STREAM) +#include <io.h> +#endif  #include "terms.h"  #include "myctype.h"  #include "regex.h" @@ -407,6 +410,10 @@ main(int argc, char **argv, char **envp)      wc_ces CodePage;  #endif  #endif +#if defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) +    char **getimage_args = NULL; +#endif /* defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) */ +      GC_INIT();  #if defined(ENABLE_NLS) || (defined(USE_M17N) && defined(HAVE_LANGINFO_CODESET))      setlocale(LC_ALL, ""); @@ -428,6 +435,10 @@ main(int argc, char **argv, char **envp)      CurrentDir = currentdir();      CurrentPid = (int)getpid(); +#if defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) +    if (argv[0] && *argv[0]) +	MyProgramName = argv[0]; +#endif /* defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) */      BookmarkFile = NULL;      config_file = NULL; @@ -751,6 +762,15 @@ main(int argc, char **argv, char **envp)  	    else if (!strcmp("-reqlog",argv[i])) {  		w3m_reqlog=rcFile("request.log");  	    } +#if defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) +	    else if (!strcmp("-$$getimage", argv[i])) { +		++i; +		getimage_args = argv + i; +		i += 4; +		if (i > argc) +		    usage(); +	    } +#endif /* defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) */  	    else {  		usage();  	    } @@ -839,6 +859,30 @@ main(int argc, char **argv, char **envp)      if (w3m_backend)  	backend(); +#if defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) +    if (getimage_args) { +	char *image_url = conv_from_system(getimage_args[0]); +	char *base_url = conv_from_system(getimage_args[1]); +	ParsedURL base_pu; +	 +	parseURL2(base_url, &base_pu, NULL); +	image_source = getimage_args[2]; +	newbuf = loadGeneralFile(image_url, &base_pu, NULL, 0, NULL); +	if (!newbuf || !newbuf->real_type || +	    strncasecmp(newbuf->real_type, "image/", 6)) +	    unlink(getimage_args[2]); +#if defined(HAVE_SYMLINK) && defined(HAVE_LSTAT) +	symlink(getimage_args[2], getimage_args[3]); +#else +	{ +	    FILE *f = fopen(getimage_args[3], "w"); +	    if (f) +		fclose(f); +	} +#endif +	w3m_exit(0); +    } +#endif /* defined(DONT_CALL_GC_AFTER_FORK) && defined(USE_IMAGE) */      if (w3m_dump)  	mySignal(SIGINT, SIG_IGN); @@ -64,12 +64,22 @@ ha2d(char x, char y)  Str  decodeB(char **ww)  { +    struct growbuf gb; + +    growbuf_init(&gb); +    decodeB_to_growbuf(&gb, ww); +    return growbuf_to_Str(&gb); +} + +void +decodeB_to_growbuf(struct growbuf *gb, char **ww) +{      unsigned char c[4];      char *wp = *ww;      char d[3];      int i, n_pad; -    Str ap = Strnew_size(strlen(wp)); +    growbuf_reserve(gb, strlen(wp) + 1);      n_pad = 0;      while (1) {  	for (i = 0; i < 4; i++) { @@ -93,39 +103,50 @@ decodeB(char **ww)  	for (i = 0; i < 4; i++) {  	    c[i] = c2e(c[i]);  	    if (c[i] == BAD_BASE64) { -		*ww = wp; -		return ap; +		goto last;  	    }  	}  	d[0] = ((c[0] << 2) | (c[1] >> 4));  	d[1] = ((c[1] << 4) | (c[2] >> 2));  	d[2] = ((c[2] << 6) | c[3]);  	for (i = 0; i < 3 - n_pad; i++) { -	    Strcat_char(ap, d[i]); +	    GROWBUF_ADD_CHAR(gb, d[i]);  	}  	if (n_pad || *wp == '\0' || *wp == '?')  	    break;      } +last: +    growbuf_reserve(gb, gb->length + 1); +    gb->ptr[gb->length] = '\0';      *ww = wp; -    return ap; +    return;  }  Str  decodeU(char **ww)  { +    struct growbuf gb; + +    growbuf_init(&gb); +    decodeU_to_growbuf(&gb, ww); +    return growbuf_to_Str(&gb); +} + +void +decodeU_to_growbuf(struct growbuf *gb, char **ww) +{      unsigned char c1, c2;      char *w = *ww;      int n, i; -    Str a;      if (*w <= 0x20 || *w >= 0x60) -	return Strnew_size(0); +	return;      n = *w - 0x20; -    a = Strnew_size(n); +    growbuf_reserve(gb, n + 1);      for (w++, i = 2; *w != '\0' && n; n--) {  	c1 = (w[0] - 0x20) % 0x40;  	c2 = (w[1] - 0x20) % 0x40; -	Strcat_char(a, (c1 << i) | (c2 >> (6 - i))); +	gb->ptr[gb->length++] = (c1 << i) | (c2 >> (6 - i));  	if (i == 6) {  	    w += 2;  	    i = 2; @@ -135,7 +156,8 @@ decodeU(char **ww)  	    i += 2;  	}      } -    return a; +    gb->ptr[gb->length] = '\0'; +    return;  }  /* RFC2047 (4.2. The "Q" encoding) */ @@ -165,9 +187,19 @@ decodeQ(char **ww)  Str  decodeQP(char **ww)  { +    struct growbuf gb; + +    growbuf_init(&gb); +    decodeQP_to_growbuf(&gb, ww); +    return growbuf_to_Str(&gb); +} + +void +decodeQP_to_growbuf(struct growbuf *gb, char **ww) +{      char *w = *ww; -    Str a = Strnew_size(strlen(w)); +    growbuf_reserve(gb, strlen(w) + 1);      for (; *w != '\0'; w++) {  	if (*w == '=') {  	    w++; @@ -180,15 +212,16 @@ decodeQP(char **ww)  	    else {  		if (*w == '\0' || *(w + 1) == '\0')  		    break; -		Strcat_char(a, ha2d(*w, *(w + 1))); +		gb->ptr[gb->length++] = ha2d(*w, *(w + 1));  		w++;  	    }  	}  	else -	    Strcat_char(a, *w); +	    gb->ptr[gb->length++] = *w;      } +    gb->ptr[gb->length] = '\0';      *ww = w; -    return a; +    return;  }  #ifdef USE_M17N @@ -607,9 +607,12 @@ extern char *getAnchorText(Buffer *buf, AnchorList *al, Anchor *a);  extern Buffer *link_list_panel(Buffer *buf);  extern Str decodeB(char **ww); +extern void decodeB_to_growbuf(struct growbuf *gb, char **ww);  extern Str decodeQ(char **ww);  extern Str decodeQP(char **ww); +extern void decodeQP_to_growbuf(struct growbuf *gb, char **ww);  extern Str decodeU(char **ww); +extern void decodeU_to_growbuf(struct growbuf *gb, char **ww);  #ifdef USE_M17N  extern Str decodeWord(char **ow, wc_ces * charset);  extern Str decodeMIME(Str orgstr, wc_ces * charset); @@ -811,5 +814,3 @@ extern void dispVer(void);  void srand48(long);  long lrand48(void);  #endif - -#include "indep.h" | 
