source: neercs/trunk/src/main.c @ 3940

Last change on this file since 3940 was 3940, checked in by Jean-Yves Lamoureux, 11 years ago
  • Move client's mainloop to client.c
  • Property svn:keywords set to Id
File size: 13.0 KB
Line 
1/*
2 *  neercs        console-based window manager
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                2008 Jean-Yves Lamoureux <jylam@lnxscene.org>
5 *                2008 Pascal Terjan <pterjan@linuxfr.org>
6 *                All Rights Reserved
7 *
8 *  $Id: main.c 3940 2009-11-18 14:55:57Z jylam $
9 *
10 *  This program is free software. It comes without any warranty, to
11 *  the extent permitted by applicable law. You can redistribute it
12 *  and/or modify it under the terms of the Do What The Fuck You Want
13 *  To Public License, Version 2, as published by Sam Hocevar. See
14 *  http://sam.zoy.org/wtfpl/COPYING for more details.
15 */
16
17#include "config.h"
18
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <signal.h>
25#include <sys/ioctl.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <sys/time.h>
29#include <time.h>
30#include <pwd.h>
31
32
33#if !defined HAVE_GETOPT_LONG
34#   include "mygetopt.h"
35#elif defined HAVE_GETOPT_H
36#   include <getopt.h>
37#endif
38#if defined HAVE_GETOPT_LONG
39#   define mygetopt getopt_long
40#   define myoptind optind
41#   define myoptarg optarg
42#   define myoption option
43#endif
44#include <errno.h>
45#include <caca.h>
46#include <caca.h>
47
48#include "neercs.h"
49
50
51void version(void)
52{
53    printf("%s\n", PACKAGE_STRING);
54    printf("Copyright (C) 2006, 2008 Sam Hocevar <sam@zoy.org>\n");
55    printf("                         Jean-Yves Lamoureux <jylam@lnxscene.org>\n\n");
56    printf("This is free software.  You may redistribute copies of it under the\n");
57    printf("terms of the Do What The Fuck You Want To Public License, Version 2\n");
58    printf("<http://sam.zoy.org/wtfpl/>.\n");
59    printf("There is NO WARRANTY, to the extent permitted by law.\n");
60    printf("\n");
61    printf("For more informations, visit http://libcaca.zoy.org/wiki/neercs\n");
62}
63
64void usage(int argc, char **argv)
65{
66    printf("%s\n", PACKAGE_STRING);
67    printf("Usage : %s [command1] [command2] ... [commandN]\n", argv[0]);
68    printf("Example : %s zsh top \n\n", argv[0]);
69    printf("Options :\n");
70    printf("\t--config\t-c <file>\t\tuse given config file\n");
71    printf("\t--pid\t\t-P [pid]\t\tgrab process\n");
72    printf("\t\t\t-r [session]\t\treattach to a detached neercs\n");
73    printf("\t\t\t-R [session]\t\treattach if possible, otherwise start a new session\n");
74    printf("\t\t\t-S <name>\t\tname this session <name> instead of <pid>\n");
75    printf("\t--version\t-v \t\t\tdisplay version and exit\n");
76    printf("\t--help\t\t-h \t\t\tthis help\n");
77}
78
79int main(int argc, char **argv)
80{
81    struct screen_list *screen_list = NULL;
82    int args;
83
84    int mainret = -1;
85       
86    screen_list = create_screen_list();
87    screen_list->default_shell = getenv("SHELL");
88
89    args = argc -1;
90    if(screen_list->default_shell == NULL  && args <= 0)
91    {
92        fprintf(stderr, "Environment variable SHELL not set and no arguments given. kthxbye.\n");
93        goto end;
94    }
95
96    if(handle_command_line(argc, argv, screen_list) < 0)
97        goto end;
98
99    /* Read global configuration first */
100    read_configuration_file("/etc/neercsrc", screen_list);
101
102    /* Then local one  */
103    if(screen_list->user_path)
104    {
105        read_configuration_file(screen_list->user_path, screen_list);
106        free(screen_list->user_path);
107    }
108
109    if(screen_list->attach)
110    {
111        if(screen_list->nb_to_grab || screen_list->to_start)
112        {
113            fprintf(stderr, "-R can not be associated with commands or pids!\n");
114            goto end;
115        }
116
117        attach(screen_list);
118
119        if(screen_list->forceattach && !screen_list->attach)
120            goto end;
121    }
122
123    /* Build default session name */
124    if(!screen_list->session_name)
125    {
126        char mypid[32]; /* FIXME Compute the length of PID_MAX ? */
127        snprintf(mypid, 31, "%d", getpid());
128        mypid[31]= '\0';
129        screen_list->session_name = strdup(mypid);
130        if(!screen_list->session_name)
131        {
132            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
133            goto end;
134        }
135    }
136    if(!screen_list->socket_path[SOCK_CLIENT])
137        screen_list->socket_path[SOCK_CLIENT] =
138            build_socket_path(screen_list->socket_dir, screen_list->session_name, SOCK_CLIENT);
139
140    if(!screen_list->socket_path[SOCK_SERVER])
141        screen_list->socket_path[SOCK_SERVER] =
142            build_socket_path(screen_list->socket_dir, screen_list->session_name, SOCK_SERVER);
143
144    /* Fork the server if needed */
145    if(!screen_list->attach)
146    {
147        debug("Spawning a new server");
148        if(start_server(screen_list))
149            goto end;
150    }
151
152
153    mainloop(screen_list);
154       
155    /* Clean up */
156    mainret = 0;
157end:
158
159    if(screen_list)
160    {
161        free_screen_list(screen_list);
162    }
163
164    return mainret;
165}
166
167void free_screen_list(struct screen_list *screen_list)
168{
169    int i;
170    struct option *option;
171
172    if(screen_list->dp)
173        caca_free_display(screen_list->dp);
174
175    if(screen_list->cv)
176        caca_free_canvas(screen_list->cv);
177   
178    for(i = 0; i < screen_list->count; i++)
179    {
180        destroy_screen(screen_list->screen[i]);
181    }
182
183    if(screen_list->socket_path[SOCK_SERVER])
184        free(screen_list->socket_path[SOCK_SERVER]);
185   
186    if(screen_list->socket_path[SOCK_CLIENT])
187    {
188        unlink(screen_list->socket_path[SOCK_CLIENT]);
189        free(screen_list->socket_path[SOCK_CLIENT]);
190    }
191   
192    if(screen_list->socket[SOCK_CLIENT])
193        close(screen_list->socket[SOCK_CLIENT]);
194   
195    if(screen_list->socket[SOCK_SERVER])
196        close(screen_list->socket[SOCK_SERVER]);
197
198    if(screen_list->screen)
199        free(screen_list->screen);
200
201    option = screen_list->config;
202   
203    while(option)
204    {
205        struct option *kromeugnon = option;
206        option = option->next;
207        if(kromeugnon->key)   free(kromeugnon->key);
208        if(kromeugnon->value) free(kromeugnon->value);
209        free(kromeugnon);
210    }
211   
212    for(i=0; i<screen_list->recurrent_list->count; i++)
213    {
214        remove_recurrent(screen_list->recurrent_list, i);
215        i = 0;
216    }
217
218    if(screen_list->recurrent_list->recurrent)
219        free(screen_list->recurrent_list->recurrent);
220    if(screen_list->recurrent_list)
221        free(screen_list->recurrent_list);
222   
223    if(screen_list->session_name)
224        free(screen_list->session_name);
225
226    if(screen_list->title)
227        free(screen_list->title);
228   
229    free(screen_list);
230}
231
232struct screen_list *create_screen_list(void)
233{
234
235    struct screen_list *screen_list = NULL;
236    struct passwd *user_info;
237    char *user_dir = NULL;
238
239    /* Create screen list */
240    screen_list = (struct screen_list*)     malloc(sizeof(struct screen_list));
241    if(!screen_list)
242    {
243        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
244        return NULL;
245    }
246    screen_list->screen = (struct screen**) malloc(sizeof(sizeof(struct screen*)));
247    if(!screen_list->screen)
248    {
249        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
250        free(screen_list);
251        return NULL;
252    }
253
254    screen_list->count = 0;
255    screen_list->mini = 1;
256    screen_list->help = 0;
257    screen_list->status = 1;
258    screen_list->title = NULL;
259    screen_list->window_list = 0;
260    screen_list->wm_type = WM_VSPLIT;
261    screen_list->in_bell = 0;
262    screen_list->changed = 0;
263    screen_list->requested_delay = 0;
264    screen_list->delay = 1000/60; /* Don't refresh more than 60 times per second */
265    screen_list->pty = screen_list->prevpty = 0;
266    screen_list->dont_update_coords = 0;
267    screen_list->screensaver_timeout = (60) * 1000000;
268    screen_list->screensaver_data = NULL;
269    screen_list->in_screensaver = 0;
270    screen_list->locked = 0;
271    screen_list->lock_offset = 0;
272    screen_list->lock_on_detach = 0;   
273    screen_list->attached = 1;
274    screen_list->socket[SOCK_SERVER] = 0;
275    screen_list->socket[SOCK_CLIENT] = 0;
276    screen_list->socket_dir    = NULL;
277    screen_list->socket_path[SOCK_SERVER] = NULL;
278    screen_list->socket_path[SOCK_CLIENT] = NULL;
279    screen_list->session_name  = NULL;
280    screen_list->default_shell = NULL;
281    screen_list->user_path     = NULL;
282    screen_list->autolock_timeout = -1;
283    screen_list->to_grab = NULL;
284    screen_list->to_start = NULL;
285    screen_list->nb_to_grab = 0;
286    screen_list->attach = 0;
287    screen_list->forceattach = 0;
288   
289    screen_list->force_refresh = 0;
290    screen_list->cube.in_switch = 0;
291    screen_list->cube.duration = 1000000;
292
293
294    screen_list->recurrent_list = NULL;
295    screen_list->cv = NULL;
296    screen_list->dp = NULL;
297
298    memset(screen_list->lockmsg, 0, 1024);
299    memset(screen_list->lockpass, 0, 1024);
300
301
302
303    /* Build local config file path */
304    user_dir = getenv("HOME");
305    if(!user_dir)
306    {
307        user_info = getpwuid(getuid());
308        if(user_info)
309        {
310            user_dir = user_info->pw_dir;
311        }
312    }
313    if(user_dir)
314    {
315        screen_list->user_path = malloc(strlen(user_dir) + strlen("/.neercsrc") + 1);
316        sprintf(screen_list->user_path, "%s/%s", user_dir, ".neercsrc");
317    }
318
319
320    screen_list->recurrent_list = (struct recurrent_list*) malloc(sizeof(struct recurrent_list));
321    screen_list->recurrent_list->recurrent = (struct recurrent**) malloc(sizeof(struct recurrent*));
322    if(!screen_list->recurrent_list->recurrent)
323    {
324        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
325        free(screen_list);
326        free(screen_list->screen);
327        return NULL;
328    }
329    screen_list->recurrent_list->count = 0;
330
331
332
333    return screen_list;
334}
335
336
337
338int handle_command_line(int argc, char *argv[], struct screen_list *screen_list)
339{
340    int s = 0, i;
341    for(;;)
342    {
343        int option_index = 0;
344        int pidopt;
345        static struct myoption long_options[] =
346            {
347                { "config",      1, NULL, 'c' },
348#if defined USE_GRAB
349                { "pid",         0, NULL, 'P' },
350#endif
351                { "help",        0, NULL, 'h' },
352                { "version",     0, NULL, 'v' },
353                { NULL, 0, NULL, 0 },
354            };
355#if defined USE_GRAB
356        int c = mygetopt(argc, argv, "c:S:R::r::P::hv", long_options, &option_index);
357#else
358        int c = mygetopt(argc, argv, "c:S:R::r::hv", long_options, &option_index);
359#endif
360        if(c == -1)
361            break;
362
363        switch(c)
364        {
365        case 'c': /* --config */
366            if(screen_list->user_path)
367                free(screen_list->user_path);
368            screen_list->user_path = strdup(myoptarg);
369            s+=2;
370            break;
371        case 'S':
372            if(!screen_list->session_name)
373                screen_list->session_name = strdup(myoptarg);
374            s+=2;
375            break;
376        case 'P': /* --pid */
377            if(myoptarg)
378            {
379                pidopt = atoi(myoptarg);
380                if(pidopt <= 0)
381                {
382                    fprintf(stderr, "Invalid pid %d\n", pidopt);
383                    if(screen_list->to_grab)
384                        free(screen_list->to_grab);
385                    return -1;
386                }
387            }
388            else
389                pidopt = select_process(screen_list);
390            if(pidopt <= 0)
391            {
392                s+=1;
393                break;
394            }
395            if(!screen_list->to_grab)
396            {
397                /* At most argc-1-s times -P <pid> + final 0 */
398                screen_list->to_grab = (int *)malloc(((argc-1-s)/2+1)*sizeof(int));
399                if(!screen_list->to_grab)
400                {
401                    fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
402                    return -1;
403                }
404            }
405            screen_list->to_grab[screen_list->nb_to_grab++] = pidopt;
406            screen_list->to_grab[screen_list->nb_to_grab] = 0;
407            s+=2;
408            break;
409        case 'r':
410            screen_list->forceattach = 1;
411        case 'R':
412            if(screen_list->attach)
413            {
414                fprintf(stderr, "Attaching can only be requested once\n");
415                return -1;
416            }
417            if(myoptarg)
418            {
419                if(screen_list->session_name)
420                    free(screen_list->session_name);
421                screen_list->session_name = strdup(myoptarg);
422                s+=1;
423            }
424            screen_list->attach = 1;
425            s+=1;
426            break;
427        case 'h': /* --help */
428            usage(argc, argv);
429            return -1;
430            break;
431        case 'v': /* --version */
432            version();
433            return -1;
434            break;
435        case -2:
436            return -1;
437        default:
438            fprintf(stderr, "Unknown argument #%d\n", myoptind);
439            return -1;
440            break;
441        }
442    }
443    if(s >= 0 && s < argc - 1)
444    {
445        screen_list->to_start = (char**)malloc((argc-s)*sizeof(char*));
446        if(!screen_list->to_start)
447        {
448            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
449            return -1;
450        }
451        for(i=0; i<(argc-1) - s; i++)
452        {
453            screen_list->to_start[i] = strdup(argv[i+s+1]);
454        }
455        screen_list->to_start[argc-1-s] = NULL;
456    }
457    return s;
458}
Note: See TracBrowser for help on using the repository browser.