]> git.decadent.org.uk Git - ion3.git/blob - pwm/pwm.c
[svn-upgrade] Integrating new upstream version, ion3 (20071130)
[ion3.git] / pwm / pwm.c
1 /*
2  * ion/pwm/pwm.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18
19 #include <libtu/util.h>
20 #include <libtu/optparser.h>
21 #include <libtu/errorlog.h>
22 #include <libextl/readconfig.h>
23 #include <libmainloop/exec.h>
24
25 #include <ioncore/common.h>
26 #include <ioncore/global.h>
27 #include <ioncore/ioncore.h>
28 #include <ioncore/exec.h>
29 #include <ioncore/event.h>
30 #include "../version.h"
31
32
33 /* Options. Getopt is not used because getopt_long is quite gnu-specific
34  * and they don't know of '-display foo' -style args anyway.
35  * Instead, I've reinvented the wheel in libtu :(.
36  */
37 static OptParserOpt pwm_opts[]={
38     {OPT_ID('d'), "display",  OPT_ARG, "host:dpy.scr", 
39      DUMMY_TR("X display to use")},
40     
41     {'c', "conffile", OPT_ARG, "config_file", 
42      DUMMY_TR("Configuration file")},
43     
44     {'s', "searchdir", OPT_ARG, "dir", 
45      DUMMY_TR("Add directory to search path")},
46
47     {OPT_ID('o'), "oneroot",  0, NULL,
48      DUMMY_TR("Manage default screen only")},
49
50     {OPT_ID('s'), "session",  OPT_ARG, "session_name", 
51      DUMMY_TR("Name of session (affects savefiles)")},
52     
53     {OPT_ID('S'), "smclientid", OPT_ARG, "client_id", 
54      DUMMY_TR("Session manager client ID")},
55
56     {OPT_ID('N'), "noerrorlog", 0, NULL, 
57      DUMMY_TR("Do not create startup error log and display it "
58               "with xmessage.")},
59     
60     {'h', "help", 0, NULL, 
61      DUMMY_TR("Show this help")},
62     
63     {'V', "version", 0, NULL,
64      DUMMY_TR("Show program version")},
65     
66     {OPT_ID('a'), "about", 0, NULL,
67      DUMMY_TR("Show about text")},
68     
69     END_OPTPARSEROPTS
70 };
71
72
73 static void help()
74 {
75     int i;
76     printf(TR("Usage: %s [options]\n\n"), libtu_progname());
77     for(i=0; pwm_opts[i].descr!=NULL; i++)
78         pwm_opts[i].descr=TR(pwm_opts[i].descr);
79     optparser_printhelp(OPTP_MIDLONG, pwm_opts);
80     printf("\n");
81 }
82
83
84 int main(int argc, char*argv[])
85 {
86     const char *cfgfile="cfg_pwm";
87     const char *display=NULL;
88     char *cmd=NULL;
89     int stflags=0;
90     int opt;
91     ErrorLog el;
92     FILE *ef=NULL;
93     char *efnam=NULL;
94     bool may_continue=FALSE;
95     bool noerrorlog=FALSE;
96
97     libtu_init(argv[0]);
98
99     if(!ioncore_init("pwm3", argc, argv, LOCALEDIR))
100         return EXIT_FAILURE;
101
102     extl_add_searchdir(EXTRABINDIR); /* ion-completefile */
103     extl_add_searchdir(MODULEDIR);
104     extl_add_searchdir(ETCDIR);
105 #ifdef PWM_ETCDIR    
106     extl_add_searchdir(PWM_ETCDIR);
107 #endif
108     extl_add_searchdir(SHAREDIR);
109     extl_add_searchdir(LCDIR);
110     extl_set_userdirs("pwm3");
111
112     optparser_init(argc, argv, OPTP_MIDLONG, pwm_opts);
113     
114     while((opt=optparser_get_opt())){
115         switch(opt){
116         case OPT_ID('d'):
117             display=optparser_get_arg();
118             break;
119         case 'c':
120             cfgfile=optparser_get_arg();
121             break;
122         case 's':
123             extl_add_searchdir(optparser_get_arg());
124             break;
125         case OPT_ID('S'):
126             ioncore_g.sm_client_id=optparser_get_arg();
127             break;
128         case OPT_ID('o'):
129             stflags|=IONCORE_STARTUP_ONEROOT;
130             break;
131         case OPT_ID('s'):
132             extl_set_sessiondir(optparser_get_arg());
133             break;
134         case OPT_ID('N'):
135             noerrorlog=TRUE;
136             break;
137         case 'h':
138             help();
139             return EXIT_SUCCESS;
140         case 'V':
141             printf("%s\n", ION_VERSION);
142             return EXIT_SUCCESS;
143         case OPT_ID('a'):
144             printf("%s\n", ioncore_aboutmsg());
145             return EXIT_SUCCESS;
146         default:
147             warn(TR("Invalid command line."));
148             help();
149             return EXIT_FAILURE;
150         }
151     }
152
153     if(!noerrorlog){
154         /* We may have to pass the file to xmessage so just using tmpfile()
155          * isn't sufficient.
156          */
157         libtu_asprintf(&efnam, "%s/pwm-%d-startup-errorlog", P_tmpdir,
158                        getpid());
159         if(efnam==NULL){
160             warn_err();
161         }else{
162             ef=fopen(efnam, "wt");
163             if(ef==NULL){
164                 warn_err_obj(efnam);
165                 free(efnam);
166                 efnam=NULL;
167             }else{
168                 cloexec_braindamage_fix(fileno(ef));
169                 fprintf(ef, TR("PWM startup error log:\n"));
170                 errorlog_begin_file(&el, ef);
171             }
172         }
173     }
174
175     if(ioncore_startup(display, cfgfile, stflags))
176         may_continue=TRUE;
177
178 fail:
179     if(!may_continue)
180         warn(TR("Refusing to start due to encountered errors."));
181     
182     if(ef!=NULL){
183         pid_t pid=-1;
184         if(errorlog_end(&el) && ioncore_g.dpy!=NULL){
185             fclose(ef);
186             pid=fork();
187             if(pid==0){
188                 ioncore_setup_display(DefaultScreen(ioncore_g.dpy));
189                 if(!may_continue)
190                     XCloseDisplay(ioncore_g.dpy);
191                 else
192                     close(ioncore_g.conn);
193                 libtu_asprintf(&cmd, CF_XMESSAGE " %s", efnam);
194                 if(cmd==NULL){
195                     warn_err();
196                 }else if(system(cmd)==-1){
197                     warn_err_obj(cmd);
198                 }
199                 unlink(efnam);
200                 exit(EXIT_SUCCESS);
201             }
202             if(!may_continue && pid>0)
203                 waitpid(pid, NULL, 0);
204         }else{
205             fclose(ef);
206         }
207         if(pid<0)
208             unlink(efnam);
209         free(efnam);
210     }
211
212     if(!may_continue)
213         return EXIT_FAILURE;
214     
215     ioncore_mainloop();
216     
217     /* The code should never return here */
218     return EXIT_SUCCESS;
219 }