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:
M | ChangeLog | | | 39 | +++++++++++++++++++++++++++++++++++++++ |
M | file.c | | | 82 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
M | fm.h | | | 14 | ++++++++++++++ |
M | form.c | | | 1 | + |
M | funcname.tab | | | 1 | + |
M | html.h | | | 1 | + |
M | main.c | | | 255 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
M | proto.h | | | 11 | ++++++++++- |
M | url.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 --> %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);