/*
* iroffer by David Johnson (PMG)
* Copyright (C) 1998-2005 David Johnson
*
* By using this file, you agree to the terms and conditions set
* forth in the GNU General Public License. More information is
* available in the README file.
*
* If you received this file without documentation, it can be
* downloaded from http://iroffer.org/
*
* @(#) iroffer_admin.c 1.215@(#)
* pmg@wellington.i202.centerclick.org|src/iroffer_admin.c|20051123201143|48668
*
*/
/* include the headers */
#include "iroffer_config.h"
#include "iroffer_defines.h"
#include "iroffer_headers.h"
#include "iroffer_globals.h"
/* local functions */
static void
#ifdef __GNUC__
__attribute__ ((format(printf, 2, 3)))
#endif
u_respond(const userinput * const u, const char *format, ...);
static void u_help(const userinput * const u);
static void u_xdl(const userinput * const u);
static void u_xds(const userinput * const u);
static void u_dcl(const userinput * const u);
static void u_dcld(const userinput * const u);
static void u_qul(const userinput * const u);
static void u_close(const userinput * const u);
static void u_closeu(const userinput * const u);
static void u_nomin(const userinput * const u);
static void u_nomax(const userinput * const u);
static void u_rmq(const userinput * const u);
static void u_raw(const userinput * const u);
static void u_redraw(const userinput * const u);
static void u_delhist(const userinput * const u);
static void u_info(const userinput * const u);
static void u_remove(const userinput * const u);
static void u_removedir(const userinput * const u);
static void u_send(const userinput * const u);
static void u_psend(const userinput * const u);
static void u_msg(const userinput * const u);
static void u_mesg(const userinput * const u);
static void u_mesq(const userinput * const u);
static void u_quit(const userinput * const u);
static void u_status(const userinput * const u);
static void u_chfile(const userinput * const u);
static void u_chdesc(const userinput * const u);
static void u_chnote(const userinput * const u);
static void u_chmins(const userinput * const u);
static void u_chmaxs(const userinput * const u);
static void u_chgets(const userinput * const u);
static void u_add(const userinput * const u);
static void u_adddir(const userinput * const u);
static void u_addnew(const userinput * const u);
static void u_chatme(const userinput * const u);
static void u_chatl(const userinput * const u);
static void u_closec(const userinput * const u);
static void u_rehash(const userinput * const u);
static void u_botinfo(const userinput * const u);
static void u_ignl(const userinput * const u);
static void u_ignore(const userinput * const u);
static void u_unignore(const userinput * const u);
static void u_nosave(const userinput * const u);
static void u_nosend(const userinput * const u);
static void u_nolist(const userinput * const u);
static void u_renumber(const userinput * const u);
static void u_msgread(const userinput * const u);
static void u_msgdel(const userinput * const u);
static void u_memstat(const userinput * const u);
static void u_qsend(const userinput * const u);
static void u_shutdown(const userinput * const u);
static void u_debug(const userinput * const u);
static void u_jump(const userinput * const u);
static void u_servqc(const userinput * const u);
static void u_servers(const userinput * const u);
static void u_trinfo(const userinput * const u);
static void u_listul(const userinput * const u);
static void u_clearrecords(const userinput * const u);
static void u_rmul(const userinput * const u);
static void u_crash(const userinput * const u);
static void u_chanl(const userinput * const u);
typedef struct
{
const short help_section;
const userinput_method_e methods_allowed;
void (*handler)(const userinput * const);
const char *command;
const char *args;
const char *desc;
} userinput_parse_t;
/* local info */
static const userinput_parse_t userinput_parse[] = {
{1,method_allow_all,u_help, "HELP",NULL,"Shows Help"},
{1,method_allow_all_xdl,u_xdl, "XDL",NULL,"Lists Offered Files"},
{1,method_allow_all,u_xds, "XDS",NULL,"Save XDCC File"},
{1,method_allow_all,u_dcl, "DCL",NULL,"Lists Current Transfers"},
{1,method_allow_all,u_dcld, "DCLD",NULL,"Lists Current Transfers with Details"},
{1,method_allow_all,u_trinfo, "TRINFO","n","Lists Information About Transfer n"},
{1,method_allow_all,u_qul, "QUL",NULL,"Lists Current Queue"},
{1,method_allow_all,u_ignl, "IGNL",NULL,"Show Ignored List"},
{1,method_allow_all,u_listul, "LISTUL",NULL,"Shows contents of upload directory"},
{1,method_allow_all,u_chanl, "CHANL",NULL,"Shows channel list with member list"},
{2,method_allow_all,u_close, "CLOSE","n","Cancels Transfer with ID = n"},
{2,method_allow_all,u_closeu, "CLOSEU","n","Cancels Upload with ID = n"},
{2,method_allow_all,u_rmq, "RMQ","n","Removes Queue Number n"},
{2,method_allow_all,u_nomin, "NOMIN","n","Disables Minspeed For Transfer ID n"},
{2,method_allow_all,u_nomax, "NOMAX","n","Disables Maxspeed For Transfer ID n"},
{2,method_allow_all,u_send, "SEND","nick n","Sends Pack n to nick"},
{2,method_allow_all,u_psend, "PSEND","<channel> <style>","Sends <style> (full|minimal|summary) XDCC LIST to <channel>"},
{2,method_allow_all,u_qsend, "QSEND",NULL,"Sends Out The First Queued Pack"},
{3,method_allow_all,u_info, "INFO","n","Show Info for Pack n"},
{3,method_allow_all,u_remove, "REMOVE","n","Removes Pack n"},
{3,method_allow_all,u_removedir,"REMOVEDIR","<dir>","Remove Every File in <dir>"},
{3,method_allow_all,u_renumber, "RENUMBER","x y","Moves Pack x to y"},
{3,method_allow_all,u_add, "ADD","<filename>","Add New Pack With <filename>"},
{3,method_allow_all,u_adddir, "ADDDIR","<dir>","Add Every File in <dir>"},
{3,method_allow_all,u_addnew, "ADDNEW","<dir>","Add any new files in <dir>"},
{3,method_allow_all,u_chfile, "CHFILE","n <msg>","Change File of pack n to <msg>"},
{3,method_allow_all,u_chdesc, "CHDESC","n <msg>","Change Description of pack n to <msg>"},
{3,method_allow_all,u_chnote, "CHNOTE","n <msg>","Change Note of pack n to <msg>"},
{3,method_allow_all,u_chmins, "CHMINS","n x","Change min speed of pack n to x KB"},
{3,method_allow_all,u_chmaxs, "CHMAXS","n x","Change max speed of pack n to x KB"},
{3,method_allow_all,u_chgets, "CHGETS","n x","Change the get count of a pack"},
{4,method_allow_all,u_msg, "MSG","<nick> <message>","Send a message to a user"},
{4,method_allow_all,u_mesg, "MESG","<message>","Sends msg to all users who are transferring"},
{4,method_allow_all,u_mesq, "MESQ","<message>","Sends msg to all users in a queue"},
{4,method_allow_all,u_ignore, "IGNORE","n <hostmask>","Ignore hostmask (nick!user@host) for n minutes, wildcards allowed"},
{4,method_allow_all,u_unignore, "UNIGNORE","<hostmask>","Un-Ignore hostmask"},
{4,method_allow_all,u_nosave, "NOSAVE","n","Disables XDCC AutoSave for next n minutes"},
{4,method_allow_all,u_nosend, "NOSEND","n","Disables XDCC Send for next n minutes"},
{4,method_allow_all,u_nolist, "NOLIST","n","Disables XDCC List and Plist for next n mins"},
{4,method_allow_all,u_msgread, "MSGREAD",NULL,"Show MSG log"},
{4,method_allow_all,u_msgdel, "MSGDEL",NULL,"Delete MSG log"},
{4,method_allow_all,u_rmul, "RMUL","<file>","Delete a file in the Upload Dir"},
{4,method_allow_all,u_raw, "RAW","<command>","Send <command> to server (RAW IRC)"},
{5,method_allow_all,u_servers, "SERVERS",NULL,"Shows the server list"},
{5,method_allow_all,u_jump, "JUMP","<num>","Switches to a random server or server <num>"},
{5,method_allow_all,u_servqc, "SERVQC",NULL,"Clears the server send queue"},
{5,method_allow_all,u_status, "STATUS",NULL,"Show Useful Information"},
{5,method_allow_all,u_rehash, "REHASH",NULL,"Re-reads config file(s) and reconfigures"},
{5,method_allow_all,u_botinfo, "BOTINFO",NULL,"Show Information about the bot status"},
{5,method_allow_all,u_memstat, "MEMSTAT",NULL,"Show Information about memory usage"},
{5,method_allow_all,u_clearrecords, "CLEARRECORDS",NULL,"Clears transfer, bandwidth, uptime, total sent, and transfer limits"},
{5,method_console, u_redraw, "REDRAW",NULL,"Redraws the Screen"},
{5,method_console, u_delhist, "DELHIST",NULL,"Deletes console history"},
{5,method_dcc, u_quit, "QUIT",NULL,"Close this DCC chat"},
{5,method_msg, u_chatme, "CHATME",NULL,"Sends you a DCC Chat Request"},
{5,method_allow_all,u_chatl, "CHATL",NULL,"Lists DCC Chat Information"},
{5,method_allow_all,u_closec, "CLOSEC","n","Closes DCC Chat with ID = n"},
{5,method_console, u_debug, "DEBUG","n","Set Debugging level to n"},
{5,method_allow_all,u_shutdown, "SHUTDOWN","<act>","Shutdown iroffer, <act> is \"now\", \"delayed\", or \"cancel\""},
{6,method_console, u_crash, "CRASH",NULL,"Cause a segmentation fault"},
};
void u_fillwith_console (userinput * const u, char *line)
{
updatecontext();
if (line[0] && (line[strlen(line)-1] == '\n'))
{
line[strlen(line)-1] = '\0';
}
u->method = method_console;
u->snick = NULL;
u->chat = NULL;
u->cmd = caps(getpart(line,1));
u->arg1 = getpart(line,2);
u->arg2 = getpart(line,3);
u->arg3 = getpart(line,4);
if (u->arg1)
{
u->arg1e = mymalloc(strlen(line) - strlen(u->cmd) - 1 + 1);
strcpy(u->arg1e, line + strlen(u->cmd) + 1);
}
else
{
u->arg1e = NULL;
}
if (u->arg2)
{
u->arg2e = mymalloc(strlen(line) - strlen(u->cmd) - strlen(u->arg1) - 2 + 1);
strcpy(u->arg2e, line + strlen(u->cmd) + strlen(u->arg1) + 2);
}
else
{
u->arg2e = NULL;
}
return;
}
void u_fillwith_dcc (userinput * const u, dccchat_t *chat, char *line)
{
updatecontext();
if (line[strlen(line)-1] == '\n')
{
line[strlen(line)-1] = '\0';
}
u->method = method_dcc;
u->snick = NULL;
u->chat = chat;
u->cmd = caps(getpart(line,1));
u->arg1 = getpart(line,2);
u->arg2 = getpart(line,3);
u->arg3 = getpart(line,4);
if (u->arg1)
{
u->arg1e = mymalloc(strlen(line) - strlen(u->cmd) - 1 + 1);
strcpy(u->arg1e, line + strlen(u->cmd) + 1);
}
else
{
u->arg1e = NULL;
}
if (u->arg2)
{
u->arg2e = mymalloc(strlen(line) - strlen(u->cmd) - strlen(u->arg1) - 2 + 1);
strcpy(u->arg2e, line + strlen(u->cmd) + strlen(u->arg1) + 2);
}
else
{
u->arg2e = NULL;
}
return;
}
void u_fillwith_msg (userinput * const u, const char* n, const char *line)
{
char *t1,*t2,*t3,*t4,*t5;
int len;
updatecontext();
u->method = method_msg;
if (n)
{
u->snick = mymalloc(strlen(n)+1);
strcpy(u->snick, n);
}
else
{
u->snick = NULL;
}
u->chat = NULL;
t1 = getpart(line,1);
t2 = getpart(line,2);
t3 = getpart(line,3);
t4 = getpart(line,4);
t5 = getpart(line,5);
u->cmd = caps(getpart(line,6));
u->arg1 = getpart(line,7);
u->arg2 = getpart(line,8);
u->arg3 = getpart(line,9);
len = strlen(t1) + strlen(t2) + strlen(t3) + strlen(t4) + strlen(t5) + 5;
if (u->arg1)
{
u->arg1e = mymalloc(strlen(line) - len - strlen(u->cmd) - 1 + 1);
strcpy(u->arg1e, line + len + strlen(u->cmd) + 1);
}
else
{
u->arg1e = NULL;
}
if (u->arg2)
{
u->arg2e = mymalloc(strlen(line) - len - strlen(u->cmd) - strlen(u->arg1) - 2 + 1);
strcpy(u->arg2e, line + len + strlen(u->cmd) + strlen(u->arg1) + 2);
}
else
{
u->arg2e = NULL;
}
mydelete(t1);
mydelete(t2);
mydelete(t3);
mydelete(t4);
mydelete(t5);
return;
}
void u_fillwith_clean (userinput * const u)
{
updatecontext();
mydelete(u->snick);
u->chat = NULL;
mydelete(u->cmd);
mydelete(u->arg1e);
mydelete(u->arg2e);
mydelete(u->arg1);
mydelete(u->arg2);
mydelete(u->arg3);
}
static void u_respond(const userinput * const u, const char *format, ...)
{
va_list args;
updatecontext();
va_start(args, format);
switch (u->method)
{
case method_console:
vioutput(CALLTYPE_NORMAL, OUT_S, COLOR_NO_COLOR, format, args);
break;
case method_dcc:
vwritedccchat(u->chat, 1, format, args);
break;
case method_out_all:
vioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, format, args);
break;
case method_fd:
{
ssize_t retval;
char tempstr[maxtextlength];
int llen;
llen = vsnprintf(tempstr,maxtextlength-3,format,args);
if ((llen < 0) || (llen >= maxtextlength-3))
{
outerror(OUTERROR_TYPE_WARN,"string too long!");
tempstr[0] = '\0';
llen = 0;
}
if (!gdata.xdcclistfileraw)
{
removenonprintablectrl(tempstr);
}
#if defined(_OS_CYGWIN)
tempstr[llen++] = '\r';
#endif
tempstr[llen++] = '\n';
tempstr[llen] = '\0';
retval = write(u->fd, tempstr, strlen(tempstr));
if (retval < 0)
{
outerror(OUTERROR_TYPE_WARN_LOUD,"Write failed: %s", strerror(errno));
}
}
break;
case method_msg:
vprivmsg(u->snick, format, args);
break;
case method_xdl_channel:
case method_xdl_channel_min:
case method_xdl_channel_sum:
case method_xdl_user_privmsg:
vprivmsg_slow(u->snick, format, args);
break;
case method_xdl_user_notice:
vnotice_slow(u->snick, format, args);
break;
case method_allow_all:
default:
break;
}
va_end(args);
}
void u_parseit(userinput * const u) {
int i,found = 0;
updatecontext();
if (!u->cmd || !strlen(u->cmd)) {
u_respond(u,"** Missing Command, try again");
u_fillwith_clean(u);
return;
}
for (i=0; !found && i<(sizeof(userinput_parse)/sizeof(userinput_parse_t)); i++)
if ( (!strcmp(userinput_parse[i].command,u->cmd)) &&
(userinput_parse[i].methods_allowed & u->method) ) {
found=1;
userinput_parse[i].handler(u);
}
if (!found)
u_respond(u,"** User Command Not Recognized, try \"HELP\"");
if (found && u->method==method_console)
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_MAGENTA,"ADMIN %s Requested (console)",u->cmd);
if (found && u->method==method_dcc)
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_MAGENTA,"ADMIN %s Requested (DCC Chat: %s)", u->cmd, u->chat->nick ? u->chat->nick : "???");
if (found && u->method==method_msg)
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_MAGENTA,"ADMIN %s Requested (MSG: %s)",u->cmd,u->snick);
u_fillwith_clean(u);
}
static void u_help(const userinput * const u)
{
int i,which=0;
updatecontext();
for (which=1; which<6; which++)
{
u_respond(u,"-- %s Commands --",
which==1?"Info":
which==2?"Transfer":
which==3?"Pack":
which==4?"Misc":
which==5?"Bot":"<Unknown>");
for (i=0; i<(sizeof(userinput_parse)/sizeof(userinput_parse_t)); i++)
{
if (userinput_parse[i].methods_allowed & u->method &&
userinput_parse[i].help_section == which)
{
if (userinput_parse[i].args)
{
int spaces;
spaces = 20 - 1;
spaces -= sstrlen(userinput_parse[i].command);
spaces -= sstrlen(userinput_parse[i].args);
spaces = max2(0,spaces);
u_respond(u," %s %s %.*s: %s",
userinput_parse[i].command,
userinput_parse[i].args,
spaces, " ",
userinput_parse[i].desc);
}
else
{
u_respond(u," %-20s : %s",
userinput_parse[i].command,
userinput_parse[i].desc);
}
}
}
}
u_respond(u,"For additional help, see the complete documentation at http://iroffer.org/");
}
static void u_xdl(const userinput * const u) {
char *tempstr;
const char *spaces[] = { ""," "," "," "," "," "," " };
int a,i,m,m1,s;
float toffered;
int len;
xdcc *xd;
ir_uint64 xdccsent;
updatecontext();
tempstr = mycalloc(maxtextlength);
if (u->method==method_xdl_channel_min) m = 1; else m = 0;
if (u->method==method_xdl_channel_sum) m1 = 1; else m1 = 0;
if (gdata.headline)
{
u_respond(u,"\2**\2 %s \2**\2",gdata.headline);
}
if (!m && !m1)
{
if (gdata.slotsmax - irlist_size(&gdata.trans) < 0)
{
a = irlist_size(&gdata.trans);
}
else
{
a = gdata.slotsmax;
}
snprintf(tempstr, maxtextlength - 1,
"\2**\2 %i pack%s \2**\2 %i of %i slot%s open",
irlist_size(&gdata.xdccs),
irlist_size(&gdata.xdccs) != 1 ? "s" : "",
a - irlist_size(&gdata.trans),
a,
a != 1 ? "s" : "");
len = strlen(tempstr);
if (gdata.slotsmax <= irlist_size(&gdata.trans))
{
snprintf(tempstr + len, maxtextlength - 1 - len,
", Queue: %i/%i",
irlist_size(&gdata.mainqueue),
gdata.queuesize);
len = strlen(tempstr);
}
if (gdata.transferminspeed > 0)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
", Min: %1.1fKB/s",
gdata.transferminspeed);
len = strlen(tempstr);
}
if (gdata.transfermaxspeed > 0)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
", Max: %1.1fKB/s",
gdata.transfermaxspeed);
len = strlen(tempstr);
}
if (gdata.record > 0.5)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
", Record: %1.1fKB/s",
gdata.record);
len = strlen(tempstr);
}
u_respond(u,"%s",tempstr);
for (i=0,xdccsent=0; i<XDCC_SENT_SIZE; i++)
{
xdccsent += (ir_uint64)gdata.xdccsent[i];
}
snprintf(tempstr, maxtextlength - 1,
"\2**\2 Bandwidth Usage \2**\2 Current: %1.1fKB/s,",
((float)xdccsent) / XDCC_SENT_SIZE / 1024.0);
len = strlen(tempstr);
if (gdata.maxb)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
" Cap: %i.0KB/s,",
gdata.maxb / 4);
len = strlen(tempstr);
}
if (gdata.sentrecord > 0.5)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
" Record: %1.1fKB/s",
gdata.sentrecord);
len = strlen(tempstr);
}
u_respond(u,"%s",tempstr);
u_respond(u,"\2**\2 To request a file, type \"/msg %s xdcc send #x\" \2**\2",
(gdata.user_nick ? gdata.user_nick : "??"));
u_respond(u,"\2**\2 To request details, type \"/msg %s xdcc info #x\" \2**\2",
(gdata.user_nick ? gdata.user_nick : "??"));
}
if (m1)
{
if (!gdata.restrictprivlist)
{
u_respond(u,"\2**\2 For a listing type: \"/msg %s xdcc list\" \2**\2",
(gdata.user_nick ? gdata.user_nick : "??"));
}
if (gdata.creditline)
{
u_respond(u,"\2**\2 %s \2**\2",gdata.creditline);
}
mydelete(tempstr);
return;
}
s = 0;
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
s = max2(s,xd->gets);
xd = irlist_get_next(xd);
}
i = s; s = 5;
if (i < 10000) s = 4;
if (i < 1000) s = 3;
if (i < 100) s = 2;
if (i < 10) s = 1;
i = 1;
toffered = 0;
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
char *sizestrstr;
toffered += (float)xd->st_size;
sizestrstr = sizestr(1, xd->st_size);
snprintf(tempstr, maxtextlength - 1,
"\2#%-2i\2 %*ix [%s] %s",
i,
s, xd->gets,
sizestrstr,
xd->desc);
len = strlen(tempstr);
mydelete(sizestrstr);
if (xd->minspeed > 0 && xd->minspeed != gdata.transferminspeed)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
" [%1.1fK Min]",
xd->minspeed);
len = strlen(tempstr);
}
if (xd->maxspeed > 0 && xd->maxspeed != gdata.transfermaxspeed)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
" [%1.1fK Max]",
xd->maxspeed);
len = strlen(tempstr);
}
u_respond(u,"%s",tempstr);
if (xd->note && strlen(xd->note))
{
u_respond(u," \2^-\2%s%s",spaces[s],xd->note);
}
i++;
xd = irlist_get_next(xd);
}
if (gdata.creditline)
{
u_respond(u,"\2**\2 %s \2**\2",gdata.creditline);
}
if (!m)
{
u_respond(u,
"Total Offered: %1.1f MB Total Transferred: %1.2f %cB",
toffered/1024.0/1024.0,
(gdata.totalsent/1024/1024) > 1024 ? ( (gdata.totalsent/1024/1024/1024) > 1024 ? ((float)gdata.totalsent)/1024/1024/1024/1024 : ((float)gdata.totalsent)/1024/1024/1024 ) : ((float)gdata.totalsent)/1024/1024 ,
(gdata.totalsent/1024/1024) > 1024 ? ( (gdata.totalsent/1024/1024/1024) > 1024 ? 'T' : 'G' ) : 'M'
);
}
mydelete(tempstr);
}
static void u_xds(const userinput * const u)
{
updatecontext();
write_statefile();
xdccsavetext();
}
static void u_dcl(const userinput * const u)
{
const char *y;
int i;
upload *ul;
transfer *tr;
updatecontext();
if (!irlist_size(&gdata.trans) && !irlist_size(&gdata.uploads))
{
u_respond(u,"No Active Transfers");
return;
}
if (irlist_size(&gdata.trans))
{
u_respond(u,"Current Transfer%s",irlist_size(&gdata.trans)!=1?"s":"");
u_respond(u," ID User File Status");
}
tr = irlist_get_head(&gdata.trans);
while(tr)
{
switch (tr->tr_status)
{
case TRANSFER_STATUS_LISTENING:
y = "Listening";
break;
case TRANSFER_STATUS_SENDING:
y = "Sending";
break;
case TRANSFER_STATUS_WAITING:
y = "Finishing";
break;
case TRANSFER_STATUS_DONE:
y = "Closing";
break;
default:
y = "Unknown!";
break;
}
if (tr->tr_status == TRANSFER_STATUS_SENDING)
{
u_respond(u," %3i %-9s %-32s %s %2.0f%%",
tr->id,tr->nick,getfilename(tr->xpack->file),y,
((float)tr->bytessent)*100.0/((float)tr->xpack->st_size));
}
else
{
u_respond(u," %3i %-9s %-32s %s",
tr->id,tr->nick,getfilename(tr->xpack->file),y);
}
tr = irlist_get_next(tr);
}
if (irlist_size(&gdata.uploads))
{
u_respond(u,"Current Upload%s",irlist_size(&gdata.uploads)!=1?"s":"");
u_respond(u," ID User File Status");
}
i = 0;
ul = irlist_get_head(&gdata.uploads);
while (ul)
{
switch (ul->ul_status)
{
case UPLOAD_STATUS_CONNECTING:
y = "Connecting";
break;
case UPLOAD_STATUS_GETTING:
y = "Getting";
break;
case UPLOAD_STATUS_WAITING:
y = "Finishing";
break;
case UPLOAD_STATUS_DONE:
y = "Done";
break;
default:
y = "Unknown!";
break;
}
if (ul->ul_status == UPLOAD_STATUS_GETTING)
{
u_respond(u," %2i %-9s %-32s %s %2.0f%%",
i,ul->nick,getfilename(ul->file),y,
((float)ul->bytesgot)*100.0/((float)ul->totalsize));
}
else
{
u_respond(u," %2i %-9s %-32s %s",
i,ul->nick,getfilename(ul->file),y);
}
ul = irlist_get_next(ul);
i++;
}
}
static void u_dcld(const userinput * const u)
{
char *tempstr2, *tempstr3, *tempstr4;
const char *y;
int i,left,started;
upload *ul;
transfer *tr;
updatecontext();
if (!irlist_size(&gdata.trans) && !irlist_size(&gdata.uploads))
{
u_respond(u,"No Active Transfers");
return;
}
tempstr2 = mycalloc(maxtextlengthshort);
tempstr3 = mycalloc(maxtextlengthshort);
tempstr4 = mycalloc(maxtextlengthshort);
if (irlist_size(&gdata.trans))
{
u_respond(u,"Current Transfer%s",irlist_size(&gdata.trans)!=1?"s":"");
u_respond(u," ID User File Status");
u_respond(u," ^- Speed Current/ End Start/Remain Min/ Max Resumed");
u_respond(u," --------------------------------------------------------------------");
}
tr = irlist_get_head(&gdata.trans);
while(tr)
{
switch (tr->tr_status)
{
case TRANSFER_STATUS_LISTENING:
y = "Listening";
break;
case TRANSFER_STATUS_SENDING:
y = "Sending";
break;
case TRANSFER_STATUS_WAITING:
y = "Finishing";
break;
case TRANSFER_STATUS_DONE:
y = "Closing";
break;
default:
y = "Unknown!";
break;
}
if (tr->tr_status == TRANSFER_STATUS_SENDING)
{
u_respond(u,"%3i %-9s %-32s %s %2.0f%%",
tr->id,tr->nick,getfilename(tr->xpack->file),y,
((float)tr->bytessent)*100.0/((float)tr->xpack->st_size));
}
else
{
u_respond(u,"%3i %-9s %-32s %s",
tr->id,tr->nick,getfilename(tr->xpack->file),y);
}
if (tr->tr_status == TRANSFER_STATUS_SENDING || tr->tr_status == TRANSFER_STATUS_WAITING)
{
left = min2(359999,(tr->xpack->st_size-tr->bytessent)/((int)(max2(tr->lastspeed,0.001)*1024)));
started = min2(359999,gdata.curtime-tr->connecttime);
snprintf(tempstr2, maxtextlengthshort - 1,
"%1.1fK", tr->xpack->minspeed);
snprintf(tempstr3, maxtextlengthshort - 1,
"%6liK", (long)(tr->startresume)/1024);
snprintf(tempstr4, maxtextlengthshort - 1,
"%1.1fK", tr->xpack->maxspeed);
u_respond(u,
" ^- %5.1fK/s %6" LLPRINTFMT "iK/%6" LLPRINTFMT "iK %2i%c%02i%c/%2i%c%02i%c %5s/%5s %7s",
tr->lastspeed,
(long long)((tr->bytessent)/1024),
(long long)((tr->xpack->st_size)/1024),
started < 3600 ? started/60 : started/60/60 ,
started < 3600 ? 'm' : 'h',
started < 3600 ? started%60 : (started/60)%60 ,
started < 3600 ? 's' : 'm',
left < 3600 ? left/60 : left/60/60 ,
left < 3600 ? 'm' : 'h',
left < 3600 ? left%60 : (left/60)%60 ,
left < 3600 ? 's' : 'm',
(tr->nomin || (tr->xpack->minspeed == 0.0)) ? "no" : tempstr2 ,
(tr->nomax || (tr->xpack->maxspeed == 0.0)) ? "no" : tempstr4 ,
tr->startresume ? tempstr3 : "no");
}
else
{
u_respond(u," ^- ----- -------/------- -----/------ -----/----- ---");
}
tr = irlist_get_next(tr);
}
if (irlist_size(&gdata.uploads))
{
u_respond(u,"Current Upload%s",irlist_size(&gdata.uploads)!=1?"s":"");
u_respond(u," ID User File Status");
u_respond(u," ^- Speed Current/ End Start/Remain");
u_respond(u," --------------------------------------------------------------");
}
i = 0;
ul = irlist_get_head(&gdata.uploads);
while(ul)
{
switch (ul->ul_status)
{
case UPLOAD_STATUS_CONNECTING:
y = "Connecting";
break;
case UPLOAD_STATUS_GETTING:
y = "Getting";
break;
case UPLOAD_STATUS_WAITING:
y = "Finishing";
break;
case UPLOAD_STATUS_DONE:
y = "Done";
break;
default:
y = "Unknown!";
break;
}
if (ul->ul_status == UPLOAD_STATUS_GETTING)
{
u_respond(u," %2i %-9s %-32s %s %2.0f%%",
i,ul->nick,getfilename(ul->file),y,
((float)ul->bytesgot)*100.0/((float)ul->totalsize));
}
else
{
u_respond(u," %2i %-9s %-32s %s",
i,ul->nick,getfilename(ul->file),y);
}
if (ul->ul_status == UPLOAD_STATUS_GETTING || ul->ul_status == UPLOAD_STATUS_WAITING)
{
left = min2(359999,(ul->totalsize-ul->bytesgot)/((int)(max2(ul->lastspeed,0.001)*1024)));
started = min2(359999,gdata.curtime-ul->connecttime);
u_respond(u,
" ^- %5.1fK/s %6" LLPRINTFMT "iK/%6" LLPRINTFMT "iK %2i%c%02i%c/%2i%c%02i%c",
ul->lastspeed,
(long long)((ul->bytesgot)/1024),
(long long)((ul->totalsize)/1024),
started < 3600 ? started/60 : started/60/60 ,
started < 3600 ? 'm' : 'h',
started < 3600 ? started%60 : (started/60)%60 ,
started < 3600 ? 's' : 'm',
left < 3600 ? left/60 : left/60/60 ,
left < 3600 ? 'm' : 'h',
left < 3600 ? left%60 : (left/60)%60 ,
left < 3600 ? 's' : 'm'
);
}
else
{
u_respond(u, " ^- ----- -------/------- -----/------ -----/----- ---");
}
ul = irlist_get_next(ul);
i++;
}
u_respond(u," --------------------------------------------------------------------");
mydelete(tempstr2);
mydelete(tempstr3);
mydelete(tempstr4);
}
static void u_qul(const userinput * const u)
{
int i;
unsigned long rtime, lastrtime;
pqueue *pq;
transfer *tr;
updatecontext();
if (!irlist_size(&gdata.mainqueue))
{
u_respond(u,"No Users Queued");
return;
}
u_respond(u,"Current Queue:");
u_respond(u," # User File Waiting Left");
lastrtime=0;
/* if we are sending more than allowed, we need to skip the difference */
for (i=0; i<irlist_size(&gdata.trans)-gdata.slotsmax; i++)
{
rtime=-1;
tr = irlist_get_head(&gdata.trans);
while(tr)
{
int left = min2(359999,(tr->xpack->st_size-tr->bytessent)/((int)(max2(tr->lastspeed,0.001)*1024)));
if (left > lastrtime && left < rtime)
{
rtime = left;
}
tr = irlist_get_next(tr);
}
if (rtime < 359999)
{
lastrtime=rtime;
}
}
i=1;
pq = irlist_get_head(&gdata.mainqueue);
while(pq)
{
rtime=-1;
tr = irlist_get_head(&gdata.trans);
while(tr)
{
int left = min2(359999,(tr->xpack->st_size-tr->bytessent)/((int)(max2(tr->lastspeed,0.001)*1024)));
if (left > lastrtime && left < rtime)
{
rtime = left;
}
tr = irlist_get_next(tr);
}
lastrtime=rtime;
if (rtime < 359999)
{
u_respond(u," %2i %-9s %-32s %2lih%2lim %2lih%2lim",
i,
pq->nick,
getfilename(pq->xpack->file),
(gdata.curtime-pq->queuedtime)/60/60,
((gdata.curtime-pq->queuedtime)/60)%60,
rtime/60/60,
(rtime/60)%60);
}
else
{
u_respond(u," %2i %-9s %-32s %2lih%2lim Unknown",
i,
pq->nick,
getfilename(pq->xpack->file),
(gdata.curtime-pq->queuedtime)/60/60,
((gdata.curtime-pq->queuedtime)/60)%60);
}
pq = irlist_get_next(pq);
i++;
}
}
static void u_close(const userinput * const u)
{
int num = -1;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ((num < 0) || !does_tr_id_exist(num))
{
u_respond(u,"Invalid ID number, Try \"DCL\" for a list");
}
else
{
t_closeconn(does_tr_id_exist(num),"Owner Requested Close",0);
}
}
static void u_closeu(const userinput * const u)
{
int num = -1;
upload *ul;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ((num < 0) || (num >= irlist_size(&gdata.uploads)))
{
u_respond(u,"Invalid ID number, Try \"DCL\" for a list");
}
else
{
ul = irlist_get_nth(&gdata.uploads, num);
l_closeconn(ul,"Owner Requested Close",0);
}
}
static void u_nomin(const userinput * const u)
{
int num = -1;
transfer *tr;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ((num < 0) || !does_tr_id_exist(num))
{
u_respond(u,"Invalid ID number, Try \"DCL\" for a list");
}
else
{
tr = does_tr_id_exist(num);
tr->nomin = 1;
}
}
static void u_nomax(const userinput * const u)
{
int num = -1;
transfer *tr;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ((num < 0) || !does_tr_id_exist(num))
{
u_respond(u,"Invalid ID number, Try \"DCL\" for a list");
}
else
{
tr = does_tr_id_exist(num);
tr->nomax = 1;
}
}
static void u_rmq(const userinput * const u)
{
int num = 0;
pqueue *pq;
updatecontext();
if (u->arg1)
{
num = atoi(u->arg1);
}
if (num < 1)
{
u_respond(u,"Invalid ID number, Try \"QUL\" for a list");
return;
}
pq = irlist_get_nth(&gdata.mainqueue, num-1);
if (!pq)
{
u_respond(u,"Invalid ID number, Try \"QUL\" for a list");
}
else
{
notice(pq->nick,"** Removed From Queue: Owner Requested Remove");
mydelete(pq->nick);
mydelete(pq->hostname);
irlist_delete(&gdata.mainqueue, pq);
}
}
static void u_raw(const userinput * const u)
{
updatecontext();
if (!u->arg1e || !strlen(u->arg1e))
{
u_respond(u,"Try Specifying a Command");
return;
}
writeserver(WRITESERVER_NOW, "%s", u->arg1e);
}
static void u_info(const userinput * const u)
{
int num = 0;
xdcc *xd;
char *sizestrstr;
char *sendnamestr;
char tempstr[maxtextlengthshort];
updatecontext();
if (u->arg1) { num = atoi(u->arg1); }
if (num < 1 || num > irlist_size(&gdata.xdccs))
{
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
u_respond(u, "Pack Info for Pack #%i:", num);
u_respond(u, " Filename %s", xd->file);
sendnamestr = getsendname(xd->file);
u_respond(u, " Sendname %s", sendnamestr);
mydelete(sendnamestr);
u_respond(u, " Description %s", xd->desc);
if (xd->note[0])
{
u_respond(u, " Note %s", xd->note);
}
sizestrstr = sizestr(1, xd->st_size);
u_respond(u, " Filesize %" LLPRINTFMT "i [%sB]",
(long long)xd->st_size, sizestrstr);
mydelete(sizestrstr);
getdatestr(tempstr, xd->mtime, maxtextlengthshort);
u_respond(u, " Last Modified %s", tempstr);
u_respond(u, " Device/Inode %" LLPRINTFMT "u/%" LLPRINTFMT "u",
(unsigned long long)xd->st_dev, (unsigned long long)xd->st_ino);
u_respond(u, " Gets %d", xd->gets);
if (xd->minspeed)
{
u_respond(u, " Minspeed %1.1fKB/sec", xd->minspeed);
}
if (xd->maxspeed)
{
u_respond(u, " Maxspeed %1.1fKB/sec", xd->maxspeed);
}
if (xd->has_md5sum)
{
u_respond(u, " md5sum " MD5_PRINT_FMT, MD5_PRINT_DATA(xd->md5sum));
}
return;
}
static void u_remove(const userinput * const u) {
int num = 0;
pqueue *pq;
transfer *tr;
xdcc *xd;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ( num < 1 || num > irlist_size(&gdata.xdccs) ) {
u_respond(u,"Try a valid pack number");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
tr = irlist_get_head(&gdata.trans);
while(tr)
{
if ((tr->tr_status != TRANSFER_STATUS_DONE) &&
(tr->xpack == xd))
{
t_closeconn(tr,"Pack removed",0);
}
tr = irlist_get_next(tr);
}
pq = irlist_get_head(&gdata.mainqueue);
while(pq)
{
if (pq->xpack == xd)
{
notice(pq->nick,"** Removed From Queue: Pack removed");
mydelete(pq->nick);
mydelete(pq->hostname);
pq = irlist_delete(&gdata.mainqueue, pq);
}
else
{
pq = irlist_get_next(pq);
}
}
u_respond(u,"Removed Pack %i [%s]", num, xd->desc);
if (gdata.md5build.xpack == xd)
{
outerror(OUTERROR_TYPE_WARN,"[MD5]: Canceled (remove)");
FD_CLR(gdata.md5build.file_fd, &gdata.readset);
close(gdata.md5build.file_fd);
gdata.md5build.file_fd = FD_UNUSED;
gdata.md5build.xpack = NULL;
}
assert(xd->file_fd == FD_UNUSED);
assert(xd->file_fd_count == 0);
#ifdef HAVE_MMAP
assert(!irlist_size(&xd->mmaps));
#endif
mydelete(xd->file);
mydelete(xd->desc);
mydelete(xd->note);
irlist_delete(&gdata.xdccs, xd);
write_statefile();
xdccsavetext();
}
static void u_removedir(const userinput * const u)
{
DIR *d;
struct dirent *f;
char *tempstr, *thedir;
int thedirlen;
xdcc *xd;
updatecontext();
if (!u->arg1e || !strlen(u->arg1e))
{
u_respond(u,"Try Specifying a Directory");
return;
}
convert_to_unix_slash(u->arg1e);
if (u->arg1e[strlen(u->arg1e)-1] == '/')
{
u->arg1e[strlen(u->arg1e)-1] = '\0';
}
thedirlen = strlen(u->arg1e);
if (gdata.filedir)
{
thedirlen += strlen(gdata.filedir) + 1;
}
thedir = mycalloc(thedirlen+1);
strcpy(thedir, u->arg1e);
d = opendir(thedir);
if (!d && (errno == ENOENT) && gdata.filedir)
{
snprintf(thedir, thedirlen+1, "%s/%s",
gdata.filedir, u->arg1e);
d = opendir(thedir);
}
if (!d)
{
u_respond(u,"Can't Access Directory: %s",strerror(errno));
return;
}
while ((f = readdir(d)))
{
struct stat st;
int len = strlen(f->d_name);
int n;
tempstr = mycalloc(len + thedirlen + 2);
snprintf(tempstr, len + thedirlen + 2,
"%s/%s", thedir, f->d_name);
if (stat(tempstr,&st) < 0)
{
u_respond(u,"cannot access %s, ignoring: %s",
tempstr, strerror(errno));
mydelete(tempstr);
continue;
}
else if (!S_ISREG(st.st_mode))
{
mydelete(tempstr);
continue;
}
n = 0;
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
n++;
if ((xd->st_dev == st.st_dev) &&
(xd->st_ino == st.st_ino))
{
userinput u2;
char tempstr2[8];
snprintf(tempstr2, 8, "%d", n);
u2 = *u;
u2.arg1 = tempstr2;
u_remove(&u2);
/* start over, the list has changed */
n = 0;
xd = irlist_get_head(&gdata.xdccs);
}
else
{
xd = irlist_get_next(xd);
}
}
mydelete(tempstr);
}
closedir(d);
mydelete(thedir);
return;
}
static void u_redraw(const userinput * const u) {
updatecontext();
initscreen(0);
gotobot();
}
static void u_delhist(const userinput * const u)
{
updatecontext();
u_respond(u, "Deleted all %d lines of console history",
irlist_size(&gdata.console_history));
irlist_delete_all(&gdata.console_history);
gdata.console_history_offset = 0;
return;
}
static void u_send(const userinput * const u) {
int num = 0;
updatecontext();
if (u->arg2) num = atoi(u->arg2);
if (!u->arg1 || !strlen(u->arg1)) {
u_respond(u,"Try Specifying a Nick");
return;
}
if (num > irlist_size(&gdata.xdccs) || num < 1) {
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
u_respond(u,"Sending %s pack %i",u->arg1,num);
sendxdccfile(u->arg1,"man","man",num,NULL);
}
static void u_psend(const userinput * const u)
{
userinput manplist;
userinput_method_e method;
updatecontext();
if (!u->arg1 || !strlen(u->arg1))
{
u_respond(u,"Try Specifying a Channel");
return;
}
if (!u->arg2 || !strlen(u->arg2))
{
method = method_xdl_channel;
u_respond(u, "No PLIST style specified. Using style full");
}
else
{
if (strcmp(u->arg2,"full") == 0)
{
method = method_xdl_channel;
}
else if (strcmp(u->arg2,"minimal") == 0)
{
method = method_xdl_channel_min;
}
else if (strcmp(u->arg2,"summary") == 0)
{
if (gdata.restrictprivlist && !gdata.creditline && !gdata.headline)
{
u_respond(u,"Summary Plist makes no sense with restrictprivlist set and no creditline or headline");
return;
}
else
{
method = method_xdl_channel_sum;
}
}
else
{
u_respond(u, "PLIST format is not (full|minimal|summary)");
return;
}
}
u_fillwith_msg(&manplist,u->arg1,"A A A A A xdl");
manplist.method = method;
u_parseit(&manplist);
u_respond(u,"Sending PLIST with style %s to %s",
u->arg2 ? u->arg2 : "full",
u->arg1);
}
static void u_msg(const userinput * const u)
{
updatecontext();
if (!u->arg1 || !strlen(u->arg1))
{
u_respond(u,"Try Specifying a Nick");
return;
}
if (!u->arg2e || !strlen(u->arg2e))
{
u_respond(u,"Try Specifying a Message");
return;
}
privmsg_fast(u->arg1,"%s",u->arg2e);
}
static void u_mesg(const userinput * const u)
{
transfer *tr;
updatecontext();
if (!u->arg1e || !strlen(u->arg1e))
{
u_respond(u,"Try Specifying a Message");
return;
}
tr = irlist_get_head(&gdata.trans);
while(tr)
{
notice(tr->nick,"MESSAGE FROM OWNER: %s",u->arg1e);
tr = irlist_get_next(tr);
}
u_respond(u,"Sent message to %i user%s",irlist_size(&gdata.trans),irlist_size(&gdata.trans)!=1?"s":"");
}
static void u_mesq(const userinput * const u)
{
int count;
pqueue *pq;
updatecontext();
if (!u->arg1e || !strlen(u->arg1e))
{
u_respond(u,"Try Specifying a Message");
return;
}
count=0;
pq = irlist_get_head(&gdata.mainqueue);
while(pq)
{
notice(pq->nick,"MESSAGE FROM OWNER: %s",u->arg1e);
count++;
pq = irlist_get_next(pq);
}
u_respond(u,"Sent message to %i user%s",count,count!=1?"s":"");
}
static void u_quit(const userinput * const u)
{
updatecontext();
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L,COLOR_MAGENTA,"DCC CHAT: QUIT");
u_respond(u,"Bye.");
shutdowndccchat(u->chat,1);
/* caller deletes */
}
static void u_status(const userinput * const u) {
char *tempstr = mycalloc(maxtextlength);
updatecontext();
getstatusline(tempstr,maxtextlength);
u_respond(u,"%s",tempstr);
mydelete(tempstr);
}
static void u_chfile(const userinput * const u) {
int num = 0;
int xfiledescriptor;
struct stat st;
char tempstr[maxtextlength];
transfer *tr;
xdcc *xd;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if (num < 1 || num > irlist_size(&gdata.xdccs)) {
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
if (!u->arg2e || !strlen(u->arg2e)) {
u_respond(u,"Try Specifying a Filename");
return;
}
/* verify file is ok first */
tempstr[0] = '\0';
convert_to_unix_slash(u->arg2e);
xfiledescriptor=open(u->arg2e, O_RDONLY | ADDED_OPEN_FLAGS);
if (xfiledescriptor < 0 && (errno == ENOENT) && gdata.filedir) {
snprintf(tempstr, maxtextlength - 1,
"%s/%s", gdata.filedir, u->arg2e);
convert_to_unix_slash(tempstr);
xfiledescriptor=open(tempstr, O_RDONLY | ADDED_OPEN_FLAGS);
}
if (xfiledescriptor < 0) {
u_respond(u,"Cant Access File: %s",strerror(errno));
return;
}
if (fstat(xfiledescriptor,&st) < 0)
{
u_respond(u,"Cant Access File Details: %s",strerror(errno));
close(xfiledescriptor);
return;
}
close(xfiledescriptor);
if ( st.st_size == 0 ) {
u_respond(u,"File has size of 0 bytes!");
return;
}
if ((st.st_size > gdata.max_file_size) || (st.st_size < 0)) {
u_respond(u,"File is too large.");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
tr = irlist_get_head(&gdata.trans);
while(tr)
{
if ((tr->tr_status != TRANSFER_STATUS_DONE) &&
(tr->xpack == xd))
{
t_closeconn(tr,"Pack file changed",0);
}
tr = irlist_get_next(tr);
}
u_respond(u, "CHFILE: [Pack %i] Old: %s New: %s",
num,xd->file,tempstr[0] ? tempstr : u->arg2e);
mydelete(xd->file);
xd->file = mycalloc(strlen(tempstr[0] ? tempstr : u->arg2e) + 1);
strcpy(xd->file, tempstr[0] ? tempstr : u->arg2e);
xd->st_size = st.st_size;
xd->st_dev = st.st_dev;
xd->st_ino = st.st_ino;
xd->mtime = st.st_mtime;
if (gdata.md5build.xpack == xd)
{
outerror(OUTERROR_TYPE_WARN,"[MD5]: Canceled (chfile)");
FD_CLR(gdata.md5build.file_fd, &gdata.readset);
close(gdata.md5build.file_fd);
gdata.md5build.file_fd = FD_UNUSED;
gdata.md5build.xpack = NULL;
}
xd->has_md5sum = 0;
memset(xd->md5sum,0,sizeof(MD5Digest));
assert(xd->file_fd == FD_UNUSED);
assert(xd->file_fd_count == 0);
#ifdef HAVE_MMAP
assert(!irlist_size(&xd->mmaps));
#endif
write_statefile();
xdccsavetext();
}
static void u_add(const userinput * const u) {
int xfiledescriptor;
struct stat st;
xdcc *xd;
updatecontext();
if (!u->arg1e || !strlen(u->arg1e)) {
u_respond(u,"Try Specifying a Filename");
return;
}
xd = irlist_add(&gdata.xdccs, sizeof(xdcc));
xd->file = mymalloc(strlen(u->arg1e)+1);
strcpy(xd->file,u->arg1e);
xd->note = mymalloc(1);
strcpy(xd->note,"");
xd->desc = mymalloc(strlen(getfilename(u->arg1e)) + 1);
strcpy(xd->desc,getfilename(u->arg1e));
convert_to_unix_slash(xd->file);
xd->gets = 0;
xd->minspeed = gdata.transferminspeed;
xd->maxspeed = gdata.transfermaxspeed;
xfiledescriptor=open(xd->file, O_RDONLY | ADDED_OPEN_FLAGS);
if (xfiledescriptor < 0 && (errno == ENOENT) && gdata.filedir)
{
mydelete(xd->file);
xd->file = mymalloc(strlen(gdata.filedir)+1+strlen(u->arg1e)+1);
sprintf(xd->file,"%s/%s",gdata.filedir,u->arg1e);
convert_to_unix_slash(xd->file);
xfiledescriptor=open(xd->file, O_RDONLY | ADDED_OPEN_FLAGS);
}
if (xfiledescriptor < 0) {
u_respond(u,"Cant Access File: %s",strerror(errno));
mydelete(xd->file);
mydelete(xd->desc);
mydelete(xd->note);
irlist_delete(&gdata.xdccs, xd);
return;
}
if (fstat(xfiledescriptor,&st) < 0)
{
u_respond(u,"Cant Access File Details: %s",strerror(errno));
mydelete(xd->file);
mydelete(xd->desc);
mydelete(xd->note);
irlist_delete(&gdata.xdccs, xd);
close(xfiledescriptor);
return;
}
if (!S_ISREG(st.st_mode))
{
u_respond(u,"%s is not a file",xd->file);
mydelete(xd->file);
mydelete(xd->desc);
mydelete(xd->note);
irlist_delete(&gdata.xdccs, xd);
close(xfiledescriptor);
return;
}
close(xfiledescriptor);
xd->st_size = st.st_size;
xd->st_dev = st.st_dev;
xd->st_ino = st.st_ino;
xd->mtime = st.st_mtime;
xd->file_fd = FD_UNUSED;
xd->file_fd_count = 0;
xd->file_fd_location = 0;
if ( xd->st_size == 0 ) {
u_respond(u,"File has size of 0 bytes!");
mydelete(xd->file);
mydelete(xd->desc);
mydelete(xd->note);
irlist_delete(&gdata.xdccs, xd);
return;
}
if ((xd->st_size > gdata.max_file_size) || (xd->st_size < 0)) {
u_respond(u,"File is too large.");
mydelete(xd->file);
mydelete(xd->desc);
mydelete(xd->note);
irlist_delete(&gdata.xdccs, xd);
return;
}
u_respond(u, "ADD PACK: [Pack: %i] [File: %s] Use CHDESC to change description",
irlist_size(&gdata.xdccs),xd->file);
write_statefile();
xdccsavetext();
}
static void u_adddir(const userinput * const u)
{
DIR *d;
struct dirent *f;
char *thefile, *tempstr, *thedir;
irlist_t dirlist = {};
int thedirlen;
updatecontext();
if (!u->arg1e || !strlen(u->arg1e))
{
u_respond(u,"Try Specifying a Directory");
return;
}
convert_to_unix_slash(u->arg1e);
if (u->arg1e[strlen(u->arg1e)-1] == '/')
{
u->arg1e[strlen(u->arg1e)-1] = '\0';
}
thedirlen = strlen(u->arg1e);
if (gdata.filedir)
{
thedirlen += strlen(gdata.filedir) + 1;
}
thedir = mymalloc(thedirlen+1);
strcpy(thedir, u->arg1e);
d = opendir(thedir);
if (!d && (errno == ENOENT) && gdata.filedir)
{
snprintf(thedir, thedirlen+1, "%s/%s",
gdata.filedir, u->arg1e);
d = opendir(thedir);
}
if (!d)
{
u_respond(u,"Can't Access Directory: %s",strerror(errno));
return;
}
while ((f = readdir(d)))
{
struct stat st;
int len = strlen(f->d_name);
tempstr = mycalloc(len + thedirlen + 2);
snprintf(tempstr, len + thedirlen + 2,
"%s/%s", thedir, f->d_name);
if (stat(tempstr,&st) < 0)
{
u_respond(u,"cannot access %s, ignoring: %s",
tempstr, strerror(errno));
}
else if (strcmp(f->d_name,".") &&
strcmp(f->d_name,"..") &&
S_ISDIR(st.st_mode))
{
u_respond(u," Ignoring directory: %s", tempstr);
}
else if (S_ISREG(st.st_mode))
{
thefile = irlist_add(&dirlist, len + thedirlen + 2);
strcpy(thefile, tempstr);
}
mydelete(tempstr);
}
closedir(d);
irlist_sort(&dirlist, irlist_sort_cmpfunc_string, NULL);
u_respond(u,"Adding %d files...",
irlist_size(&dirlist));
thefile = irlist_get_head(&dirlist);
while (thefile)
{
userinput u2;
u_respond(u," Adding %s:",thefile);
u2 = *u;
u2.arg1e = thefile;
u_add(&u2);
thefile = irlist_delete(&dirlist, thefile);
}
mydelete(thedir);
return;
}
static void u_addnew(const userinput * const u)
{
DIR *d;
struct dirent *f;
char *thefile, *tempstr, *thedir;
irlist_t dirlist = {};
int thedirlen, foundit;
xdcc *xd;
updatecontext();
if (!u->arg1e || !strlen(u->arg1e))
{
u_respond(u,"Try Specifying a Directory");
return;
}
convert_to_unix_slash(u->arg1e);
if (u->arg1e[strlen(u->arg1e)-1] == '/')
{
u->arg1e[strlen(u->arg1e)-1] = '\0';
}
thedirlen = strlen(u->arg1e);
if (gdata.filedir)
{
thedirlen += strlen(gdata.filedir) + 1;
}
thedir = mymalloc(thedirlen+1);
strcpy(thedir, u->arg1e);
d = opendir(thedir);
if (!d && (errno == ENOENT) && gdata.filedir)
{
snprintf(thedir, thedirlen+1, "%s/%s",
gdata.filedir, u->arg1e);
d = opendir(thedir);
}
if (!d)
{
u_respond(u,"Can't Access Directory: %s",strerror(errno));
return;
}
while ((f = readdir(d)))
{
struct stat st;
int len = strlen(f->d_name);
tempstr = mycalloc(len + thedirlen + 2);
snprintf(tempstr, len + thedirlen + 2,
"%s/%s", thedir, f->d_name);
if (stat(tempstr,&st) < 0)
{
u_respond(u,"cannot access %s, ignoring: %s",
tempstr, strerror(errno));
}
else if (strcmp(f->d_name,".") &&
strcmp(f->d_name,"..") &&
S_ISDIR(st.st_mode))
{
u_respond(u," Ignoring directory: %s", tempstr);
}
else if (S_ISREG(st.st_mode))
{
foundit = 0;
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
if (!strcmp(tempstr, xd->file))
{
foundit = 1;
break;
}
xd = irlist_get_next(xd);
}
if (foundit == 0)
{
thefile = irlist_add(&dirlist, len + thedirlen + 2);
strcpy(thefile, tempstr);
}
}
mydelete(tempstr);
}
closedir(d);
irlist_sort(&dirlist, irlist_sort_cmpfunc_string, NULL);
u_respond(u,"Adding %d new files...",
irlist_size(&dirlist));
thefile = irlist_get_head(&dirlist);
while (thefile)
{
userinput u2;
u_respond(u," Adding %s:",thefile);
u2 = *u;
u2.arg1e = thefile;
u_add(&u2);
thefile = irlist_delete(&dirlist, thefile);
}
mydelete(thedir);
return;
}
static void u_chdesc(const userinput * const u) {
int num = 0;
xdcc *xd;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if (num < 1 || num > irlist_size(&gdata.xdccs)) {
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
if (!u->arg2e || !strlen(u->arg2e)) {
u_respond(u,"Try Specifying a Description");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
u_respond(u, "CHDESC: [Pack %i] Old: %s New: %s",
num,xd->desc,u->arg2e);
mydelete(xd->desc);
xd->desc = mymalloc(strlen(u->arg2e) + 1);
strcpy(xd->desc,u->arg2e);
write_statefile();
xdccsavetext();
}
static void u_chnote(const userinput * const u) {
int num = 0;
xdcc *xd;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if (num < 1 || num > irlist_size(&gdata.xdccs)) {
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
u_respond(u, "CHNOTE: [Pack %i] Old: %s New: %s",
num,xd->note,
u->arg2e ? u->arg2e : "");
mydelete(xd->note);
if (!u->arg2e)
{
xd->note = mymalloc(1);
strcpy(xd->note,"");
}
else
{
xd->note = mymalloc(strlen(u->arg2e) + 1);
strcpy(xd->note,u->arg2e);
}
write_statefile();
xdccsavetext();
}
static void u_chmins(const userinput * const u) {
int num = 0;
xdcc *xd;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if (num < 1 || num > irlist_size(&gdata.xdccs)) {
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
if (!u->arg2 || !strlen(u->arg2)) {
u_respond(u,"Try Specifying a Minspeed");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
u_respond(u, "CHMINS: [Pack %i] Old: %1.1f New: %1.1f",
num,xd->minspeed,atof(u->arg2));
xd->minspeed = gdata.transferminspeed;
if ( atof(u->arg2) != gdata.transferminspeed )
xd->minspeed = atof(u->arg2);
write_statefile();
xdccsavetext();
}
static void u_chmaxs(const userinput * const u) {
int num = 0;
xdcc *xd;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if (num < 1 || num > irlist_size(&gdata.xdccs)) {
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
if (!u->arg2 || !strlen(u->arg2)) {
u_respond(u,"Try Specifying a Maxspeed");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
u_respond(u, "CHMAXS: [Pack %i] Old: %1.1f New: %1.1f",
num,xd->maxspeed,atof(u->arg2));
xd->maxspeed = gdata.transfermaxspeed;
if ( atof(u->arg2) != gdata.transfermaxspeed )
xd->maxspeed = atof(u->arg2);
write_statefile();
xdccsavetext();
}
static void u_chgets(const userinput * const u)
{
int num = 0;
xdcc *xd;
updatecontext();
if (u->arg1)
{
num = atoi(u->arg1);
}
if (num < 1 || num > irlist_size(&gdata.xdccs))
{
u_respond(u,"Try Specifying a Valid Pack Number");
return;
}
if (!u->arg2 || !strlen(u->arg2))
{
u_respond(u,"Try Specifying a Count");
return;
}
xd = irlist_get_nth(&gdata.xdccs, num-1);
u_respond(u, "CHGETS: [Pack %i] Old: %d New: %d",
num,xd->gets,atoi(u->arg2));
xd->gets = atoi(u->arg2);
write_statefile();
xdccsavetext();
}
static void u_chatme(const userinput * const u) {
updatecontext();
u_respond(u,"Sending You A DCC Chat Request");
if (setupdccchatout(u->snick))
u_respond(u,"[Failed to listen, try again]");
}
static void u_chatl(const userinput * const u)
{
char *tempstr;
dccchat_t *chat;
int count;
updatecontext();
if (!gdata.num_dccchats)
{
u_respond(u,"No Active DCC Chats");
return;
}
for (chat = irlist_get_head(&gdata.dccchats), count = 1;
chat;
chat = irlist_get_next(chat), count++)
{
if (chat->status == DCCCHAT_UNUSED)
{
continue;
}
u_respond(u,"DCC CHAT %d:",count);
switch (chat->status)
{
case DCCCHAT_LISTENING:
u_respond(u," Chat sent to %s. Waiting for inbound connection.",
chat->nick);
break;
case DCCCHAT_CONNECTING:
u_respond(u," Chat received from %s. Waiting for outbound connection.",
chat->nick);
break;
case DCCCHAT_AUTHENTICATING:
u_respond(u," Chat established with %s. Waiting for password.",
chat->nick);
break;
case DCCCHAT_CONNECTED:
u_respond(u," Chat established with %s.",
chat->nick);
break;
case DCCCHAT_UNUSED:
default:
outerror(OUTERROR_TYPE_CRASH,
"Unexpected dccchat state %d", chat->status);
break;
}
tempstr = mycalloc(maxtextlengthshort);
getdatestr(tempstr,chat->connecttime,maxtextlengthshort);
u_respond(u," Connected at %s",tempstr);
getdatestr(tempstr,chat->connecttime,maxtextlengthshort);
u_respond(u," Last contact %s",tempstr);
mydelete(tempstr);
u_respond(u," Local: %lu.%lu.%lu.%lu:%d, Remote: %lu.%lu.%lu.%lu:%d",
(chat->localip >> 24) & 0xFF,
(chat->localip >> 16) & 0xFF,
(chat->localip >> 8) & 0xFF,
(chat->localip ) & 0xFF,
chat->localport,
(chat->remoteip >> 24) & 0xFF,
(chat->remoteip >> 16) & 0xFF,
(chat->remoteip >> 8) & 0xFF,
(chat->remoteip ) & 0xFF,
chat->remoteport);
}
return;
}
static void u_closec(const userinput * const u)
{
int num = -1;
dccchat_t *chat;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ((num < 1) || (num > irlist_size(&gdata.dccchats)))
{
u_respond(u,"Invalid ID number, Try \"CHATL\" for a list");
}
else
{
chat = irlist_get_nth(&gdata.dccchats, num-1);
if (chat == u->chat)
{
u_respond(u, "Disconnecting yourself.");
shutdowndccchat(chat,1);
}
else
{
writedccchat(chat, 0, "Disconnected due to CLOSEC\n");
shutdowndccchat(chat,1);
}
}
return;
}
static void u_rehash(const userinput * const u) {
/* other variables */
char *templine = mycalloc(maxtextlength);
int h,i,filedescriptor,needtojump;
channel_t *ch, *rch;
xdcc *xd;
updatecontext();
if (u->method==method_out_all) u_respond(u,"Caught SIGUSR2, Rehashing...");
gdata.r_transferminspeed = gdata.transferminspeed;
gdata.r_transfermaxspeed = gdata.transfermaxspeed;
if (gdata.logfd != FD_UNUSED)
{
close(gdata.logfd);
gdata.logfd = FD_UNUSED;
}
reinit_config_vars();
set_loginname();
/* go */
for (h=0; h<MAXCONFIG && gdata.configfile[h]; h++) {
u_respond(u,"Reloading %s ...",gdata.configfile[h]);
filedescriptor=open(gdata.configfile[h], O_RDONLY | ADDED_OPEN_FLAGS);
if (filedescriptor < 0) {
u_respond(u,"Cant Access File, Aborting rehash: %s",strerror(errno));
u_respond(u,"**WARNING** missing vital information, fix and re-rehash ASAP");
mydelete(templine);
return;
}
while (getfline(templine,maxtextlength,filedescriptor,1))
{
if ((templine[0] != '#') && templine[0])
{
getconfig_set(templine,1);
}
}
close(filedescriptor);
}
/* see what needs to be redone */
u_respond(u,"Reconfiguring...");
needtojump=0;
if (gdata.local_vhost != gdata.r_local_vhost)
{
needtojump=1;
}
/* part deleted channels, add common channels */
ch = irlist_get_head(&gdata.channels);
while(ch)
{
rch = irlist_get_head(&gdata.r_channels);
while(rch)
{
if (!strcmp(ch->name,rch->name))
{
break;
}
rch = irlist_get_next(rch);
}
if (!rch)
{
if (!needtojump && (ch->flags & CHAN_ONCHAN))
{
writeserver(WRITESERVER_NORMAL, "PART %s", ch->name);
}
if (gdata.debug > 2)
{
ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR,
"1 = %s parted\n",ch->name);
}
clearmemberlist(ch);
mydelete(ch->name);
mydelete(ch->key);
ch = irlist_delete(&gdata.channels, ch);
}
else
{
rch->flags |= ch->flags & CHAN_ONCHAN;
rch->members = ch->members;
mydelete(ch->name);
mydelete(ch->key);
*ch = *rch;
if (gdata.debug > 2)
{
ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR,
"2 = %s common\n", ch->name);
}
irlist_delete(&gdata.r_channels, rch);
ch = irlist_get_next(ch);
}
}
/* join/add new channels */
rch = irlist_get_head(&gdata.r_channels);
while(rch)
{
ch = irlist_get_head(&gdata.channels);
while(ch)
{
if (!strcmp(ch->name,rch->name))
{
break;
}
ch = irlist_get_next(ch);
}
if (!ch)
{
ch = irlist_add(&gdata.channels, sizeof(channel_t));
*ch = *rch;
ch->flags &= ~CHAN_ONCHAN;
if (!needtojump)
{
joinchannel(ch);
}
if (gdata.debug > 2)
{
ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR,
"3 = %s new\n",ch->name);
}
rch = irlist_delete(&gdata.r_channels, rch);
}
else
{
outerror(OUTERROR_TYPE_CRASH,"channel found!");
}
}
gdata.local_vhost = gdata.r_local_vhost;
gdata.r_local_vhost = 0;
if (needtojump) {
u_respond(u,"vhost changed, reconnecting");
switchserver(-1);
/* switchserver takes care of joining channels */
}
if (((!gdata.pidfile) && (gdata.r_pidfile)) ||
((gdata.pidfile) && (!gdata.r_pidfile)) ||
((gdata.pidfile) && (gdata.r_pidfile) && strcmp(gdata.pidfile,gdata.r_pidfile)))
{
u_respond(u,"pidfile changed, switching");
if (gdata.pidfile)
{
unlink(gdata.pidfile);
}
if (gdata.r_pidfile)
{
writepidfile(gdata.r_pidfile);
}
}
mydelete(gdata.pidfile);
gdata.pidfile = gdata.r_pidfile;
gdata.r_pidfile = NULL;
if (!gdata.r_config_nick)
{
u_respond(u,"user_nick missing! keeping old nick!");
}
else
{
if (strcmp(gdata.config_nick,gdata.r_config_nick))
{
u_respond(u,"user_nick changed, renaming nick to %s", gdata.r_config_nick);
writeserver(WRITESERVER_NOW, "NICK %s", gdata.r_config_nick);
}
mydelete(gdata.config_nick);
gdata.config_nick = gdata.r_config_nick;
gdata.r_config_nick = NULL;
}
gdata.maxb = gdata.overallmaxspeed;
if (gdata.overallmaxspeeddayspeed != gdata.overallmaxspeed) {
struct tm *localt;
localt = localtime(&gdata.curtime);
if (localt->tm_hour >= gdata.overallmaxspeeddaytimestart
&& localt->tm_hour < gdata.overallmaxspeeddaytimeend
&& ( gdata.overallmaxspeeddaydays & (1 << localt->tm_wday)) )
gdata.maxb = gdata.overallmaxspeeddayspeed;
}
if ( gdata.r_transferminspeed != gdata.transferminspeed)
{
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
if (xd->minspeed == gdata.r_transferminspeed)
{
xd->minspeed = gdata.transferminspeed;
}
xd = irlist_get_next(xd);
}
}
if ( gdata.r_transfermaxspeed != gdata.transfermaxspeed)
{
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
if (xd->maxspeed == gdata.r_transfermaxspeed)
{
xd->maxspeed = gdata.transfermaxspeed;
}
xd = irlist_get_next(xd);
}
}
/* check for completeness */
u_respond(u,"Checking for completeness of config file ...");
if ( !irlist_size(&gdata.servers)
|| gdata.config_nick == NULL || gdata.user_realname == NULL
|| gdata.user_modes == NULL
|| gdata.slotsmax == 0)
u_respond(u,"**WARNING** missing vital information, fix and re-rehash ASAP");
if ( irlist_size(&gdata.uploadhost) && ( gdata.uploaddir == NULL || strlen(gdata.uploaddir) < 2 ) )
u_respond(u,"**WARNING** incomplete upload information, fix and re-rehash ASAP");
if ( !irlist_size(&gdata.downloadhost) )
{
u_respond(u,"**WARNING** no download hosts defined");
}
if ( !gdata.statefile )
{
u_respond(u,"**WARNING** no state file defined");
}
u_respond(u,"Done.");
reverify_restrictsend();
for (i=0; i<100; i++)
{
if (!gdata.exiting &&
irlist_size(&gdata.mainqueue) &&
(irlist_size(&gdata.trans) < min2(MAXTRANS,gdata.slotsmax)))
{
sendaqueue(0);
}
}
mydelete(templine);
}
static void u_botinfo(const userinput * const u) {
char *tempstr = mycalloc(maxtextlength);
struct rusage r;
int len;
int ii;
channel_t *ch;
updatecontext();
u_respond(u,"BotInfo:");
u_respond(u,"iroffer v" VERSIONLONG ", http://iroffer.org/%s%s",
gdata.hideos ? "" : " - ",
gdata.hideos ? "" : gdata.osstring);
getuptime(tempstr, 0, gdata.startuptime, maxtextlength);
u_respond(u,"iroffer started up %s ago",tempstr);
getuptime(tempstr, 0, gdata.curtime-gdata.totaluptime, maxtextlength);
u_respond(u,"total running time of %s",tempstr);
getrusage(RUSAGE_SELF,&r);
u_respond(u,"cpu usage: %2.2fs user (%2.5f%%), %2.2fs system (%2.5f%%)",
((float)r.ru_utime.tv_sec+(((float)r.ru_utime.tv_usec)/1000000.0)),
100.0*((float)r.ru_utime.tv_sec+(((float)r.ru_utime.tv_usec)/1000000.0))/((float)(max2(1,gdata.curtime-gdata.startuptime))),
((float)r.ru_stime.tv_sec+(((float)r.ru_stime.tv_usec)/1000000.0)),
100.0*((float)r.ru_stime.tv_sec+(((float)r.ru_stime.tv_usec)/1000000.0))/((float)(max2(1,gdata.curtime-gdata.startuptime)))
);
u_respond(u,"configured nick: %s, actual nick: %s, realname: %s, modes: %s",
gdata.config_nick,
(gdata.user_nick ? gdata.user_nick : "??"),
gdata.user_realname,
gdata.user_modes);
switch (gdata.connectionmethod.how)
{
case how_direct:
u_respond(u,"current server: %s:%u (direct)",
gdata.curserver.hostname,gdata.curserver.port);
break;
case how_bnc:
if (gdata.connectionmethod.vhost)
{
u_respond(u,"current server: %s:%u (bnc at %s:%i with %s)",
gdata.curserver.hostname,gdata.curserver.port,gdata.connectionmethod.host,gdata.connectionmethod.port,gdata.connectionmethod.vhost);
}
else
{
u_respond(u,"current server: %s:%u (bnc at %s:%i)",
gdata.curserver.hostname,gdata.curserver.port,gdata.connectionmethod.host,gdata.connectionmethod.port);
}
break;
case how_wingate:
u_respond(u,"current server: %s:%u (wingate at %s:%i)",
gdata.curserver.hostname,gdata.curserver.port,gdata.connectionmethod.host,gdata.connectionmethod.port);
break;
case how_custom:
u_respond(u,"current server: %s:%u (custom at %s:%i)",
gdata.curserver.hostname,gdata.curserver.port,gdata.connectionmethod.host,gdata.connectionmethod.port);
break;
}
u_respond(u,"current server actual name: %s ",
gdata.curserveractualname ? gdata.curserveractualname : "<unknown>");
ch = irlist_get_head(&gdata.channels);
while(ch)
{
snprintf(tempstr, maxtextlength - 1,
"channel %10s: joined: %3s",
ch->name,
ch->flags & CHAN_ONCHAN ? "yes" : "no ");
len = strlen(tempstr);
if (ch->key)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
", key: %s",
ch->key);
len = strlen(tempstr);
}
if (ch->plisttime)
{
snprintf(tempstr + len, maxtextlength - 1 - len,
", plist every %2i min (%s)",
ch->plisttime,
ch->flags & CHAN_MINIMAL ? "minimal" : (ch->flags & CHAN_SUMMARY ? "summary" : "full"));
}
u_respond(u,"%s",tempstr);
ch = irlist_get_next(ch);
}
u_respond(u, "bandwidth: lowsend: %i, minspeed: %1.1f, maxspeed: %1.1f, overallmaxspeed: %i",
gdata.lowbdwth,gdata.transferminspeed,gdata.transfermaxspeed,gdata.maxb/4);
if (gdata.overallmaxspeed != gdata.overallmaxspeeddayspeed)
{
u_respond(u, " default max: %i, day max: %i ( %i:00 -> %i:59, days=\"%s%s%s%s%s%s%s\" )",
gdata.overallmaxspeed/4,gdata.overallmaxspeeddayspeed/4,
gdata.overallmaxspeeddaytimestart,gdata.overallmaxspeeddaytimeend-1,
(gdata.overallmaxspeeddaydays & (1 << 1)) ? "M":"",
(gdata.overallmaxspeeddaydays & (1 << 2)) ? "T":"",
(gdata.overallmaxspeeddaydays & (1 << 3)) ? "W":"",
(gdata.overallmaxspeeddaydays & (1 << 4)) ? "R":"",
(gdata.overallmaxspeeddaydays & (1 << 5)) ? "F":"",
(gdata.overallmaxspeeddaydays & (1 << 6)) ? "S":"",
(gdata.overallmaxspeeddaydays & (1 << 0)) ? "U":"");
}
else
{
u_respond(u, " default max: %i, day max: (same)",
gdata.overallmaxspeed/4);
}
for (ii=0; ii<NUMBER_TRANSFERLIMITS; ii++)
{
char *tempstr2 = mycalloc(maxtextlength);
getdatestr(tempstr2, gdata.transferlimits[ii].ends, maxtextlength);
if (gdata.transferlimits[ii].limit)
{
u_respond(u, "transferlimit: %7s (ends %s): used %" LLPRINTFMT "uMB, limit %" LLPRINTFMT "uMB",
transferlimit_type_to_string(ii), tempstr2,
gdata.transferlimits[ii].used / 1024 / 1024,
gdata.transferlimits[ii].limit / 1024 / 1024);
}
else
{
u_respond(u, "transferlimit: %7s (ends %s): used %" LLPRINTFMT "uMB, limit unlimited",
transferlimit_type_to_string(ii),tempstr2 ,
gdata.transferlimits[ii].used / 1024 / 1024);
}
}
u_respond(u, "files: pid: %s, log: %s, state: %s, xdcclist: %s",
(gdata.pidfile?gdata.pidfile:"(none)"),
(gdata.logfile?gdata.logfile:"(none)"),
(gdata.statefile?gdata.statefile:"(none)"),
(gdata.xdcclistfile?gdata.xdcclistfile:"(none)"));
u_respond(u, "config file%s: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
gdata.configfile[1]?"s":"",
gdata.configfile[0],
gdata.configfile[1]?", ":"",gdata.configfile[1]?gdata.configfile[1]:"",
gdata.configfile[2]?", ":"",gdata.configfile[2]?gdata.configfile[2]:"",
gdata.configfile[3]?", ":"",gdata.configfile[3]?gdata.configfile[3]:"",
gdata.configfile[4]?", ":"",gdata.configfile[4]?gdata.configfile[4]:"",
gdata.configfile[5]?", ":"",gdata.configfile[5]?gdata.configfile[5]:"",
gdata.configfile[6]?", ":"",gdata.configfile[6]?gdata.configfile[6]:"",
gdata.configfile[7]?", ":"",gdata.configfile[7]?gdata.configfile[7]:"",
gdata.configfile[8]?", ":"",gdata.configfile[8]?gdata.configfile[8]:"",
gdata.configfile[9]?", ":"",gdata.configfile[9]?gdata.configfile[9]:""
);
if (irlist_size(&gdata.uploadhost)) {
snprintf(tempstr,maxtextlength - 1,
"%" LLPRINTFMT "iMB",
(long long)(gdata.uploadmaxsize/1024/1024));
u_respond(u, "upload allowed, dir: %s, max size: %s",
gdata.uploaddir,
gdata.uploadmaxsize?tempstr:"none");
}
if (gdata.stdout_buffer_init)
{
u_respond(u,"console buffering: %u written, %u flushed, %u dropped (%u queued)",
gdata.stdout_buffer.count_written,
gdata.stdout_buffer.count_flushed,
gdata.stdout_buffer.count_dropped,
gdata.stdout_buffer.count_written - gdata.stdout_buffer.count_flushed);
}
u_respond(u,"transfer method: %s (blocksize %d)",
#if defined(HAVE_LINUX_SENDFILE)
(gdata.transfermethod == TRANSFERMETHOD_LINUX_SENDFILE) ? "linux-sendfile" :
#endif
#if defined(HAVE_FREEBSD_SENDFILE)
(gdata.transfermethod == TRANSFERMETHOD_FREEBSD_SENDFILE) ? "freebsd-sendfile" :
#endif
#if defined(HAVE_MMAP)
(gdata.transfermethod == TRANSFERMETHOD_MMAP) ? "mmap/write" :
#endif
(gdata.transfermethod == TRANSFERMETHOD_READ_WRITE) ? "read/write" : "unknown",
BUFFERSIZE);
if (gdata.delayedshutdown) {
u_respond(u,"NOTICE: Delayed shutdown activated, iroffer will shutdown once there are no active transfers");
u_respond(u,"NOTICE: To cancel the delayed shutdown, issue \"SHUTDOWN CANCEL\"");
}
mydelete(tempstr);
}
static void u_ignl(const userinput * const u)
{
int first;
int left, ago;
igninfo *ignore;
updatecontext();
if (!irlist_size(&gdata.ignorelist))
{
u_respond(u,"No Hosts Ignored or Watched");
return;
}
first = 1;
ignore = irlist_get_head(&gdata.ignorelist);
while(ignore)
{
if (ignore->flags & IGN_IGNORING)
{
if (first)
{
u_respond(u,"Current Ignore List:");
u_respond(u," Last Request Un-Ignore Type Hostmask");
first = 0;
}
ago = gdata.curtime-ignore->lastcontact;
left = gdata.autoignore_threshold*(ignore->bucket+1);
u_respond(u," %4i%c%02i%c ago %4i%c%02i%c %6s %-32s",
ago < 3600 ? ago/60 : ago/60/60 ,
ago < 3600 ? 'm' : 'h',
ago < 3600 ? ago%60 : (ago/60)%60 ,
ago < 3600 ? 's' : 'm',
left < 3600 ? left/60 : left/60/60 ,
left < 3600 ? 'm' : 'h',
left < 3600 ? left%60 : (left/60)%60 ,
left < 3600 ? 's' : 'm',
ignore->flags & IGN_MANUAL ? "manual" : "auto",
ignore->hostmask);
}
ignore = irlist_get_next(ignore);
}
first = 1;
ignore = irlist_get_head(&gdata.ignorelist);
while(ignore)
{
if (!(ignore->flags & IGN_IGNORING))
{
if (first)
{
u_respond(u,"Current Watch List:");
u_respond(u," Last Request Un-Watch Hostmask");
first = 0;
}
ago = gdata.curtime-ignore->lastcontact;
left = gdata.autoignore_threshold*(ignore->bucket+1);
u_respond(u," %4i%c%02i%c ago %4i%c%02i%c %-32s",
ago < 3600 ? ago/60 : ago/60/60 ,
ago < 3600 ? 'm' : 'h',
ago < 3600 ? ago%60 : (ago/60)%60 ,
ago < 3600 ? 's' : 'm',
left < 3600 ? left/60 : left/60/60 ,
left < 3600 ? 'm' : 'h',
left < 3600 ? left%60 : (left/60)%60 ,
left < 3600 ? 's' : 'm',
ignore->hostmask);
}
ignore = irlist_get_next(ignore);
}
return;
}
static void u_ignore(const userinput * const u)
{
int num=0;
igninfo *ignore;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if (!u->arg1)
{
u_respond(u,"Try specifying an amount of time to ignore");
return;
}
if (!u->arg2 || strlen(u->arg2) < 4)
{
u_respond(u,"Try specifying a hostmask longer than 4 characters");
return;
}
ignore = irlist_get_head(&gdata.ignorelist);
while(ignore)
{
if (ignore->regexp && !regexec(ignore->regexp,u->arg2,0,NULL,0))
{
break;
}
ignore = irlist_get_next(ignore);
}
if (!ignore)
{
char *tempstr;
ignore = irlist_add(&gdata.ignorelist, sizeof(igninfo));
ignore->regexp = mycalloc(sizeof(regex_t));
ignore->hostmask = mymalloc(strlen(u->arg2)+1);
strcpy(ignore->hostmask,u->arg2);
tempstr = hostmasktoregex(u->arg2);
if (regcomp(ignore->regexp,tempstr,REG_ICASE|REG_NOSUB))
{
ignore->regexp = NULL;
}
ignore->flags |= IGN_IGNORING;
ignore->lastcontact = gdata.curtime;
mydelete(tempstr);
}
ignore->flags |= IGN_MANUAL;
ignore->bucket = (num*60)/gdata.autoignore_threshold;
u_respond(u, "Ignore activated for %s which will last %i min",
u->arg2,num);
write_statefile();
}
static void u_unignore(const userinput * const u)
{
igninfo *ignore;
updatecontext();
if (!u->arg1)
{
u_respond(u,"Try specifying a hostmask to un-ignore");
return;
}
ignore = irlist_get_head(&gdata.ignorelist);
while(ignore)
{
if (strcmp(ignore->hostmask,u->arg1) == 0)
{
mydelete(ignore->hostmask);
if (ignore->regexp)
{
regfree(ignore->regexp);
}
mydelete(ignore->regexp);
irlist_delete(&gdata.ignorelist, ignore);
u_respond(u, "Ignore removed for %s",u->arg1);
write_statefile();
break;
}
else
{
ignore = irlist_get_next(ignore);
}
}
if (!ignore)
{
u_respond(u,"Hostmask not found");
}
return;
}
static void u_nosave(const userinput * const u) {
int num = 0;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
gdata.noautosave=gdata.curtime + 60*num - 1;
u_respond(u,"** XDCC AutoSave has been disabled for the next %i minute%s",num,num!=1?"s":"");
}
static void u_nosend(const userinput * const u) {
int num = 0;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
gdata.nonewcons=gdata.curtime + 60*num - 1;
u_respond(u,"** XDCC Send has been disabled for the next %i minute%s",num,num!=1?"s":"");
}
static void u_nolist(const userinput * const u) {
int num = 0;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
gdata.nolisting=gdata.curtime + 60*num - 1;
u_respond(u,"** XDCC List and PLIST have been disabled for the next %i minute%s",num,num!=1?"s":"");
}
static void u_renumber(const userinput * const u)
{
int oldp = 0, newp = 0;
xdcc *xdo, *xdn;
updatecontext();
if (u->arg1) oldp = atoi(u->arg1);
if (u->arg2) newp = atoi(u->arg2);
if ((oldp < 1) ||
(oldp > irlist_size(&gdata.xdccs)) ||
(newp < 1) ||
(newp > irlist_size(&gdata.xdccs)) ||
(newp == oldp))
{
u_respond(u,"Invalid pack number");
return;
}
u_respond(u,"** Moved pack %i to %i",oldp,newp);
/* get pack we are renumbering */
xdo = irlist_get_nth(&gdata.xdccs, oldp-1);
irlist_remove(&gdata.xdccs, xdo);
if (newp == 1)
{
irlist_insert_head(&gdata.xdccs, xdo);
}
else
{
xdn = irlist_get_nth(&gdata.xdccs, newp-2);
irlist_insert_after(&gdata.xdccs, xdo, xdn);
}
write_statefile();
xdccsavetext();
}
static void u_msgread(const userinput * const u)
{
int count;
char *tempstr;
msglog_t *ml;
updatecontext();
tempstr = mycalloc(maxtextlength);
for (ml = irlist_get_head(&gdata.msglog); ml; ml = irlist_get_next(ml))
{
getdatestr(tempstr, ml->when, maxtextlength);
u_respond(u, "%s: %s", tempstr, ml->hostmask);
u_respond(u, " ^- %s", ml->message);
}
mydelete(tempstr);
count = irlist_size(&gdata.msglog);
u_respond(u, "msglog: %i message%s in log%s%s",
count,
count != 1 ? "s" : "",
count ? ", use MSGDEL to remove " : "",
count > 1 ? "them" : (count == 1 ? "it" : ""));
return;
}
static void u_msgdel(const userinput * const u)
{
msglog_t *ml;
updatecontext();
u_respond(u,"msglog: deleted %d messages",
irlist_size(&gdata.msglog));
while ((ml = irlist_get_head(&gdata.msglog)))
{
mydelete(ml->hostmask);
mydelete(ml->message);
irlist_delete(&gdata.msglog, ml);
}
write_statefile();
return;
}
static void u_memstat(const userinput * const u)
{
int i;
long numcountrecent, sizecount;
struct rusage r;
#ifdef HAVE_MMAP
xdcc *xd;
int mmap_count;
#endif
updatecontext();
u_respond(u,"iroffer memory usage:");
getrusage(RUSAGE_SELF,&r);
u_respond(u,"rusage: maxrss %li, ixrss %li, idrss %li, "
"isrss %li, minflt %li, majflt %li, nswap %li",
r.ru_maxrss, r.ru_ixrss, r.ru_idrss,
r.ru_isrss, r.ru_minflt, r.ru_majflt, r.ru_nswap);
u_respond(u," inbloc %li, oublock %li, msgsnd %li, "
"msgrcv %li, nsignals %li, nvcsw %li, nivcsw %li",
r.ru_inblock, r.ru_oublock, r.ru_msgsnd,
r.ru_msgrcv, r.ru_nsignals, r.ru_nvcsw, r.ru_nivcsw);
u_respond(u, "gdata: %d bytes", sizeof(gdata_t));
numcountrecent = sizecount = 0;
for (i=0; i<(MEMINFOHASHSIZE * gdata.meminfo_depth); i++)
{
if (gdata.meminfo[i].ptr != NULL)
{
sizecount += gdata.meminfo[i].size;
if (gdata.meminfo[i].alloctime > gdata.curtime-600)
{
numcountrecent++;
}
}
}
u_respond(u, "heap: %li bytes, %i allocations (%li created in past 10 min) (depth %d)",
sizecount,
gdata.meminfo_count,
numcountrecent,
gdata.meminfo_depth);
#ifdef HAVE_MMAP
mmap_count = 0;
for (xd = irlist_get_head(&gdata.xdccs); xd; xd = irlist_get_next(xd))
{
mmap_count += irlist_size(&xd->mmaps);
}
u_respond(u,"mmaps: %i kbytes, %d file mappings",
mmap_count * IR_MMAP_SIZE / 1024, mmap_count);
#endif
if (u->arg1 && !strcmp(u->arg1,"list"))
{
meminfo_t *meminfo;
meminfo_t *meminfo2 = NULL;
int meminfo_depth;
/*
* we need to copy the entire table so we dont walk it
* while it while it can be modified
*/
again:
meminfo_depth = gdata.meminfo_depth;
meminfo = mycalloc(sizeof(meminfo_t) * MEMINFOHASHSIZE * meminfo_depth);
if (meminfo_depth != gdata.meminfo_depth)
{
meminfo2 = meminfo;
goto again;
}
memcpy(meminfo, gdata.meminfo,
sizeof(meminfo_t) * MEMINFOHASHSIZE * meminfo_depth);
u_respond(u,"iroffer heap details:");
u_respond(u," id | address | size | when | where");
for (i=0; i<(MEMINFOHASHSIZE * meminfo_depth); i++)
{
if (meminfo[i].ptr != NULL)
{
u_respond(u, "%3i %3i | 0x%8.8lX | %6iB | %7lis | %s:%d %s()",
i / meminfo_depth,
i % meminfo_depth,
(long)meminfo[i].ptr,
meminfo[i].size,
meminfo[i].alloctime-gdata.startuptime,
meminfo[i].src_file,
meminfo[i].src_line,
meminfo[i].src_func);
}
}
mydelete(meminfo);
mydelete(meminfo2);
}
#ifdef HAVE_MMAP
if (u->arg1 && !strcmp(u->arg1,"list") && mmap_count)
{
int pack_count = 1;
u_respond(u,"iroffer memmap details:");
u_respond(u," pack | location | address | references");
for (xd = irlist_get_head(&gdata.xdccs); xd; xd = irlist_get_next(xd))
{
mmap_info_t *mm;
irlist_sort(&xd->mmaps, irlist_sort_cmpfunc_off_t, NULL);
for (mm = irlist_get_head(&xd->mmaps); mm; mm = irlist_get_next(mm))
{
u_respond(u," %4i | 0x%8.8" LLPRINTFMT "X .. 0x%8.8" LLPRINTFMT "X | %p | %10d",
pack_count,
(unsigned long long)mm->mmap_offset,
(unsigned long long)mm->mmap_offset + (unsigned long long)mm->mmap_size - 1,
mm->mmap_ptr,
mm->ref_count);
}
pack_count++;
}
}
#endif
if (!u->arg1 || strcmp(u->arg1,"list"))
{
u_respond(u,"for a detailed listing use \"memstat list\"");
}
}
static void u_qsend(const userinput * const u)
{
updatecontext();
if (!irlist_size(&gdata.mainqueue))
{
u_respond(u,"No Users Queued");
return;
}
if (irlist_size(&gdata.trans) >= MAXTRANS)
{
u_respond(u,"Too many transfers");
return;
}
sendaqueue(2);
return;
}
static void u_shutdown(const userinput * const u) {
updatecontext();
if (u->arg1)
{
caps(u->arg1);
}
if (!u->arg1 || (strcmp(u->arg1,"NOW") && strcmp(u->arg1,"DELAYED") && strcmp(u->arg1,"CANCEL")) ) {
u_respond(u,"Usage: SHUTDOWN <now|delayed|cancel>");
return;
}
if (!strcmp(u->arg1,"NOW")) {
shutdowniroffer();
}
else if (!strcmp(u->arg1,"DELAYED")) {
u_respond(u,"Delayed shutdown activated, iroffer will shutdown once there are no active transfers");
u_respond(u,"To cancel the delayed shutdown, issue \"SHUTDOWN CANCEL\"");
gdata.delayedshutdown=1;
}
else if (!strcmp(u->arg1,"CANCEL")) {
u_respond(u,"Delayed shutdown canceled");
gdata.delayedshutdown=0;
}
}
static void u_debug(const userinput * const u) {
updatecontext();
if (!u->arg1) return;
gdata.debug = atoi(u->arg1);
}
static void u_servqc(const userinput * const u)
{
updatecontext();
u_respond(u,"Cleared server queue of %d lines",
irlist_size(&gdata.serverq_fast) +
irlist_size(&gdata.serverq_normal) +
irlist_size(&gdata.serverq_slow));
irlist_delete_all(&gdata.serverq_fast);
irlist_delete_all(&gdata.serverq_normal);
irlist_delete_all(&gdata.serverq_slow);
return;
}
static void u_jump(const userinput * const u)
{
updatecontext();
if (u->arg1)
{
int num;
num = atoi(u->arg1);
if ((num < 1) || (num > irlist_size(&gdata.servers)))
{
u_respond(u,"Try specifying a valid server number, use \"servers\" for a list");
}
else
{
gdata.serverconnectbackoff = 0;
switchserver(num-1);
}
}
else
{
gdata.serverconnectbackoff = 0;
switchserver(-1);
}
}
static void u_servers(const userinput * const u)
{
int i;
server_t *ss;
updatecontext();
u_respond(u,"Server List:");
u_respond(u," Num Server Port Password");
ss = irlist_get_head(&gdata.servers);
i = 1;
while(ss)
{
u_respond(u," %3i %-27s %6u %s",
i,
ss->hostname,
ss->port,
ss->password ? "(hidden)" : "(none)");
ss = irlist_get_next(ss);
i++;
}
u_respond(u,"Current Server: %s:%u (%s)",
gdata.curserver.hostname,
gdata.curserver.port,
gdata.curserveractualname ? gdata.curserveractualname : "<unknown>");
}
static void u_trinfo(const userinput * const u)
{
int num = -1;
char *tempstr2, *tempstr3;
const char *y;
int left,started,lcontact;
transfer *tr;
updatecontext();
if (u->arg1) num = atoi(u->arg1);
if ((num < 0) || !does_tr_id_exist(num))
{
u_respond(u,"Try Specifying a Valid Transfer Number");
return;
}
u_respond(u,"Transfer Info for ID %i:",num);
tr = does_tr_id_exist(num);
switch (tr->tr_status)
{
case TRANSFER_STATUS_LISTENING:
y = "Listening";
break;
case TRANSFER_STATUS_SENDING:
y = "Sending";
break;
case TRANSFER_STATUS_WAITING:
y = "Finishing";
break;
case TRANSFER_STATUS_DONE:
y = "Closing";
break;
default:
y = "Unknown!";
break;
}
u_respond(u,"User %s, Hostname %s, Status %s",
tr->nick,tr->hostname,y);
u_respond(u,"File: %s",getfilename(tr->xpack->file));
u_respond(u,"Start %" LLPRINTFMT "iK, Current %" LLPRINTFMT "iK, End %" LLPRINTFMT "iK (%2.0f%% File, %2.0f%% Xfer)",
(long long)((tr->startresume)/1024),
(long long)((tr->bytessent)/1024),
(long long)((tr->xpack->st_size)/1024),
((float)tr->bytessent)*100.0/((float)tr->xpack->st_size),
((float)(tr->bytessent-tr->startresume))*100.0/((float)max2(1,(tr->xpack->st_size-tr->startresume))));
tempstr2 = mycalloc(maxtextlengthshort);
tempstr3 = mycalloc(maxtextlengthshort);
snprintf(tempstr2,maxtextlengthshort-1,"%1.1fK/s",tr->xpack->minspeed);
snprintf(tempstr3,maxtextlengthshort-1,"%1.1fK/s",tr->xpack->maxspeed);
u_respond(u,"Min %s, Current %1.1fK/s, Max %s, In Transit %" LLPRINTFMT "iK",
(tr->nomin || (tr->xpack->minspeed == 0.0)) ? "no" : tempstr2 ,
tr->lastspeed,
(tr->nomax || (tr->xpack->maxspeed == 0.0)) ? "no" : tempstr3 ,
(long long)(tr->bytessent-tr->lastack)/1024);
mydelete(tempstr2);
mydelete(tempstr3);
left = min2(359999,(tr->xpack->st_size-tr->bytessent)/((int)(max2(tr->lastspeed,0.001)*1024)));
started = min2(359999,gdata.curtime-tr->connecttime);
lcontact = min2(359999,gdata.curtime-tr->lastcontact);
u_respond(u,"Transfer started %i%c %i%c ago, Finish in %i%c %i%c, Last contact %i%c %i%c ago.",
started < 3600 ? started/60 : started/60/60 ,
started < 3600 ? 'm' : 'h',
started < 3600 ? started%60 : (started/60)%60 ,
started < 3600 ? 's' : 'm',
left < 3600 ? left/60 : left/60/60 ,
left < 3600 ? 'm' : 'h',
left < 3600 ? left%60 : (left/60)%60 ,
left < 3600 ? 's' : 'm',
lcontact < 3600 ? lcontact/60 : lcontact/60/60 ,
lcontact < 3600 ? 'm' : 'h',
lcontact < 3600 ? lcontact%60 : (lcontact/60)%60 ,
lcontact < 3600 ? 's' : 'm');
u_respond(u,"Local: %ld.%ld.%ld.%ld:%d, Remote: %ld.%ld.%ld.%ld:%d",
tr->localip>>24, (tr->localip>>16) & 0xFF, (tr->localip>>8) & 0xFF, tr->localip & 0xFF, tr->listenport,
tr->remoteip>>24, (tr->remoteip>>16) & 0xFF, (tr->remoteip>>8) & 0xFF, tr->remoteip & 0xFF, tr->remoteport);
u_respond(u,"Sockets: Listen %i, Transfer %i, File %i",
(tr->listensocket == FD_UNUSED) ? 0 : tr->listensocket,
(tr->clientsocket == FD_UNUSED) ? 0 : tr->clientsocket,
(tr->xpack->file_fd == FD_UNUSED) ? 0 : tr->xpack->file_fd);
#ifdef HAVE_MMAP
if (tr->mmap_info)
{
u_respond(u,"MMAP: [%p] 0x%.8" LLPRINTFMT "X .. 0x%.8" LLPRINTFMT "X .. 0x%.8" LLPRINTFMT "X",
tr->mmap_info->mmap_ptr,
(unsigned long long)tr->mmap_info->mmap_offset,
(unsigned long long)tr->bytessent,
(unsigned long long)tr->mmap_info->mmap_offset + (unsigned long long)tr->mmap_info->mmap_size - 1);
}
#endif
}
static void u_listul(const userinput * const u)
{
DIR *d;
struct dirent *f;
char *thefile, *tempstr;
irlist_t dirlist = {};
int thedirlen;
#ifndef NO_STATVFS
struct statvfs stf;
#else
#ifndef NO_STATFS
struct statfs stf;
#endif
#endif
updatecontext();
if (!irlist_size(&gdata.uploadhost) || !gdata.uploaddir)
{
u_respond(u,"No upload hosts or no uploaddir defined.");
return;
}
thedirlen = strlen(gdata.uploaddir);
d = opendir(gdata.uploaddir);
if (!d)
{
u_respond(u,"Can't Access Upload Directory: %s",strerror(errno));
return;
}
while ((f = readdir(d)))
{
if (strcmp(f->d_name,".") && strcmp(f->d_name,".."))
{
thefile = irlist_add(&dirlist, strlen(f->d_name) + 1);
strcpy(thefile, f->d_name);
}
}
closedir(d);
irlist_sort(&dirlist, irlist_sort_cmpfunc_string, NULL);
if (!irlist_size(&dirlist))
{
u_respond(u,"Upload directory is empty");
}
else
{
u_respond(u,"Listing '%s':", gdata.uploaddir);
thefile = irlist_get_head(&dirlist);
while (thefile)
{
struct stat st;
int len = strlen(thefile);
tempstr = mycalloc(len + thedirlen + 2);
snprintf(tempstr, len + thedirlen + 2,
"%s/%s", gdata.uploaddir, thefile);
if (lstat(tempstr,&st) < 0)
{
u_respond(u,"cannot access '%s', ignoring: %s",
tempstr, strerror(errno));
}
else if (S_ISREG(st.st_mode))
{
char *sizestrstr;
sizestrstr = sizestr(1, st.st_size);
u_respond(u,"%9s %s",
sizestrstr,
thefile);
mydelete(sizestrstr);
}
else if (S_ISDIR (st.st_mode) ||
S_ISCHR (st.st_mode) ||
S_ISBLK (st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISLNK (st.st_mode) ||
S_ISSOCK(st.st_mode))
{
u_respond(u,"%9s %s",
S_ISDIR (st.st_mode) ? "=DIR=" :
S_ISCHR (st.st_mode) ? "=CHAR=" :
S_ISBLK (st.st_mode) ? "=BLOCK=" :
S_ISFIFO(st.st_mode) ? "=FIFO=" :
S_ISLNK (st.st_mode) ? "=SYMLINK=" :
S_ISSOCK(st.st_mode) ? "=SOCKET=" :
"???",
thefile);
}
mydelete(tempstr);
thefile = irlist_delete(&dirlist, thefile);
}
}
#ifndef NO_STATVFS
if (statvfs(gdata.uploaddir, &stf) < 0)
{
u_respond(u,"Unable to determine device sizes: %s",
strerror(errno));
}
else
{
char *d_size, *d_used, *d_free, *d_resv;
d_size = sizestr(0, (off_t)stf.f_blocks * (off_t)stf.f_frsize);
d_used = sizestr(0, (off_t)(stf.f_blocks - stf.f_bavail) * (off_t)stf.f_frsize);
d_free = sizestr(0, (off_t)stf.f_bavail * (off_t)stf.f_frsize);
d_resv = sizestr(0, (off_t)(stf.f_bfree - stf.f_bavail) * (off_t)stf.f_frsize);
u_respond(u,"Device size: %s, used %s, free %s, reserved %s",
d_size, d_used, d_free, d_resv);
mydelete(d_size);
mydelete(d_used);
mydelete(d_free);
mydelete(d_resv);
}
#else
#ifndef NO_STATFS
if (statfs(gdata.uploaddir, &stf) < 0)
{
u_respond(u,"Unable to determine device sizes: %s",
strerror(errno));
}
else
{
char *d_size, *d_used, *d_free, *d_resv;
d_size = sizestr(0, (off_t)stf.f_blocks * (off_t)stf.f_bsize);
d_used = sizestr(0, (off_t)(stf.f_blocks - stf.f_bavail) * (off_t)stf.f_bsize);
d_free = sizestr(0, (off_t)stf.f_bavail * (off_t)stf.f_bsize);
d_resv = sizestr(0, (off_t)(stf.f_bfree - stf.f_bavail) * (off_t)stf.f_bsize);
u_respond(u,"Device size: %s, used %s, free %s, reserved %s",
d_size, d_used, d_free, d_resv);
mydelete(d_size);
mydelete(d_used);
mydelete(d_free);
mydelete(d_resv);
}
#endif
#endif
return;
}
static void u_clearrecords(const userinput * const u)
{
int ii;
updatecontext();
gdata.record = 0;
gdata.sentrecord = 0;
gdata.totalsent = 0;
gdata.totaluptime = 0;
for (ii=0; ii<NUMBER_TRANSFERLIMITS; ii++)
{
gdata.transferlimits[ii].ends = 0;
}
u_respond(u,"Cleared transfer record, bandwidth record, total sent, total uptime, and transfer limits");
}
static void u_rmul(const userinput * const u) {
char *tempstr;
updatecontext();
if (!irlist_size(&gdata.uploadhost) || !gdata.uploaddir) {
u_respond(u,"No upload hosts or no uploaddir defined.");
return;
}
if (!u->arg1e || !strlen(u->arg1e)) {
u_respond(u,"Try Specifying a Filename");
return;
}
convert_to_unix_slash(u->arg1e);
if (strstr(u->arg1e,"/")) {
u_respond(u,"Filename contains invalid characters");
return;
}
tempstr = mymalloc(strlen(gdata.uploaddir) + 1 + strlen(u->arg1e) + 1);
sprintf(tempstr,"%s/%s",gdata.uploaddir,u->arg1e);
if (doesfileexist(tempstr)) {
if (unlink(tempstr) < 0)
u_respond(u,"Unable to remove the file");
else
u_respond(u,"Deleted");
}
else
u_respond(u,"That filename doesn't exist");
mydelete(tempstr);
}
static void u_crash(const userinput * const u) {
updatecontext();
*((int*)(0)) = 0;
}
#define USERS_PER_CHAN_LINE 6
static void u_chanl(const userinput * const u)
{
int j;
member_t *member;
char *tempstr = mycalloc(maxtextlength);
channel_t *ch;
updatecontext();
u_respond(u,"Channel Members:");
ch = irlist_get_head(&gdata.channels);
while(ch)
{
j = 0;
member = irlist_get_head(&ch->members);
while(member)
{
if (!(j%USERS_PER_CHAN_LINE))
{
snprintf(tempstr,maxtextlength-1,"%s: ",ch->name);
}
snprintf(tempstr + strlen(tempstr),
maxtextlength - 1 - strlen(tempstr),
"%s%s ", member->prefixes, member->nick);
if (!((j+1)%USERS_PER_CHAN_LINE))
{
u_respond(u,"%s",tempstr);
tempstr[0] = '\0';
}
member = irlist_get_next(member);
j++;
}
if (j%USERS_PER_CHAN_LINE)
{
u_respond(u,"%s",tempstr);
}
u_respond(u,"%s: %i user%s",ch->name,j,j!=1?"s":"");
ch = irlist_get_next(ch);
}
mydelete(tempstr);
}
/* End of File */
syntax highlighted by Code2HTML, v. 0.9.1