added Vector_zeroEnd() function
[util-vserver.git] / util-vserver / src / keep-ctx-alive.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "util.h"
24
25 #include <lib/vserver.h>
26 #include <lib/internal.h>
27
28 #include <getopt.h>
29 #include <errno.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32
33 #define ENSC_WRAPPERS_PREFIX    "keep-ctx-alive: "
34 #define ENSC_WRAPPERS_VSERVER   1
35 #define ENSC_WRAPPERS_SOCKET    1
36 #define ENSC_WRAPPERS_UNISTD    1
37 #define ENSC_WRAPPERS_IOSOCK    1
38 #define ENSC_WRAPPERS_IO        1
39 #include <wrappers.h>
40
41
42 #define CMD_HELP                0x1000
43 #define CMD_VERSION             0x1001
44 #define CMD_SOCKET              0x4000
45 #define CMD_TIMEOUT             0x4001
46 #define CMD_QUIT                0x4002
47
48 int     wrapper_exit_code = 1;
49
50 struct option const
51 CMDLINE_OPTIONS[] = {
52   { "help",       no_argument,       0, CMD_HELP },
53   { "version",    no_argument,       0, CMD_VERSION },
54   { "socket",     required_argument, 0, CMD_SOCKET },
55   { "timeout",    required_argument, 0, CMD_TIMEOUT },
56   { "quit",       required_argument, 0, CMD_QUIT },
57   {0,0,0,0},
58 };
59
60 static void
61 showHelp(int fd, char const *cmd, int res)
62 {
63   WRITE_MSG(fd, "Usage:\n    ");
64   WRITE_STR(fd, cmd);
65   WRITE_MSG(fd,
66             " --socket <filename> [--timeout <seconds>]\n"
67             "\n"
68             "Please report bugs to " PACKAGE_BUGREPORT "\n");
69
70   exit(res);
71 }
72
73 static void
74 showVersion()
75 {
76   WRITE_MSG(1,
77             "keep-ctx-alive " VERSION " -- keeps a context alive\n"
78             "This program is part of " PACKAGE_STRING "\n\n"
79             "Copyright (C) 2004 Enrico Scholz\n"
80             VERSION_COPYRIGHT_DISCLAIMER);
81   exit(0);
82 }
83
84 static void
85 printXid(int fd)
86 {
87   xid_t         xid = Evc_get_task_xid(0);
88   char          buf[sizeof(xid)*3 + 2];
89   size_t        l;
90
91   l = utilvserver_fmt_long(buf, xid);
92   EwriteAll(fd, buf, l);
93   Eclose(fd);
94 }
95
96 static void handleMessage(int fd)
97 {
98   char                  buf[128];
99   size_t                len;
100   struct sockaddr_un    addr;
101   socklen_t             addr_len = sizeof(addr);
102   int                   new_fd   = Eaccept(fd, &addr, &addr_len);
103
104   len = Erecv(new_fd, buf, sizeof buf,0);
105   if (len==0) exit(1);
106   
107     // TODO: handle message???
108   exit(0);
109 }
110
111 static int
112 sendQuitSignal(char const *filename, char const *msg)
113 {
114   int                   fd;
115   struct sockaddr_un    addr;
116
117   ENSC_INIT_UNIX_SOCK(addr, filename);
118   fd = Esocket(PF_UNIX, SOCK_STREAM, 0);
119   Econnect(fd, &addr, sizeof(addr));
120
121   if (msg) EsendAll(fd, msg, strlen(msg));
122   Eclose(fd);
123
124   return EXIT_SUCCESS;
125 }
126
127 static int
128 doit(char const *filename, struct timeval *timeout)
129 {
130   int                   fd;
131   struct sockaddr_un    sock;
132   pid_t                 pid;
133   fd_set                fd_set;
134
135   ENSC_INIT_UNIX_SOCK(sock, filename);
136
137   fd = Esocket(PF_UNIX, SOCK_STREAM, 0);
138   Ebind(fd, &sock, sizeof sock);
139   Elisten(fd, 5);
140
141   printXid(1);
142
143   FD_ZERO(&fd_set);
144   FD_SET(fd, &fd_set);
145
146   pid = Efork();
147   if (pid==0) {
148     Eselect(fd+1, &fd_set, 0,0, timeout);
149     if (FD_ISSET(fd, &fd_set)) handleMessage(fd);
150     exit(1);
151   }
152
153   return EXIT_SUCCESS;
154 }
155
156 int main(int argc, char *argv[])
157 {
158   char const *          socket_name = 0;
159   struct timeval        timeout = { 0,0 };
160   struct timeval        *timeout_ptr = 0;
161   char const *          quit_msg = false;
162   
163   while (1) {
164     int         c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
165     if (c==-1) break;
166
167     switch (c) {
168       case CMD_HELP             :  showHelp(1, argv[0], 0);
169       case CMD_VERSION          :  showVersion();
170       case CMD_SOCKET           :  socket_name = optarg; break;
171       case CMD_QUIT             :  quit_msg    = optarg; break;
172       case CMD_TIMEOUT          :
173         timeout.tv_sec = atoi(optarg);
174         timeout_ptr    = &timeout;
175         break;
176       default           :
177         WRITE_MSG(2, "Try '");
178         WRITE_STR(2, argv[0]);
179         WRITE_MSG(2, " --help\" for more information.\n");
180         return 255;
181         break;
182     }
183   }
184
185   if (socket_name==0)
186     WRITE_MSG(2, "reserve-context: No socketname specified\n");
187   if (quit_msg)
188     return sendQuitSignal(socket_name, quit_msg);
189   else
190     return doit(socket_name, timeout_ptr);
191
192   return EXIT_FAILURE;
193 }