/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * miav_server.cc * * Sat Aug 21 17:32:24 2004 * Copyright 2004 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of MIaV. * * MIaV 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. * * MIaV 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 MIaV; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include "miav_server.h" #include "miav_config.h" #include "info_console.h" #include #include #include "server.h" #include "socket.h" #include #include // For getpwent and getgrent #include #include #include #ifdef HAVE_GETOPT_H #include #elif defined(HAVE_STDLIB_H) // Solaris has getopt() here #include #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[]) { 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); 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; } } delete socket; return 0; }