w3m

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/w3m.git/
Log | Files | Refs | README

commit f88fec758a3124b1cb377fb5d3a6c07fdadb264e
parent 271978188f87f92e15b723a191d11440e4103005
Author: ukai <ukai>
Date:   Fri, 15 Nov 2002 15:19:43 +0000

[w3m-dev 03431] save file by background process
* file.c (loadGeneralFile): use _doFileCopy()
	(_doFileCopy): renamed from doFileCopy()
			lock
			fork & save
	(doFileSave): lock
			fork & save
* fm.h (DownloadList): added
	(FirstDL): added
	(LastDL): added
* form.c (struct internal_action): add download
* funcname.tab (DOWNLOAD_LIST): added
* html.h (URLFile): add url
* main.c (dump_extra): add add_download_list
	(main): add_download_list, ldDL()
	(_quitfm): added
	(quitfm): rewrite with _quitfm()
	(qquitfm): ditto
	(w3m_exit): stopDownload()
	(addDownloadList): added
	(checkDownloadList): added
	(convert_size3): added
	(DownloadListBuffer): added
	(download_action): added
	(stopDownload): added
	(ldDL): added
* proto.h (ldDL): added
	(convert_size): added
	(convert_size2): added
	(doFileCopy): deleted
	(_doFileCopy): added
	(addDownloadList): added
	(stopDownload): added
	(checkDownloadList): added
	(download_action): added
* url.c (openURL): save url in uf
From: Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>

Diffstat:
MChangeLog | 39+++++++++++++++++++++++++++++++++++++++
Mfile.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mfm.h | 14++++++++++++++
Mform.c | 1+
Mfuncname.tab | 1+
Mhtml.h | 1+
Mmain.c | 255++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mproto.h | 11++++++++++-
Murl.c | 1+
9 files changed, 383 insertions(+), 22 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,42 @@ +2002-11-16 Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp> + + * [w3m-dev 03431] save file by background process + * file.c (loadGeneralFile): use _doFileCopy() + (_doFileCopy): renamed from doFileCopy() + lock + fork & save + (doFileSave): lock + fork & save + * fm.h (DownloadList): added + (FirstDL): added + (LastDL): added + * form.c (struct internal_action): add download + * funcname.tab (DOWNLOAD_LIST): added + * html.h (URLFile): add url + * main.c (dump_extra): add add_download_list + (main): add_download_list, ldDL() + (_quitfm): added + (quitfm): rewrite with _quitfm() + (qquitfm): ditto + (w3m_exit): stopDownload() + (addDownloadList): added + (checkDownloadList): added + (convert_size3): added + (DownloadListBuffer): added + (download_action): added + (stopDownload): added + (ldDL): added + * proto.h (ldDL): added + (convert_size): added + (convert_size2): added + (doFileCopy): deleted + (_doFileCopy): added + (addDownloadList): added + (stopDownload): added + (checkDownloadList): added + (download_action): added + * url.c (openURL): save url in uf + 2002-11-15 Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp> * [w3m-dev 03430] disable display of alarm command diff --git a/file.c b/file.c @@ -1944,9 +1944,9 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, signal(SIGINT, prevtrap); if (pu.scheme == SCM_LOCAL) { UFclose(&f); - doFileCopy(pu.real_file, + _doFileCopy(pu.real_file, conv_from_system(guess_save_name - (NULL, pu.real_file))); + (NULL, pu.real_file)), TRUE); } else { if (DecodeCTE && IStype(f.stream) != IST_ENCODED) @@ -7178,11 +7178,18 @@ _MoveFile(char *path1, char *path2) } void -doFileCopy(char *tmpf, char *defstr) +_doFileCopy(char *tmpf, char *defstr, int download) { Str msg; Str filen; char *p, *q = NULL; + pid_t pid; + char *lock; +#if !(defined(HAVE_SYMLINK) && defined(HAVE_LSTAT)) + FILE *f; +#endif + struct stat st; + clen_t size = 0; if (fmInitialized) { p = searchKeyData(); @@ -7207,10 +7214,40 @@ doFileCopy(char *tmpf, char *defstr) disp_err_message(msg->ptr, FALSE); return; } - if (_MoveFile(tmpf, p) < 0) { - msg = Sprintf("Can't save to %s", p); - disp_err_message(msg->ptr, FALSE); + if (!download) { + if (_MoveFile(tmpf, p) < 0) { + msg = Sprintf("Can't save to %s", p); + disp_err_message(msg->ptr, FALSE); + } + return; } + lock = tmpfname(TMPF_DFL, ".lock")->ptr; +#if defined(HAVE_SYMLINK) && defined(HAVE_LSTAT) + symlink(p, lock); +#else + f = fopen(lock, "w"); + if (f) + fclose(f); +#endif + pushText(fileToDelete, lock); + flush_tty(); + pid = fork(); + if (!pid) { + reset_signals(); + signal(SIGINT, SIG_IGN); +#ifdef HAVE_SETPGRP + SETPGRP(); +#endif + close_tty(); + QuietMessage = TRUE; + fmInitialized = FALSE; + _MoveFile(tmpf, p); + unlink(lock); + exit(0); + } + if (!stat(tmpf, &st)) + size = st.st_size; + addDownloadList(pid, tmpf, p, lock, size); } else { q = searchKeyData(); @@ -7255,6 +7292,11 @@ doFileSave(URLFile uf, char *defstr) Str msg; Str filen; char *p, *q; + pid_t pid; + char *lock; +#if !(defined(HAVE_SYMLINK) && defined(HAVE_LSTAT)) + FILE *f; +#endif if (fmInitialized) { p = searchKeyData(); @@ -7272,10 +7314,38 @@ doFileSave(URLFile uf, char *defstr) disp_err_message(msg->ptr, FALSE); return; } +/* if (save2tmp(uf, p) < 0) { msg = Sprintf("Can't save to %s", p); disp_err_message(msg->ptr, FALSE); } +*/ + lock = tmpfname(TMPF_DFL, ".lock")->ptr; +#if defined(HAVE_SYMLINK) && defined(HAVE_LSTAT) + symlink(p, lock); +#else + f = fopen(lock, "w"); + if (f) + fclose(f); +#endif + pushText(fileToDelete, lock); + flush_tty(); + pid = fork(); + if (!pid) { + reset_signals(); + signal(SIGINT, SIG_IGN); +#ifdef HAVE_SETPGRP + SETPGRP(); +#endif + close_tty(); + QuietMessage = TRUE; + fmInitialized = FALSE; + save2tmp(uf, p); + UFclose(&uf); + unlink(lock); + exit(0); + } + addDownloadList(pid, uf.url, p, lock, current_content_length); } else { q = searchKeyData(); diff --git a/fm.h b/fm.h @@ -453,6 +453,18 @@ typedef struct _TabBuffer { Buffer *firstBuffer; } TabBuffer; +typedef struct _DownloadList { + pid_t pid; + char *url; + char *save; + char *lock; + clen_t size; + time_t time; + int ok; + struct _DownloadList *next; + struct _DownloadList *prev; +} DownloadList; + #define COPY_BUFPOSITION(dstbuf, srcbuf) {\ (dstbuf)->topLine = (srcbuf)->topLine; \ (dstbuf)->currentLine = (srcbuf)->currentLine; \ @@ -795,6 +807,8 @@ global int TabCols init(10); : (nTab - 1) / ((nTab * TabCols - 1) / (COLS - 2) + 1) + 1) #define Currentbuf (CurrentTab->currentBuffer) #define Firstbuf (CurrentTab->firstBuffer) +global DownloadList *FirstDL init(NULL); +global DownloadList *LastDL init(NULL); global int CurrentKey; global char *CurrentKeyData; global char *CurrentCmdData; diff --git a/form.c b/form.c @@ -31,6 +31,7 @@ struct { #ifdef USE_COOKIE {"cookie", set_cookie_flag}, #endif /* USE_COOKIE */ + {"download", download_action}, {"none", NULL}, {NULL, NULL}, }; diff --git a/funcname.tab b/funcname.tab @@ -20,6 +20,7 @@ DICT_WORD_AT dictwordat DISPLAY_IMAGE dispI DOWN ldown1 DOWNLOAD svSrc +DOWNLOAD_LIST ldDL EDIT editBf EDIT_SCREEN editScr END goLineL diff --git a/html.h b/html.h @@ -72,6 +72,7 @@ typedef struct { #ifdef USE_SSL char *ssl_certificate; #endif + char *url; } URLFile; #define CMP_NOCOMPRESS 0 diff --git a/main.c b/main.c @@ -85,6 +85,7 @@ static void dump_extra(Buffer *); int prec_num = 0; int prev_key = -1; int on_target = 1; +static int add_download_list = FALSE; void set_buffer_environ(Buffer *); @@ -1026,6 +1027,10 @@ main(int argc, char **argv, char **envp) set_buffer_environ(Currentbuf); keyPressEventProc((int)c); prec_num = 0; + if (add_download_list) { + add_download_list = FALSE; + ldDL(); + } } } prev_key = CurrentKey; @@ -2165,23 +2170,21 @@ movRW(void) displayBuffer(Currentbuf, B_NORMAL); } -/* Question and Quit */ -void -qquitfm(void) +static void +_quitfm(int confirm) { - char *ans; - if (!confirm_on_quit) - quitfm(); - ans = inputChar("Do you want to exit w3m? (y/n)"); - if (ans && tolower(*ans) == 'y') - quitfm(); - displayBuffer(Currentbuf, B_NORMAL); -} + char *ans = "y"; + + if (checkDownloadList()) + ans = inputChar("Download process retains. " + "Do you want to exit w3m? (y/n)"); + else if (confirm) + ans = inputChar("Do you want to exit w3m? (y/n)"); + if (!(ans && tolower(*ans) == 'y')) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } -/* Quit */ -void -quitfm(void) -{ term_title(""); /* XXX */ #ifdef USE_IMAGE if (activeImage) @@ -2198,6 +2201,20 @@ quitfm(void) w3m_exit(0); } +/* Quit */ +void +quitfm(void) +{ + _quitfm(FALSE); +} + +/* Question and Quit */ +void +qquitfm(void) +{ + _quitfm(confirm_on_quit); +} + /* Select buffer */ void selBuf(void) @@ -5158,6 +5175,7 @@ w3m_exit(int i) #ifdef USE_MIGEMO init_migemo(); /* close pipe to migemo */ #endif + stopDownload(); deleteFiles(); #ifdef USE_SSL free_ssl_ctx(); @@ -5683,3 +5701,210 @@ tabL(void) tab = tab->prevTab, i++) ; moveTab(CurrentTab, tab ? tab : FirstTab, FALSE); } + +void +addDownloadList(pid_t pid, char *url, char *save, char *lock, clen_t size) +{ + DownloadList *d; + + d = New(DownloadList); + d->pid = pid; + d->url = url; + if (save[0] != '/' && save[0] != '~') + save = Strnew_m_charp(CurrentDir, "/", save, NULL)->ptr; + d->save = expandName(save); + d->lock = lock; + d->size = size; + d->time = time(0); + d->ok = FALSE; + d->next = NULL; + d->prev = LastDL; + if (LastDL) + LastDL->next = d; + else + FirstDL = d; + LastDL = d; + add_download_list = TRUE; +} + +int +checkDownloadList(void) +{ + DownloadList *d; + struct stat st; + + if (!FirstDL) + return FALSE; + for (d = FirstDL; d != NULL; d = d->next) { +#ifdef HAVE_LSTAT + if (!d->ok && !lstat(d->lock, &st)) +#else + if (!d->ok && !stat(d->lock, &st)) +#endif + return TRUE; + } + return FALSE; +} + +static char * +convert_size3(clen_t size) +{ + Str tmp = Strnew(); + int n; + + do { + n = size % 1000; + size /= 1000; + tmp = Sprintf(size ? ",%.3d%s" : "%d%s", n, tmp->ptr); + } while (size); + return tmp->ptr; +} + +static Buffer * +DownloadListBuffer(void) +{ + DownloadList *d; + Str src = NULL; + struct stat st; + time_t cur_time; + int duration, rate, eta; + size_t size; + + if (!FirstDL) + return NULL; + cur_time = time(0); + src = Strnew_charp("<html><head><title>Download Panel</title></head>\ +<body><h1 align=center>Download Panel</h1>\ +<form method=internal action=download>\ +<input type=submit name=update value=Update><hr>\n"); + for (d = LastDL; d != NULL; d = d->prev) { +#ifdef HAVE_LSTAT + if (lstat(d->lock, &st)) +#else + if (stat(d->lock, &st)) +#endif + d->ok = TRUE; + Strcat_charp(src, "<pre>\n"); + Strcat(src, Sprintf("%s\n --&gt; %s\n ", html_quote(d->url), + html_quote(d->save))); + duration = cur_time - d->time; + if (!stat(d->save, &st)) { + size = st.st_size; + if (d->ok) { + d->size = size; + duration = st.st_mtime - d->time; + } + } + else + size = 0; + if (d->size) { + int i, l = COLS - 6; + if (size < d->size) + i = l * size / d->size; + else + i = l; + l -= i; + while (i-- > 0) + Strcat_char(src, '#'); + while (l-- > 0) + Strcat_char(src, '_'); + Strcat_char(src, '\n'); + } + if (!d->ok && size < d->size) + Strcat(src, Sprintf(" %s / %s bytes (%d%%)", + convert_size3(size), convert_size3(d->size), + (int)(100.0 * size / d->size))); + else + Strcat(src, Sprintf(" %s bytes loaded", convert_size3(size))); + if (duration > 0) { + rate = size / duration; + Strcat(src, Sprintf(" %02d:%02d:%02d rate %s/sec", + duration / (60 * 60), (duration / 60) % 60, + duration % 60, convert_size(rate, 1))); + if (!d->ok && size < d->size && rate) { + eta = (d->size - size) / rate; + Strcat(src, Sprintf(" eta %02d:%02d:%02d", eta / (60 * 60), + (eta / 60) % 60, eta % 60)); + } + } + Strcat_char(src, '\n'); + if (d->ok) { + Strcat(src, Sprintf("<input type=submit name=ok%d value=OK>", + d->pid)); + if (size < d->size) + Strcat_charp(src, " Download incompleted"); + else + Strcat_charp(src, " Download completed"); + } else + Strcat(src, Sprintf("<input type=submit name=stop%d value=STOP>", + d->pid)); + Strcat_charp(src, "\n</pre><hr>\n"); + } + Strcat_charp(src, "</form></body></html>"); + return loadHTMLString(src); +} + +void +download_action(struct parsed_tagarg *arg) +{ + DownloadList *d; + pid_t pid; + + for (; arg; arg = arg->next) { + if (!strcmp(arg->arg, "update")) + break; + else if (!strncmp(arg->arg, "stop", 4)) { + pid = (pid_t)atoi(&arg->arg[4]); + kill(pid, SIGKILL); + } + else if (!strncmp(arg->arg, "ok", 2)) + pid = (pid_t)atoi(&arg->arg[2]); + else + continue; + for (d = FirstDL; d; d = d->next) { + if (d->pid == pid) { + unlink(d->lock); + if (d->prev) + d->prev->next = d->next; + else + FirstDL = d->next; + if (d->next) + d->next->prev = d->prev; + else + LastDL = d->prev; + break; + } + } + } + if (FirstDL) { + ldDL(); + deletePrevBuf(); + } + else + backBf(); +} + +void +stopDownload(void) +{ + DownloadList *d; + + if (!FirstDL) + return; + for (d = FirstDL; d != NULL; d = d->next) { + if (d->ok) + continue; + kill(d->pid, SIGKILL); + unlink(d->lock); + } +} + +/* download panel */ +void +ldDL(void) +{ + if (!FirstDL) + return; + cmd_loadBuffer(DownloadListBuffer(), BP_NO_URL, LB_NOLINK); + nextA(); +} diff --git a/proto.h b/proto.h @@ -128,6 +128,7 @@ extern void tabURL(void); extern void tabrURL(void); extern void tabR(void); extern void tabL(void); +extern void ldDL(void); extern int currentLn(Buffer *buf); extern void tmpClearBuffer(Buffer *buf); @@ -185,6 +186,8 @@ extern void HTMLlineproc0(char *istr, struct html_feed_environ *h_env, int internal); #define HTMLlineproc1(x,y) HTMLlineproc0(x,y,TRUE) extern Buffer *loadHTMLBuffer(URLFile *f, Buffer *newBuf); +extern char *convert_size(clen_t size, int usefloat); +extern char *convert_size2(clen_t size1, clen_t size2, int usefloat); extern void showProgress(clen_t *linelen, clen_t *trbyte); extern void init_henv(struct html_feed_environ *, struct readbuffer *, struct environment *, int, TextLineList *, int, int); @@ -209,7 +212,8 @@ extern Line *getNextPage(Buffer *buf, int plen); extern int save2tmp(URLFile uf, char *tmpf); extern int doExternal(URLFile uf, char *path, char *type, Buffer **bufp, Buffer *defaultbuf); -extern void doFileCopy(char *tmpf, char *defstr); +extern void _doFileCopy(char *tmpf, char *defstr, int download); +#define doFileCopy(tmpf, defstr) _doFileCopy(tmpf, defstr, FALSE); extern void doFileMove(char *tmpf, char *defstr); extern void doFileSave(URLFile uf, char *defstr); extern int checkCopyFile(char *path1, char *path2); @@ -221,6 +225,11 @@ extern void readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu); extern char *checkHeader(Buffer *buf, char *field); extern TabBuffer *newTab(void); extern TabBuffer *deleteTab(TabBuffer *tab); +extern void addDownloadList(pid_t pid, char *url, char *save, char *lock, + clen_t size); +extern void stopDownload(void); +extern int checkDownloadList(void); +extern void download_action(struct parsed_tagarg *arg); extern Buffer *newBuffer(int width); extern Buffer *nullBuffer(void); extern void clearBuffer(Buffer *buf); diff --git a/url.c b/url.c @@ -1476,6 +1476,7 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current, } uf.scheme = pu->scheme; + uf.url = parsedURL2Str(pu)->ptr; pu->is_nocache = (option->flag & RG_NOCACHE); uf.ext = filename_extension(pu->file, 1);