From: Ted Lemon Date: Thu, 9 Apr 1998 05:18:56 +0000 (+0000) Subject: Interactive client for browsing internal database. X-Git-Tag: carrel-2~128 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2367591ef265fbc12b397abeece4bc31fe28b939;p=thirdparty%2Fdhcp.git Interactive client for browsing internal database. --- diff --git a/common/interact.c b/common/interact.c new file mode 100644 index 000000000..561af8748 --- /dev/null +++ b/common/interact.c @@ -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 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; +}