Add manpage for notionflux
[notion.git] / notion / notion.c
blob502eff3f5327c7b5715b8bbde03aacb167275826
1 /*
2 * notion/notion/notion.c
4 * Copyright (c) the Notion team 2013.
5 * Copyright (c) Tuomo Valkonen 1999-2009.
7 * See the included file LICENSE for details.
8 */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
20 #include <libtu/util.h>
21 #include <libtu/optparser.h>
22 #include <libtu/errorlog.h>
23 #include <libtu/prefix.h>
24 #include <libextl/readconfig.h>
25 #include <libmainloop/exec.h>
27 #include <ioncore/common.h>
28 #include <ioncore/global.h>
29 #include <ioncore/ioncore.h>
30 #include <ioncore/exec.h>
31 #include <ioncore/event.h>
32 #include "../version.h"
34 #ifndef P_tmpdir
35 #define P_tmpdir "/tmp"
36 #endif
38 /* Options. Getopt is not used because getopt_long is quite gnu-specific
39 * and they don't know of '-display foo' -style args anyway.
40 * Instead, I've reinvented the wheel in libtu :(.
42 static OptParserOpt ion_opts[]={
43 {OPT_ID('d'), "display", OPT_ARG, "host:dpy.scr",
44 DUMMY_TR("X display to use")},
46 {'c', "conffile", OPT_ARG, "config_file",
47 DUMMY_TR("Configuration file")},
49 {'s', "searchdir", OPT_ARG, "dir",
50 DUMMY_TR("Add directory to search path")},
52 {OPT_ID('o'), "oneroot", 0, NULL,
53 DUMMY_TR("Manage default screen only")},
55 {OPT_ID('s'), "session", OPT_ARG, "session_name",
56 DUMMY_TR("Name of session (affects savefiles)")},
58 {OPT_ID('S'), "smclientid", OPT_ARG, "client_id",
59 DUMMY_TR("Session manager client ID")},
61 {OPT_ID('N'), "noerrorlog", 0, NULL,
62 DUMMY_TR("Do not create startup error log and display it "
63 "with xmessage.")},
65 {'h', "help", 0, NULL,
66 DUMMY_TR("Show this help")},
68 {'V', "version", 0, NULL,
69 DUMMY_TR("Show program version")},
71 {OPT_ID('a'), "about", 0, NULL,
72 DUMMY_TR("Show about text")},
74 END_OPTPARSEROPTS
78 void check_new_user_help()
80 const char *userdir=extl_userdir();
81 char *oldbeard=NULL;
82 char *tmp=NULL, *cmd=NULL;
83 pid_t pid;
84 bool ret;
86 if(userdir==NULL){
87 warn(TR("Could not get user configuration file directory."));
88 return;
91 libtu_asprintf(&oldbeard, "%s/.welcome_msg_displayed", userdir);
93 if(oldbeard==NULL)
94 return;
96 if(access(oldbeard, F_OK)==0){
97 free(oldbeard);
98 return;
101 libtu_asprintf(&tmp, TR("%s/welcome.txt"), SHAREDIR);
103 if(tmp!=NULL){
104 if(access(tmp, F_OK)==0)
105 libtu_asprintf(&cmd, "%s %s", CF_XMESSAGE, tmp);
106 else
107 libtu_asprintf(&cmd, "%s %s/welcome.txt", CF_XMESSAGE, SHAREDIR);
109 free(tmp);
111 if(cmd!=NULL){
112 ret=ioncore_exec(cmd);
114 free(cmd);
116 if(ret){
117 /* This should actually be done when less or xmessage returns,
118 * but that would mean yet another script...
120 mkdir(userdir, 0700);
121 if(open(oldbeard, O_CREAT|O_RDWR, 0600)<0)
122 warn_err_obj(oldbeard);
127 free(oldbeard);
131 static void help()
133 int i;
134 printf(TR("Usage: %s [options]\n\n"), libtu_progname());
135 for(i=0; ion_opts[i].descr!=NULL; i++)
136 ion_opts[i].descr=TR(ion_opts[i].descr);
137 optparser_printhelp(OPTP_MIDLONG, ion_opts);
138 printf("\n");
142 int main(int argc, char*argv[])
144 const char *cfgfile="cfg_notion";
145 const char *display=NULL;
146 char *cmd=NULL;
147 int stflags=0;
148 int opt;
149 ErrorLog el;
150 FILE *ef=NULL;
151 char *efnam=NULL;
152 bool may_continue=FALSE;
153 bool noerrorlog=FALSE;
154 char *localedir;
156 libtu_init(argv[0]);
158 #ifdef CF_RELOCATABLE_BIN_LOCATION
159 prefix_set(argv[0], CF_RELOCATABLE_BIN_LOCATION);
160 #endif
162 localedir=prefix_add(LOCALEDIR);
164 if(!ioncore_init(CF_EXECUTABLE, argc, argv, localedir))
165 return EXIT_FAILURE;
167 if(localedir!=NULL)
168 free(localedir);
170 prefix_wrap_simple(extl_add_searchdir, EXTRABINDIR); /* ion-completefile */
171 prefix_wrap_simple(extl_add_searchdir, MODULEDIR);
172 prefix_wrap_simple(extl_add_searchdir, ETCDIR);
173 prefix_wrap_simple(extl_add_searchdir, SHAREDIR);
174 prefix_wrap_simple(extl_add_searchdir, LCDIR);
175 extl_set_userdirs(CF_EXECUTABLE);
177 optparser_init(argc, argv, OPTP_MIDLONG, ion_opts);
179 while((opt=optparser_get_opt())){
180 switch(opt){
181 case OPT_ID('d'):
182 display=optparser_get_arg();
183 break;
184 case 'c':
185 cfgfile=optparser_get_arg();
186 break;
187 case 's':
188 extl_add_searchdir(optparser_get_arg());
189 break;
190 case OPT_ID('S'):
191 ioncore_g.sm_client_id=optparser_get_arg();
192 break;
193 case OPT_ID('o'):
194 stflags|=IONCORE_STARTUP_ONEROOT;
195 break;
196 case OPT_ID('s'):
197 extl_set_sessiondir(optparser_get_arg());
198 break;
199 case OPT_ID('N'):
200 noerrorlog=TRUE;
201 break;
202 case 'h':
203 help();
204 return EXIT_SUCCESS;
205 case 'V':
206 printf("%s\n", ION_VERSION);
207 return EXIT_SUCCESS;
208 case OPT_ID('a'):
209 printf("%s\n", ioncore_aboutmsg());
210 return EXIT_SUCCESS;
211 default:
212 warn(TR("Invalid command line."));
213 help();
214 return EXIT_FAILURE;
218 if(!noerrorlog){
219 /* We may have to pass the file to xmessage so just using tmpfile()
220 * isn't sufficient.
222 libtu_asprintf(&efnam, "%s/ion-%d-startup-errorlog", P_tmpdir,
223 getpid());
224 if(efnam==NULL){
225 warn_err();
226 }else{
227 ef=fopen(efnam, "wt");
228 if(ef==NULL){
229 warn_err_obj(efnam);
230 free(efnam);
231 efnam=NULL;
232 }else{
233 cloexec_braindamage_fix(fileno(ef));
234 fprintf(ef, TR("Notion startup error log:\n"));
235 errorlog_begin_file(&el, ef);
240 if(ioncore_startup(display, cfgfile, stflags))
241 may_continue=TRUE;
243 fail:
244 if(!may_continue)
245 warn(TR("Refusing to start due to encountered errors."));
246 else
247 check_new_user_help();
249 if(ef!=NULL){
250 pid_t pid=-1;
251 if(errorlog_end(&el) && ioncore_g.dpy!=NULL){
252 fclose(ef);
253 pid=fork();
254 if(pid==0){
255 ioncore_setup_display(DefaultScreen(ioncore_g.dpy));
256 if(!may_continue)
257 XCloseDisplay(ioncore_g.dpy);
258 else
259 close(ioncore_g.conn);
260 libtu_asprintf(&cmd, CF_XMESSAGE " %s", efnam);
261 if(cmd==NULL){
262 warn_err();
263 }else if(system(cmd)==-1){
264 warn_err_obj(cmd);
266 unlink(efnam);
267 exit(EXIT_SUCCESS);
269 if(!may_continue && pid>0)
270 waitpid(pid, NULL, 0);
271 }else{
272 fclose(ef);
274 if(pid<0)
275 unlink(efnam);
276 free(efnam);
279 if(!may_continue)
280 return EXIT_FAILURE;
282 ioncore_mainloop();
284 /* The code should never return here */
285 return EXIT_SUCCESS;