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

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