From: Daniel Kiper <daniel.kiper@oracle.com>
To: george.dunlap@eu.citrix.com, ian.campbell@citrix.com,
ian.jackson@eu.citrix.com, jbeulich@suse.com, keir@xen.org,
stefano.stabellini@eu.citrix.com, xen-devel@lists.xen.org
Cc: Daniel Kiper <daniel.kiper@oracle.com>
Subject: [PATCH 1/2] xgetty: Do not edit /etc/inittab when switching from Xen to Linux and back
Date: Thu, 14 Nov 2013 12:44:08 +0100 [thread overview]
Message-ID: <1384429449-13692-2-git-send-email-daniel.kiper@oracle.com> (raw)
In-Reply-To: <1384429449-13692-1-git-send-email-daniel.kiper@oracle.com>
xgetty establishes serial console name from system boot command
line (/proc/cmdline) and then runs getty. This is very useful if
someone switches very often between Linux and Xen and uses serial
console. xgetty does boring things and runs getty on relevant line.
This way nobody needs to worry about /etc/inittab changes anymore.
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
tools/Makefile | 1 +
tools/xgetty/Makefile | 17 ++++
tools/xgetty/xgetty.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 272 insertions(+)
create mode 100644 tools/xgetty/Makefile
create mode 100644 tools/xgetty/xgetty.c
diff --git a/tools/Makefile b/tools/Makefile
index 00c69ee..55b3c69 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -25,6 +25,7 @@ SUBDIRS-$(CONFIG_NetBSD) += xenbackendd
SUBDIRS-y += libfsimage
SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
SUBDIRS-$(CONFIG_Linux) += libvchan
+SUBDIRS-$(CONFIG_Linux) += xgetty
# do not recurse in to a dir we are about to delete
ifneq "$(MAKECMDGOALS)" "distclean"
diff --git a/tools/xgetty/Makefile b/tools/xgetty/Makefile
new file mode 100644
index 0000000..fde57c0
--- /dev/null
+++ b/tools/xgetty/Makefile
@@ -0,0 +1,17 @@
+XEN_ROOT=$(CURDIR)/../..
+
+include $(XEN_ROOT)/tools/Rules.mk
+
+.PHONY: all clean install
+
+all: xgetty
+
+xgetty: xgetty.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+install: all
+ [ -d $(DESTDIR)$(SBINDIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
+ $(INSTALL_PROG) xgetty $(DESTDIR)$(SBINDIR)/xgetty
+
+clean:
+ rm -fr $(DEPS) *.o xgetty
diff --git a/tools/xgetty/xgetty.c b/tools/xgetty/xgetty.c
new file mode 100644
index 0000000..ca3a594
--- /dev/null
+++ b/tools/xgetty/xgetty.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2013 Daniel Kiper, Oracle Corporation
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#define BOOT_CMDLINE "/proc/cmdline"
+
+#define GETTY "/sbin/getty"
+
+static char *xgetty_file = "xgetty";
+
+static char *opt_b = NULL;
+static int opt_c = 1;
+static char *opt_g = GETTY;
+static char *opt_t = NULL;
+
+static void usage(int status)
+{
+ FILE *stream;
+
+ stream = ( status == EXIT_SUCCESS ) ? stdout : stderr;
+
+ fprintf(stream, "\nxgetty Ver. 1.0.0\n\n"
+ "xgetty establishes serial console name from system boot command\n"
+ "line (%s) and then runs getty. This is very useful if\n"
+ "someone switches very often between Linux and Xen and uses serial\n"
+ "console. xgetty does boring things and runs getty on relevant line.\n"
+ "This way nobody needs to worry about /etc/inittab changes anymore.\n\n"
+ "Usage: xgetty [<options>] [-- [<getty_options>]]\n\n"
+ "Options:\n"
+ " -b <baud_rate> - baud rate (required),\n"
+ " -c <console> - serial console number in system boot\n"
+ " command line (default: 1),\n"
+ " -g <getty> - path to getty (default: %s),\n"
+ " -h - display this help,\n"
+ " -t <term> - terminal type.\n\n"
+ "<getty_options> are passed without any changes to getty.\n\n"
+ "Warning: do not pass a line name, baud rate and terminal type\n"
+ "in <getty_options>. Line name is established by xgetty.\n"
+ "Baud rate and terminal type (if needed) must be\n"
+ "passed via relevant xgetty options.\n\n"
+ "xgetty takes into account ttyS*, hvc* and xvc* only\n"
+ "in system boot command line.\n\n"
+ "Example: xgetty -g /sbin/agetty -b 115200 -c 2 -- -i\n\n",
+ BOOT_CMDLINE, GETTY);
+
+ exit(status);
+}
+
+static void do_log(int priority, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ openlog(xgetty_file, LOG_PID, LOG_AUTHPRIV);
+ vsyslog(priority, format, ap);
+ closelog();
+
+ va_end(ap);
+}
+
+static void init(int argc, char *const argv[])
+{
+ char *endptr, *s;
+ int c;
+
+ s = basename(argv[0]);
+
+ if ( strcmp(s, ".") && strcmp(s, "/") )
+ xgetty_file = s;
+
+ opterr = 0;
+
+ while ( (c = getopt(argc, argv, "+b:c:g:ht:")) != -1 )
+ switch (c)
+ {
+ case 'b':
+ opt_b = optarg;
+ break;
+
+ case 'c':
+ errno = 0;
+ opt_c = strtol(optarg, &endptr, 10);
+
+ if ( errno || *endptr || opt_c < 1 )
+ {
+ fprintf(stderr, "Wrong serial console number\n");
+ do_log(LOG_WARNING, "Wrong serial console number");
+ usage(EXIT_FAILURE);
+ }
+
+ break;
+
+ case 'g':
+ opt_g = optarg;
+ break;
+
+ case 'h':
+ usage(EXIT_SUCCESS);
+
+ case 't':
+ opt_t = optarg;
+ break;
+
+ default:
+ fprintf(stderr, "Wrong arguments\n");
+ do_log(LOG_WARNING, "Wrong arguments");
+ usage(EXIT_FAILURE);
+ }
+
+ if ( !opt_b )
+ {
+ fprintf(stderr, "Baud rate is not specified\n");
+ do_log(LOG_ERR, "Baud rate is not specified");
+ usage(EXIT_FAILURE);
+ }
+}
+
+static char *get_console_name(void)
+{
+ FILE *stream;
+ char *boot_cmdline = NULL, *tok;
+ int i = 1;
+ size_t n;
+ ssize_t rc;
+
+ stream = fopen(BOOT_CMDLINE, "r");
+
+ if ( !stream )
+ {
+ do_log(LOG_ERR, "Cannot open file: %s: %m", BOOT_CMDLINE);
+ exit(EXIT_FAILURE);
+ }
+
+ rc = getline(&boot_cmdline, &n, stream);
+
+ if ( rc == -1 )
+ {
+ do_log(LOG_ERR, "Cannot read file: %s: %m", BOOT_CMDLINE);
+ exit(EXIT_FAILURE);
+ }
+
+ fclose(stream);
+
+ tok = strtok(boot_cmdline, " \n\r\t");
+
+ while ( tok )
+ {
+ if ( strstr(tok, "console=ttyS") == tok ||
+ strstr(tok, "console=hvc") == tok ||
+ strstr(tok, "console=xvc") == tok)
+ {
+ if ( i == opt_c )
+ {
+ tok += strlen("console=");
+ return strtok(tok, ", \n\r\t");
+ }
+
+ if ( ++i > opt_c )
+ return NULL;
+ }
+
+ tok = strtok(NULL, " \n\r\t");
+ }
+
+ return NULL;
+}
+
+static void exec_getty(int argc, char *const argv[], char *console)
+{
+ char **g_argv;
+ /* Path to getty, console name, baud rate and final NULL. */
+ int g_argc = 4;
+ int i = 0, j = optind;
+
+ if ( !console )
+ {
+ do_log(LOG_INFO, "Serial console not found. Nothing to do. "
+ "I am going sleep... Yawn...");
+ sleep(86400); /* Sleep one day... */
+ exit(EXIT_SUCCESS);
+ }
+
+ /* How many plain getty options do we have? */
+ g_argc += argc - optind;
+
+ /* Add space for terminal type if needed. */
+ if ( opt_t )
+ ++g_argc;
+
+ g_argv = calloc(g_argc, sizeof(char *));
+
+ if ( !g_argv )
+ {
+ do_log(LOG_ERR, "Cannot allocate memory for getty args: %m");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Path to getty. */
+ g_argv[i++] = opt_g;
+
+ /* Plain options to getty. */
+ while ( j < argc )
+ g_argv[i++] = argv[j++];
+
+ /* Console name. */
+ g_argv[i++] = console;
+
+ /* Baud rate. */
+ g_argv[i++] = opt_b;
+
+ /* Terminal type if available. */
+ if ( opt_t )
+ g_argv[i] = opt_t;
+
+ /* Run getty. */
+ execv(opt_g, g_argv);
+
+ /* Ugh... Something went wrong... Dying... */
+ do_log(LOG_ERR, "Cannot execute %s: %m", opt_g);
+}
+
+int main(int argc, char *const argv[])
+{
+ char *console;
+
+ init(argc, argv);
+ console = get_console_name();
+ exec_getty(argc, argv, console);
+
+ return EXIT_FAILURE;
+}
--
1.7.10.4
next prev parent reply other threads:[~2013-11-14 11:44 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-14 11:44 xgetty: Smart serial console getty for Xen Daniel Kiper
2013-11-14 11:44 ` Daniel Kiper [this message]
2013-11-14 11:51 ` [PATCH 1/2] xgetty: Do not edit /etc/inittab when switching from Xen to Linux and back Ian Campbell
2013-11-14 15:50 ` Daniel Kiper
2013-11-15 10:28 ` George Dunlap
2013-11-14 11:44 ` [PATCH 2/2] MAINTAINERS: Add XGETTY maintainer Daniel Kiper
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1384429449-13692-2-git-send-email-daniel.kiper@oracle.com \
--to=daniel.kiper@oracle.com \
--cc=george.dunlap@eu.citrix.com \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=jbeulich@suse.com \
--cc=keir@xen.org \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).