03148811a9556d30903ede671024a826b886cdb6
[util-vserver.git] / src / keep-ctx-alive.c
1 // $Id: keep-ctx-alive.c,v 1.3 2004/12/16 00:11:01 ensc Exp $    --*- 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 #include <sys/select.h>
33
34 #define ENSC_WRAPPERS_PREFIX    "keep-ctx-alive: "
35 #define ENSC_WRAPPERS_VSERVER   1
36 #define ENSC_WRAPPERS_SOCKET    1
37 #define ENSC_WRAPPERS_UNISTD    1
38 #define ENSC_WRAPPERS_IOSOCK    1
39 #define ENSC_WRAPPERS_IO        1
40 #include <wrappers.h>
41
42
43 #define CMD_HELP                0x1000
44 #define CMD_VERSION             0x1001
45 #define CMD_SOCKET              0x4000
46 #define CMD_TIMEOUT             0x4001
47 #define CMD_QUIT                0x4002
48
49 int     wrapper_exit_code = 1;
50
51 struct option const
52 CMDLINE_OPTIONS[] = {
53   { "help",       no_argument,       0, CMD_HELP },
54   { "version",    no_argument,       0, CMD_VERSION },
55   { "socket",     required_argument, 0, CMD_SOCKET },
56   { "timeout",    required_argument, 0, CMD_TIMEOUT },
57   { "quit",       required_argument, 0, CMD_QUIT },
58   {0,0,0,0},
59 };
60
61 static void
62 showHelp(int fd, char const *cmd, int res)
63 {
64   WRITE_MSG(fd, "Usage:\n    ");
65   WRITE_STR(fd, cmd);
66   WRITE_MSG(fd,
67             " --socket <filename> [--timeout <seconds>]\n"
68             "\n"
69             "Please report bugs to " PACKAGE_BUGREPORT "\n");
70
71   exit(res);
72 }
73
74 static void
75 showVersion()
76 {
77   WRITE_MSG(1,
78             "keep-ctx-alive " VERSION " -- keeps a context alive\n"
79             "This program is part of " PACKAGE_STRING "\n\n"
80             "Copyright (C) 2004 Enrico Scholz\n"
81             VERSION_COPYRIGHT_DISCLAIMER);
82   exit(0);
83 }
84
85 static void
86 printXid(int fd)
87 {
88   xid_t         xid = Evc_get_task_xid(0);
89   char          buf[sizeof(xid)*3 + 2];
90   size_t        l;
91
92   l = utilvserver_fmt_long(buf, xid);
93   EwriteAll(fd, buf, l);
94   Eclose(fd);
95 }
96
97 static void handleMessage(int fd)
98 {
99   char                  buf[128];
100   size_t                len;
101   struct sockaddr_un    addr;
102   socklen_t             addr_len = sizeof(addr);
103   int                   new_fd   = Eaccept(fd, &addr, &addr_len);
104
105   len = Erecv(new_fd, buf, sizeof buf,0);
106   if (len==0) exit(1);
107   
108     // TODO: handle message???
109   exit(0);
110 }
111
112 static int
113 sendQuitSignal(char const *filename, char const *msg)
114 {
115   int                   fd;
116   struct sockaddr_un    addr;
117
118   ENSC_INIT_UNIX_SOCK(addr, filename);
119   fd = Esocket(PF_UNIX, SOCK_STREAM, 0);
120   Econnect(fd, &addr, sizeof(addr));
121
122   if (msg) EsendAll(fd, msg, strlen(msg));
123   Eclose(fd);
124
125   return EXIT_SUCCESS;
126 }
127
128 static int
129 doit(char const *filename, struct timeval *timeout)
130 {
131   int                   fd;
132   struct sockaddr_un    sock;
133   pid_t                 pid;
134   fd_set                fdset;
135
136   ENSC_INIT_UNIX_SOCK(sock, filename);
137
138   fd = Esocket(PF_UNIX, SOCK_STREAM, 0);
139   Ebind(fd, &sock, sizeof sock);
140   Elisten(fd, 5);
141
142   printXid(1);
143
144   FD_ZERO(&fdset);
145   FD_SET(fd, &fdset);
146
147   pid = Efork();
148   if (pid==0) {
149     Eselect(fd+1, &fdset, 0,0, timeout);
150     if (FD_ISSET(fd, &fdset)) handleMessage(fd);
151     exit(1);
152   }
153
154   return EXIT_SUCCESS;
155 }
156
157 int main(int argc, char *argv[])
158 {
159   char const *          socket_name = 0;
160   struct timeval        timeout = { 0,0 };
161   struct timeval        *timeout_ptr = 0;
162   char const *          quit_msg = false;
163   
164   while (1) {
165     int         c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
166     if (c==-1) break;
167
168     switch (c) {
169       case CMD_HELP             :  showHelp(1, argv[0], 0);
170       case CMD_VERSION          :  showVersion();
171       case CMD_SOCKET           :  socket_name = optarg; break;
172       case CMD_QUIT             :  quit_msg    = optarg; break;
173       case CMD_TIMEOUT          :
174         timeout.tv_sec = atoi(optarg);
175         timeout_ptr    = &timeout;
176         break;
177       default           :
178         WRITE_MSG(2, "Try '");
179         WRITE_STR(2, argv[0]);
180         WRITE_MSG(2, " --help\" for more information.\n");
181         return 255;
182         break;
183     }
184   }
185
186   if (socket_name==0)
187     WRITE_MSG(2, "reserve-context: No socketname specified\n");
188   if (quit_msg)
189     return sendQuitSignal(socket_name, quit_msg);
190   else
191     return doit(socket_name, timeout_ptr);
192
193   return EXIT_FAILURE;
194 }