Changeset 3327 for neercs/trunk


Ignore:
Timestamp:
Nov 16, 2008, 10:55:46 PM (12 years ago)
Author:
Pascal Terjan
Message:
  • Have an interactive menu to select the session to attach
File:
1 edited

Legend:

Unmodified
Added
Removed
  • neercs/trunk/src/attach.c

    r3324 r3327  
    3333}
    3434
     35static char * socket_to_session(char const * sockpath)
     36{
     37    char *p, *s;
     38    p = strrchr(sockpath, '/');
     39    if(!p)
     40    {
     41        debug("Invalid socket path %s", sockpath);
     42        return NULL;
     43    }
     44    p+=8; /* skip neercs. */
     45    s = strdup(p);
     46    p = strrchr(s, '.');
     47    *p = '\0'; /* drop .sock */
     48    p = strrchr(s, '.');
     49    *p = '\0'; /* drop .srv */
     50    p = strdup(s);
     51    free(s);
     52    return p;
     53}
     54
    3555int create_socket(struct screen_list* screen_list, enum socket_type socktype)
    3656{
     
    109129    int sock;
    110130    struct sockaddr_un addr;
    111     char *p, *s;
    112131
    113132    debug("Connecting to %s", screen_list->socket_path[socktype]);
     
    134153    if(socktype == SOCK_SERVER)
    135154    {
    136         p = strrchr(screen_list->socket_path[socktype], '/');
    137         p+=8; /* skip neercs. */
    138         s = strdup(p);
    139         p = strrchr(s, '.');
    140         *p = '\0'; /* drop .sock */
    141         p = strrchr(s, '.');
    142         *p = '\0'; /* drop .srv */
    143         p = strdup(s);
    144         free(s);
    145         return p;
     155        return socket_to_session(screen_list->socket_path[socktype]);
    146156    }
    147157    else
     
    163173}
    164174
     175static char * select_socket(struct screen_list* screen_list)
     176{
     177    char **sockets = NULL, **usable_sockets = NULL;
     178    int i, sock, nb_usable_sockets = 0;
     179    char *ret = NULL;
     180
     181    sockets = list_sockets(screen_list->socket_dir, screen_list->session_name);
     182    if(sockets)
     183    {
     184        for(i=0; sockets[i]; i++);
     185
     186        /* Return the socket or NULL if there is not more than one match */
     187        if(i<=1)
     188        {
     189            if(sockets[0])
     190                ret = strdup(sockets[0]);
     191            goto end;
     192        }
     193
     194        /* Else ask the user to chose one */
     195        usable_sockets = malloc(i*sizeof(char*));
     196        for(i=0; sockets[i]; i++)
     197        {
     198            struct sockaddr_un addr;
     199            if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
     200                perror("select_socket:socket");
     201                goto end;
     202            }
     203            memset(&addr,0,sizeof(addr));
     204            addr.sun_family = AF_UNIX;
     205            strcpy(addr.sun_path, sockets[i]);
     206            if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
     207            {
     208                switch(errno)
     209                {
     210                case EACCES:
     211                    debug("Connection refused on %s", sockets[i]);
     212                    break;
     213                case ECONNREFUSED:
     214                    fprintf(stderr, "%s is dead\n", sockets[i]);
     215                    break;
     216                default:
     217                    fprintf(stderr, "Unknown error on %s:%s\n", sockets[i], strerror(errno));
     218                }
     219            }
     220            else
     221            {
     222                usable_sockets[nb_usable_sockets] = strdup(sockets[i]);
     223                nb_usable_sockets++;
     224                close(sock);
     225            }
     226        }
     227        if(!nb_usable_sockets)
     228            goto end;
     229        if(nb_usable_sockets == 1)
     230        {
     231            ret = usable_sockets[0];
     232            goto end;
     233        }
     234        else
     235        {
     236            caca_event_t ev;
     237            enum caca_event_type t;
     238            int current_line = 1;
     239            int refresh = 1;
     240            screen_list->cv = caca_create_canvas(0, 0);
     241            screen_list->dp = caca_create_display(screen_list->cv);
     242            if(!screen_list->dp)
     243                goto end;
     244            caca_set_cursor(screen_list->dp, 0);
     245            caca_printf(screen_list->cv, 1, 0, "Please select a session to reconnect:");
     246            while(1)
     247            {
     248                if(refresh)
     249                {
     250                    for(i=0; i<nb_usable_sockets; i++)
     251                    {
     252                        if(i == current_line-1)
     253                        {
     254                            caca_set_attr(screen_list->cv, CACA_BOLD);
     255                            caca_set_color_ansi(screen_list->cv, CACA_GREEN, CACA_BLACK);
     256                            caca_put_char(screen_list->cv, 0, i+1, '>');
     257                        }
     258                        else
     259                        {
     260                            caca_set_attr(screen_list->cv, 0);
     261                            caca_set_color_ansi(screen_list->cv, CACA_LIGHTGRAY, CACA_BLACK);
     262                            caca_put_char(screen_list->cv, 0, i+1, ' ');
     263                        }
     264                        caca_printf(screen_list->cv,
     265                                    1, i+1,
     266                                    "%s",
     267                                    socket_to_session(usable_sockets[i]));
     268                    }
     269                    caca_refresh_display(screen_list->dp);
     270                    refresh = 0;
     271                }
     272
     273                if(!caca_get_event(screen_list->dp,
     274                                  CACA_EVENT_KEY_PRESS
     275                                  |CACA_EVENT_RESIZE
     276                                  |CACA_EVENT_QUIT,
     277                                  &ev, 10000))
     278                    continue;
     279
     280                t = caca_get_event_type(&ev);
     281
     282                if(t & CACA_EVENT_KEY_PRESS)
     283                {
     284                    unsigned int c = caca_get_event_key_ch(&ev);
     285                    switch(c)
     286                    {
     287                    case CACA_KEY_UP:
     288                        if(current_line>1)
     289                            current_line--;
     290                        break;
     291                    case CACA_KEY_DOWN:
     292                        if(current_line<nb_usable_sockets)
     293                            current_line++;
     294                        break;
     295                    case CACA_KEY_RETURN:
     296                        ret = strdup(usable_sockets[current_line-1]);
     297                        goto end;
     298                        break;
     299                    default:
     300                        break;
     301                    }
     302                    refresh = 1;
     303                }
     304                else if(t & CACA_EVENT_RESIZE)
     305                {
     306                    refresh = 1;
     307                }
     308                else if(t & CACA_EVENT_QUIT)
     309                    goto end;
     310            }
     311        }
     312    }
     313
     314end:
     315    if(sockets)
     316    {
     317        for(i=0; sockets[i]; i++)
     318            free(sockets[i]);
     319        free(sockets);
     320    }
     321    if(usable_sockets)
     322    {
     323        for(i=0; i<nb_usable_sockets; i++)
     324            free(usable_sockets[i]);
     325        free(usable_sockets);
     326    }
     327    if(screen_list->dp)
     328    {
     329        caca_free_display(screen_list->dp);
     330        screen_list->dp = NULL;
     331    }
     332    if(screen_list->cv)
     333    {
     334        caca_free_canvas(screen_list->cv);
     335        screen_list->cv = NULL;
     336    }
     337    return ret;
     338}
     339
    165340void attach(struct screen_list* screen_list)
    166341{
    167     char **sockets;
    168     int i;
    169 
    170     sockets = list_sockets(screen_list->socket_dir, screen_list->session_name);
    171     if(sockets && sockets[0])
     342    screen_list->socket_path[SOCK_SERVER] = select_socket(screen_list);
     343
     344    if(screen_list->socket_path[SOCK_SERVER])
    172345    {
    173346        char *session;
    174         for(i=0; sockets[i]; i++);
    175         i--;
    176         screen_list->socket_path[SOCK_SERVER] = strdup(sockets[i]);
    177347        session = connect_socket(screen_list, SOCK_SERVER);
    178         while(!session && i > 0)
    179         {
    180             free(screen_list->socket_path[SOCK_SERVER]);
    181             i--;
    182             screen_list->socket_path[SOCK_SERVER] = strdup(sockets[i]);
    183             session = connect_socket(screen_list, SOCK_SERVER);
    184         }
    185         debug("Connected to session %s", session);
    186348        if(session)
    187349        {
     350            debug("Connected to session %s", session);
    188351            /* Create main canvas and associated caca window */
    189352            screen_list->cv = caca_create_canvas(0, 0);
     
    208371            screen_list->attach = 0;
    209372        }
    210         for(i=0; sockets[i]; i++)
    211             free(sockets[i]);
    212         free(sockets);
    213373    }
    214374    else
Note: See TracChangeset for help on using the changeset viewer.