ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtd.C
Revision: 1.12
Committed: Sun Apr 4 23:52:37 2004 UTC (20 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_7
Changes since 1.10: +7 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.9 #include "../config.h"
2     #include "rxvt.h"
3 pcg 1.1 #include "rxvtdaemon.h"
4     #include "iom.h"
5    
6     #include <cstdio>
7     #include <cstdlib>
8 pcg 1.3 #include <cstdarg>
9     #include <cstring>
10 pcg 1.1
11     #include <unistd.h>
12 pcg 1.12 #include <fcntl.h>
13 pcg 1.5 #include <sys/types.h>
14     #include <sys/stat.h>
15 pcg 1.1 #include <sys/socket.h>
16     #include <sys/un.h>
17    
18 pcg 1.3 #include <cerrno>
19    
20     extern char **environ;
21    
22 pcg 1.1 struct server : rxvt_connection {
23 pcg 1.10 log_callback log_cb;
24    
25 pcg 1.1 void read_cb (io_watcher &w, short revents); io_watcher read_ev;
26 pcg 1.10 void log_msg (const char *msg);
27 pcg 1.1
28     server (int fd)
29 pcg 1.10 : read_ev (this, &server::read_cb),
30     log_cb (this, &server::log_msg)
31 pcg 1.1 {
32     this->fd = fd;
33     read_ev.start (fd, EVENT_READ);
34     }
35    
36 pcg 1.3 void err (const char *format = 0, ...);
37 pcg 1.1 };
38    
39 pcg 1.5 struct unix_listener {
40 pcg 1.1 int fd;
41    
42     void accept_cb (io_watcher &w, short revents); io_watcher accept_ev;
43    
44 pcg 1.5 unix_listener (const char *sockname);
45 pcg 1.1 };
46    
47 pcg 1.5 unix_listener::unix_listener (const char *sockname)
48     : accept_ev (this, &unix_listener::accept_cb)
49 pcg 1.1 {
50     if ((fd = socket (PF_LOCAL, SOCK_STREAM, 0)) < 0)
51     {
52     perror ("unable to create listening socket");
53     exit (EXIT_FAILURE);
54     }
55    
56 pcg 1.12 fcntl (fd, F_SETFD, FD_CLOEXEC);
57    
58 pcg 1.1 sockaddr_un sa;
59    
60     sa.sun_family = AF_UNIX;
61 pcg 1.5 strcpy (sa.sun_path, sockname);
62 pcg 1.1
63     unlink (rxvt_connection::unix_sockname ());
64    
65 pcg 1.5 mode_t omask = umask (0077);
66    
67 pcg 1.1 if (bind (fd, (sockaddr *)&sa, sizeof (sa)))
68     {
69     perror ("unable to bind listening socket");
70     exit (EXIT_FAILURE);
71     }
72    
73 pcg 1.5 umask (omask);
74    
75 pcg 1.1 if (listen (fd, 5))
76     {
77     perror ("unable to listen on socket");
78     exit (EXIT_FAILURE);
79     }
80    
81     accept_ev.start (fd, EVENT_READ);
82     }
83    
84 pcg 1.5 void unix_listener::accept_cb (io_watcher &w, short revents)
85 pcg 1.1 {
86     int fd2 = accept (fd, 0, 0);
87    
88     if (fd2 >= 0)
89 pcg 1.12 {
90     fcntl (fd2, F_SETFD, FD_CLOEXEC);
91     new server (fd2);
92     }
93 pcg 1.1 }
94    
95 pcg 1.10 void server::log_msg (const char *msg)
96     {
97     send ("MSG"), send (msg);
98     }
99    
100 pcg 1.3 void server::err (const char *format, ...)
101 pcg 1.1 {
102 pcg 1.3 if (format)
103     {
104     char err[1024];
105    
106     va_list ap;
107     va_start (ap, format);
108     vsnprintf (err, 1024, format, ap);
109     va_end (ap);
110    
111 pcg 1.10 send ("MSG"), send (err);
112 pcg 1.3 }
113    
114 pcg 1.10 send ("END", 0);
115 pcg 1.1 close (fd);
116     delete this;
117     }
118    
119     void server::read_cb (io_watcher &w, short revents)
120     {
121 pcg 1.2 auto_str tok;
122 pcg 1.1
123 pcg 1.2 if (recv (tok))
124 pcg 1.1 {
125 pcg 1.2 if (!strcmp (tok, "NEW"))
126 pcg 1.1 {
127 pcg 1.9 stringvec *argv = new stringvec;
128     stringvec *envv = new stringvec;
129 pcg 1.2
130     for (;;)
131     {
132     if (!recv (tok))
133     return err ();
134    
135     if (!strcmp (tok, "END"))
136     break;
137 pcg 1.3 else if (!strcmp (tok, "ENV") && recv (tok))
138 pcg 1.9 envv->push_back (tok.get ());
139 pcg 1.3 else if (!strcmp (tok, "CWD") && recv (tok))
140     {
141     if (chdir (tok))
142     err ("unable to change to working directory to '%s': %s",
143     (char *)tok, strerror (errno));
144     }
145 pcg 1.2 else if (!strcmp (tok, "ARG") && recv (tok))
146 pcg 1.9 argv->push_back (tok.get ());
147 pcg 1.2 else
148 pcg 1.3 return err ("protocol error: unexpected NEW token");
149 pcg 1.2 }
150    
151 pcg 1.9 envv->push_back (0);
152 pcg 1.3
153     {
154     char **old_environ = environ;
155 pcg 1.9 environ = envv->begin ();
156 pcg 1.3
157 pcg 1.10 rxvt_term *term = new rxvt_term;
158    
159     term->log_hook = &log_cb;
160 pcg 1.9 term->argv = argv;
161     term->envv = envv;
162 pcg 1.2
163 pcg 1.10 bool success;
164    
165     try
166     {
167     success = term->init (argv->size (), argv->begin ());
168     }
169     catch (const class rxvt_failure_exception &e)
170     {
171     success = false;
172     }
173    
174 pcg 1.3 environ = old_environ;
175 pcg 1.10
176     if (!success)
177     term->destroy ();
178    
179     send ("END"); send (success ? 1 : 0);
180 pcg 1.3 }
181 pcg 1.1 }
182     else
183 pcg 1.3 return err ("protocol error: request '%s' unsupported.", (char *)tok);
184 pcg 1.1 }
185     else
186 pcg 1.2 return err ();
187 pcg 1.1 }
188    
189     int
190 pcg 1.8 main (int argc, const char *const *argv)
191 pcg 1.1 {
192 pcg 1.5 rxvt_init_signals ();
193    
194     char *sockname = rxvt_connection::unix_sockname ();
195     unix_listener l (sockname);
196     printf ("rxvtd listening on %s.\n", sockname);
197     free (sockname);
198    
199 pcg 1.1 iom.loop ();
200    
201     #if 0
202 pcg 1.8 if (rxvt_init (argc, argv) == NULL)
203 pcg 1.1 return EXIT_FAILURE;
204    
205     dR;
206 pcg 1.8 rxvt_main_loop (aR); /* main processing loop */
207 pcg 1.1 #endif
208     return EXIT_SUCCESS;
209     }
210 pcg 1.7