1 | /* |
---|
2 | main.c for LCDd |
---|
3 | |
---|
4 | Contains main(), plus signal callback functions and a help screen. |
---|
5 | |
---|
6 | Program init, command-line handling, and the main loop are |
---|
7 | implemented here. Also, minimal data about the program such as |
---|
8 | the revision number. |
---|
9 | |
---|
10 | Some of this stuff should probably be move elsewhere eventually, |
---|
11 | such as command-line handling and the main loop. main() is supposed |
---|
12 | to be "dumb". |
---|
13 | |
---|
14 | */ |
---|
15 | |
---|
16 | #include <stdlib.h> |
---|
17 | #include <stdio.h> |
---|
18 | #include <string.h> |
---|
19 | #include <signal.h> |
---|
20 | #include <unistd.h> |
---|
21 | |
---|
22 | #include "../shared/debug.h" |
---|
23 | |
---|
24 | #include "drivers/lcd.h" |
---|
25 | #include "sock.h" |
---|
26 | #include "clients.h" |
---|
27 | #include "screenlist.h" |
---|
28 | #include "screen.h" |
---|
29 | #include "parse.h" |
---|
30 | #include "render.h" |
---|
31 | #include "serverscreens.h" |
---|
32 | #include "input.h" |
---|
33 | #include "main.h" |
---|
34 | |
---|
35 | |
---|
36 | char *version = VERSION; |
---|
37 | char *build_date = __DATE__; |
---|
38 | |
---|
39 | |
---|
40 | /* no longer needed |
---|
41 | static screen_size sizes[] = |
---|
42 | { |
---|
43 | {"16x2", 16, 2}, |
---|
44 | {"16x4", 16, 4}, |
---|
45 | {"20x2", 20, 2}, |
---|
46 | {"20x4", 20, 4}, |
---|
47 | {"40x2", 40, 2}, |
---|
48 | {"40x4", 40, 4}, |
---|
49 | {NULL , 0, 0}, |
---|
50 | }; |
---|
51 | */ |
---|
52 | |
---|
53 | // This is currently only a list of available arguments, but doesn't |
---|
54 | // really *do* anything. It just helps to figure out which parameters |
---|
55 | // go to the server, and which ones go to individual drivers... |
---|
56 | static parameter args[] = |
---|
57 | { |
---|
58 | {"-h", "--help"}, |
---|
59 | {"-d", "--driver"}, |
---|
60 | {"-t", "--type"}, |
---|
61 | {"-f", "--foreground"}, |
---|
62 | {"-b", "--backlight"}, |
---|
63 | {NULL, NULL}, |
---|
64 | }; |
---|
65 | |
---|
66 | |
---|
67 | void exit_program(int val); |
---|
68 | void HelpScreen(); |
---|
69 | |
---|
70 | |
---|
71 | int main(int argc, char **argv) |
---|
72 | { |
---|
73 | // TODO: Use a config file! |
---|
74 | //char cfgfile[256] = "/etc/LCDd.cf"; |
---|
75 | int i, err, tmp; |
---|
76 | int daemon_mode=1; |
---|
77 | int disable_server_screen=0; |
---|
78 | int child; |
---|
79 | screen *s = NULL; |
---|
80 | char *str, *ing; // strings for commandline handling |
---|
81 | // screen_size *size = &sizes[0]; // No longer needed |
---|
82 | |
---|
83 | |
---|
84 | |
---|
85 | // Ctrl-C will cause a clean exit... |
---|
86 | signal(SIGINT, exit_program); |
---|
87 | // and "kill"... |
---|
88 | signal(SIGTERM, exit_program); |
---|
89 | // and "kill -HUP" (hangup)... |
---|
90 | signal(SIGHUP, exit_program); |
---|
91 | // and just in case, "kill -KILL" (which cannot be trapped; but oh well) |
---|
92 | signal(SIGKILL, exit_program); |
---|
93 | |
---|
94 | |
---|
95 | |
---|
96 | // If no paramaters given, give the help screen. |
---|
97 | if(argc == 1) HelpScreen(); |
---|
98 | |
---|
99 | // Don't spawn a child if we're using the curses driver |
---|
100 | for(i=1; i<argc; i++) |
---|
101 | { |
---|
102 | if(0 == strcmp(argv[i], "-f") || |
---|
103 | 0 == strcmp(argv[i], "--foreground") || |
---|
104 | 0 == strcmp(argv[i], "curses")) |
---|
105 | daemon_mode = 0; |
---|
106 | } |
---|
107 | |
---|
108 | // Now, go into daemon mode... |
---|
109 | #ifndef DEBUG |
---|
110 | if(daemon_mode) |
---|
111 | { |
---|
112 | if ((child = fork()) != 0) |
---|
113 | { |
---|
114 | usleep(1500000); // Wait for child to initialize |
---|
115 | exit(0); /* PARENT EXITS */ |
---|
116 | } |
---|
117 | // This line removed because it eats error messages... |
---|
118 | //setsid(); /* RELEASE TTY */ |
---|
119 | } |
---|
120 | #endif |
---|
121 | |
---|
122 | |
---|
123 | |
---|
124 | // Set up lcd driver base system |
---|
125 | lcd_init(""); |
---|
126 | |
---|
127 | |
---|
128 | // Parse the command line now... |
---|
129 | // TODO: Move this to a separate function? |
---|
130 | for(i=1; i<argc; i++) |
---|
131 | { |
---|
132 | if(0 == strcmp(argv[i], "-d") || |
---|
133 | 0 == strcmp(argv[i], "--driver")) |
---|
134 | { |
---|
135 | if(argc <= i+1) HelpScreen(); |
---|
136 | str = argv[++i]; |
---|
137 | ing = NULL; |
---|
138 | |
---|
139 | // Check to see if the next parameter is intended for LCDd, |
---|
140 | // or if it should be passed to the driver... |
---|
141 | if(argc > i+1) |
---|
142 | { |
---|
143 | int j, skip=0; |
---|
144 | for(j=1; args[j].lg; j++) // check each option except "help" |
---|
145 | if(! strcmp(argv[i+1], args[j].sh) || |
---|
146 | ! strcmp(argv[i+1], args[j].lg)) skip=1; |
---|
147 | |
---|
148 | if(! skip) |
---|
149 | { |
---|
150 | ing = argv[++i]; |
---|
151 | } |
---|
152 | //else i++; |
---|
153 | } |
---|
154 | err = lcd_add_driver(str, ing); |
---|
155 | if(err <= 0) |
---|
156 | { |
---|
157 | printf("Error loading driver %s. Continuing anyway...\n", |
---|
158 | str); |
---|
159 | } |
---|
160 | if((err > 0) && (0 == strcmp(str, "curses"))) daemon_mode=0; |
---|
161 | } |
---|
162 | else if(0 == strcmp(argv[i], "-h") || |
---|
163 | 0 == strcmp(argv[i], "--help")) |
---|
164 | { |
---|
165 | HelpScreen(); |
---|
166 | } |
---|
167 | // Redundant, but it prevents errors... |
---|
168 | else if(0 == strcmp(argv[i], "-f") || |
---|
169 | 0 == strcmp(argv[i], "--foreground")) |
---|
170 | { |
---|
171 | daemon_mode = 0; |
---|
172 | } |
---|
173 | else if(0 == strcmp(argv[i], "-b") || |
---|
174 | 0 == strcmp(argv[i], "--backlight")) |
---|
175 | { |
---|
176 | if(argc <= i+1) HelpScreen(); |
---|
177 | str = argv[++i]; |
---|
178 | if(0 == strcmp(str, "off")) |
---|
179 | backlight_state = backlight = BACKLIGHT_OFF; |
---|
180 | else if(0 == strcmp(str, "on")) |
---|
181 | backlight_state = backlight = BACKLIGHT_ON; |
---|
182 | else if(0 == strcmp(str, "open")) |
---|
183 | backlight = BACKLIGHT_OPEN; |
---|
184 | else HelpScreen(); |
---|
185 | } |
---|
186 | else if(0 == strcmp(argv[i], "-t") || |
---|
187 | 0 == strcmp(argv[i], "--type")) |
---|
188 | { |
---|
189 | if(i + 1 > argc) |
---|
190 | HelpScreen(); |
---|
191 | else |
---|
192 | { |
---|
193 | int wid, hgt; |
---|
194 | |
---|
195 | i++; |
---|
196 | sscanf(argv[i], "%ix%i", &wid, &hgt); |
---|
197 | if(wid>80 || wid<16 || hgt>25 || hgt<2) |
---|
198 | { |
---|
199 | fprintf(stderr, |
---|
200 | "LCDd: Invalid lcd size \"%s\". Using 20x4.\n", |
---|
201 | argv[i]); |
---|
202 | lcd.wid = 20; |
---|
203 | lcd.hgt = 4; |
---|
204 | } |
---|
205 | else |
---|
206 | { |
---|
207 | lcd.wid = wid; |
---|
208 | lcd.hgt = hgt; |
---|
209 | } |
---|
210 | |
---|
211 | /* no longer needed |
---|
212 | int j=0, valid=0; |
---|
213 | i++; |
---|
214 | for(j=0; sizes[j].size; j++) |
---|
215 | { |
---|
216 | if(0 == strcmp(sizes[j].size, argv[i])) |
---|
217 | { |
---|
218 | valid = 1; |
---|
219 | size = &sizes[j]; |
---|
220 | lcd.wid = size->wid; |
---|
221 | lcd.hgt = size->hgt; |
---|
222 | } |
---|
223 | } |
---|
224 | if(!valid) |
---|
225 | { |
---|
226 | fprintf(stderr, "LCDd: Invalid lcd size \"%s\". Using 20x4.\n", argv[i]); |
---|
227 | } |
---|
228 | */ |
---|
229 | } |
---|
230 | } |
---|
231 | else if(0 == strcmp(argv[i], "-i") || |
---|
232 | 0 == strcmp(argv[i], "--serverinfo")) |
---|
233 | { |
---|
234 | if(i + 1 > argc) |
---|
235 | HelpScreen(); |
---|
236 | else |
---|
237 | { |
---|
238 | i++; |
---|
239 | if(0 == strcmp(argv[i], "off")) disable_server_screen = 1; |
---|
240 | } |
---|
241 | } |
---|
242 | else |
---|
243 | { |
---|
244 | // otherwise... Get help! |
---|
245 | printf("Invalid parameter: %s\n", argv[i]); |
---|
246 | HelpScreen(); |
---|
247 | } |
---|
248 | } |
---|
249 | |
---|
250 | |
---|
251 | |
---|
252 | // Now init a bunch of required stuff... |
---|
253 | |
---|
254 | if(sock_create_server() <= 0) |
---|
255 | { |
---|
256 | printf("Error opening socket.\n"); |
---|
257 | return 1; |
---|
258 | } |
---|
259 | |
---|
260 | if(client_init() < 0) |
---|
261 | { |
---|
262 | printf("Error initializing client list\n"); |
---|
263 | return 1; |
---|
264 | } |
---|
265 | |
---|
266 | if(screenlist_init() < 0) |
---|
267 | { |
---|
268 | printf("Error initializing screen list\n"); |
---|
269 | return 1; |
---|
270 | } |
---|
271 | |
---|
272 | // Make sure the server screen shows up every once in a while.. |
---|
273 | if(server_screen_init() < 0) |
---|
274 | { |
---|
275 | printf("Error initializing server screens\n"); |
---|
276 | return 1; |
---|
277 | } |
---|
278 | else if(disable_server_screen) |
---|
279 | { |
---|
280 | server_screen->priority = 256; |
---|
281 | } |
---|
282 | |
---|
283 | |
---|
284 | |
---|
285 | |
---|
286 | |
---|
287 | // Main loop... |
---|
288 | while(1) |
---|
289 | { |
---|
290 | sock_poll_clients(); |
---|
291 | parse_all_client_messages(); |
---|
292 | handle_input(); |
---|
293 | |
---|
294 | // TODO: Move this code to screenlist.c... |
---|
295 | // ... it should just say "handle_screens();" |
---|
296 | // Timer gets reset by screenlist_next() |
---|
297 | timer++; |
---|
298 | // this line's here because s was getting overwritten at one time... |
---|
299 | //s = screenlist_current(); |
---|
300 | if(s && (timer >= s->duration)) |
---|
301 | { |
---|
302 | screenlist_next(); |
---|
303 | } |
---|
304 | // Just in case it gets out of hand... |
---|
305 | if(timer >= 0x10000) timer = 0; |
---|
306 | update_server_screen(timer); |
---|
307 | s = screenlist_current(); |
---|
308 | |
---|
309 | // render something here... |
---|
310 | if(s) draw_screen(s, timer); |
---|
311 | else no_screen_screen(timer); |
---|
312 | |
---|
313 | usleep(TIME_UNIT); |
---|
314 | } |
---|
315 | |
---|
316 | |
---|
317 | // Quit! |
---|
318 | exit_program(0); |
---|
319 | |
---|
320 | return 0; |
---|
321 | } |
---|
322 | |
---|
323 | |
---|
324 | void exit_program(int val) |
---|
325 | { |
---|
326 | // TODO: These things shouldn't be so interdependent. The order |
---|
327 | // things are shut down in shouldn't matter... |
---|
328 | |
---|
329 | // Say goodbye! |
---|
330 | goodbye_screen(); |
---|
331 | // Can go anywhere... |
---|
332 | lcd_shutdown(); |
---|
333 | |
---|
334 | // Must come before screenlist_shutdown |
---|
335 | client_shutdown(); |
---|
336 | // Must come after client_shutdown |
---|
337 | screenlist_shutdown(); |
---|
338 | // Should come after client_shutdown |
---|
339 | sock_close_all(); |
---|
340 | |
---|
341 | exit(0); |
---|
342 | |
---|
343 | } |
---|
344 | |
---|
345 | |
---|
346 | void HelpScreen() |
---|
347 | { |
---|
348 | printf("LCDproc server daemon, %s\n", version); |
---|
349 | printf("Copyright (c) 1999 Scott Scriven, William Ferrell, and misc contributors\n"); |
---|
350 | printf("This program is freely redistributable under the terms of the GNU Public License\n\n"); |
---|
351 | printf("Usage: lcdproc [options]\n"); |
---|
352 | printf("\tOptions in []'s are optional. Available options are:\n"); |
---|
353 | printf("\t-h\t--help\n\t\t\tDisplay this help screen\n"); |
---|
354 | printf("\t-t\t--type <size>\n\t\t\tSelect an LCD size (20x4, 16x2, etc...)\n"); |
---|
355 | printf("\t-d\t--driver <driver> [args]\n\t\t\tAdd a driver to use:\n"); |
---|
356 | printf("\t\t\tCFontz, curses, HD44780, irmanin, joy,\n\t\t\tMtxOrb, text\n"); |
---|
357 | printf("\t\t\t(args will be passed to the driver for init)\n"); |
---|
358 | printf("\t-f\t--foreground\n\t\t\tRun in the foreground (no daemon)\n"); |
---|
359 | printf("\t-b\t--backlight <mode>\n\t\t\tSet backlight mode (on, off, open)\n"); |
---|
360 | printf("\t-i\t--serverinfo off\n\t\t\tSet the server screen to low priority\n"); |
---|
361 | printf("\n"); |
---|
362 | printf("\tUse \"man LCDd\" for more info.\n"); |
---|
363 | printf("\tHelp on each driver's parameters are obtained upon request:\n\t\t\"LCDd -d driver --help\"\n"); |
---|
364 | printf("Example:\n"); |
---|
365 | printf("\tLCDd -d MtxOrb \"--device /dev/lcd --contrast 200\" -d joy\n"); |
---|
366 | printf("\n"); |
---|
367 | exit(0); |
---|
368 | } |
---|
369 | |
---|