public inbox for util-linux@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] sgetty: Smart serial console getty
@ 2013-12-04 22:31 Daniel Kiper
  2013-12-05 11:05 ` Karel Zak
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel Kiper @ 2013-12-04 22:31 UTC (permalink / raw)
  To: kzak, util-linux, xen-devel; +Cc: Daniel Kiper

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@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] sgetty: Smart serial console getty
  2013-12-04 22:31 [RFC PATCH] sgetty: Smart serial console getty Daniel Kiper
@ 2013-12-05 11:05 ` Karel Zak
  2013-12-05 13:37   ` Daniel Kiper
  0 siblings, 1 reply; 4+ messages in thread
From: Karel Zak @ 2013-12-05 11:05 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: util-linux, xen-devel


 Hi Daniel,

On Wed, Dec 04, 2013 at 11:31:37PM +0100, Daniel Kiper wrote:
> 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.

Would be better to extend agetty(1) to read console name from kernel
command line rather than introduce a special wrapper?

Something like:

   agetty --detect-console [baud_rate...] [term]

Note that in login-utils/sulogin-consoles.c we have code to detect
consoles for sulogin, for example detect_consoles_from_cmdline().

We did a lot of work to consolidate and clean up agetty and kill
things like mingetty in last years. So I'd like to have only util,
especially if all the magic is just console name only.

> 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

yeah, that's probably a generic issue.

BTW, I guess that systemd does not use hardcoded console names (like
/etc/inittab), ... just for the record :-) (I have no problem to
support classic inittab.)

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] sgetty: Smart serial console getty
  2013-12-05 11:05 ` Karel Zak
@ 2013-12-05 13:37   ` Daniel Kiper
  2013-12-05 14:24     ` Karel Zak
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel Kiper @ 2013-12-05 13:37 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, xen-devel

Hi Karel,

On Thu, Dec 05, 2013 at 12:05:08PM +0100, Karel Zak wrote:
>
>  Hi Daniel,
>
> On Wed, Dec 04, 2013 at 11:31:37PM +0100, Daniel Kiper wrote:
> > 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.
>
> Would be better to extend agetty(1) to read console name from kernel
> command line rather than introduce a special wrapper?
>
> Something like:
>
>    agetty --detect-console [baud_rate...] [term]

Make sens.

> Note that in login-utils/sulogin-consoles.c we have code to detect
> consoles for sulogin, for example detect_consoles_from_cmdline().

Great... I will try to use it. Should I build this file as a library
and then link into agetty or just link ordinary object file
(login-utils/sulogin-consoles.o) with it?

> We did a lot of work to consolidate and clean up agetty and kill
> things like mingetty in last years. So I'd like to have only util,
> especially if all the magic is just console name only.

Agreed.

> > 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
>
> yeah, that's probably a generic issue.
>
> BTW, I guess that systemd does not use hardcoded console names (like
> /etc/inittab), ... just for the record :-) (I have no problem to
> support classic inittab.)

That is great. However, I do not know systemd (I only heard about that)
and maybe my question is stupid but I am curious how it starts getty
on serial console, i.e. how it gets a name of serial console and
passes it to getty.

Daniel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] sgetty: Smart serial console getty
  2013-12-05 13:37   ` Daniel Kiper
@ 2013-12-05 14:24     ` Karel Zak
  0 siblings, 0 replies; 4+ messages in thread
From: Karel Zak @ 2013-12-05 14:24 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: util-linux, xen-devel

On Thu, Dec 05, 2013 at 02:37:07PM +0100, Daniel Kiper wrote:
> >    agetty --detect-console [baud_rate...] [term]
> 
> Make sens.
> 
> > Note that in login-utils/sulogin-consoles.c we have code to detect
> > consoles for sulogin, for example detect_consoles_from_cmdline().
> 
> Great... I will try to use it. Should I build this file as a library
> and then link into agetty or just link ordinary object file
> (login-utils/sulogin-consoles.o) with it?

 You can move the function (or some fragment of the function) to
 the lib/ttyutils.c, the file is already used for libcommon.so (lib
 used everywhere in the package).

> > BTW, I guess that systemd does not use hardcoded console names (like
> > /etc/inittab), ... just for the record :-) (I have no problem to
> > support classic inittab.)
> 
> That is great. However, I do not know systemd (I only heard about that)
> and maybe my question is stupid but I am curious how it starts getty
> on serial console, i.e. how it gets a name of serial console and
> passes it to getty.

 from kernel command line, more details:
 http://0pointer.de/blog/projects/serial-console.html

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-12-05 14:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-04 22:31 [RFC PATCH] sgetty: Smart serial console getty Daniel Kiper
2013-12-05 11:05 ` Karel Zak
2013-12-05 13:37   ` Daniel Kiper
2013-12-05 14:24     ` Karel Zak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox