Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

main.c

00001 /*
00002  *  main.c : main() of the server (flcdd)
00003  *           This file is part of the FreeLCD package.
00004  *  $Id: main_8c-source.html,v 1.1 2003/02/16 22:50:41 unicorn Exp $
00005  *
00006  *  This program is free software; you can redistribute it and/or modify it
00007  *  under the terms of the GNU General Public License as published by the
00008  *  Free Software Foundation; either version 2 of the License, or (at your
00009  *  option) any later version.
00010  * 
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00019  *  MA  02111-1307  USA
00020  *
00021  *  Copyright (c) 2002, 2003, Jeroen van den Berg <unicorn@hippie.nu>
00022  */
00023 
00024 #define GNU_PREFIX ""   /* "GNU " */
00025 
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029 
00030 #ifdef HAVE_UNISTD_H
00031 # include <unistd.h>
00032 #else
00033 # ifdef HAVE_SYS_UNISTD_H
00034 #  include <sys/unistd.h>
00035 # endif
00036 #endif
00037 
00038 #ifdef HAVE_LOCALE_H
00039 # include <locale.h>
00040 #endif
00041 
00042 #ifdef HAVE_SYSLOG_H
00043 # include <syslog.h>
00044 #else
00045 # define syslog(FOO)
00046 #endif
00047 
00048 #ifdef HAVE_TYPES_H
00049 # include <types.h>
00050 #else 
00051 # ifdef HAVE_SYS_TYPES_H
00052 #  include <sys/types.h>
00053 # endif
00054 #endif
00055 
00056 #ifdef HAVE_STRING_H
00057 # include <string.h>
00058 #else
00059 # ifdef HAVE_STRINGS_H
00060 #  include <strings.h>
00061 # endif
00062 #endif
00063 
00064 #include <pwd.h>
00065 #include <errno.h>
00066 #include <signal.h>
00067 #include <stdio.h>
00068 #include <stdlib.h>
00069 #include <sys/stat.h>
00070 
00071 #ifdef HAVE_GETOPT_LONG
00072 # include <getopt.h>
00073 #endif
00074 
00075 #ifdef HAVE_SOCKET_H
00076 # include <socket.h>
00077 #else
00078 # ifdef HAVE_SYS_SOCKET_H
00079 #  include <sys/socket.h>
00080 # endif
00081 #endif
00082 
00083 #include "common/socket.h"
00084 
00085 #include "renderers/charrenderer.h"
00086 #include "renderers/charcanvas.h"
00087 
00088 #include "connections.h"
00089 #include "drivers.h"
00090 #include "xmlconfig.h"
00091 
00092 /* gettext helper macro */
00093 #if ENABLE_NLS
00094 # include <libintl.h>
00095 # define _(foo) gettext (foo)
00096 #else
00097 # define bindtextdomain(X,Y)
00098 # define textdomain(Domain)
00099 # define _(foo) foo
00100 #endif /* enable_nls */
00101 
00102 #ifdef HAVE_GETOPT_LONG
00103 /* Options definition */
00104 static struct option longopts[] = {
00105   {"port", required_argument, 0, 'p'},
00106 #ifdef HAVE_FORK
00107   {"foreground", no_argument, 0, 'f'},
00108 #endif
00109   {"help", no_argument, 0, 'h'},
00110   {"version", no_argument, 0, 'V'},
00111   {0, 0, 0, 0}
00112 };
00113 #endif /* have getopt_long */
00114 
00115 
00116 
00117 /*----------------------------------------------------- sighup_handler --*/
00118 void
00119 sighup_handler ()
00120 {
00121   syslog (LOG_INFO, _("received SIGHUP"));
00122 }
00123 
00124 /*---------------------------------------------------- sigterm_handler --*/
00125 void
00126 sigterm_handler ()
00127 {
00128   syslog (LOG_INFO, _("received SIGTERM, exiting"));
00129   exit (EXIT_SUCCESS);
00130 }
00131 
00132 /*------------------------------------------------------- exit_program --*/
00133 void
00134 exit_program ()
00135 {
00136   syslog (LOG_INFO, _("exiting"));
00137   closelog ();
00138   exit (EXIT_FAILURE);
00139 }
00140 
00141 /*------------------------------------------------------------ sys_err --*/
00142 void
00143 sys_err (const char *errstr)
00144 {
00145   syslog (LOG_ERR, errstr);
00146   exit_program ();
00147 }
00148 
00149 /*---------------------------------------------------------- show_help --*/
00150 void
00151 show_help (const char *app_name)
00152 {
00153   printf (_("Usage: %s [options] ...\nOptions:\n"), app_name);
00154 #ifdef HAVE_GETOPT_LONG
00155   printf (_(" \
00156 --port, -p <portnr> Let the server listen on another port number\n"));
00157   printf (_(" --foreground, -f    Run the server in the foreground\n"));
00158   printf (_(" --help, -h          Program usage\n"));
00159   printf (_(" --version, -V       Show program version and exit\n"));
00160 #else
00161   printf (_(" -p <portnr>  Let the server listen on another port number\n"));
00162   printf (_(" -b           Run the server in the foreground\n"));
00163   printf (_(" -h           Program usage\n"));
00164   printf (_(" -V           Show program version and exit\n"));
00165 #endif
00166   printf (_("\nReport bugs to <%s>\n"), PACKAGE_BUGREPORT);
00167 }
00168 
00169 /*------------------------------------------------------- show_version --*/
00170 void
00171 show_version (const char *app_name)
00172 {
00173   printf ("%s - %s%s\n", app_name, GNU_PREFIX, PACKAGE_STRING);
00174   printf (_("Copyright (C) %s %s\n"), "2002, 2003", "Jeroen van den Berg");
00175   printf (_("\
00176 This program is free software; you may redistribute it under the terms of\n\
00177 the GNU General Public License.  This program comes with absolutely NO\n\
00178 WARRANTY. For more information about these matters, see the file named\n\
00179 COPYING.\n"));
00180 }
00181 
00182 /*------------------------------------------------ drop_root_privilege --*/
00183 void
00184 drop_root_privilege (const char *user)
00185 {
00186   struct passwd *pw_ent;
00187 
00188   /*  If we have root privs, try to set our uid to something safer.
00189    *  First try a specified username, then try "nobody" (which is a
00190    *  reasonable fallback on most systems).
00191    */
00192   if (getuid () == 0 || geteuid () == 0)
00193     {
00194       pw_ent = getpwnam (user);
00195       if (! pw_ent)
00196         {
00197           syslog (LOG_WARNING,
00198                   _("user %s is not a valid user, fallback to 'nobody'\n"),
00199                   user);
00200           pw_ent = getpwnam ("nobody");
00201           if (! pw_ent)
00202             {
00203               sys_err (_("cannot drop root privileges, aborting"));
00204               exit (EXIT_FAILURE);
00205             }
00206         }
00207 
00208       if (setuid (pw_ent->pw_uid) < 0)
00209         sys_err ("setuid");
00210     }
00211 }
00212 
00213 
00214 /*--------------------------------------------------------------- main --*/
00215 int
00216 main (int argc, char **argv)
00217 {
00218   char         c;
00219   int          run_in_foreground = 0; /* (--foreground) */
00220   unsigned int port = 8800; /* (--port) */
00221   const char   *app_name;
00222   pid_t        child; 
00223   long         tmp;
00224   socket_t     sock;
00225   fd_set       fdset;
00226   xml_node     *xconf;
00227   xml_node     *output_config;
00228   void         *driver;
00229   xml_node *fooxy;
00230   cl_layout *foox;
00231   cc_canvas *canvas;
00232   unsigned int i;
00233   
00234   /* Set up gettext internationalisation */
00235   setlocale (LC_ALL, "");
00236   bindtextdomain (PACKAGE, "/usr/share/locale");        /* LOCALEDIR ); */
00237   textdomain (PACKAGE);
00238 
00239   /* Find out name of executable */
00240   app_name = *argv + strlen (*argv) - 1;
00241   while (app_name > *argv && *(app_name - 1) != '/')
00242     --app_name;
00243 
00244   /* Parse command line options */
00245 #ifdef HAVE_GETOPT_LONG
00246   while ((c = getopt_long (argc, argv, "p:bhV", longopts, 0)) > 0)
00247 #else
00248   while ((c = getopt (argc, argv, "p:bhV")) > 0)
00249 #endif
00250     {
00251       switch (c)
00252         {
00253         case 'p':               /* --port, -p */
00254           tmp = strtol (optarg, 0, 10);
00255           if (errno == ERANGE || tmp < 1 || tmp > 65536)
00256             {
00257               fprintf (stderr,
00258                        _("Port number must be between 1 and 65536\n"));
00259               exit (EXIT_FAILURE);
00260             }
00261           port = tmp;
00262           break;
00263 
00264         case 'f':               /* --foreground, -f */
00265           run_in_foreground = 1;
00266           break;
00267           
00268         case 'h':               /* --help, -h */
00269           show_help (app_name);
00270           exit (EXIT_SUCCESS);
00271           break;
00272 
00273         case 'V':               /* --version, -V */
00274           show_version (app_name);
00275           exit (EXIT_SUCCESS);
00276           break;
00277 
00278         case '?':               /* Invalid option */
00279           show_help (app_name);
00280           exit (EXIT_FAILURE);
00281           break;
00282 
00283         default:
00284           /* In an ideal world, this shouldn't happen. */
00285           exit (EXIT_FAILURE);
00286         }
00287     }
00288 
00289   if (optind < argc)
00290     {
00291       perror (_("too many arguments"));
00292       exit (EXIT_FAILURE);
00293     }
00294 
00295   /* Fork into the background */
00296 #ifdef HAVE_FORK
00297   if (!run_in_foreground)
00298     {
00299       child = fork();
00300       if( child < 0 )
00301         sys_err( "fork" );
00302             
00303       if( child != 0 )
00304         exit( EXIT_SUCCESS );
00305 
00306       /* Create a new session */
00307       if( setsid() < 0 )
00308         sys_err( "setsid" );
00309     }
00310 #endif
00311 
00312   /* Configure system logging */
00313   openlog (app_name, LOG_CONS | LOG_PID | LOG_PERROR, LOG_DAEMON);
00314 
00315   /* Take some precautions */
00316   /*
00317   if( chdir( "/" ) < 0 )
00318     sys_err( "chdir" );
00319   */
00320   umask (0);
00321   if (!run_in_foreground)
00322     {
00323       close( STDOUT_FILENO );
00324       close( STDERR_FILENO );
00325     }
00326   close( STDIN_FILENO );
00327 
00328   /* Open server socket */
00329   sock = socket_create_server (port, &fdset);
00330   if (sock < 0)
00331     {
00332       switch (sock)
00333         {
00334         case -1:
00335           sys_err ("socket()");
00336           break;
00337         case -2:
00338           sys_err ("setsockopt()");
00339           break;
00340         case -3:
00341           sys_err ("bind()");
00342           break;
00343         case -4:
00344           sys_err ("listen()");
00345           break;
00346         default:
00347           sys_err (_("cannot open server socket"));
00348           break;
00349         }
00350       exit (EXIT_FAILURE);
00351     }
00352 
00353   /* We do not need "dangerous" privileges anymore, drop them before
00354    * messing with potential dangers like plug-ins. 
00355    */
00356   drop_root_privilege (app_name);
00357 
00358   /* Parse rc file */
00359   xconf = xc_parse_config_file ("flcdd.xml");
00360   if (! xconf)
00361     {
00362       sys_err (_("Failed to parse inifile"));
00363       exit (EXIT_FAILURE);
00364     }
00365 
00366   /* FIXME */
00367   fooxy = xc_parse_config_file ("../renderers/testlayout.xml");
00368   foox = cl_make_layout (fooxy);
00369 
00370   canvas = cc_create_canvas (20, 4);
00371   for (i = 0; i < foox->layout_data_size; ++i)
00372     {
00373       unsigned int x = foox->layout_data[i].x;
00374       unsigned int y = foox->layout_data[i].y;
00375       unsigned int j;
00376 
00377       for (j = 0; j < foox->layout_data[i].width; ++j)
00378         cc_put_char (canvas, x + j, y, foox->layout_data[i].utf8_data[j]);
00379     }
00380 
00381   /* Load driver modules */
00382   drivers_init ();
00383   output_config = 0;
00384   while ((output_config = xmlt_find (xconf, output_config, OUTPUT)) != 0)
00385     {
00386       const char* output_id_s = xmlt_get_attrib (output_config, ID);
00387       int output_id = 1;
00388 
00389       if (output_id_s)
00390           output_id = atoi (output_id_s);
00391 
00392       driver = drivers_create_output (output_config);
00393 
00394       if (!driver)
00395         puts ("drivers_create_output failed");
00396     }
00397 
00398   drivers_process_canvas (driver, canvas);
00399   xmlt_free_document (xconf);
00400 
00401   signal (SIGHUP, sighup_handler);
00402   signal (SIGTERM, sigterm_handler);
00403 
00404   /* Enter event loop */
00405   /* syslog (LOG_INFO, _("running")); */
00406   while (1)
00407     {
00408       /*  Poll the sockets from our file descriptor set, and call
00409        *  one of the conn_* functions whenever something interesting
00410        *  happens.
00411        */
00412       socket_poll (sock, &fdset, conn_open, conn_data, conn_close);
00413     }
00414 
00415   closelog ();
00416   return EXIT_SUCCESS;
00417 }

Generated on Sun Feb 16 23:39:49 2003 for FreeLCD by doxygen1.2.18