source: neercs/trunk/src/attach.c @ 2488

Last change on this file since 2488 was 2488, checked in by pterjan, 6 years ago
  • Have -r/-R/-S like screen
  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
1#include <errno.h>
2#include <fcntl.h>
3#include <glob.h>
4#include <limits.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8
9#include <sys/socket.h>
10#include <sys/un.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13
14#include "neercs.h"
15
16static char * build_socket_path(char *socket_dir, char *session_name)
17{
18    char *path, *dir;
19    path = (char *)malloc(PATH_MAX+1);
20    dir = socket_dir;
21    if(!dir)
22        dir = getenv("NEERCSDIR");
23    if(!dir)
24        dir = getenv("TMPDIR");
25    if(!dir)
26        dir = "/tmp";
27    if(path)
28        snprintf(path, PATH_MAX+1, "%s/neercs.%s.sock", dir, session_name);
29    return path;
30}
31
32int create_socket(struct screen_list* screen_list)
33{
34    int sock;
35    struct sockaddr_un myaddr;
36
37    sock = socket(AF_UNIX, SOCK_DGRAM, 0);
38
39    if(sock < 0)
40    {
41        perror("create_socket:socket");
42        return errno;
43    }
44
45    memset(&myaddr, 0, sizeof(struct sockaddr_un));
46
47    myaddr.sun_family = AF_UNIX;
48    screen_list->socket_path = build_socket_path(screen_list->socket_path, screen_list->session_name);
49    strncpy(myaddr.sun_path, screen_list->socket_path, sizeof(myaddr.sun_path) - 1);
50    unlink(myaddr.sun_path);
51
52    if(bind(sock, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_un)) < 0)
53    {
54        free(screen_list->socket_path);
55        screen_list->socket_path = NULL;
56        close(sock);
57        perror("create_socket:bind");
58        return errno;
59    }
60    fcntl(sock, F_SETFL, O_NONBLOCK);
61
62    debug("Listening on %s (%d)", screen_list->socket_path, sock);
63
64    screen_list->socket = sock;
65
66    return 0;
67}
68
69int 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
106static 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
145int 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;
159}
160
161char ** list_sockets(char *socket_dir, char *session_name)
162{
163    char *pattern, *dir;
164    glob_t globbuf;
165
166    globbuf.gl_pathv = NULL;
167
168    pattern = (char *)malloc(PATH_MAX+1);
169
170    dir = socket_dir;
171    if(!dir)
172        dir = getenv("NEERCSDIR");
173    if(!dir)
174        dir = getenv("TMPDIR");
175    if(!dir)
176        dir = "/tmp";
177
178    if(!pattern)
179        return globbuf.gl_pathv;
180
181    if(session_name && strlen(session_name)+strlen(dir)+13<PATH_MAX)
182        sprintf(pattern, "%s/neercs.%s.sock", dir, session_name);
183    else
184        snprintf(pattern, PATH_MAX, "%s/neercs.*.sock", dir);
185    pattern[PATH_MAX] = '\0';
186
187    debug("Looking for sockets in the form %s", pattern);
188
189    glob(pattern, 0, NULL, &globbuf);
190
191    free(pattern);
192
193    return globbuf.gl_pathv;
194}
195
196
197/* FIXME Is this really not defined anywhere ? */
198extern char **environ;
199
200int request_attach(char *socket_path)
201{
202    int sock;
203    char fdstr[PATH_MAX], lnk[PATH_MAX];
204    char buf[4096];
205    struct sockaddr_un addr;
206
207    debug("Connecting to %s", socket_path);
208
209    /* Open the socket */
210    if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
211        perror("request_attach:socket");
212        return 1;
213    }
214
215    memset(&addr,0,sizeof(addr));
216    addr.sun_family = AF_UNIX;
217    strcpy(addr.sun_path,socket_path);
218    if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
219    {
220        printf("Failed to connect to %s: %s\n", socket_path, strerror(errno));
221        return 1;
222    }
223
224    debug("Sending environment", 0);
225
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")
230
231    snprintf(fdstr, sizeof(fdstr), "/proc/%d/fd/0", getpid());
232    readlink(fdstr, lnk, sizeof(lnk)-1);
233    lnk[PATH_MAX-1] = '\0';
234
235    close(0);
236
237    debug("Requesting attach to %s", lnk);
238
239    /* Request attaching */
240    snprintf(buf, 4096, "ATTACH %s", lnk);
241    write(sock, buf, strlen(buf));
242    close(sock);
243
244    debug("Exiting", 0);
245    exit(0);
246}
Note: See TracBrowser for help on using the repository browser.