diff -u -r -N irssi-0.8.5-org/src/core/commands.c irssi-0.8.5-mod/src/core/commands.c --- irssi-0.8.5-org/src/core/commands.c Wed Feb 13 16:10:09 2002 +++ irssi-0.8.5-mod/src/core/commands.c Sun Oct 20 19:30:17 2002 @@ -472,7 +472,7 @@ return pos; } -static char *cmd_get_quoted_param(char **data) +char *cmd_get_quoted_param(char **data) { char *pos, quote; diff -u -r -N irssi-0.8.5-org/src/core/commands.h irssi-0.8.5-mod/src/core/commands.h --- irssi-0.8.5-org/src/core/commands.h Wed Feb 13 16:10:09 2002 +++ irssi-0.8.5-mod/src/core/commands.h Sun Oct 20 19:30:17 2002 @@ -139,6 +139,7 @@ #define PARAM_FLAG_OPTCHAN_NAME (0x00020000|PARAM_FLAG_OPTCHAN) char *cmd_get_param(char **data); +char *cmd_get_quoted_param(char **data); /* get parameters from command - you should point free_me somewhere and cmd_params_free() it after you don't use any of the parameters anymore. diff -u -r -N irssi-0.8.5-org/src/irc/dcc/Makefile.am irssi-0.8.5-mod/src/irc/dcc/Makefile.am --- irssi-0.8.5-org/src/irc/dcc/Makefile.am Mon Nov 5 17:10:13 2001 +++ irssi-0.8.5-mod/src/irc/dcc/Makefile.am Sun Oct 20 19:25:48 2002 @@ -12,7 +12,8 @@ dcc-get.c \ dcc-send.c \ dcc-resume.c \ - dcc-autoget.c + dcc-autoget.c \ + dcc-queue.c noinst_HEADERS = \ dcc-rec.h \ @@ -22,4 +23,5 @@ dcc-chat.h \ dcc-get.h \ dcc-send.h \ + dcc-queue.h \ module.h diff -u -r -N irssi-0.8.5-org/src/irc/dcc/Makefile.in irssi-0.8.5-mod/src/irc/dcc/Makefile.in --- irssi-0.8.5-org/src/irc/dcc/Makefile.in Wed Jun 19 20:09:58 2002 +++ irssi-0.8.5-mod/src/irc/dcc/Makefile.in Sun Oct 20 20:14:08 2002 @@ -1,4 +1,4 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation @@ -111,10 +111,10 @@ INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/core/ -I$(top_srcdir)/src/irc/core/ $(GLIB_CFLAGS) -libirc_dcc_a_SOURCES = dcc.c dcc-chat.c dcc-get.c dcc-send.c dcc-resume.c dcc-autoget.c +libirc_dcc_a_SOURCES = dcc.c dcc-chat.c dcc-get.c dcc-send.c dcc-resume.c dcc-autoget.c dcc-queue.c -noinst_HEADERS = dcc-rec.h dcc-file-rec.h dcc.h dcc-file.h dcc-chat.h dcc-get.h dcc-send.h module.h +noinst_HEADERS = dcc-rec.h dcc-file-rec.h dcc.h dcc-file.h dcc-chat.h dcc-get.h dcc-send.h dcc-queue.h module.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../../../config.h @@ -129,7 +129,7 @@ libirc_dcc_a_LIBADD = libirc_dcc_a_OBJECTS = dcc.$(OBJEXT) dcc-chat.$(OBJEXT) \ dcc-get.$(OBJEXT) dcc-send.$(OBJEXT) dcc-resume.$(OBJEXT) \ -dcc-autoget.$(OBJEXT) +dcc-autoget.$(OBJEXT) dcc-queue.$(OBJEXT) AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -143,8 +143,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = tar +TAR = gtar GZIP_ENV = --best +DEP_FILES = .deps/dcc-autoget.P .deps/dcc-chat.P .deps/dcc-get.P \ +.deps/dcc-queue.P .deps/dcc-resume.P .deps/dcc-send.P .deps/dcc.P SOURCES = $(libirc_dcc_a_SOURCES) OBJECTS = $(libirc_dcc_a_OBJECTS) @@ -152,9 +154,9 @@ .SUFFIXES: .SUFFIXES: .S .c .lo .o .obj .s $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/irc/dcc/Makefile + cd $(top_srcdir) && $(AUTOMAKE) --gnu src/irc/dcc/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status @@ -168,9 +170,6 @@ maintainer-clean-noinstLIBRARIES: -.c.o: - $(COMPILE) -c $< - # FIXME: We should only use cygpath when building on Windows, # and only if it is available. .c.obj: @@ -193,9 +192,6 @@ maintainer-clean-compile: -.c.lo: - $(LIBTOOL) --mode=compile $(COMPILE) -c $< - .s.lo: $(LIBTOOL) --mode=compile $(COMPILE) -c $< @@ -251,6 +247,11 @@ subdir = src/irc/dcc distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/irc/dcc/Makefile @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ @@ -261,71 +262,38 @@ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done -dcc-autoget.o: dcc-autoget.c module.h ../../../src/common.h \ - ../../../config.h ../../../src/irc/core/irc.h \ - ../../../src/core/commands.h ../../../src/core/signals.h \ - ../../../src/core/masks.h ../../../src/core/settings.h \ - ../../../src/core/servers.h ../../../src/core/modules.h \ - ../../../src/core/server-connect-rec.h \ - ../../../src/core/server-rec.h dcc-get.h dcc.h \ - ../../../src/core/network.h dcc-rec.h dcc-file-rec.h -dcc-chat.o: dcc-chat.c module.h ../../../src/common.h ../../../config.h \ - ../../../src/irc/core/irc.h ../../../src/core/commands.h \ - ../../../src/core/signals.h ../../../src/core/network.h \ - ../../../src/core/net-nonblock.h \ - ../../../src/core/net-sendbuffer.h \ - ../../../src/core/line-split.h ../../../src/core/misc.h \ - ../../../src/core/settings.h \ - ../../../src/irc/core/irc-servers.h \ - ../../../src/core/chat-protocols.h ../../../src/core/servers.h \ - ../../../src/core/modules.h \ - ../../../src/core/server-connect-rec.h \ - ../../../src/core/server-rec.h \ - ../../../src/irc/core/irc-queries.h ../../../src/core/queries.h \ - ../../../src/core/query-rec.h \ - ../../../src/core/window-item-rec.h ../../../src/core/masks.h \ - dcc-chat.h dcc.h dcc-rec.h -dcc-get.o: dcc-get.c module.h ../../../src/common.h ../../../config.h \ - ../../../src/irc/core/irc.h ../../../src/core/commands.h \ - ../../../src/core/signals.h ../../../src/core/network.h \ - ../../../src/core/misc.h ../../../src/core/settings.h \ - ../../../src/irc/core/irc-servers.h \ - ../../../src/core/chat-protocols.h ../../../src/core/servers.h \ - ../../../src/core/modules.h \ - ../../../src/core/server-connect-rec.h \ - ../../../src/core/server-rec.h dcc-get.h dcc.h dcc-rec.h \ - dcc-file-rec.h -dcc-resume.o: dcc-resume.c module.h ../../../src/common.h \ - ../../../config.h ../../../src/irc/core/irc.h \ - ../../../src/core/commands.h ../../../src/core/signals.h \ - ../../../src/core/network.h ../../../src/core/misc.h dcc-file.h \ - dcc.h ../../../src/core/modules.h dcc-rec.h dcc-file-rec.h \ - dcc-get.h dcc-send.h dcc-chat.h -dcc-send.o: dcc-send.c module.h ../../../src/common.h ../../../config.h \ - ../../../src/irc/core/irc.h ../../../src/core/commands.h \ - ../../../src/core/signals.h ../../../src/core/network.h \ - ../../../src/core/net-sendbuffer.h ../../../src/core/misc.h \ - ../../../src/core/settings.h \ - ../../../src/irc/core/irc-servers.h \ - ../../../src/core/chat-protocols.h ../../../src/core/servers.h \ - ../../../src/core/modules.h \ - ../../../src/core/server-connect-rec.h \ - ../../../src/core/server-rec.h dcc-send.h dcc.h dcc-rec.h \ - dcc-file-rec.h dcc-chat.h -dcc.o: dcc.c module.h ../../../src/common.h ../../../config.h \ - ../../../src/irc/core/irc.h ../../../src/core/commands.h \ - ../../../src/core/signals.h ../../../src/core/network.h \ - ../../../src/core/line-split.h ../../../src/core/misc.h \ - ../../../src/core/settings.h ../../../src/core/ignore.h \ - ../../../src/core/levels.h ../../../src/irc/core/irc-servers.h \ - ../../../src/core/chat-protocols.h ../../../src/core/servers.h \ - ../../../src/core/modules.h \ - ../../../src/core/server-connect-rec.h \ - ../../../src/core/server-rec.h \ - ../../../src/core/servers-setup.h \ - ../../../src/core/server-setup-rec.h dcc-chat.h dcc.h dcc-rec.h \ - dcc-get.h dcc-file-rec.h dcc-send.h +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp info-am: info: info-am dvi-am: @@ -362,27 +330,27 @@ maintainer-clean-generic: mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ - mostlyclean-libtool mostlyclean-tags \ + mostlyclean-libtool mostlyclean-tags mostlyclean-depend \ mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \ - clean-generic mostlyclean-am + clean-depend clean-generic mostlyclean-am clean: clean-am distclean-am: distclean-noinstLIBRARIES distclean-compile \ - distclean-libtool distclean-tags distclean-generic \ - clean-am + distclean-libtool distclean-tags distclean-depend \ + distclean-generic clean-am -rm -f libtool distclean: distclean-am maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean-compile maintainer-clean-libtool \ - maintainer-clean-tags maintainer-clean-generic \ - distclean-am + maintainer-clean-tags maintainer-clean-depend \ + maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." @@ -393,12 +361,14 @@ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile mostlyclean-libtool distclean-libtool \ clean-libtool maintainer-clean-libtool tags mostlyclean-tags \ -distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ -dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ -install-exec install-data-am install-data install-am install \ -uninstall-am uninstall all-redirect all-am all installdirs \ -mostlyclean-generic distclean-generic clean-generic \ -maintainer-clean-generic clean mostlyclean distclean maintainer-clean +distclean-tags clean-tags maintainer-clean-tags distdir \ +mostlyclean-depend distclean-depend clean-depend \ +maintainer-clean-depend info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean # Tell versions [3.59,3.63) of GNU make to not export all variables. diff -u -r -N irssi-0.8.5-org/src/irc/dcc/dcc-file-rec.h irssi-0.8.5-mod/src/irc/dcc/dcc-file-rec.h --- irssi-0.8.5-org/src/irc/dcc/dcc-file-rec.h Sat Feb 10 04:02:24 2001 +++ irssi-0.8.5-mod/src/irc/dcc/dcc-file-rec.h Sun Oct 20 19:35:00 2002 @@ -2,6 +2,7 @@ unsigned long size, skipped; /* file size / skipped at start */ int fhandle; /* file handle */ +int queue; /* queue number */ /* counter buffer */ char count_buf[4]; diff -u -r -N irssi-0.8.5-org/src/irc/dcc/dcc-queue.c irssi-0.8.5-mod/src/irc/dcc/dcc-queue.c --- irssi-0.8.5-org/src/irc/dcc/dcc-queue.c Thu Jan 1 02:00:00 1970 +++ irssi-0.8.5-mod/src/irc/dcc/dcc-queue.c Sun Oct 20 19:25:39 2002 @@ -0,0 +1,279 @@ +/* + dcc-queue.c : irssi + + Copyright (C) 1999-2001 Timo Sirainen + + DCC queue by Heikki Orsila (no copyrights claimed) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "commands.h" +#include "network.h" +#include "net-sendbuffer.h" +#include "misc.h" +#include "settings.h" +#include "irc-servers.h" + +#include "dcc-queue.h" + +struct dcc_queue_node { + struct dcc_queue_node *next; + char *servertag; + char *nick; + char *file; +}; + +static int qlistsize = 0; +static struct dcc_queue_node **queuelist = 0; + + +/* dcc_queue_old finds an old queue (if it exists) +CASE: nick and server are zero. return no queue (-1) +CASE: nick or server is non-zero. returns matching queue if found. otherwise + returns no queue (-1) */ +int dcc_queue_old(const char *nick, const char *servertag) +{ + int i; + /* try to find the an queue if nick or servertag are non-zero */ + if(nick || servertag) { + struct dcc_queue_node *node; + for(i=0; inick)) { + continue; + } + } + if(servertag) { + if(strcmp(servertag, node->servertag)) { + continue; + } + } + /* found a queue matching nick/server! */ + return i; + } + } + } + return -1; +} + + +/* create a new dcc queue. don't create a stub! */ +int dcc_queue_new(void) +{ + int i, oldsize; + if(queuelist) { + for(i=0; iservertag); + g_free(node->nick); + g_free(node->file); + g_free(node); + } +} + + +/* dequeue an element from qeueue. the element must match nick/server */ +int dcc_queue_get_file(int queue, char **nick, char **fname) +{ + struct dcc_queue_node *node, *stub; + + if(queue < 0 || queue >= qlistsize) { + g_warning("dcc_queue_get_file: dcc_queue_bugs"); + return 0; + } + + stub = queuelist[queue]; + if(!stub) + return 0; + node = stub->next; /* get queue head (zero?) */ + if(!node) { + /* no files in queue => remove stub */ + queuelist[queue] = 0; + dcc_queue_free_node(stub); stub = 0; + return 0; + } + /* remove head */ + stub->next = node->next; + + *fname = strdup(node->file); + *nick = strdup(node->nick); + +#if 1 + { + char tmp[1024]; + sprintf(tmp, "dequeued %s -> %s / %s", node->file, node->nick, node->servertag); + g_warning(tmp); + } +#endif + + dcc_queue_free_node(node); + + return 1; +} + + +/* add an element to queue. element will have nick/server/fname as data. + mode specifies how the element should be added (append or prepend) +*/ + +int dcc_queue_add(int queue, int mode, const char *nick, const char *fname, + const char *servertag) +{ + struct dcc_queue_node *new, *node, *stub; + + if(queue < 0 || queue >= qlistsize) { + g_warning("dcc_queue_add: dcc_queue_bugs"); + return 0; + } + + new = g_malloc(sizeof(struct dcc_queue_node)); + new->servertag = strdup(servertag); + new->nick = strdup(nick); + new->file = strdup(fname); + new->next = 0; + + stub = queuelist[queue]; + + /* does queue stub exist? */ + if(!stub) { + /* create queue stub */ + stub = g_malloc(sizeof(struct dcc_queue_node)); + stub->servertag = strdup(servertag); + stub->nick = strdup(nick); + stub->file = 0; + stub->next = 0; + queuelist[queue] = stub; + } else { + /* stub already exists... + check if stub's server is same as queue's server */ + if(strcmp(stub->servertag, servertag)) { + g_warning("dcc_queue_add: when appending or prepending to a dcc queue, all entries in the same queue must be on the same server"); + dcc_queue_free_node(new); new = 0; + return 0; + } + } + + if(stub) { + node = stub; + if(mode == DCC_QUEUE_PREPEND) { + new->next = node->next; + } else { + /* add tail (append) */ + while(node->next) + node = node->next; + } + node->next = new; + } else { + g_warning("dcc_queue_add: couldn't allocate queue stub"); + dcc_queue_free_node(new); new = 0; + return 0; + } +#if 1 + { + char tmp[1024]; + sprintf(tmp, "queued %s -> %s / %s", new->file, new->nick, new->servertag); + g_warning(tmp); + } +#endif + return 1; +} + +/* returns non-zero if queue has a stub, otherwise zero */ +int dcc_queue_has_stub(int queue) +{ + if(queue < 0 || queue >= qlistsize) { + g_warning("dcc_queue_has_stub: dcc_queue_bugs"); + return 0; + } + return queuelist[queue] ? 1 : 0; +} + + +/* removes the head or the tail from the queue, but not the stub. returns the + number of elements removed from the queue (0 or 1). if remove_head is + non-zero, the head is removed. otherwise the tail is removed */ +static int dcc_queue_remove_entry(int queue, int remove_head) +{ + struct dcc_queue_node *head, *node, *stub; + if(queue < 0 || queue >= qlistsize) { + g_warning("dcc_queue_remove_head: dcc_queue_bugs"); + return 0; + } + stub = queuelist[queue]; + if(!stub) + return 0; + head = stub->next; /* get head node (zero?) */ + if(!head) + return 0; + if(remove_head) { + /* remove head */ + stub->next = head->next; + dcc_queue_free_node(head); + } else { + /* remove tail */ + node = stub; + while(node->next->next) + node = node->next; + dcc_queue_free_node(node->next); + node->next = 0; + } + return 1; +} + +/* removes the head, but not stub from the queue. returns number of elements + removed from the queue (0 or 1) */ +int dcc_queue_remove_head(int queue) +{ + return dcc_queue_remove_entry(queue, 1); +} + +/* removes the tail, but not stub from the queue. returns number of elements + removed from the queue (0 or 1) */ +int dcc_queue_remove_tail(int queue) +{ + return dcc_queue_remove_entry(queue, 0); +} diff -u -r -N irssi-0.8.5-org/src/irc/dcc/dcc-queue.h irssi-0.8.5-mod/src/irc/dcc/dcc-queue.h --- irssi-0.8.5-org/src/irc/dcc/dcc-queue.h Thu Jan 1 02:00:00 1970 +++ irssi-0.8.5-mod/src/irc/dcc/dcc-queue.h Sun Oct 20 19:25:39 2002 @@ -0,0 +1,30 @@ +#ifndef __DCC_QUEUE_H_ +#define __DCC_QUEUE_H_ + +#define DCC_QUEUE_NORMAL (0) +#define DCC_QUEUE_PREPEND (1) +#define DCC_QUEUE_APPEND (2) + +/* create a new queue. returns it's designation number (int) */ +int dcc_queue_new(void); + +/* finds an old queue and returns it's designation number (int). if not + found return -1 */ +int dcc_queue_old(const char *nick, const char *servertag); + +/* adds nick/fname/servertag triplet into queue */ +int dcc_queue_add(int queue, int mode, const char *nick, const char *fname, + const char *servertag); + +int dcc_queue_remove_head(int queue); + +int dcc_queue_remove_tail(int queue); + +/* removes first entry from the queue and returns the filename */ +int dcc_queue_get_file(int queue, char **nick, char **fname); + +/* returns non-zero if queue has a stub, otherwise zero */ +int dcc_queue_has_stub(int queue); + +#endif + diff -u -r -N irssi-0.8.5-org/src/irc/dcc/dcc-send.c irssi-0.8.5-mod/src/irc/dcc/dcc-send.c --- irssi-0.8.5-org/src/irc/dcc/dcc-send.c Sun Jan 20 05:10:27 2002 +++ irssi-0.8.5-mod/src/irc/dcc/dcc-send.c Sun Oct 20 19:25:28 2002 @@ -18,6 +18,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include +#include +#include + #include "module.h" #include "signals.h" #include "commands.h" @@ -30,6 +35,119 @@ #include "dcc-send.h" #include "dcc-chat.h" +#include "dcc-queue.h" + +static void dcc_send_one_file(int queue, const char *target, const char *fname, + IRC_SERVER_REC *server, WI_ITEM_REC *item, + int *success); + +static void dcc_queue_send_next(int queue, + IRC_SERVER_REC *server, WI_ITEM_REC *item) +{ + char *fname, *nick; + int send_started = 0; + + while(!send_started) { + if(!dcc_queue_get_file(queue, &nick, &fname)) + break; + dcc_send_one_file(queue, nick, fname, server, item, &send_started); + g_free(fname); + g_free(nick); + } +} + +/* SYNTAX: DCC SEND [OPTION] ... + where OPTION is one of -append, -prepend, -flush, -rmtail and -rmhead. + all may contain shell expansion characters: * ? [] ~ + (~ expansion may not be supported on all platforms) + */ +static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, + WI_ITEM_REC *item) +{ + char *nick, *fname, *fileargs; + void *free_arg; + GHashTable *optlist; + int i, files; + glob_t globbuf; + struct stat st; + int flags = GLOB_NOCHECK; + int queue = -1; + int mode = DCC_QUEUE_NORMAL; + int start_new_transfer = 1; + + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST, "dcc send", + &optlist, &nick, &fileargs)) + return; + + if (g_hash_table_lookup(optlist, "append") != NULL) + mode = DCC_QUEUE_APPEND; + else if (g_hash_table_lookup(optlist, "prepend") != NULL) + mode = DCC_QUEUE_PREPEND; + else if (g_hash_table_lookup(optlist, "rmhead") != NULL) { + queue = dcc_queue_old(nick, server->tag); + dcc_queue_remove_head(queue); + goto free_args; + } else if (g_hash_table_lookup(optlist, "rmtail") != NULL) { + queue = dcc_queue_old(nick, server->tag); + dcc_queue_remove_tail(queue); + goto free_args; + } else if (g_hash_table_lookup(optlist, "flush") != NULL) { + queue = dcc_queue_old(nick, server->tag); + while(dcc_queue_remove_head(queue)); + goto free_args; + } + + globbuf.gl_offs = 0; +#ifdef GLOB_TILDE + flags |= GLOB_TILDE; +#endif + + /* this loop parses all parameters and adds them to glubbuf */ + while(1) { + fname = cmd_get_quoted_param(&fileargs); + if(!fname[0]) + break; + + if(glob(fname, flags, 0, &globbuf) < 0) + break; + + /* this flag must not be set before first call to glob! (man glob) */ + flags |= GLOB_APPEND; + } + + files = 0; + + /* add all globbed files to a proper queue */ + for(i=0; i 0) { + if(queue < 0) { + /* in append and prepend mode try to find an old queue. if an old + queue is not found create a new queue. if not append or prepend + mode, create a new queue */ + if(mode != DCC_QUEUE_NORMAL) { + queue = dcc_queue_old(nick, server->tag); + } + start_new_transfer = 0; + if(queue < 0) { + queue = dcc_queue_new(); + start_new_transfer = 1; + } + } + if(dcc_queue_add(queue, mode, nick, globbuf.gl_pathv[i], server->tag)) + files++; + } + } + } + + if(files > 0 && start_new_transfer) + dcc_queue_send_next(queue, server, item); + + globfree(&globbuf); + free_args: + cmd_params_free(free_arg); +} static SEND_DCC_REC *dcc_send_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat, @@ -41,6 +159,7 @@ dcc->orig_type = module_get_uniq_id_str("DCC", "GET"); dcc->type = module_get_uniq_id_str("DCC", "SEND"); dcc->fhandle = -1; + dcc->queue = -1; dcc_init_rec(DCC(dcc), server, chat, nick, arg); return dcc; @@ -51,6 +170,8 @@ if (!IS_DCC_SEND(dcc)) return; if (dcc->fhandle != -1) close(dcc->fhandle); + + dcc_queue_send_next(dcc->queue, dcc->server, 0); } /* input function: DCC SEND - we're ready to send more data */ @@ -164,12 +285,11 @@ return str; } -/* SYNTAX: DCC SEND */ -static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, - WI_ITEM_REC *item) +static void dcc_send_one_file(int queue, const char *target, const char *fname, + IRC_SERVER_REC *server, WI_ITEM_REC *item, + int *success) { - char *target, *fname, *str; - void *free_arg; + char *str; char host[MAX_IP_LEN]; int hfile, port; long fsize; @@ -178,16 +298,19 @@ IPADDR own_ip; GIOChannel *handle; - g_return_if_fail(data != NULL); + *success = 0; + + if(!target || !fname) + cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, - &target, &fname)) - return; if (*target == '\0' || *fname == '\0') - cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - /* if we're in dcc chat, send the request via it. */ - chat = item_get_dcc(item); + if(item) + /* if we're in dcc chat, send the request via it. */ + chat = item_get_dcc(item); + else + chat = NULL; if (chat != NULL && (chat->mirc_ctcp || g_strcasecmp(target, chat->nick) != 0)) @@ -197,11 +320,10 @@ server = NULL; if ((server == NULL || !server->connected) && chat == NULL) - cmd_param_error(CMDERR_NOT_CONNECTED); + cmd_return_error(CMDERR_NOT_CONNECTED); if (dcc_find_request(DCC_SEND_TYPE, target, fname)) { - signal_emit("dcc error send exists", 2, target, fname); - cmd_params_free(free_arg); + signal_emit("dcc error send exists", 2, target, fname); return; } @@ -212,7 +334,6 @@ if (hfile == -1) { signal_emit("dcc error file open", 3, target, fname, GINT_TO_POINTER(errno)); - cmd_params_free(free_arg); return; } fsize = lseek(hfile, 0, SEEK_END); @@ -224,7 +345,7 @@ &own_ip, &port); if (handle == NULL) { close(hfile); - cmd_param_error(CMDERR_ERRNO); + cmd_return_error(CMDERR_ERRNO); } fname = g_basename(fname); @@ -234,6 +355,7 @@ dcc->port = port; dcc->size = fsize; dcc->fhandle = hfile; + dcc->queue = queue; dcc->file_quoted = strchr(fname, ' ') != NULL; dcc->tagconn = g_input_add(handle, G_INPUT_READ, (GInputFunction) dcc_send_connected, dcc); @@ -249,7 +371,7 @@ dcc_ctcp_message(server, target, chat, FALSE, str); g_free(str); - cmd_params_free(free_arg); + *success = 1; } void dcc_send_init(void) @@ -259,6 +381,7 @@ signal_add("dcc destroyed", (SIGNAL_FUNC) sig_dcc_destroyed); command_bind("dcc send", NULL, (SIGNAL_FUNC) cmd_dcc_send); + command_set_options("dcc send", "append flush prepend rmhead rmtail"); } void dcc_send_deinit(void)