aboutsummaryrefslogtreecommitdiff
path: root/src/inetd-bi.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-24 21:19:56 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-11-24 21:19:56 +0200
commit534098c3d35f36ab9d333fb0ee800c7ffaf0dcbd (patch)
tree5e8ed3f413000e73f8ff00286e1615f2408e9c37 /src/inetd-bi.c
parenta7779d56bb758157e122a420a56f2d7b4475e554 (diff)
downloadpies-534098c3d35f36ab9d333fb0ee800c7ffaf0dcbd.tar.gz
pies-534098c3d35f36ab9d333fb0ee800c7ffaf0dcbd.tar.bz2
Implement inetd builtin services.
* src/inetd-bi.c: New file. * src/Makefile.am (pies_SOURCES): Add inetd-bi.c. * src/pies.h (struct component): New member `builtin'. (qotdfile): New extern. (inetd_builtin): New struct. (inetd_builtin_lookup): New proto. * src/progman.c (prog_start): Handle internal services. * src/inetd.c (inetd_conf_file): Handle internal services. * src/pies.c (qotdfile): New global. (pies_keywords): New keyword "qotd-file".
Diffstat (limited to 'src/inetd-bi.c')
-rw-r--r--src/inetd-bi.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/src/inetd-bi.c b/src/inetd-bi.c
new file mode 100644
index 0000000..f86f373
--- /dev/null
+++ b/src/inetd-bi.c
@@ -0,0 +1,305 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2009 Sergey Poznyakoff
+
+ GNU Pies is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Pies is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "pies.h"
+#include <netdb.h>
+
+#define INTBUFSIZE 8192
+
+/* Echo protocol, RFC 862 */
+void
+echo_stream (int fd)
+{
+ int rc;
+ char buffer[INTBUFSIZE];
+
+ while ((rc = read (fd, buffer, sizeof buffer)) > 0
+ && write (fd, buffer, rc) > 0)
+ ;
+}
+
+void
+echo_dg (int fd)
+{
+ int rc;
+ char buffer[INTBUFSIZE];
+ struct sockaddr sa;
+ socklen_t size = sizeof sa;
+
+ rc = recvfrom (fd, buffer, sizeof buffer, 0, &sa, &size);
+ if (rc < 0)
+ return;
+ sendto (fd, buffer, rc, 0, &sa, sizeof sa);
+}
+
+/* Discard protocol, RFC 863 */
+void
+discard_stream (int fd)
+{
+ int rc;
+ char buffer[INTBUFSIZE];
+
+ while (1)
+ {
+ while ((rc = read (fd, buffer, sizeof buffer)) > 0)
+ ;
+ if (rc == 0 || errno != EINTR)
+ break;
+ }
+}
+
+void
+discard_dg (int fd)
+{
+ char buffer[INTBUFSIZE];
+ read (fd, buffer, sizeof buffer);
+}
+
+
+/* Time Protocol, RFC 868 */
+
+/* Return a machine readable date and time as seconds since
+ midnight, Jan 1, 1900. */
+
+#define SEVENTY_YEARS ((unsigned long)25567 * 24 * 60 * 60)
+
+unsigned long
+time_since_1900 (void)
+{
+ struct timeval tv;
+
+ if (gettimeofday (&tv, NULL) < 0)
+ {
+ logmsg (LOG_ERR, "gettimeofday: %s", strerror (errno));
+ return 0;
+ }
+ return htonl ((long) (tv.tv_sec + SEVENTY_YEARS));
+}
+
+void
+time_stream (int fd)
+{
+ unsigned long result = time_since_1900 ();
+ write (fd, (char *) &result, sizeof result);
+}
+
+void
+time_dg (int fd)
+{
+ unsigned long result;
+ struct sockaddr sa;
+ socklen_t size = sizeof sa;
+
+ if (recvfrom (fd, (char *) &result, sizeof result, 0, &sa, &size) < 0)
+ return;
+ result = time_since_1900 ();
+ sendto (fd, (char *) &result, sizeof result, 0, &sa, sizeof sa);
+}
+
+/* Daytime Protocol, RFC 867 */
+void
+daytime_stream (int fd)
+{
+ char buffer[27];
+ time_t now;
+
+ time (&now);
+ sprintf (buffer, "%.24s\r\n", ctime (&now));
+ write (fd, buffer, strlen (buffer));
+}
+
+void
+daytime_dg (int fd)
+{
+ char buffer[27];
+ time_t now;
+ struct sockaddr sa;
+ socklen_t size = sizeof sa;
+
+ time (&now);
+
+ if (recvfrom (fd, buffer, sizeof buffer, 0, &sa, &size) < 0)
+ return;
+ sprintf (buffer, "%.24s\r\n", ctime (&now));
+ sendto (fd, buffer, strlen (buffer), 0, &sa, sizeof sa);
+}
+
+/* Character Generator Protocol, RFC 864 */
+
+#define LINESIZ 72
+
+static void
+chargen_next_line (char *text)
+{
+ static int ch = 0;
+ int i, c;
+
+ do
+ ch = (ch + 1) % 128;
+ while (!c_isprint (ch));
+
+ for (i = 0, c = ch; i < LINESIZ; )
+ {
+ if (c_isprint (c))
+ text[i++] = c;
+ c = (c + 1) % 128;
+ }
+}
+
+void
+chargen_stream (int fd)
+{
+ char text[LINESIZ + 2];
+
+ text[LINESIZ] = '\r';
+ text[LINESIZ + 1] = '\n';
+
+ while (1)
+ {
+ chargen_next_line (text);
+ if (write (fd, text, sizeof text) != sizeof text)
+ break;
+ }
+}
+
+void
+chargen_dg (int fd)
+{
+ struct sockaddr sa;
+ socklen_t size = sizeof sa;
+ char text[LINESIZ + 2];
+
+ if (recvfrom (fd, text, sizeof text, 0, &sa, &size) < 0)
+ return;
+ text[LINESIZ] = '\r';
+ text[LINESIZ + 1] = '\n';
+ chargen_next_line (text);
+ sendto (fd, text, sizeof text, 0, &sa, sizeof sa);
+}
+
+
+/* Quote of the Day Protocol, RFC 865 */
+
+#define QOTD_MAX 512
+#define QOTD_DEF "Quote of the Day\r\n"
+
+static size_t
+trnl (char *text, size_t size)
+{
+ size_t off = size;
+
+ for (; off > 0; off--)
+ if (text[off] == '\n')
+ {
+ if (text[off-1] == '\r')
+ off--;
+ else
+ {
+ if (size == QOTD_MAX)
+ size--;
+ memmove (text + off + 1, text + off, size - off);
+ text[off] = '\r';
+ size++;
+ }
+ }
+ return size;
+}
+
+size_t
+qotd_read (char *text)
+{
+ ssize_t rc;
+ int fd = open (qotdfile, O_RDONLY);
+ if (fd == -1)
+ {
+ logmsg (LOG_ERR, _("cannot open %s: %s"), qotdfile, strerror (errno));
+ strncpy (text, QOTD_DEF, QOTD_MAX);
+ rc = QOTD_MAX;
+ }
+ else
+ {
+ rc = read (fd, text, QOTD_MAX);
+ if (rc >= 0)
+ rc = trnl (text, rc);
+ else
+ {
+ logmsg (LOG_ERR, _("error reading %s: %s"),
+ qotdfile, strerror (errno));
+ strncpy (text, QOTD_DEF, QOTD_MAX);
+ rc = QOTD_MAX;
+ }
+ }
+ close (fd);
+ return rc;
+}
+
+void
+qotd_stream (int fd)
+{
+ char text[QOTD_MAX];
+ size_t len = qotd_read (text);
+ write (fd, text, len);
+}
+
+void
+qotd_dg (int fd)
+{
+ char text[QOTD_MAX];
+ struct sockaddr sa;
+ socklen_t size = sizeof sa;
+ size_t len;
+ if (recvfrom (fd, text, sizeof text, 0, &sa, &size) < 0)
+ return;
+ len = qotd_read (text);
+ sendto (fd, text, len, 0, &sa, sizeof sa);
+}
+
+
+struct inetd_builtin inetd_builtin_tab[] = {
+ /* Echo received data */
+ {"echo", SOCK_STREAM, 0, 0, echo_stream},
+ {"echo", SOCK_DGRAM, 1, 0, echo_dg},
+ /* Internet /dev/null */
+ {"discard", SOCK_STREAM, 0, 0, discard_stream},
+ {"discard", SOCK_DGRAM, 1, 0, discard_dg},
+ /* Return 32 bit time since 1900 */
+ {"time", SOCK_STREAM, 1, 0, time_stream},
+ {"time", SOCK_DGRAM, 1, 0, time_dg},
+ /* Return human-readable time */
+ {"daytime", SOCK_STREAM, 1, 0, daytime_stream},
+ {"daytime", SOCK_DGRAM, 1, 0, daytime_dg},
+ /* Character generator */
+ {"chargen", SOCK_STREAM, 0, 0, chargen_stream},
+ {"chargen", SOCK_DGRAM, 1, 0, chargen_dg},
+ /* Quote of the Day */
+ {"qotd", SOCK_STREAM, 0, 0, qotd_stream},
+ {"qotd", SOCK_DGRAM, 1, 0, qotd_dg},
+#if 0
+ {"tcpmux", SOCK_STREAM, 0, 0, tcpmux},
+#endif
+ {NULL, 0, 0, 0, NULL}
+};
+
+struct inetd_builtin *
+inetd_builtin_lookup (const char *service, int socktype)
+{
+ struct inetd_builtin *bp;
+
+ for (bp = inetd_builtin_tab; bp->service; bp++)
+ if (bp->socktype == socktype && strcmp (bp->service, service) == 0)
+ return bp;
+ return NULL;
+}

Return to:

Send suggestions and report system problems to the System administrator.