From 5588e96b39c1b7d8df72b9d370637de303af44fe Mon Sep 17 00:00:00 2001 From: piaip Date: Thu, 11 Jun 2009 05:30:07 +0000 Subject: * make port binding to standalone configuration fine (etc/bindports.conf) * refine some file names git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4560 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- daemon/logind/logind.c | 92 ++++++++++++++++++++++++++++++++--------------- include/common.h | 7 +++- mbbsd/admin.c | 4 +-- mbbsd/mbbsd.c | 68 ++++++++++++++++++++++++++++++++++- mbbsd/register.c | 2 +- sample/etc/bindports.conf | 47 ++++++++++++++++++++++++ 6 files changed, 187 insertions(+), 33 deletions(-) create mode 100644 sample/etc/bindports.conf diff --git a/daemon/logind/logind.c b/daemon/logind/logind.c index e6694228..d8220362 100644 --- a/daemon/logind/logind.c +++ b/daemon/logind/logind.c @@ -521,7 +521,7 @@ _set_bind_opt(int sock) #define AUTH_FAIL_YX PASSWD_PROMPT_YX #define USERID_EMPTY_MSG ANSI_RESET "請重新輸入。" #define USERID_EMPTY_YX PASSWD_PROMPT_YX -#define SERVICE_FAIL_MSG ANSI_COLOR(0;1;31) "抱歉,系統目前正在維護中,請稍候再試。" ANSI_RESET "\r\n" +#define SERVICE_FAIL_MSG ANSI_COLOR(0;1;31) "抱歉,部份系統正在維護中,請稍候再試。" ANSI_RESET "\r\n" #define SERVICE_FAIL_YX BOTTOM_YX #define OVERLOAD_CPU_MSG "系統過載, 請稍後再來...\r\n" #define OVERLOAD_CPU_YX BOTTOM_YX @@ -1215,14 +1215,6 @@ tunnel_cb(int fd, short event, void *arg) /////////////////////////////////////////////////////////////////////// // Main -#ifndef LOGIND_TUNNEL_PATH -#define LOGIND_TUNNEL_PATH BBSHOME "/run/logind.tunnel" -#endif - -#ifndef FN_BINDLIST -#define FN_BINDLIST BBSHOME "/etc/logind_ports" // a file with list of ports to bind. -#endif - static int bind_port(int port) { @@ -1249,13 +1241,63 @@ bind_port(int port) return 0; } +static int +parse_bindports_conf(FILE *fp, char *tunnel_path, int sz_tunnel_path) +{ + char buf [PATHLEN], vprogram[STRLEN], vport[STRLEN], vtunnel[STRLEN]; + int bound_ports = 0; + int iport = 0; + + // format: [ vprogram port ] or [ vprogram tunnel path ] + while (fgets(buf, sizeof(buf), fp)) + { + if (sscanf(buf, "%s %s", vprogram, vport) != 2) + continue; + if (strcmp(vprogram, "logind") != 0) + continue; + if (strcmp(vport, "tunnel") == 0) + { + if (sscanf(buf, "%s %s %s", vprogram, vport, vtunnel) != 3) + { + fprintf(stderr, "incorrect tunnel configuration. abort.\r\n"); + exit(1); + } + // there can be only one tunnel, so user command line is more important. + if (*tunnel_path) + { + fprintf(stderr, + "warning: ignored configuration file and use %s as tunnel path.", + tunnel_path); + continue; + } + strlcpy(tunnel_path, vtunnel, sz_tunnel_path); + continue; + } + + iport = atoi(vport); + if (!iport) + { + fprintf(stderr, "warning: unknown settings: %s\r\n", buf); + continue; + } + + if (bind_port(iport) < 0) + { + fprintf(stderr, "cannot bind to port: %d. abort.\r\n", iport); + exit(3); + } + bound_ports++; + } + return bound_ports; +} + int main(int argc, char *argv[]) { int ch, port = 0, bound_ports = 0, tfd, as_daemon = 1; FILE *fp; - const char *tunnel_path = LOGIND_TUNNEL_PATH; - const char *config_file = FN_BINDLIST; + char tunnel_path[PATHLEN] = ""; + const char *config_file = FN_CONF_BINDPORTS; Signal(SIGPIPE, SIG_IGN); @@ -1270,7 +1312,7 @@ main(int argc, char *argv[]) if (optarg) port = atoi(optarg); break; case 't': - tunnel_path = optarg; + strlcpy(tunnel_path, optarg, sizeof(tunnel_path)); break; case 'D': as_daemon = 0; @@ -1280,7 +1322,10 @@ main(int argc, char *argv[]) break; case 'h': default: - fprintf(stderr, "usage: %s [-v][-D] [-f bindlist_file] [-p port] [-t tunnel_path]\r\n", argv[0]); + fprintf(stderr, "usage: %s [-v][-D] [-f bindport_conf] [-p port] [-t tunnel_path]\r\n", argv[0]); + fprintf(stderr, "\t-f: read configuration from file (default: %s)\r\n", BBSHOME "/" FN_CONF_BINDPORTS); + fprintf(stderr, "\t-v: provide verbose messages\r\n"); + fprintf(stderr, "\t-D: do not enter daemon mode.\r\n"); return 1; } } @@ -1309,20 +1354,7 @@ main(int argc, char *argv[]) // bind from port list file if( NULL != (fp = fopen(config_file, "rt")) ) { - char buf [STRLEN]; - while (fgets(buf, sizeof(buf), fp)) - { - port = atoi(strtok(buf, " #\r\n")); - if (!port) - continue; - - if (bind_port(port) < 0) - { - fprintf(stderr, "cannot bind to port: %d. abort.\r\n", port); - return 3; - } - bound_ports++; - } + bound_ports += parse_bindports_conf(fp, tunnel_path, sizeof(tunnel_path)); fclose(fp); } @@ -1331,6 +1363,11 @@ main(int argc, char *argv[]) fprintf(stderr, "error: no ports to bind. abort.\r\n"); return 4; } + if (!*tunnel_path) + { + fprintf(stderr, "error: must assign one tunnel path. abort.\r\n"); + return 4; + } /* Give up root privileges: no way back from here */ setgid(BBSGID); @@ -1342,7 +1379,6 @@ main(int argc, char *argv[]) daemonize(BBSHOME "/run/logind.pid", NULL); } - // create tunnel if ( (tfd = tobindex(tunnel_path, 1, _set_bind_opt, 1)) < 0) { diff --git a/include/common.h b/include/common.h index 8cb003ed..4991036b 100644 --- a/include/common.h +++ b/include/common.h @@ -7,6 +7,12 @@ #define DEFAULT_BOARD str_sysop +// BBS Configuration Files +#define FN_CONF_EDITABLE "etc/editable" // 站務可編輯的系統檔案列表 +#define FN_CONF_RESERVED_ID "etc/reserved.id" // 保留系統用無法註冊的 ID +#define FN_CONF_BINDPORTS "etc/bindports.conf" // 預設要提供連線服務的 port 列表 + +// BBS Data File Names #define FN_PASSWD BBSHOME "/.PASSWDS" /* User records */ #define FN_CHICKEN "chicken" #define FN_USSONG "ussong" /* 點歌統計 */ @@ -35,7 +41,6 @@ #define FN_TICKET_BRDLIST "boardlist" #define FN_BRDLISTHELP "etc/boardlist.help" #define FN_BOARDHELP "etc/board.help" -#define FN_RESERVED_ID "etc/reserved.id" // 保留系統用無法註冊的 ID #define FN_USERMEMO "memo.txt" // 使用者個人記事本 #define FN_BADLOGIN "logins.bad" // in BBSHOME & user directory diff --git a/mbbsd/admin.c b/mbbsd/admin.c index 84bf25ea..90676799 100644 --- a/mbbsd/admin.c +++ b/mbbsd/admin.c @@ -762,11 +762,11 @@ x_file(void) char buf[PATHLEN]; FILE *fp = NULL; - fp = fopen("etc/editable", "rt"); + fp = fopen(FN_CONF_EDITABLE, "rt"); if (!fp) { // you can find a sample in sample/etc/editable - vmsg("未設定可編輯檔案列表[etc/editable],請洽系統站長。"); + vmsgf("未設定可編輯檔案列表[%s],請洽系統站長。", FN_CONF_EDITABLE); return 0; } diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c index 4ae67910..d7487370 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -1579,6 +1579,7 @@ static void usage(char *argv0) "\t-n tunnel enable tunnel mode, imply -d\n" "\t-p port listen port\n" "\t-l fd pre-listen fd\n" + "\t-f bindport_conf read from configuration file\n" "\n" "non-daemon mode\n" "\t-D use non-daemon mode, imply -t tty\n" @@ -1598,6 +1599,59 @@ static void usage(char *argv0) ); } +bool parse_bindport_conf(const char *path, struct ProgramOption *option) +{ + FILE *fp = fopen(path, "rt"); + char buf[PATHLEN], vprogram[STRLEN], vport[STRLEN], vopt[STRLEN]; + int port = 0; + if (!fp) + return false; + + while (fgets(buf, sizeof(buf), fp)) + { + if (sscanf(buf, "%s %s", vprogram, vport) != 2 || + strcmp(vprogram, "mbbsd") != 0) + continue; + + if (strcmp(vport, "tunnel") == 0) + { + if (sscanf(buf, "%s %s %s", vprogram, vport, vopt) != 3) + { + fprintf(stderr, "error: invalid tunnel setting in %s.\r\n", + path); + exit(1); + } + option->tunnel_mode = true; + if (option->flag_tunnel_path) + { + fprintf(stderr, "warning: ignore tunnel path specified in %s.\r\n", + path); + continue; + } + option->flag_tunnel_path = strdup(vopt); + continue; + } + + // normal port? + port = atoi(vport); + if (!port) + { + fprintf(stderr,"warning: unknown setting: %s\r\n", buf); + continue; + } + if (option->nport >= MAX_BINDPORT) + { + fprintf(stderr, "too many port (>%d)\n", MAX_BINDPORT); + exit(1); + } + // add port + option->port[option->nport++] = port; + } + + fclose(fp); + return true; +} + bool parse_argv(int argc, char *argv[], struct ProgramOption *option) { int ch; @@ -1608,10 +1662,15 @@ bool parse_argv(int argc, char *argv[], struct ProgramOption *option) option->flag_listenfd = -1; option->flag_checkload = true; - while ((ch = getopt(argc, argv, "dn:p:l:Dt:h:e:bu:FC")) != -1) { + while ((ch = getopt(argc, argv, "dn:p:f:l:Dt:h:e:bu:FC")) != -1) { switch (ch) { case 'n': option->tunnel_mode = true; + if (option->flag_tunnel_path) + { + fprintf(stderr, "warning: changed tunnel path to %s.\r\n", optarg); + } + free(option->flag_tunnel_path); option->flag_tunnel_path = strdup(optarg); // reuse 'd' mode, no break here. case 'd': @@ -1620,6 +1679,13 @@ bool parse_argv(int argc, char *argv[], struct ProgramOption *option) option->term_mode = TermMode_TELNET; option->flag_fork = true; break; + case 'f': + if (!parse_bindport_conf(optarg, option)) + { + perror(optarg); + exit(1); + } + break; case 'p': if (option->nport < MAX_BINDPORT) { int port = atoi(optarg); diff --git a/mbbsd/register.c b/mbbsd/register.c index 45797c13..473f2f57 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -69,7 +69,7 @@ removespace(char *s) int reserved_user_id(const char *userid) { - if (file_exist_record(FN_RESERVED_ID, userid)) + if (file_exist_record(FN_CONF_RESERVED_ID, userid)) return 1; return 0; } diff --git a/sample/etc/bindports.conf b/sample/etc/bindports.conf new file mode 100644 index 00000000..de90f73b --- /dev/null +++ b/sample/etc/bindports.conf @@ -0,0 +1,47 @@ +# Bind Port List +# ---------------------------------------------- +# syntax: