Changeset 2588 for neercs


Ignore:
Timestamp:
Jul 27, 2008, 1:17:04 AM (12 years ago)
Author:
Pascal Terjan
Message:
  • Rewrote detach handling, enjoy silent neercs
Location:
neercs/trunk/src
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • neercs/trunk/src/Makefile.am

    r2509 r2588  
    44neercs_SOURCES = neercs.h mygetopt.c recurrent.c main.c screens.c term.c \
    55                 grab.c effects.c wm.c screensaver.c attach.c configuration.c \
    6                  mytrace.c mytrace.h input.c lock.c
     6                 mytrace.c mytrace.h input.c lock.c server.c
    77neercs_CFLAGS = @CACA_CFLAGS@
    88neercs_LDADD = @CACA_LIBS@ @UTIL_LIBS@ @PAM_LIBS@
  • neercs/trunk/src/attach.c

    r2488 r2588  
    1212#include <sys/stat.h>
    1313
     14#include <caca.h>
     15
    1416#include "neercs.h"
    1517
    16 static char * build_socket_path(char *socket_dir, char *session_name)
     18char * build_socket_path(char *socket_dir, char *session_name)
    1719{
    1820    char *path, *dir;
     
    4648
    4749    myaddr.sun_family = AF_UNIX;
    48     screen_list->socket_path = build_socket_path(screen_list->socket_path, screen_list->session_name);
    4950    strncpy(myaddr.sun_path, screen_list->socket_path, sizeof(myaddr.sun_path) - 1);
    50     unlink(myaddr.sun_path);
    5151
    5252    if(bind(sock, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_un)) < 0)
     
    6565
    6666    return 0;
    67 }
    68 
    69 int detach(struct screen_list* screen_list, caca_display_t * dp)
    70 {
    71     int fd;
    72     int pid;
    73 
    74     screen_list->attached = 0;
    75     caca_free_display(dp);
    76 
    77     close(0);
    78     close(1);
    79     close(2);
    80 
    81     fd = open("/dev/null", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
    82     dup2(fd, 0);
    83     if(fd != 0)
    84         close(fd);
    85     fd = open("/tmp/log.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
    86     dup2(fd, 1);
    87     dup2(fd, 2);
    88     if (fd > 2)
    89         close(fd);
    90 
    91     if(!screen_list->socket)
    92     {
    93         pid = fork();
    94         if (pid < 0)
    95             return 1;
    96         if (pid > 0)
    97             exit(0);
    98 
    99         create_socket(screen_list);
    100         setsid();
    101     }
    102 
    103     return 0;
    104 }
    105 
    106 static int handle_command(char * cmd, struct screen_list* screen_list, cucul_canvas_t * cv, caca_display_t ** dp)
    107 {
    108     int refresh = 0;
    109     debug("Received command %s", cmd);
    110     if(!strncmp("ENV ", cmd, 4))
    111     {
    112         putenv(strdup(cmd+4));
    113     }
    114     else if(!strncmp("ATTACH ", cmd, 7))
    115     {
    116         int fd;
    117         screen_list->attached = 1;
    118         close(screen_list->socket);
    119         screen_list->socket= 0;
    120         unlink(screen_list->socket_path);
    121         screen_list->socket_path = NULL;
    122         close(0);
    123         fd=open(cmd+7, O_RDWR);
    124         dup2(fd, 0);
    125         close(1);
    126         fd=open(cmd+7, O_RDWR);
    127         dup2(fd, 1);
    128         close(2);
    129         fd=open(cmd+7, O_RDWR);
    130         dup2(fd, 2);
    131         *dp = caca_create_display(cv);
    132         if(*dp)
    133         {
    134             caca_set_cursor(*dp, 1);
    135             refresh = 1;
    136         }
    137     }
    138     else
    139     {
    140         fprintf(stderr, "Unknown command received: %s\n", cmd);
    141     }
    142     return refresh;
    143 }
    144 
    145 int read_socket(struct screen_list* screen_list, cucul_canvas_t * cv, caca_display_t ** dp) {
    146     ssize_t n;
    147     char buf[4097];
    148     int refresh = 0;
    149 
    150     if(!screen_list->socket)
    151         return 0;
    152 
    153     while (screen_list->socket && (n = read(screen_list->socket, buf, sizeof(buf)-1)) > 0)
    154     {
    155         buf[n] = 0;
    156         refresh |= handle_command(buf, screen_list, cv, dp);
    157     }
    158     return refresh;
    15967}
    16068
     
    194102}
    195103
    196 
    197 /* FIXME Is this really not defined anywhere ? */
    198 extern char **environ;
    199 
    200 int request_attach(char *socket_path)
     104char * connect_server(char *socket_path, struct screen_list* screen_list)
    201105{
    202106    int sock;
    203     char fdstr[PATH_MAX], lnk[PATH_MAX];
    204     char buf[4096];
    205107    struct sockaddr_un addr;
    206108
     
    210112    if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
    211113        perror("request_attach:socket");
    212         return 1;
     114        return NULL;
    213115    }
    214116
     
    219121    {
    220122        printf("Failed to connect to %s: %s\n", socket_path, strerror(errno));
    221         return 1;
     123        return NULL;
    222124    }
     125    fcntl(sock, F_SETFL, O_NONBLOCK);
    223126
    224     debug("Sending environment", 0);
     127    screen_list->socket_path = socket_path;
     128    screen_list->socket = sock;
    225129
    226     /* Send our environment */
    227 #define sendvar(var) if(getenv(var)) {snprintf(buf, 4096, "ENV %s=%s", var, getenv(var)); write(sock, buf, strlen(buf));}
    228     sendvar("DISPLAY")
    229     sendvar("CACA_DRIVER")
     130    return strdup(socket_path); /* FIXME */
     131}
    230132
    231     snprintf(fdstr, sizeof(fdstr), "/proc/%d/fd/0", getpid());
    232     readlink(fdstr, lnk, sizeof(lnk)-1);
    233     lnk[PATH_MAX-1] = '\0';
     133int request_attach(struct screen_list* screen_list)
     134{
     135    debug("Requesting attach");
    234136
    235     close(0);
     137    write(screen_list->socket, "ATTACH", strlen("ATTACH"));
    236138
    237     debug("Requesting attach to %s", lnk);
     139    return 0;
     140}
    238141
    239     /* Request attaching */
    240     snprintf(buf, 4096, "ATTACH %s", lnk);
    241     write(sock, buf, strlen(buf));
    242     close(sock);
     142int send_event(caca_event_t ev, int sock)
     143{
     144    enum caca_event_type t;
    243145
    244     debug("Exiting", 0);
    245     exit(0);
     146    t = caca_get_event_type(&ev);
     147
     148    if(t & CACA_EVENT_KEY_PRESS)
     149    {
     150        char buf[16];
     151        int bytes;
     152        bytes = snprintf(buf, sizeof(buf)-1, "KEY %d", caca_get_event_key_ch(&ev));
     153        buf[bytes] = '\0';
     154        debug("Sending key press to server: %s", buf);
     155        return write(sock, buf, strlen(buf)) <= 0;
     156    }
     157    else if(t & CACA_EVENT_RESIZE)
     158        return write(sock, "RESIZE", strlen("RESIZE")) <= 0;
     159    else if(t & CACA_EVENT_QUIT)
     160        return write(sock, "QUIT", strlen("QUIT")) <= 0;
     161
     162    return 0;
    246163}
     164
  • neercs/trunk/src/input.c

    r2581 r2588  
    136136    case 'd':
    137137    case 0x04: //CACA_KEY_CTRL_D:
    138         detach(screen_list, screen_list->dp);
     138        detach(screen_list);
    139139        break;
    140140    }
  • neercs/trunk/src/main.c

    r2581 r2588  
    8181    struct screen_list *screen_list = NULL;
    8282    struct passwd *user_info;
    83     char *user_path = NULL, *user_dir = NULL, *session_name = NULL;
     83    char *user_path = NULL, *user_dir = NULL;
    8484    int i, args, s=0;
    85     int eof = 0, refresh = 1, command = 0;
     85    int refresh = 1;
    8686    long long unsigned int last_key_time = 0;
    8787    int mainret = 0;
    8888    int attach = 0, forceattach = 0;
    8989    int *to_grab = NULL;
     90    char **to_start = NULL;
    9091    int nb_to_grab = 0;
    9192
     
    159160            break;
    160161        case 'S':
    161             if(screen_list->session_name)
    162                 free(screen_list->session_name);
    163             screen_list->session_name = strdup(myoptarg);
     162            if(!screen_list->session_name)
     163                screen_list->session_name = strdup(myoptarg);
    164164            s+=2;
    165165            break;
     
    175175            if(!to_grab)
    176176            {
    177                 /* At most argc-1-s times -P <pid> */
    178                 to_grab = (int *)malloc(((argc-1-s)/2)*sizeof(int));
     177                /* At most argc-1-s times -P <pid> + final 0 */
     178                to_grab = (int *)malloc(((argc-1-s)/2+1)*sizeof(int));
    179179                if(!to_grab)
    180180                {
     
    184184            }
    185185            to_grab[nb_to_grab++] = pidopt;
     186            to_grab[nb_to_grab] = 0;
    186187            s+=2;
    187188            break;
     
    196197            if(myoptarg)
    197198            {
    198                 session_name = strdup(myoptarg);
     199                if(screen_list->session_name)
     200                    free(screen_list->session_name);
     201                screen_list->session_name = strdup(myoptarg);
    199202                s+=1;
    200203            }
     
    217220    }
    218221
     222    if(s < argc - 1)
     223    {
     224        to_start = (char**)malloc((argc-s)*sizeof(char*));
     225        if(!to_start)
     226        {
     227            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
     228            return -1;
     229        }
     230        for(i=0; i<(argc-1) - s; i++)
     231        {
     232            to_start[i] = strdup(argv[i+s+1]);
     233        }
     234        to_start[argc-1-s] = NULL;
     235    }
     236
    219237    /* Read global configuration first */
    220238    read_configuration_file("/etc/neercsrc", screen_list);
     
    235253            return -1;
    236254        }
    237         sockets = list_sockets(screen_list->socket_dir, session_name);
    238         if(!screen_list->session_name)
    239             screen_list->session_name = session_name;
    240         else
    241             free(session_name);
     255        sockets = list_sockets(screen_list->socket_dir, screen_list->session_name);
    242256        if(sockets && sockets[0])
    243257        {
    244             request_attach(sockets[0]);
    245             fprintf(stderr, "Failed to attach!\n");
     258            char *session;
     259            for(i=0; sockets[i]; i++);
     260            i--;
     261            session = connect_server(sockets[i], screen_list);
     262            if(session)
     263            {
     264                request_attach(screen_list);
     265                if(screen_list->session_name)
     266                    free(screen_list->session_name);
     267                screen_list->session_name = session;
     268            }
     269            else
     270            {
     271                fprintf(stderr, "Failed to attach!\n");
     272                attach = 0;
     273            }
    246274            for(i=0; sockets[i]; i++)
    247275                free(sockets[i]);
     
    251279        {
    252280            fprintf(stderr, "No socket found!\n");
    253         }
    254         if(forceattach)
     281            attach = 0;
     282        }
     283        if(forceattach && !attach)
    255284            return -1;
    256285    }
     
    268297            return -1;
    269298        }
     299    }
     300
     301    /* Fork the server if needed */
     302    if(!attach)
     303    {
     304        pid_t pid;
     305
     306        screen_list->socket_path = build_socket_path(screen_list->socket_path, screen_list->session_name);
     307
     308        pid = fork();
     309        if(pid < 0)
     310        {
     311            fprintf(stderr, "Failed to create child process\n");
     312            return -1;
     313        }
     314        if(pid == 0)
     315        {
     316            int fd;
     317            close(0);
     318            close(1);
     319            close(2);
     320            fd = open("/dev/null", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
     321            dup2(fd, 0);
     322#ifndef DEBUG
     323            dup2(fd, 1);
     324            dup2(fd, 2);
     325            if (fd > 2)
     326                close(fd);
     327#else
     328            if(fd != 0)
     329                close(fd);
     330            fd = open("/tmp/log.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
     331            dup2(fd, 1);
     332            dup2(fd, 2);
     333            if (fd > 2)
     334                close(fd);
     335#endif
     336            setsid();
     337            return server_main(to_grab, to_start, screen_list);
     338        }
     339
     340        free(connect_server(screen_list->socket_path, screen_list));
    270341    }
    271342
     
    276347        return 1;
    277348    caca_set_cursor(screen_list->dp, 1);
    278 
    279349    screen_list->width  = cucul_get_canvas_width(screen_list->cv);
    280350    screen_list->height = cucul_get_canvas_height(screen_list->cv) - ((screen_list->mini*6) + (screen_list->status));
    281351
    282     if(nb_to_grab == 0 && s == argc -1)
    283     {
    284         add_screen(screen_list,
    285                    create_screen(screen_list->width,
    286                                  screen_list->height,
    287                                  screen_list->default_shell));
    288     }
    289 
    290     /* Attach processes */
    291     for(i=0; i<nb_to_grab; i++)
    292     {
    293         add_screen(screen_list,create_screen_grab(screen_list->width, screen_list->height, to_grab[i]));
    294     }
    295     free(to_grab);
    296 
    297     /* Launch command line processes */
    298     for(i=0; i<(argc-1) - s; i++)
    299     {
    300         add_screen(screen_list, create_screen(screen_list->width, screen_list->height, argv[i+s+1]));
    301     }
    302 
    303     /* Windows are in a temporary state, resize them to the right dimensions */
    304     update_windows_props(screen_list);
    305 
    306352    last_key_time = get_us();
    307353
     
    310356        caca_event_t ev;
    311357        int ret = 0;
    312 
    313         /* Read program output */
    314         refresh |= update_screens_contents(screen_list);
    315 
    316         /* If screen was attached, read its output */
    317         refresh |= read_socket(screen_list, screen_list->cv, &screen_list->dp);
    318 
    319         /* No more screens, exit */
    320         if(!screen_list->count) break;
    321 
    322         /* Update each screen canvas  */
    323         refresh |= update_terms(screen_list);
    324 
    325         /* Get events, if any */
    326         if(screen_list->attached)
    327             ret = caca_get_event(screen_list->dp, CACA_EVENT_ANY, &ev, 0);
    328         else
    329             sleep(1);
    330 
    331         if(ret && (caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS))
    332         {
    333             unsigned int c = caca_get_event_key_ch(&ev);
    334             char *str = NULL;
    335             int size = 0;
    336             /* CTRL-A has been pressed before, handle this as a
    337              * command, except that CTRL-A a sends literal CTRL-A */
    338             if(command && (c != 'a'))
    339             {
    340                 command = 0;
    341                 refresh |= handle_command_input(screen_list, c);
    342             }
    343             else
    344             {
    345                 /* Not in command mode */
    346                 last_key_time = get_us();
    347                 caca_set_cursor(screen_list->dp, 1);
    348 
    349                 /* Kill screensaver */
    350                 if(screen_list->in_screensaver)
    351                 {
    352                     screensaver_kill(screen_list);
    353                     screen_list->in_screensaver = 0;
    354                     refresh = 1;
    355                     continue;
    356                 }
    357                 /* Handle lock window */
    358                 if(screen_list->locked)
    359                     refresh |= update_lock(c, screen_list);
    360                 else
    361                 {
    362                     switch(c)
    363                     {
    364                     case 0x01: //CACA_KEY_CTRL_A:
    365                         command = 1; break;
    366                     case CACA_KEY_ESCAPE:
    367                         if(screen_list->help)
    368                         {
    369                             screen_list->help = 0;
    370                             refresh = 1;
    371                             break;
    372                         }
    373                     default:
    374                         /* CTRL-A a sends literal CTRL-A */
    375                         if (command && (c == 'a'))
    376                         {
    377                             c = 0x01;
    378                         }
    379                         /* Normal key, convert it if needed */
    380                         str = convert_input_ansi(&c, &size);
    381                         write(screen_list->screen[screen_list->pty]->fd, str, size);
    382                         break;
    383                     }
    384                 }
    385             }
    386         }
    387         /* Window resized */
    388         else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_RESIZE))
    389         {
    390             update_windows_props(screen_list);
    391             cucul_clear_canvas(screen_list->cv);
    392             refresh = 1;
    393         }
    394         /* Window closed */
    395         else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_QUIT))
    396         {
    397             refresh = 1;
    398             break;
    399         }
    400 
    401         /* Launch reccurents if any */
    402         refresh |= handle_recurrents(screen_list);
    403 
    404         /* Resfresh screen */
    405         if(!screen_list->attached)
    406         {
    407             /* No need to refresh */
    408         }
    409         /* Draw lock window */
    410         else if(screen_list->locked)
    411         {
    412             draw_lock(screen_list);
    413             refresh = 1;
    414         }
    415         else
    416         {
    417             if((refresh || screen_list->in_bell) &&
    418                (get_us() - last_key_time < screen_list->screensaver_timeout))
    419             {
    420                 refresh_screens(screen_list);
    421                 if(screen_list->screen[screen_list->pty]->title)
    422                     caca_set_display_title(screen_list->dp, screen_list->screen[screen_list->pty]->title);
    423                 else
    424                     caca_set_display_title(screen_list->dp, PACKAGE_STRING);
    425                 refresh = 1;
    426 
    427             }
    428             if((get_us() - last_key_time > screen_list->screensaver_timeout))
    429             {
    430                 if(!screen_list->in_screensaver)
    431                     screensaver_init(screen_list);
    432                 screen_list->in_screensaver = 1;
    433 
    434                 caca_set_cursor(screen_list->dp, 0);
    435                 draw_screensaver(screen_list);
    436                 refresh = 1;
    437             }
    438 
    439             if((get_us() - last_key_time > screen_list->autolock_timeout))
    440             {
    441                 screen_list->locked = 1;
    442                 refresh = 1;
    443             }
    444 
    445         }
    446 
    447         /* Refresh screen if needed */
    448         if(refresh)
    449         {
    450             caca_refresh_display(screen_list->dp);
    451             refresh = 0;
    452         }
    453 
    454         eof = 1;
    455         for(i=0; i < screen_list->count; i++)
    456             if(screen_list->screen[i]->fd >= 0)
    457                 eof = 0;
    458         if(eof)
     358        ssize_t n;
     359        char buf[4097];
     360
     361        while (screen_list->socket && (n = read(screen_list->socket, buf, sizeof(buf)-1)) > 0)
     362        {
     363            buf[n] = 0;
     364            debug("Received from server: %s", buf);
     365            if(!strncmp("DETACH", buf, 6))
     366            {
     367                ret = 1;
     368                break;
     369            }
     370            else if(!strncmp("REFRESH", buf, 7))
     371            {
     372                /* FIXME update the canvas first */
     373                caca_refresh_display(screen_list->dp);
     374            }
     375            else if(!strncmp("CURSOR ", buf, 7))
     376            {
     377                caca_set_cursor(screen_list->dp, atoi(buf+7));
     378            }
     379            else if(!strncmp("TITLE ", buf, 6))
     380            {
     381                caca_set_display_title(screen_list->dp, buf+6);
     382                caca_refresh_display(screen_list->dp);
     383            }
     384        }
     385        if(ret)
     386            break;
     387
     388        ret = caca_get_event(screen_list->dp, CACA_EVENT_ANY, &ev, 100000);
     389        if(ret)
     390            ret = send_event(ev, screen_list->socket);
     391
     392        if(ret)
    459393            break;
    460394    }
     
    472406
    473407    if(screen_list->socket_path) {
    474         unlink(screen_list->socket_path);
    475408        free(screen_list->socket_path);
    476409    }
     
    510443    return mainret;
    511444}
    512 
    513 
    514445
    515446
     
    566497    return screen_list;
    567498}
    568 
    569 
    570 
    571 long long get_us(void)
    572 {
    573     struct timeval tv;
    574     gettimeofday(&tv, NULL);
    575     return (tv.tv_sec*(1000000) + tv.tv_usec);
    576 }
  • neercs/trunk/src/neercs.h

    r2582 r2588  
    216216long long get_us(void);
    217217
    218 int detach(struct screen_list* screen_list, caca_display_t * dp);
    219 int request_attach(char *socket_path);
     218int detach(struct screen_list* screen_list);
     219int request_attach(struct screen_list* screen_list);
     220char * build_socket_path(char *socket_dir, char *session_name);
    220221int create_socket(struct screen_list* screen_list);
    221 int read_socket(struct screen_list* screen_list, cucul_canvas_t * cv, caca_display_t ** dp);
     222char * connect_server(char *socket_path, struct screen_list* screen_list);
    222223char ** list_sockets(char *socket_dir, char *session_name);
     224int server_main(int *to_grab, char **to_start, struct screen_list *screen_list);
     225int send_event(caca_event_t ev, int sock);
    223226
    224227/* Screens management */
Note: See TracChangeset for help on using the changeset viewer.