/* ARISA - Admin Interface - Queue Menu * Copyright (C) 2003 Carl Ritson * * 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 */ static int is_queue_new(queue_t *q) { int i; LOCK(global); for(i = 0; i < global->no_queues; ++i) { if(global->queues[i] == q) { UNLOCK(global); return 0; } } UNLOCK(global); return 1; } /** Queue Menu Commands **/ MENU_HELPER(cmd_queues_helper) { int i,j; LOCK(global); for(j = 0; args[no_args-1][j] != '\0'; ++j) { if(args[no_args-1][j] == '?') break; } for(i = 0; i < global->no_queues; ++i) { LOCK(global->queues[i]); if(global->queues[i]->deleted == 0 && (j == 0 || strncmp(global->queues[i]->name,args[no_args-1],j) == 0)) admin_msg(ac,"%s",global->queues[i]->name); UNLOCK(global->queues[i]); } UNLOCK(global); } MENU_CMD(cmd_queue_delete) { queue_t *q = (queue_t *)ins->data; int done = 1; if(!is_queue_new(q)) { queue_del(q); LOCK(q); if(q->deleted != 0) admin_msg(ac,"Queue %s deleted.",q->name); else { done = 0; admin_msg(ac,"Queue %s deletion not possible.",q->name); } UNLOCK(q); } if(done) return RET_UP; else return 0; } MENU_CMD(cmd_queue_rename) { queue_t *q = (queue_t *)ins->data; char buffer[96]; if(queue_rename(q,args[1]) == 0) { if(ins->prompt != NULL && ins->free_prompt != 0) xfree(ins->prompt); snprintf(buffer,sizeof(buffer),"queue: %s",args[1]); ins->prompt = xstrdup(buffer); ins->free_prompt = 1; admin_output_prompt(ac); } else admin_msg(ac,"Failed to rename to %s.",args[1]); return 0; } MENU_CMD(cmd_queue_save) { queue_t *q = (queue_t *)ins->data; int ret; if(is_queue_new(q)) { LOCK(q); if(q->pool != NULL) { LOCK(q->pool); if(q->pool->deleted != 0) { UNLOCK(q->pool); q->pool = NULL; } else UNLOCK(q->pool); } if(q->pool != NULL) { UNLOCK(q); ret = queue_add(q); if(ret == 0) { ins->free = NULL; LOCK(q); LOCK(q->pool); if(q->pool->deleted != 0) { UNLOCK(q->pool); UNLOCK(q); queue_del(q); admin_msg(ac,"Pool was deleted as queue was saved, queue has now also been deleted."); return RET_UP; } UNLOCK(q->pool); UNLOCK(q); admin_msg(ac,"Successfully saved."); } else admin_msg(ac,"Save failed."); } else { UNLOCK(q); admin_msg(ac,"Unable to save no pool set."); } } else admin_msg(ac,"Queue is already saved."); return 0; } MENU_CMD(cmd_queue_sends) { queue_t *q = (queue_t *)ins->data; int ret = RET_EXE_ERR; LOCK(q); if(q->pool != NULL) ret = cmd_pool_sends_p(q->pool,ac,args,no_args); else admin_msg(ac,"No Pool Set"); UNLOCK(q); return ret; } MENU_CMD(cmd_queue_settings) { queue_t *q = (queue_t *)ins->data; if(no_args == 1) { pqueue_t settings; pqueue_init(&settings,0); LOCK(q); if(q->pool != NULL) { char buffer[256], iname[128], pname[128]; pool_t *p = q->pool; int i,j,found; LOCK(p); xstrncpy(pname,p->name,sizeof(pname)); UNLOCK(p); UNLOCK(q); LOCK(global); for(i = 0, found = 0; i < global->no_interfaces && !found; ++i) { interface_t *intf = global->interfaces[i]; LOCK(intf); if(intf->type == INTERFACE_SEND) { for(j = 0; j < intf->send.no_pools && !found; ++j) { if(intf->send.pools[j] == p) { xstrncpy(iname,intf->name,sizeof(iname)); found = 1; } } } UNLOCK(intf); } UNLOCK(global); assert(found != 0); snprintf(buffer,sizeof(buffer),"%s %s",iname,pname); pqueue_push_back(&settings, value_string("pool",buffer)); } else { UNLOCK(q); pqueue_push_back(&settings, value_string("pool","not set")); } queue_read_settings(q,&settings); LOCK(q); output_settings(ac,"-- Queue Settings for %s --", q->name,&settings); UNLOCK(q); } else if(no_args >= 3) { if(strncasecmp(args[1],"po",2) == 0) { if(no_args >= 3) { interface_t *intf = interface_find(args[2]); if(intf != NULL && no_args >= 4) { pool_t *p = pool_find(intf,args[3]); if(p != NULL) { LOCK(q); LOCK(p); if(p->deleted == 0) { q->pool = p; admin_msg(ac,"Pool set."); } else { admin_msg(ac,"Invalid pool %s.",args[3]); } UNLOCK(p); UNLOCK(q); } else if(strchr(args[3],'?') != NULL) { cmd_int_pools_helper(ins,ac,args+1,no_args-1); } else { admin_msg(ac,"Invalid pool %s.",args[3]); } } else if(strchr(args[2],'?') != NULL) { cmd_int_pools_helper(ins,ac,args+1,no_args-1); } else { admin_msg(ac,"Invalid interface %s.",args[2]); } } else { admin_msg(ac,"%s pool ",args[0]); } } else { if(queue_apply_setting(q,args[1],args[2]) == -1) admin_msg(ac,"Invalid setting: %s",args[1]); } } else admin_msg(ac,"%s [ ]",args[0]); return 0; } static void cmd_queue_show_info(acontext_t *ac, queue_t *q) { char buffer[32]; LOCK(q); admin_msg(ac,"-- Queue %s --",q->name); admin_msg(ac,"Queues: %d/%d",q->no_qsends,q->length); admin_msg(ac,"Last Checked: %s", q->last_checked == 0 ? "Unknown" : timestr(q->last_checked,buffer,sizeof(buffer))); admin_msg(ac,"Last Dequeue: %s", q->last_dequeue == 0 ? "Unknown" : timestr(q->last_dequeue,buffer,sizeof(buffer))); admin_msg(ac,"Last Notify: %s", q->last_notify == 0 ? "Unknown" : timestr(q->last_notify,buffer,sizeof(buffer))); UNLOCK(q); } MENU_CMD(cmd_queue_info) { queue_t *q = (queue_t *)ins->data; if(no_args > 1) { if(tolower(args[1][0]) == 'p') { pool_t *p; LOCK(q); p = q->pool; UNLOCK(q); if(p != NULL) cmd_pool_show_info(ac,p); } else cmd_queue_show_info(ac,q); } else cmd_queue_show_info(ac,q); return 0; } static void cmd_queue_display_queue(acontext_t *ac, send_t *q, int number, time_t now) { char buffer[256],buffer2[32]; LOCK(q); RLOCK(q->pack); if(q->network != NULL) LOCK(q->network); admin_cmsg(ac,"%%r%-3d%%n For: [%%9%s:%s%%n] (%s)", number+1, q->network != NULL ? q->network->name : "Unknown", q->nick != NULL ? q->nick : "Unknown", q->host); if(q->network != NULL) UNLOCK(q->network); pathtofn(q->pack->file,buffer,sizeof(buffer)); admin_cmsg(ac," File: %%9%s%%n (%lldKiB)", buffer,q->pack->size / 1024ULL); admin_msg(ac," Elp:%s, Retries: %d", etimestr(now - q->started,buffer2,sizeof(buffer2)), q->retries); RUNLOCK(q->pack); UNLOCK(q); } static int cmd_queue_queues_q(queue_t *q, acontext_t *ac, char **args, int no_args) { pool_t *p; send_t *s; char *ptr; int i,j; if(no_args == 1) { time_t now = xtime(); LOCK(q); admin_msg(ac,"-- Queues on Queue %s --",q->name); for(i = 0; i < q->no_qsends; ++i) cmd_queue_display_queue(ac,q->qsends[i],i,now); if(i == 0) admin_msg(ac,"None"); UNLOCK(q); return 0; } if(tolower(args[1][0]) == 'd' || strcasecmp(args[1],"cl") == 0) { if(no_args >= 3) { i = (int)strtol(args[2],&ptr,10); if(*ptr == '\0') { j = queue_remove_no(q,i); if(j == 0) admin_msg(ac,"Removed Queue %d",i); else admin_msg(ac,"Invalid Queue Number: %d",i); } else { if(no_args >= 4) { i = queue_remove(q,args[2],NULL, args[3],NULL,NULL,NULL); i += queue_remove(q,args[2],NULL, NULL,args[3],NULL,NULL); i += queue_remove(q,args[2],NULL, NULL,NULL,args[3],NULL); } else i = queue_remove(q,args[2],NULL, NULL,NULL,NULL,NULL); admin_msg(ac,"Removed %d Matching Queues",i); UNLOCK(q); } } else admin_msg(ac,"%s del | []",args[0]); } else if(tolower(args[1][0]) == 'm' || strncasecmp(args[1],"sw",2) == 0) { if(no_args >= 4) { i = atoi(args[2]) - 1; j = atoi(args[3]) - 1; if(tolower(args[1][0]) == 'm') { if(queue_send_move(q,i,j) != 0) admin_msg(ac,"Invalid Move: %d to %d",i,j); } else { if(queue_send_swap(q,i,j) != 0) admin_msg(ac,"Invalid Swap: %d to %d",i,j); } } else admin_msg(ac,"%s %s ",args[0],args[1]); } else if(strncasecmp(args[1],"ch",2) == 0) { queue_check_users(q); } else if(strncasecmp(args[1],"se",2) == 0) { if(no_args >= 3) { LOCK(q); i = atoi(args[2]); if(i > 0 && i <= q->no_qsends) { s = q->qsends[i-1]; PTRARR_DEL(&q->qsends,&q->no_qsends,s); p = q->pool; UNLOCK(q); j = pool_add_send(p,s,SEND_FORCE,NULL); if(j == -1) { admin_msg(ac,"Error send deleted."); free_send(s); } } else { UNLOCK(q); admin_msg(ac,"Invalid Queue Number: %s",i); } } else admin_msg(ac,"%s send ",args[0]); } else admin_msg(ac,"%s [check|del|move|send|swap] ...",args[0]); return 0; } MENU_CMD(cmd_queue_queues) { queue_t *q = (queue_t *)ins->data; return cmd_queue_queues_q(q,ac,args,no_args); } /** Queue Menu Structure **/ static const cmd_t queue_menu[] = { {"delete", cmd_queue_delete, 0,0,1,0,PRIVS_EMPTY,NULL}, {"info", cmd_queue_info, 0,1,0,0,PRIVS_EMPTY,NULL}, {"queues", cmd_queue_queues, 0,3,1,0,PRIVS_EMPTY,NULL}, {"rename", cmd_queue_rename, 1,1,1,0,PRIVS_EMPTY,NULL}, {"save", cmd_queue_save, 0,0,1,0,PRIVS_EMPTY,NULL}, {"sends", cmd_queue_sends, 0,4,1,0, PRIV_TO_MASK(PRIV_SEND_DEL), NULL}, {"settings", cmd_queue_settings, 0,3,1,0,PRIVS_EMPTY,NULL}, {NULL} }; /** Queue Menu Entry **/ MENU_CHECK(cmd_queue_check) { queue_t *q = (queue_t *)ins->data; int ret = 0; LOCK(q); if(q->deleted != 0) { admin_msg(ac,"Queue %s, Deleted.",q->name); ret = -1; } UNLOCK(q); if(ret == 0 && is_queue_new(q)) { LOCK(q); if(q->pool != NULL) { LOCK(q->pool); if(q->pool->deleted != 0) { UNLOCK(q->pool); q->pool = NULL; } else UNLOCK(q->pool); } UNLOCK(q); } return ret; } MENU_CMD(cmd_queue_entry) { char buffer[96]; queue_t *q; snprintf(buffer,sizeof(buffer),"queue: %s",args[1]); if(ins->prompt != NULL && ins->free_prompt) xfree(ins->prompt); ins->prompt = xstrdup(buffer); ins->free_prompt= 1; ins->check = cmd_queue_check; q = queue_find(args[1]); if(q == NULL) { q = alloc_queue(); q->name = xstrdup(args[1]); ins->free = (void (*)(void *)) free_queue; admin_msg(ac,"New Queue: %s",args[1]); } ins->data = q; return 0; } static void register_queue_menu(void) { menu_t *q_menu = menu_from_cmds( "queue", // name 1, // min_args 1, // max_args 1, // log 0, // hide PRIV_TO_MASK(PRIV_QUEUES), // privs cmd_queue_entry, // func cmd_queues_helper, // helper (cmd_t *)queue_menu); menu_add(main_menu_root,q_menu); menu_deref(q_menu); }