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

# Content
1 #include "../config.h"
2 #include "rxvt.h"
3 #include "rxvtdaemon.h"
4 #include "iom.h"
5
6 #include <cstdio>
7 #include <cstdlib>
8 #include <cstdarg>
9 #include <cstring>
10
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17
18 #include <cerrno>
19
20 extern char **environ;
21
22 struct server : rxvt_connection {
23 log_callback log_cb;
24
25 void read_cb (io_watcher &w, short revents); io_watcher read_ev;
26 void log_msg (const char *msg);
27
28 server (int fd)
29 : read_ev (this, &server::read_cb),
30 log_cb (this, &server::log_msg)
31 {
32 this->fd = fd;
33 read_ev.start (fd, EVENT_READ);
34 }
35
36 void err (const char *format = 0, ...);
37 };
38
39 struct unix_listener {
40 int fd;
41
42 void accept_cb (io_watcher &w, short revents); io_watcher accept_ev;
43
44 unix_listener (const char *sockname);
45 };
46
47 unix_listener::unix_listener (const char *sockname)
48 : accept_ev (this, &unix_listener::accept_cb)
49 {
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 fcntl (fd, F_SETFD, FD_CLOEXEC);
57
58 sockaddr_un sa;
59
60 sa.sun_family = AF_UNIX;
61 strcpy (sa.sun_path, sockname);
62
63 unlink (rxvt_connection::unix_sockname ());
64
65 mode_t omask = umask (0077);
66
67 if (bind (fd, (sockaddr *)&sa, sizeof (sa)))
68 {
69 perror ("unable to bind listening socket");
70 exit (EXIT_FAILURE);
71 }
72
73 umask (omask);
74
75 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 void unix_listener::accept_cb (io_watcher &w, short revents)
85 {
86 int fd2 = accept (fd, 0, 0);
87
88 if (fd2 >= 0)
89 {
90 fcntl (fd2, F_SETFD, FD_CLOEXEC);
91 new server (fd2);
92 }
93 }
94
95 void server::log_msg (const char *msg)
96 {
97 send ("MSG"), send (msg);
98 }
99
100 void server::err (const char *format, ...)
101 {
102 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 send ("MSG"), send (err);
112 }
113
114 send ("END", 0);
115 close (fd);
116 delete this;
117 }
118
119 void server::read_cb (io_watcher &w, short revents)
120 {
121 auto_str tok;
122
123 if (recv (tok))
124 {
125 if (!strcmp (tok, "NEW"))
126 {
127 stringvec *argv = new stringvec;
128 stringvec *envv = new stringvec;
129
130 for (;;)
131 {
132 if (!recv (tok))
133 return err ();
134
135 if (!strcmp (tok, "END"))
136 break;
137 else if (!strcmp (tok, "ENV") && recv (tok))
138 envv->push_back (tok.get ());
139 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 else if (!strcmp (tok, "ARG") && recv (tok))
146 argv->push_back (tok.get ());
147 else
148 return err ("protocol error: unexpected NEW token");
149 }
150
151 envv->push_back (0);
152
153 {
154 char **old_environ = environ;
155 environ = envv->begin ();
156
157 rxvt_term *term = new rxvt_term;
158
159 term->log_hook = &log_cb;
160 term->argv = argv;
161 term->envv = envv;
162
163 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 environ = old_environ;
175
176 if (!success)
177 term->destroy ();
178
179 send ("END"); send (success ? 1 : 0);
180 }
181 }
182 else
183 return err ("protocol error: request '%s' unsupported.", (char *)tok);
184 }
185 else
186 return err ();
187 }
188
189 int
190 main (int argc, const char *const *argv)
191 {
192 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 iom.loop ();
200
201 #if 0
202 if (rxvt_init (argc, argv) == NULL)
203 return EXIT_FAILURE;
204
205 dR;
206 rxvt_main_loop (aR); /* main processing loop */
207 #endif
208 return EXIT_SUCCESS;
209 }
210