[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH] sgetty: Smart serial console getty
Very often when I was switching from Xen to Linux I was forced to change /etc/inittab to make serial console working. It was boring so I thought how to solve that problem. I was not able to find sensible solution. So I decided to write something. Here it is. I posted this patch earlier to Xen-devel list but Ian Campbell stated that it is more generic and maybe I should try to include this in util-linux. I am posting sgetty here with minor changes. Maybe this solution should be merged with agetty but I am not sure right now. If you think that it is good idea then I will do that. Anyway, I am looking for your comments. I am not subscribed to util-linux list so please include my email address in your reply. Signed-off-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx> --- term-utils/Makemodule.am | 2 + term-utils/sgetty.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 term-utils/sgetty.c diff --git a/term-utils/Makemodule.am b/term-utils/Makemodule.am index e53471f..e9055fc 100644 --- a/term-utils/Makemodule.am +++ b/term-utils/Makemodule.am @@ -21,6 +21,8 @@ sbin_PROGRAMS += agetty dist_man_MANS += term-utils/agetty.8 agetty_SOURCES = term-utils/agetty.c agetty_LDADD = $(LDADD) libcommon.la +sbin_PROGRAMS += sgetty +sgetty_SOURCES = term-utils/sgetty.c endif # BUILD_AGETTY diff --git a/term-utils/sgetty.c b/term-utils/sgetty.c new file mode 100644 index 0000000..2bd3500 --- /dev/null +++ b/term-utils/sgetty.c @@ -0,0 +1,243 @@ +/* + * 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 *sgetty_file = "sgetty"; + +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, "\nsgetty Ver. 1.0.0\n\n" + "sgetty establishes serial console name from system boot command\n" + "line (%s) and then runs getty. This is very useful if e.g.\n" + "someone switches very often between Linux and Xen and uses serial\n" + "console. sgetty does boring things and runs getty on relevant line.\n" + "This way nobody needs to worry about /etc/inittab changes anymore.\n\n" + "Usage: sgetty [<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>. The line name is established by sgetty.\n" + "Baud rate and terminal type (if needed) must be\n" + "passed via relevant sgetty options.\n\n" + "sgetty takes into account and counts console arguments with ttyS*,\n" + "hvc* and xvc* only in system boot command line.\n\n" + "Example: sgetty -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(sgetty_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, "/")) + sgetty_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 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |