ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtd.C
Revision: 1.5
Committed: Thu Nov 27 10:12:10 2003 UTC (20 years, 6 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +20 -9 lines
Log Message:
*** empty log message ***

File Contents

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