diff options
Diffstat (limited to 'lanbrowsing/lisa/main.cpp')
-rw-r--r-- | lanbrowsing/lisa/main.cpp | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/lanbrowsing/lisa/main.cpp b/lanbrowsing/lisa/main.cpp new file mode 100644 index 00000000..7de59389 --- /dev/null +++ b/lanbrowsing/lisa/main.cpp @@ -0,0 +1,290 @@ +/* main.cpp + * + * Copyright (c) 1998-2000 Alexander Neundorf + * + * You may distribute under the terms of the GNU General Public + * License as specified in the COPYING file. + * + * 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. + * + */ + +#include "lisadefines.h" +#include "netmanager.h" + +#ifdef LISA_DEBUG +#undef LISA_DEBUG +#endif + +#ifdef dcerr +#undef dcerr +#endif + +#define LISA_DEBUG 0 +#define dcerr if (LISA_DEBUG==1) std::cerr<<"main " + +#include <iostream> +#include <signal.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> + +// detect linux/glibc for the gnu style --args +#if defined(__linux__) || defined(__linux) || defined(linux) +# include <features.h> +# ifdef __GLIBC__ +// only gnu libc has getopt.h... getopt(3) is defined to be in unistd.h +// by POSIX.2 +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +# include <getopt.h> +# endif // __GLIBC__ +# define GNU_GETOPT +#endif // linux + + +void printVersion() +{ + const char * versionInfo=\ + "\r\nThis is the LAN Information Server LISa "MYVERSION"\r\n"\ + "It is free software according the GNU General Public License\r\n"\ + "Copyright (c) 2000-2003 by Alexander Neundorf\r\n"\ + "email: [email protected]\r\n"; + std::cout<<versionInfo<<std::endl; +} + +void usage() +{ + printVersion(); + const char * usageInfo=\ + "-v, --version prints out a short version info\n"\ + "-u, --unix deprecated\n"\ + "-k, --kde1 deprecated\n"\ + "-K, --kde2 deprecated\n"\ + " lisa now looks always first for $(HOME)/.lisarc, then for /etc/lisarc\n"\ + "-c, --config=FILE read this and no other configuration file\n"\ + "-q, --quiet start quiet without the greeting message\n"\ + "-p, --port PORTNR start the server on this portnumber\n"\ + " if you use this LISa won't be able to\n"\ + " cooperate with other LISa's in the network\n"\ + "-h, --help you are currently reading it ;-)\n"; + std::cout<<usageInfo<<std::endl; +//I thought this would be the way to check wether long options are supported... +//#ifndef _GNU_SOURCE +// std::cout<<"Please note that the long options are not supported on +// this system"<<std::endl; +//#endif +} + +NetManager *manager(0); + + +void destruct(int sigNumber) +{ + signal(sigNumber,SIG_IGN); + dcerr<<"signal caught: "<<sigNumber<<", exiting"<<std::endl; + //signal(sigNumber,&destruct); + if (manager!=0) + manager->~NetManager(); + exit(0); +} + +void readConfig(int sigNumber) +{ + dcerr<<"readConfig(): signal caught: "<<sigNumber<<std::endl; + signal(SIGHUP,SIG_IGN); + if (manager!=0) + manager->readConfig(); + signal(SIGHUP,&readConfig); +} + +void printState(int sigNumber) +{ + dcerr<<"printState(): signal caught: "<<sigNumber<<std::endl; + signal(SIGUSR1,SIG_IGN); + if (manager!=0) + manager->printState(); + signal(SIGUSR1,&printState); +} + +void setSignalHandler() +{ + signal(SIGHUP,&readConfig); + signal(SIGUSR1,&printState); + + signal(SIGINT,&destruct); + signal(SIGQUIT,&destruct); + signal(SIGILL,&destruct); + signal(SIGTRAP,&destruct); + signal(SIGABRT,&destruct); + signal(SIGBUS,&destruct); + signal(SIGSEGV,&destruct); + signal(SIGUSR2,&destruct); + signal(SIGPIPE,&destruct); + signal(SIGALRM,&destruct); + signal(SIGTERM,&destruct); + signal(SIGFPE,&destruct); +#ifdef SIGPOLL + signal(SIGPOLL, &destruct); +#endif +#ifdef SIGSYS + signal(SIGSYS, &destruct); +#endif +#ifdef SIGVTALRM + signal(SIGVTALRM, &destruct); +#endif +#ifdef SIGXCPU + signal(SIGXCPU, &destruct); +#endif +#ifdef SIGXFSZ + signal(SIGXFSZ, &destruct); +#endif +} + +#ifdef GNU_GETOPT +static struct option const long_opts[] = +{ + {"version", no_argument, 0, 'v'}, + {"quiet", no_argument, 0, 'q'}, + {"unix", no_argument, 0, 'u'}, + {"kde1", no_argument, 0, 'k'}, + {"kde2", no_argument, 0, 'K'}, + {"config", required_argument, 0, 'c'}, + {"port", required_argument, 0, 'p'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} +}; +#endif + +int main(int argc, char** argv) +{ + int quiet(0); + int c(0); + int configStyle(UNIXCONFIGSTYLE); + MyString configFile; + int portToUse(MYPORT); + +//I thought this would be the way to check wether long options are supported... +#ifdef GNU_GETOPT + while ((c=getopt_long(argc, argv, "vqukKc:h", long_opts, 0))!=-1) +#else + while ((c=getopt(argc, argv, "vqukKc:h"))!=-1) +#endif + + { + char *endp(0); + switch (c) + { + case 0: + break; + case 'v': + printVersion(); + exit(0); + break; + case 'q': + quiet=1; + break; + case 'u': + case 'k': + case 'K': + std::cout<<"\a\nThe command line switches -k, -K, -u and \ntheir long versions "\ + "--kde1, --kde2 and --unix are not supported anymore.\n"\ + "Lisa will always first look for $(HOME)/.lisarc , then for /etc/lisarc.\n"\ + "If your lisa configuration file was created using an older version of \n"\ + "the KDE control center, copy the /root/.kde/share/config/lisarc to /etc and \n"\ + "then start lisa without any command line options.\n"<<std::endl; + return 0; + break; + + case 'c': + configFile = optarg; + configStyle = EXTRACONFIGSTYLE; + break; + + case 'p': + portToUse=strtol(optarg,&endp,10); + if (endp!=0) + { + usage(); + exit(0); + } + break; + + case 'h': + default: + usage(); + exit(0); + break; + } + } + + //fork and let the parent exit + pid_t pid=fork(); + if (pid>0) + { + //this is the parent + exit(0); + } + else if (pid<0) + { + std::cout<<"could not fork()"<<std::endl; + exit(0); + } + //we will only read/write to/from this socket in the child process + int rawSocket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); + if (rawSocket==-1) + { + std::cout<<"could not create raw socket, root privileges required"<<std::endl; + std::cout<<"take a look at the README for more information"<<std::endl; + exit(0); + } + int bufferSize(60*1024); + int on(1); + setsockopt(rawSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, + sizeof(bufferSize)); + int result=setsockopt(rawSocket, SOL_SOCKET, SO_BROADCAST, (char*)&on, + sizeof(on)); + dcerr<<"setsockopt returns "<<result<<std::endl; + //dropping root privileges + //they will be regained once in the child process + //for creating a raw socket + + //now dropping root privileges once and ever + + + setuid(getuid()); + if (geteuid() != getuid()) + _exit(255); + + //according to R. Stevens the following three lines + //make daemons feel good :) + setsid(); + chdir("/"); + umask(0); + + dcerr<<"starting, dropped root privileges"<<std::endl; + dcerr<<"port: "<<portToUse<<" file: "<<configFile<<std::endl; + NetManager netmanager(rawSocket,portToUse,configFile,configStyle,0); + manager=&netmanager; + dcerr<<"NetManager created"<<std::endl; + setSignalHandler(); + + netmanager.readConfig(); + if (netmanager.prepare()) + { + if (!quiet) + { + printVersion(); + std::cout<<"\n\rrunning on port "<<portToUse<<"\n\rHave fun ! :-)"<<std::endl; + } + netmanager.run(); + }; + dcerr<<"server finished"<<std::endl; +} |