… | |
… | |
2 | #include "rxvtdaemon.h" |
2 | #include "rxvtdaemon.h" |
3 | #include "iom.h" |
3 | #include "iom.h" |
4 | |
4 | |
5 | #include <cstdio> |
5 | #include <cstdio> |
6 | #include <cstdlib> |
6 | #include <cstdlib> |
|
|
7 | #include <cstdarg> |
|
|
8 | #include <cstring> |
7 | |
9 | |
8 | #include <unistd.h> |
10 | #include <unistd.h> |
|
|
11 | #include <sys/types.h> |
|
|
12 | #include <sys/stat.h> |
9 | #include <sys/socket.h> |
13 | #include <sys/socket.h> |
10 | #include <sys/un.h> |
14 | #include <sys/un.h> |
|
|
15 | |
|
|
16 | #include <cerrno> |
|
|
17 | |
|
|
18 | extern char **environ; |
11 | |
19 | |
12 | struct server : rxvt_connection { |
20 | struct server : rxvt_connection { |
13 | void read_cb (io_watcher &w, short revents); io_watcher read_ev; |
21 | void read_cb (io_watcher &w, short revents); io_watcher read_ev; |
14 | |
22 | |
15 | server (int fd) |
23 | server (int fd) |
… | |
… | |
17 | { |
25 | { |
18 | this->fd = fd; |
26 | this->fd = fd; |
19 | read_ev.start (fd, EVENT_READ); |
27 | read_ev.start (fd, EVENT_READ); |
20 | } |
28 | } |
21 | |
29 | |
22 | void err (); |
30 | void err (const char *format = 0, ...); |
23 | }; |
31 | }; |
24 | |
32 | |
25 | struct listener { |
33 | struct unix_listener { |
26 | int fd; |
34 | int fd; |
27 | |
35 | |
28 | void accept_cb (io_watcher &w, short revents); io_watcher accept_ev; |
36 | void accept_cb (io_watcher &w, short revents); io_watcher accept_ev; |
29 | |
37 | |
30 | listener (); |
38 | unix_listener (const char *sockname); |
31 | }; |
39 | }; |
32 | |
40 | |
33 | listener::listener () |
41 | unix_listener::unix_listener (const char *sockname) |
34 | : accept_ev (this, &listener::accept_cb) |
42 | : accept_ev (this, &unix_listener::accept_cb) |
35 | { |
43 | { |
36 | if ((fd = socket (PF_LOCAL, SOCK_STREAM, 0)) < 0) |
44 | if ((fd = socket (PF_LOCAL, SOCK_STREAM, 0)) < 0) |
37 | { |
45 | { |
38 | perror ("unable to create listening socket"); |
46 | perror ("unable to create listening socket"); |
39 | exit (EXIT_FAILURE); |
47 | exit (EXIT_FAILURE); |
40 | } |
48 | } |
41 | |
49 | |
42 | sockaddr_un sa; |
50 | sockaddr_un sa; |
43 | |
51 | |
44 | sa.sun_family = AF_UNIX; |
52 | sa.sun_family = AF_UNIX; |
45 | strcpy (sa.sun_path, rxvt_connection::unix_sockname ()); |
53 | strcpy (sa.sun_path, sockname); |
46 | |
54 | |
47 | unlink (rxvt_connection::unix_sockname ()); |
55 | unlink (rxvt_connection::unix_sockname ()); |
|
|
56 | |
|
|
57 | mode_t omask = umask (0077); |
48 | |
58 | |
49 | if (bind (fd, (sockaddr *)&sa, sizeof (sa))) |
59 | if (bind (fd, (sockaddr *)&sa, sizeof (sa))) |
50 | { |
60 | { |
51 | perror ("unable to bind listening socket"); |
61 | perror ("unable to bind listening socket"); |
52 | exit (EXIT_FAILURE); |
62 | exit (EXIT_FAILURE); |
53 | } |
63 | } |
|
|
64 | |
|
|
65 | umask (omask); |
54 | |
66 | |
55 | if (listen (fd, 5)) |
67 | if (listen (fd, 5)) |
56 | { |
68 | { |
57 | perror ("unable to listen on socket"); |
69 | perror ("unable to listen on socket"); |
58 | exit (EXIT_FAILURE); |
70 | exit (EXIT_FAILURE); |
59 | } |
71 | } |
60 | |
72 | |
61 | accept_ev.start (fd, EVENT_READ); |
73 | accept_ev.start (fd, EVENT_READ); |
62 | } |
74 | } |
63 | |
75 | |
64 | void listener::accept_cb (io_watcher &w, short revents) |
76 | void unix_listener::accept_cb (io_watcher &w, short revents) |
65 | { |
77 | { |
66 | int fd2 = accept (fd, 0, 0); |
78 | int fd2 = accept (fd, 0, 0); |
67 | |
79 | |
68 | if (fd2 >= 0) |
80 | if (fd2 >= 0) |
69 | new server (fd2); |
81 | new server (fd2); |
70 | } |
82 | } |
71 | |
83 | |
72 | void server::err () |
84 | void server::err (const char *format, ...) |
73 | { |
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 | |
74 | close (fd); |
98 | close (fd); |
75 | delete this; |
99 | delete this; |
76 | } |
100 | } |
77 | |
101 | |
78 | void server::read_cb (io_watcher &w, short revents) |
102 | void server::read_cb (io_watcher &w, short revents) |
79 | { |
103 | { |
80 | token cmd; |
104 | auto_str tok; |
81 | |
105 | |
82 | if (recv (cmd)) |
106 | if (recv (tok)) |
83 | { |
107 | { |
84 | if (!strcmp (cmd, "NEW")) |
108 | if (!strcmp (tok, "NEW")) |
85 | { |
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 | } |
86 | } |
145 | } |
87 | else |
146 | else |
88 | err (); |
147 | return err ("protocol error: request '%s' unsupported.", (char *)tok); |
89 | } |
148 | } |
90 | else |
149 | else |
91 | err (); |
150 | return err (); |
92 | } |
151 | } |
93 | |
152 | |
94 | int |
153 | int |
95 | main(int argc, const char *const *argv) |
154 | main(int argc, const char *const *argv) |
96 | { |
155 | { |
97 | listener l; |
156 | rxvt_init_signals (); |
|
|
157 | |
|
|
158 | char *sockname = rxvt_connection::unix_sockname (); |
|
|
159 | unix_listener l (sockname); |
|
|
160 | printf ("rxvtd listening on %s.\n", sockname); |
|
|
161 | free (sockname); |
|
|
162 | |
98 | iom.loop (); |
163 | iom.loop (); |
99 | |
164 | |
100 | #if 0 |
165 | #if 0 |
101 | if (rxvt_init(argc, argv) == NULL) |
166 | if (rxvt_init(argc, argv) == NULL) |
102 | return EXIT_FAILURE; |
167 | return EXIT_FAILURE; |