diff options
Diffstat (limited to 'server/miav_server.cc')
-rw-r--r-- | server/miav_server.cc | 159 |
1 files changed, 155 insertions, 4 deletions
diff --git a/server/miav_server.cc b/server/miav_server.cc index 2005afd..b1dfcac 100644 --- a/server/miav_server.cc +++ b/server/miav_server.cc @@ -27,24 +27,175 @@ #include <config.h> #include "miav_server.h" -#include "miav_daemon.h" #include "miav_config.h" #include "info_console.h" #include <stdio.h> +#include <string.h> + +#include "server.h" +#include "socket.h" + +#include <signal.h> +#include <errno.h> + +// For getpwent and getgrent +#include <sys/types.h> +#include <grp.h> +#include <pwd.h> + +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#elif defined(HAVE_STDLIB_H) // Solaris has getopt() here +#include <stdlib.h> +#else +#error "Don't know where getopt() is prototyped" +#endif + +static const char usage_str[] = +"Usage: %s [options]\n" +"Options:\n" +" -c file Read configfile from 'file'\n" +" -i Run in interactive mode (non-background mode)\n" +" -h This message\n" +; + +static char *config_file = ETC"/miav.conf"; /** * This function starts the MIaV server. */ int main(int argc, char *argv[]) { - MiavDaemon daemon; + int optc; + int lose = 0; + bool interactive = false; + + // Parse the commandline + while((optc = getopt(argc, argv, "c:ih")) != EOF) { + switch(optc) { + case 'c': + config_file = strdup(optarg); + if(!config_file) { + fprintf(stderr, "Fatal: out of memory\n"); + return 1; + } + break; + case 'i': + interactive = true; + break; + case 'h': + fprintf(stdout, usage_str, argv[0]); + return 0; + default: + lose++; + break; + } + } + + if(lose) { + // Error message was printed by getopt + return 1; + } + + fprintf(stderr, "Using config file [%s]\n", config_file); + + MiavConfig cfg(config_file); + MIaV::initConfig(&cfg); - MiavConfig cfg(ETC"/miav.conf"); + InfoConsole info; + MIaV::initInfo(&info); string *user = cfg.readString("server_user"); string *group = cfg.readString("server_group"); + + // Fetch user id + int uid = -1; + struct passwd *p = getpwent(); + while(p) { + if(strcmp(p->pw_name, user->c_str()) == 0) uid = p->pw_uid; + p = getpwent(); + } + if(uid == -1) { + fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user->c_str()); + } + + // Fetch group id + int gid = -1; + struct group *g = getgrent(); + while(g) { + if(strcmp(g->gr_name, group->c_str()) == 0) gid = g->gr_gid; + g = getgrent(); + } + if(gid == -1) { + fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group->c_str()); + } + + if(!interactive) { + fprintf(stderr, "Entering daemon mode\n"); + daemon(0,0); + signal (SIGTERM, SIG_IGN); + signal (SIGINT, SIG_IGN); + signal (SIGHUP, SIG_IGN); + } else { + fprintf(stderr, "Running interactive\n"); + } + + int port = MIaV::config->readInt("server_port"); + pid_t childpid; // variable to store the child's pid + + signal(SIGCLD, SIG_IGN); // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes + // (ellers kommer der kernel-brok) + + MIaV::info->info("Starting MIaV server v. %s", VERSION); + MIaV::info->info("Listening on port %d", port); + Socket *socket = new Socket(port); + + if(socket->hasError()) { + MIaV::info->error("Listening socket has errors, quitting."); + delete socket; + return 1; + } + + while(1) { + Socket *csocket = new Socket(socket->slisten()); + + if(socket->hasError()) { + MIaV::info->error("Server socket has errors, quitting."); + delete csocket; + break; + } + + if(csocket->hasError()) { + MIaV::info->error("Child socket has errors, quitting."); + delete csocket; + break; + } + + if(!csocket->isConnected()) { + MIaV::info->error("Child socket is not connected, quitting."); + delete csocket; + break; + } + + childpid = fork(); + + switch(childpid) { + case -1: // fork() returns -1 on failure + MIaV::info->log("Fork error: %s", strerror(errno)); + exit(1); + case 0: // fork() returns 0 to the child process + delete socket; // Close listen socket. + newConnection(csocket); + delete csocket; // Close communication socket. + exit(0); + + default: // fork() returns new pid to the parent process + break; + } + } - return daemon.run(user->c_str(), group->c_str()); + delete socket; + return 0; } |