Implemented startup script registration command-line interface.
[udpgate.git] / src / main.c
1 /* $Id$
2  * UDP Gateway utility
3  * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include <glib/gmessages.h>
23 #include <popt.h>
24 #include <locale.h>
25 #include <stdlib.h>
26 #include <glib/gutils.h>
27 #include <string.h>
28 #include <setjmp.h>
29 #include <unistd.h>
30
31 #ifdef HAVE_GNOME
32 #include <libgnome/gnome-program.h>
33 #include <libgnomeui/gnome-ui-init.h>
34 #endif
35
36 #include "main.h"       /* self */
37 #include "ui-line.h"
38 #include "network.h"
39 #include "configuration.h"
40 #include "startup.h"
41
42 #ifdef HAVE_GNOME
43 #include "ui-gnome.h"
44 #endif
45
46
47 /* Config: */
48 #define LOCAL_PORT_DEFAULT 9201
49
50
51 static int optarg_text;
52 int optarg_verbose;
53 int optarg_port=LOCAL_PORT_DEFAULT;
54 static int optarg_start;
55 static int optarg_stop;
56 int optarg_no_fork;
57 static int optarg_startup_query;
58 static int optarg_startup_on;
59 static int optarg_startup_off;
60
61 void (*ui_interactive)(void);
62
63 static const struct poptOption popt_table[]={
64
65 #define UDPGATE_POPT(shortname,longname,argInfoP,argP,valP,descripP,argDescripP) \
66                 { \
67                         longName: (longname), \
68                         shortName: (shortname), \
69                         argInfo: (argInfoP)|(!(valP) ? 0 : POPT_ARG_VAL), \
70                         arg: (void *)argP, \
71                         val: (valP), \
72                         descrip: (descripP), \
73                         argDescrip: (argDescripP), \
74                 }
75
76 #ifdef HAVE_GNOME
77 #define OPT_TEXT_IF_GNOME N_("Disable Gnome UI; --text must be first argument")
78 #else /* HAVE_GNOME */
79 #define OPT_TEXT_IF_GNOME N_("(no Gnome UI compiled - stub only); --text must be first argument")
80 #endif /* HAVE_GNOME */
81                 UDPGATE_POPT(0  ,"text"         ,POPT_ARG_NONE                          ,&optarg_text         ,0,
82                                 OPT_TEXT_IF_GNOME,NULL),                                                                  
83 #undef OPT_TEXT_IF_GNOME                                                                          
84                 UDPGATE_POPT('v',"verbose"      ,POPT_ARG_NONE                          ,&optarg_verbose      ,0,
85                                 N_("Display additional debug information"),NULL),                                         
86                 UDPGATE_POPT('p',"port"         ,POPT_ARG_INT |POPT_ARGFLAG_SHOW_DEFAULT,&optarg_port         ,0,
87                                 N_("Listen on this UDP port"),NULL),                                                      
88                 UDPGATE_POPT('s',"start"        ,POPT_ARG_NONE                          ,&optarg_start        ,0,
89                                 N_("Start the daemon"),NULL),                                                             
90                 UDPGATE_POPT('S',"stop"         ,POPT_ARG_NONE                          ,&optarg_stop         ,0,
91                                 N_("Stop the daemon"),NULL),
92                 UDPGATE_POPT('1',"no-fork"      ,POPT_ARG_NONE                          ,&optarg_no_fork      ,0,
93                                 N_("Do not detach from the current process"),NULL),
94                 UDPGATE_POPT(0  ,"startup-query",POPT_ARG_NONE                          ,&optarg_startup_query,0,
95                                 N_("Query the current state of the system startup registrance"),NULL),
96                 UDPGATE_POPT(0  ,"startup-on"   ,POPT_ARG_NONE                          ,&optarg_startup_on   ,0,
97                                 N_("Register for the automatic system startup"),NULL),
98                 UDPGATE_POPT(0  ,"startup-off"  ,POPT_ARG_NONE                          ,&optarg_startup_off  ,0,
99                                 N_("Unregister from the automatic system startup"),NULL),
100
101 #undef UDPGATE_POPT
102                 POPT_TABLEEND
103                 };
104
105 static const struct poptOption popt_table_autohelp[]={
106                 { NULL,'\0',POPT_ARG_INCLUDE_TABLE,(struct poptOption *)&popt_table,0,PACKAGE },
107                 POPT_AUTOHELP
108                 POPT_TABLEEND
109                 };
110
111
112 #ifdef HAVE_GNOME
113 static jmp_buf gnome_init_atexit_jmpbuf;
114 static gboolean gnome_init_atexit_disable;
115
116 static void gnome_init_atexit_handler(void)
117 {
118         if (gnome_init_atexit_disable)
119                 return;
120
121         longjmp(gnome_init_atexit_jmpbuf,1);
122         g_assert_not_reached();
123         _exit(EXIT_FAILURE);
124 }
125
126 static gboolean gnome_init_g_log_handler_hit;
127 static void gnome_init_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
128 {
129         gnome_init_g_log_handler_hit=TRUE;
130         g_log_default_handler(log_domain,log_level,message,user_data);
131 }
132 #endif /* HAVE_GNOME */
133
134 int main(int argc,char **argv)
135 {
136 poptContext context;
137 int errint;
138 gboolean is_interactive;
139 #ifdef HAVE_GNOME
140 gboolean no_gnome;
141 #endif /* HAVE_GNOME */
142 int exit_rc=EXIT_SUCCESS;
143
144 #if 0
145         g_log_set_always_fatal(~(0
146                         |G_LOG_LEVEL_MESSAGE
147                         |G_LOG_LEVEL_INFO
148                         |G_LOG_LEVEL_DEBUG
149                         ));
150 #endif
151
152         /* Initialize the i18n stuff */
153         setlocale(LC_ALL,"");
154         bindtextdomain(PACKAGE,LOCALEDIR);
155         textdomain(PACKAGE);
156
157         /* Read it before the command-line parsing to get the default value
158          * of 'optarg_port' displayable by 'POPT_ARGFLAG_SHOW_DEFAULT'.
159          */
160         configuration_read();
161
162         if (argv[1] && !strcmp(argv[1],"--text"))
163                 optarg_text=1;
164
165 #ifdef HAVE_GNOME
166         no_gnome=(optarg_text || !getenv("DISPLAY") || !*getenv("DISPLAY"));
167
168         if (no_gnome)
169 #endif /* HAVE_GNOME */
170         {
171                 context=poptGetContext(
172                                 PACKAGE,        /* name */
173                                 argc,(/*en-const*/const char **)argv,   /* argc,argv */
174                                 popt_table_autohelp,    /* options */
175                                 POPT_CONTEXT_POSIXMEHARDER);    /* flags; && !POPT_CONTEXT_KEEP_FIRST */
176                 if (context==NULL) {
177                         g_assert_not_reached(); /* argument recognization args_error */
178                         return EXIT_FAILURE;
179                         }
180                 errint=poptReadDefaultConfig(context,
181                                 TRUE);  /* useEnv */
182                 if (errint!=0) {
183                         g_assert_not_reached(); /* argument recognization args_error */
184                         return EXIT_FAILURE;
185                         }
186                 errint=poptGetNextOpt(context);
187                 if (errint!=-1)
188                         g_error(_("Specified option not expected"));
189                 if (poptPeekArg(context))
190                         g_error(_("No arguments expected"));
191                 }
192 #ifdef HAVE_GNOME
193         else {
194 GnomeProgram *gnome_program;
195 guint handler_id;
196
197                 gnome_init_atexit_disable=FALSE;
198                 g_atexit(gnome_init_atexit_handler);
199                 gnome_init_g_log_handler_hit=FALSE;
200                 handler_id=g_log_set_handler(
201                                 "Gtk",  /* log_domain */
202                                 G_LOG_LEVEL_WARNING,    /* log_levels */
203                                 gnome_init_g_log_handler,       /* log_func */
204                                 NULL);  /* user_data */
205                 if (!setjmp(gnome_init_atexit_jmpbuf))
206                         gnome_program=gnome_program_init(PACKAGE,VERSION,LIBGNOMEUI_MODULE,argc,argv,
207                                         GNOME_PARAM_POPT_TABLE,popt_table,
208                                         GNOME_PARAM_POPT_FLAGS,(int)POPT_CONTEXT_POSIXMEHARDER,
209                                         NULL);
210                 else {
211                         no_gnome=TRUE;
212                         /* No message: (udpgate:3693): Gtk-WARNING **: cannot open display:
213                          * was reported, probably only '--help' message was shown.
214                          */
215                         if (!gnome_init_g_log_handler_hit)
216                                 exit(EXIT_SUCCESS);
217                         }
218                 gnome_init_atexit_disable=TRUE;
219                 g_log_remove_handler(
220                                 "Gtk",  /* log_domain */
221                                 handler_id);    /* handler_id */
222                 }
223 #endif /* HAVE_GNOME */
224
225         is_interactive=(1
226                         && !optarg_start
227                         && !optarg_stop
228                         && !optarg_startup_query
229                         && !optarg_startup_on
230                         && !optarg_startup_off);
231
232         /* Initialize UI here to catch all GLog errors below. */
233         if (is_interactive
234 #ifdef HAVE_GNOME
235                         && (no_gnome || !ui_gnome_init())
236 #endif /* HAVE_GNOME */
237                         && !ui_line_init())
238                 g_error(_("No UI interface could be initialized"));
239
240         if (!is_interactive) {
241
242                 if (optarg_startup_query || optarg_startup_off || optarg_startup_on)
243                         startup_init();
244
245                 if (optarg_stop)
246                         if (!network_stop())
247                                 exit_rc=2;
248                 if (optarg_startup_query) {
249 gboolean is_on;
250
251                         if (startup_query(&is_on)) {
252                                 g_message((is_on
253                                                 ? _("System startup registrance is turned on.")
254                                                 : _("System startup registrance is turned off.")));
255                                 if (exit_rc<2)
256                                         exit_rc=(is_on ? 0 : 1);
257                                 }
258                         else
259                                 exit_rc=2;
260                         }
261                 if (optarg_startup_off) {
262                         if (!startup_off())
263                                 exit_rc=2;
264                         }
265                 if (optarg_startup_on) {
266                         if (!startup_on())
267                                 exit_rc=2;
268                         }
269                 if (optarg_start)
270                         if (!network_start(optarg_port))
271                                 exit_rc=2;
272
273                 network_detach();
274                 }
275         else
276                 (*ui_interactive)();
277
278         configuration_write();
279
280         exit(exit_rc);
281 }