/***************************************************************************** POPular -- A POP3 server and proxy for large mail systems $Id: pserv_ctrl.c,v 1.19 2001/05/24 18:28:12 sqrt Exp $ http://www.remote.org/jochen/mail/popular/ ****************************************************************************** Copyright (C) 1999-2001 Jochen Topf 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 *****************************************************************************/ #if HAVE_CONFIG_H # include #endif #include "popular.h" #include "pserv.h" #include "ctrl.h" extern struct pserv_capa capa; extern struct pservconfig conf; struct configdesc cd[] = { /* tag rw type addr min max default value */ { "backlog", 1, ctInt, &conf.backlog, 5, 1024, DEFAULT_LISTEN_BACKLOG, NULL }, /* RFC1939 says the 'inactivity autologout timer' MUST be >= 10 mins */ { "idletimeout", 1, ctTime, &conf.idletimeout, 600, 60*60*24, DEFAULT_TIMEOUT_IDLE, NULL }, { "logeachmsg", 1, ctBool, &conf.logeachmsg, 0, 1, 0, NULL }, { "maxlocalload", 1, ctInt, &conf.maxlocalload, 0, 9999, 0, NULL }, { "maxsession", 1, ctInt, &conf.maxsession, 2, MAX_SESSION, DEFAULT_MAX_SESSION, NULL }, { "pid", 0, ctInt, &conf.pid, 0, 0, 0, NULL }, { "servport", 1, ctInt, &conf.servport, 1024, 65535, DEFAULT_PORT_XPOP, NULL }, { "sessionlimit", 0, ctInt, &conf.sessionlimit, 0, 0, MAX_SESSION, NULL }, { "sessiontimeout", 1, ctTime, &conf.sessiontimeout, 0, 60*60*24, DEFAULT_TIMEOUT_SESSION, NULL }, { "statusheader", 1, ctBool, &conf.statusheader, 0, 1, 0, NULL }, /* tag rw type addr strlength default value */ { "capadir", 1, ctDir, conf.capadir, 0, sizeof(conf.capadir), 0, PSERV_CAPA_DIR }, { "id", 0, ctId, conf.id, 0, sizeof(conf.id), 0, PSERV_PRG_NAME }, { "localip", 1, ctStr, conf.localip, 0, sizeof(conf.localip), 0, "ANY" }, { "logfile", 1, ctFile, conf.logfile, 0, sizeof(conf.logfile), 0, PSERV_LOG_FILE }, { "popdir", 1, ctDir, conf.popdir, 0, sizeof(conf.popdir), 0, PSERV_POP_DIR }, { "rundir" , 0, ctDir, conf.rundir, 0, sizeof(conf.rundir), 0, RUN_DIR }, { "version", 0, ctStr, conf.version, 0, sizeof(conf.version), 0, VERSION }, { NULL, 0, ctNone, NULL, 0, 0 } }; struct ctrl_cmd_dispatch_table ccdt[] = { { "capa", ctrl_cmd_capa, 1, 2 }, { "debug", ctrl_cmd_debug, 0, 10 }, { "server", ctrl_cmd_server, 1, 1 }, { "set", ctrl_cmd_set, 2, 2 }, { "show", ctrl_cmd_show, 0, 1 }, { "shutdown", ctrl_cmd_shutdown, 1, 1 }, { NULL, NULL, 0, 0 } }; /***************************************************************************** capa_name() *****************************************************************************/ char * capa_name(struct virt_serv *vs) { switch (vs->capa_type) { case capa_error: return "ERROR"; case capa_none: return "NONE"; case capa_default: return "DEFAULT"; case capa_user: return vs->capa_ptr->name; default: return "ERROR"; } } /***************************************************************************** ctrl_cmd_capa() *****************************************************************************/ void ctrl_cmd_capa(char *argv[], int argc, char *answer) { if (! strcasecmp(argv[1], "show")) { if (argc != 2) ANSWER0("20 too many arguments"); switch (capa.capa_type) { case capa_error: ANSWER0("00 capa set ERROR"); case capa_none: ANSWER0("00 capa set NONE"); case capa_default: ANSWER0("00 capa set DEFAULT"); case capa_user: { char *x; snprintf(answer, MAXBUF, "00 capa set %s: %s", capa.name, capa.text); for (x=answer; *x; x++) { if (*x == '\r') *x=','; if (*x == '\n') *x=' '; } answer[strlen(answer)-2] = '\0'; return; } default: ANSWER0("99 illegal capa set"); } } else if (! strcasecmp(argv[1], "set")) { struct pserv_capa c; if (argc != 3) ANSWER0("20 second argument (capa id) is missing"); if (!valid_id(argv[2])) ANSWER0("13 invalid chars in id (must be [a-zA-Z0-9._-]*)"); if (!strcasecmp(argv[2], "ERROR")) { capa.capa_type = capa_error; /* XLOG-DOC:ADM:0150:config_capa * Capability was configured */ xlog_printf(xlog_adm, 0x0150, "config_capa capa=ERROR"); ANSWER0("00 capa set ERROR"); } else if (!strcasecmp(argv[2], "NONE")) { capa.capa_type = capa_none; /* XLOG-DOC:ADM:0151:config_capa * Capability was configured */ xlog_printf(xlog_adm, 0x0151, "config_capa capa=NONE"); ANSWER0("00 capa set NONE"); } else if (!strcasecmp(argv[2], "DEFAULT")) { capa.capa_type = capa_default; /* XLOG-DOC:ADM:0152:config_capa * Capability was configured */ xlog_printf(xlog_adm, 0x0152, "config_capa capa=DEFAULT"); ANSWER0("00 capa set DEFAULT"); } else { FILE *f; char buf[MAXBUF]; int offset = 0; c.capa_type = capa_user; strlcpy(c.name, argv[2], MAXLEN_ID); snprintf(buf, sizeof(buf), "%s/%s", conf.capadir, argv[2]); f = fopen(buf, "r"); if (! f) ANSWER1("33 error opening '%s'", buf); /* read in capa file converting LF to CRLF as we go */ while (fgets(c.text + offset, sizeof(c.text) - offset - 2, f)) { int len = strlen(c.text + offset); c.text[offset+len-1] = '\r'; c.text[offset+len] = '\n'; c.text[offset+len+1] = '\0'; offset += len+1; if (offset >= sizeof(c.text) - 2) { ANSWER1("13 capa '%s' too long to be loaded", argv[2]); } } fclose(f); } capa = c; /* XLOG-DOC:ADM:0153:config_capa * Capability was configured */ xlog_printf(xlog_adm, 0x0153, "config_capa capa=%s", argv[2]); ANSWER1("00 capa '%s' loaded", argv[2]); } else { ANSWER1("22 unknown subcomand: '%s'", argv[1]); } } /***************************************************************************** ctrl_cmd_server() *****************************************************************************/ void ctrl_cmd_server(char *argv[], int argc, char *answer) { if (! strcasecmp(argv[1], "online")) { switch (go_online ()) { case 0: ANSWER0("31 can't go online"); case 1: ANSWER0("00 server is online now"); default: ANSWER0("13 we are already online"); } } else if (! strcasecmp(argv[1], "offline")) { switch (go_offline ()) { case 0: ANSWER0("99 can't go offline"); case 1: ANSWER0("00 server is offline now"); default: ANSWER0("13 we are already offline"); } } else if (! strcasecmp(argv[1], "status")) { if (is_online()) { ANSWER0("00 server is online"); } else { ANSWER0("00 server is offline"); } } else { ANSWER0("22 subcommand must be 'online', 'offline' or 'status'"); } } /** THE END *****************************************************************/