]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Interactive client for browsing internal database.
authorTed Lemon <source@isc.org>
Thu, 9 Apr 1998 05:18:56 +0000 (05:18 +0000)
committerTed Lemon <source@isc.org>
Thu, 9 Apr 1998 05:18:56 +0000 (05:18 +0000)
common/interact.c [new file with mode: 0644]

diff --git a/common/interact.c b/common/interact.c
new file mode 100644 (file)
index 0000000..561af87
--- /dev/null
@@ -0,0 +1,242 @@
+/* interact.c
+
+   Text interactor for dhcp servers. */
+
+/*
+ * Copyright (c) 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ *    of its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software was written for the Internet Software Consortium by
+ * Ted Lemon <mellon@fugue.com> in cooperation with Vixie Enterprises.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.vix.com/isc''.  To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: interact.c,v 1.1 1998/04/09 05:18:56 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+int interact_initialized;
+int interact_fd;
+static struct interact_client *interact_clients;
+
+void interact_startup ()
+{
+       struct sockaddr_un name;
+       static int once;
+       int len;
+       mode_t m;
+
+       /* Only initialize interact once. */
+       if (interact_initialized)
+               error ("attempted to reinitialize interact protocol");
+       interact_initialized = 1;
+
+       /* Make a socket... */
+       interact_fd = socket (AF_UNIX, SOCK_STREAM, 0);
+       if (interact_fd < 0)
+               error ("unable to create interact socket: %m");
+
+       /* XXX for now... */
+       name.sun_family = PF_UNIX;
+       strcpy (name.sun_path, "/var/run/dhcpctl");
+#if defined (HAVE_SA_LEN)
+       name.sun_len =
+#endif
+               len = ((sizeof name) - (sizeof name.sun_path) +
+                      strlen (name.sun_path));
+       unlink (name.sun_path);
+
+       /* interact socket should be accessible only by root. */
+       m = umask (0700);
+
+       /* Bind to it... */
+       if (bind (interact_fd, (struct sockaddr *)&name, len) < 0) {
+               warn ("can't bind to interact socket: %m");
+               close (interact_fd);
+               umask (m);
+               return;
+       }
+       umask (m);
+
+       /* Listen for connections... */
+       if (listen (interact_fd, 1) < 0) {
+               warn ("can't listen on interact socket: %m");
+               close (interact_fd);
+               unlink (name.sun_path);
+               return;
+       }
+
+       add_protocol ("interact", interact_fd, new_interact_connection, 0);
+}
+
+void new_interact_connection (proto)
+       struct protocol *proto;
+{
+       struct sockaddr_un name;
+       int namelen;
+       struct interact_client *tmp;
+       int new_fd;
+       int arg;
+
+       tmp = (struct interact_client *)malloc (sizeof *tmp);
+       if (!tmp)
+               error ("Can't find memory for new client!");
+       memset (tmp, 0, sizeof *tmp);
+
+       namelen = sizeof name;
+       new_fd = accept (proto -> fd, (struct sockaddr *)&name, &namelen);
+       if (new_fd < 0) {
+               warn ("accept: %m");
+               free (tmp);
+               return;
+       }
+
+       if ((arg = fcntl (new_fd, F_GETFL, 0)) < 0) {
+       bad_flag:
+               warn ("Can't set flags on new interactive client: %m");
+               close (new_fd);
+               free (tmp);
+               return;
+       }
+       arg |= O_NONBLOCK;
+       if (fcntl (new_fd, F_SETFL, arg) < 0)
+               goto bad_flag;
+
+       tmp -> next = interact_clients;
+       tmp -> fd = new_fd;
+       interact_clients = tmp;
+       tmp -> cur_node_actions = top_level_actions;
+
+       tmp -> proto = add_protocol ("aclient", new_fd,
+                                    interact_client_input, tmp);
+}
+
+void interact_client_input (proto)
+       struct protocol *proto;
+{
+       int status;
+       char *eobuf;
+       struct interact_client *client = proto -> local;
+
+       status = read (proto -> fd, &client -> ibuf [client -> ibuflen],
+                      (sizeof client -> ibuf) - client -> ibuflen);
+       if (status < 0) {
+               warn ("interact_client_input: %m");
+       blow:
+               close (proto -> fd);
+               remove_protocol (proto);
+               free (client);
+               return;
+       }
+       /* EOF: get lost. */
+       if (status == 0)
+               goto blow;
+
+       client -> ibuflen += status;
+       eobuf = memchr (client -> ibuf, '\n', client -> ibuflen);
+       if (!eobuf) {
+               if (client -> ibuflen == sizeof client -> ibuf) {
+                       warn ("interact_client_input: buffer overflow.");
+                       goto blow;
+               }
+               return;
+       }
+
+       /* NUL terminate and blow away newline. */
+       *eobuf = 0;
+
+       if (!strcmp (client -> ibuf, "ls"))
+               (*client -> cur_node_actions.ls) (client);
+       else if (!strncmp (client -> ibuf, "print ", 6))
+               (*client -> cur_node_actions.print) (client,
+                                                       &client -> ibuf [6]);
+       else if (!strncmp (client -> ibuf, "set ", 4))
+               (*client -> cur_node_actions.set) (client,
+                                                     &client -> ibuf [4]);
+       else if (!strncmp (client -> ibuf, "rm ", 3))
+               (*client -> cur_node_actions.rm) (client,
+                                                    &client -> ibuf [3]);
+       else if (!strcmp (client -> ibuf, "cd .."))
+               (*client -> cur_node_actions.cdup) (client);
+       else if (!strncmp (client -> ibuf, "cd ", 3))
+               (*client -> cur_node_actions.cd) (client,
+                                                    &client -> ibuf [3]);
+       else if (!strcmp (client -> ibuf, "exit")) {
+               interact_client_write (client, "done.", 1);
+               goto blow;
+       } else
+               interact_client_write (client, "invalid command", 1);
+
+       /* In case the client wrote more than one command. */
+       if (client -> ibuflen -= eobuf - &client -> ibuf [0] + 1)
+               memmove (client -> ibuf, eobuf, client -> ibuflen);
+}
+
+int interact_client_write (client, string, lastp)
+       struct interact_client *client;
+       char *string;
+       int lastp;
+{
+       static char *obuf;
+       static int obufmax;
+       char *bp;
+
+       /* Unlikely to loop, but why not be sure? */
+       if (obufmax < strlen (string)) {
+               if (obuf)
+                       free (obuf);
+               obufmax = (strlen (string) + 1025) & ~1023;
+               obuf = malloc (obufmax);
+               if (!obuf) {
+                       warn ("interact_client_write: out of memory");
+               blow:
+                       close (client -> proto -> fd);
+                       remove_protocol (client -> proto);
+                       free (client);
+                       return 0;
+               }
+       }
+
+       bp = obuf;
+       if (!lastp)
+               *bp++ = '-';
+       strcpy (bp, string);
+       bp += strlen (bp);
+       *bp++ = '\n';
+       if (write (client -> fd, obuf, bp - obuf) < 0)
+               return 0;
+
+       return 1;
+}