|
|
5bfd05 |
From ea152b4e9656945f17d18bf4e5ece91e3e57ebb1 Mon Sep 17 00:00:00 2001
|
|
|
5bfd05 |
From: Karel Zak <kzak@redhat.com>
|
|
|
5bfd05 |
Date: Tue, 29 Jan 2019 11:57:55 +0100
|
|
|
5bfd05 |
Subject: [PATCH] agetty: backport RHEL-8 version
|
|
|
5bfd05 |
|
|
|
5bfd05 |
The code is identical to RHEL-8.0, except:
|
|
|
5bfd05 |
|
|
|
5bfd05 |
* disabled ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
* disabled AGETTY_RELOAD
|
|
|
5bfd05 |
* removed \e and \e{name} feature
|
|
|
5bfd05 |
|
|
|
5bfd05 |
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1664752
|
|
|
5bfd05 |
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
|
5bfd05 |
---
|
|
|
5bfd05 |
include/pathnames.h | 5 +-
|
|
|
5bfd05 |
term-utils/agetty.c | 1141 +++++++++++++++++++++++++++++++------------
|
|
|
5bfd05 |
2 files changed, 839 insertions(+), 307 deletions(-)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
diff --git a/include/pathnames.h b/include/pathnames.h
|
|
|
5bfd05 |
index fa4bddbad..ec5eef918 100644
|
|
|
5bfd05 |
--- a/include/pathnames.h
|
|
|
5bfd05 |
+++ b/include/pathnames.h
|
|
|
5bfd05 |
@@ -64,9 +64,10 @@
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* used in term-utils/agetty.c */
|
|
|
5bfd05 |
#define _PATH_ISSUE "/etc/issue"
|
|
|
5bfd05 |
-#define _PATH_OS_RELEASE "/etc/os-release"
|
|
|
5bfd05 |
+#define _PATH_ISSUEDIR _PATH_ISSUE ".d"
|
|
|
5bfd05 |
+#define _PATH_OS_RELEASE_ETC "/etc/os-release"
|
|
|
5bfd05 |
+#define _PATH_OS_RELEASE_USR "/usr/lib/os-release"
|
|
|
5bfd05 |
#define _PATH_NUMLOCK_ON _PATH_LOCALSTATEDIR "/numlock-on"
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
#define _PATH_LOGINDEFS "/etc/login.defs"
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* used in misc-utils/look.c */
|
|
|
5bfd05 |
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
|
|
|
5bfd05 |
index 948d77246..c3c7ab504 100644
|
|
|
5bfd05 |
--- a/term-utils/agetty.c
|
|
|
5bfd05 |
+++ b/term-utils/agetty.c
|
|
|
5bfd05 |
@@ -10,6 +10,7 @@
|
|
|
5bfd05 |
*
|
|
|
5bfd05 |
* This program is freely distributable.
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
#include <stdio.h>
|
|
|
5bfd05 |
#include <unistd.h>
|
|
|
5bfd05 |
#include <stdlib.h>
|
|
|
5bfd05 |
@@ -20,19 +21,21 @@
|
|
|
5bfd05 |
#include <sys/ioctl.h>
|
|
|
5bfd05 |
#include <sys/types.h>
|
|
|
5bfd05 |
#include <sys/stat.h>
|
|
|
5bfd05 |
+#include <sys/wait.h>
|
|
|
5bfd05 |
#include <fcntl.h>
|
|
|
5bfd05 |
#include <stdarg.h>
|
|
|
5bfd05 |
#include <ctype.h>
|
|
|
5bfd05 |
-#include <utmp.h>
|
|
|
5bfd05 |
+#include <utmpx.h>
|
|
|
5bfd05 |
#include <getopt.h>
|
|
|
5bfd05 |
#include <time.h>
|
|
|
5bfd05 |
-#include <sys/file.h>
|
|
|
5bfd05 |
#include <sys/socket.h>
|
|
|
5bfd05 |
#include <langinfo.h>
|
|
|
5bfd05 |
#include <grp.h>
|
|
|
5bfd05 |
#include <arpa/inet.h>
|
|
|
5bfd05 |
#include <netdb.h>
|
|
|
5bfd05 |
#include <ifaddrs.h>
|
|
|
5bfd05 |
+#include <net/if.h>
|
|
|
5bfd05 |
+#include <sys/utsname.h>
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#include "strutils.h"
|
|
|
5bfd05 |
#include "all-io.h"
|
|
|
5bfd05 |
@@ -41,14 +44,37 @@
|
|
|
5bfd05 |
#include "c.h"
|
|
|
5bfd05 |
#include "widechar.h"
|
|
|
5bfd05 |
#include "ttyutils.h"
|
|
|
5bfd05 |
+#include "env.h"
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifdef USE_PLYMOUTH_SUPPORT
|
|
|
5bfd05 |
+# include "plymouth-ctrl.h"
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifdef HAVE_SYS_PARAM_H
|
|
|
5bfd05 |
+# include <sys/param.h>
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#if defined(__FreeBSD_kernel__)
|
|
|
5bfd05 |
+# include <pty.h>
|
|
|
5bfd05 |
+# ifdef HAVE_UTMP_H
|
|
|
5bfd05 |
+# include <utmp.h>
|
|
|
5bfd05 |
+# endif
|
|
|
5bfd05 |
+# ifdef HAVE_LIBUTIL_H
|
|
|
5bfd05 |
+# include <libutil.h>
|
|
|
5bfd05 |
+# endif
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#ifdef __linux__
|
|
|
5bfd05 |
# include <sys/kd.h>
|
|
|
5bfd05 |
-# include <sys/param.h>
|
|
|
5bfd05 |
# define USE_SYSLOG
|
|
|
5bfd05 |
# ifndef DEFAULT_VCTERM
|
|
|
5bfd05 |
# define DEFAULT_VCTERM "linux"
|
|
|
5bfd05 |
# endif
|
|
|
5bfd05 |
+# if defined (__s390__) || defined (__s390x__)
|
|
|
5bfd05 |
+# define DEFAULT_TTYS0 "dumb"
|
|
|
5bfd05 |
+# define DEFAULT_TTY32 "ibm327x"
|
|
|
5bfd05 |
+# define DEFAULT_TTYS1 "vt220"
|
|
|
5bfd05 |
+# endif
|
|
|
5bfd05 |
# ifndef DEFAULT_STERM
|
|
|
5bfd05 |
# define DEFAULT_STERM "vt102"
|
|
|
5bfd05 |
# endif
|
|
|
5bfd05 |
@@ -69,6 +95,10 @@
|
|
|
5bfd05 |
# endif
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+#ifdef __FreeBSD_kernel__
|
|
|
5bfd05 |
+#define USE_SYSLOG
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
/* If USE_SYSLOG is undefined all diagnostics go to /dev/console. */
|
|
|
5bfd05 |
#ifdef USE_SYSLOG
|
|
|
5bfd05 |
# include <syslog.h>
|
|
|
5bfd05 |
@@ -86,9 +116,9 @@
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
* Things you may want to modify.
|
|
|
5bfd05 |
*
|
|
|
5bfd05 |
- * If ISSUE is not defined, agetty will never display the contents of the
|
|
|
5bfd05 |
- * /etc/issue file. You will not want to spit out large "issue" files at the
|
|
|
5bfd05 |
- * wrong baud rate. Relevant for System V only.
|
|
|
5bfd05 |
+ * If ISSUE_SUPPORT is not defined, agetty will never display the contents of
|
|
|
5bfd05 |
+ * the /etc/issue file. You will not want to spit out large "issue" files at
|
|
|
5bfd05 |
+ * the wrong baud rate. Relevant for System V only.
|
|
|
5bfd05 |
*
|
|
|
5bfd05 |
* You may disagree with the default line-editing etc. characters defined
|
|
|
5bfd05 |
* below. Note, however, that DEL cannot be used for interrupt generation
|
|
|
5bfd05 |
@@ -97,14 +127,26 @@
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Displayed before the login prompt. */
|
|
|
5bfd05 |
#ifdef SYSV_STYLE
|
|
|
5bfd05 |
-# define ISSUE _PATH_ISSUE
|
|
|
5bfd05 |
-# include <sys/utsname.h>
|
|
|
5bfd05 |
+# define ISSUE_SUPPORT
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Login prompt. */
|
|
|
5bfd05 |
#define LOGIN "login: "
|
|
|
5bfd05 |
#define LOGIN_ARGV_MAX 16 /* Numbers of args for login */
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+/*
|
|
|
5bfd05 |
+ * agetty --reload
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+# include <sys/inotify.h>
|
|
|
5bfd05 |
+# include <linux/netlink.h>
|
|
|
5bfd05 |
+# include <linux/rtnetlink.h>
|
|
|
5bfd05 |
+# define AGETTY_RELOAD_FILENAME "/run/agetty.reload" /* trigger file */
|
|
|
5bfd05 |
+# define AGETTY_RELOAD_FDNONE -2 /* uninitialized fd */
|
|
|
5bfd05 |
+static int inotify_fd = AGETTY_RELOAD_FDNONE;
|
|
|
5bfd05 |
+static int netlink_fd = AGETTY_RELOAD_FDNONE;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
* When multiple baud rates are specified on the command line, the first one
|
|
|
5bfd05 |
* we will try is the first one specified.
|
|
|
5bfd05 |
@@ -116,7 +158,7 @@
|
|
|
5bfd05 |
|
|
|
5bfd05 |
struct options {
|
|
|
5bfd05 |
int flags; /* toggle switches, see below */
|
|
|
5bfd05 |
- int timeout; /* time-out period */
|
|
|
5bfd05 |
+ unsigned int timeout; /* time-out period */
|
|
|
5bfd05 |
char *autolog; /* login the user automatically */
|
|
|
5bfd05 |
char *chdir; /* Chdir before the login */
|
|
|
5bfd05 |
char *chroot; /* Chroot before the login */
|
|
|
5bfd05 |
@@ -126,11 +168,11 @@ struct options {
|
|
|
5bfd05 |
char *vcline; /* line of virtual console */
|
|
|
5bfd05 |
char *term; /* terminal type */
|
|
|
5bfd05 |
char *initstring; /* modem init string */
|
|
|
5bfd05 |
- char *issue; /* alternative issue file */
|
|
|
5bfd05 |
+ char *issue; /* alternative issue file or directory */
|
|
|
5bfd05 |
char *erasechars; /* string with erase chars */
|
|
|
5bfd05 |
char *killchars; /* string with kill chars */
|
|
|
5bfd05 |
char *osrelease; /* /etc/os-release data */
|
|
|
5bfd05 |
- int delay; /* Sleep seconds before prompt */
|
|
|
5bfd05 |
+ unsigned int delay; /* Sleep seconds before prompt */
|
|
|
5bfd05 |
int nice; /* Run login with this priority */
|
|
|
5bfd05 |
int numspeed; /* number of baud rates to try */
|
|
|
5bfd05 |
int clocal; /* CLOCAL_MODE_* */
|
|
|
5bfd05 |
@@ -145,12 +187,12 @@ enum {
|
|
|
5bfd05 |
};
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#define F_PARSE (1<<0) /* process modem status messages */
|
|
|
5bfd05 |
-#define F_ISSUE (1<<1) /* display /etc/issue */
|
|
|
5bfd05 |
+#define F_ISSUE (1<<1) /* display /etc/issue or /etc/issue.d */
|
|
|
5bfd05 |
#define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#define F_INITSTRING (1<<4) /* initstring is set */
|
|
|
5bfd05 |
#define F_WAITCRLF (1<<5) /* wait for CR or LF */
|
|
|
5bfd05 |
-#define F_CUSTISSUE (1<<6) /* give alternative issue file */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
#define F_NOPROMPT (1<<7) /* do not ask for login name! */
|
|
|
5bfd05 |
#define F_LCUC (1<<8) /* support for *LCUC stty modes */
|
|
|
5bfd05 |
#define F_KEEPSPEED (1<<9) /* follow baud rate from kernel */
|
|
|
5bfd05 |
@@ -189,16 +231,14 @@ static const struct Speedtab speedtab[] = {
|
|
|
5bfd05 |
{2400, B2400},
|
|
|
5bfd05 |
{4800, B4800},
|
|
|
5bfd05 |
{9600, B9600},
|
|
|
5bfd05 |
-#ifdef B19200
|
|
|
5bfd05 |
+#ifdef B19200
|
|
|
5bfd05 |
{19200, B19200},
|
|
|
5bfd05 |
-#endif
|
|
|
5bfd05 |
-#ifdef B38400
|
|
|
5bfd05 |
- {38400, B38400},
|
|
|
5bfd05 |
-#endif
|
|
|
5bfd05 |
-#ifdef EXTA
|
|
|
5bfd05 |
+#elif defined(EXTA)
|
|
|
5bfd05 |
{19200, EXTA},
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
-#ifdef EXTB
|
|
|
5bfd05 |
+#ifdef B38400
|
|
|
5bfd05 |
+ {38400, B38400},
|
|
|
5bfd05 |
+#elif defined(EXTB)
|
|
|
5bfd05 |
{38400, EXTB},
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
#ifdef B57600
|
|
|
5bfd05 |
@@ -209,6 +249,42 @@ static const struct Speedtab speedtab[] = {
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
#ifdef B230400
|
|
|
5bfd05 |
{230400, B230400},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B460800
|
|
|
5bfd05 |
+ {460800, B460800},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B500000
|
|
|
5bfd05 |
+ {500000, B500000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B576000
|
|
|
5bfd05 |
+ {576000, B576000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B921600
|
|
|
5bfd05 |
+ {921600, B921600},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B1000000
|
|
|
5bfd05 |
+ {1000000, B1000000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B1152000
|
|
|
5bfd05 |
+ {1152000, B1152000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B1500000
|
|
|
5bfd05 |
+ {1500000, B1500000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B2000000
|
|
|
5bfd05 |
+ {2000000, B2000000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B2500000
|
|
|
5bfd05 |
+ {2500000, B2500000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B3000000
|
|
|
5bfd05 |
+ {3000000, B3000000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B3500000
|
|
|
5bfd05 |
+ {3500000, B3500000},
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef B4000000
|
|
|
5bfd05 |
+ {4000000, B4000000},
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
{0, 0},
|
|
|
5bfd05 |
};
|
|
|
5bfd05 |
@@ -221,6 +297,7 @@ static void open_tty(char *tty, struct termios *tp, struct options *op);
|
|
|
5bfd05 |
static void termio_init(struct options *op, struct termios *tp);
|
|
|
5bfd05 |
static void reset_vc (const struct options *op, struct termios *tp);
|
|
|
5bfd05 |
static void auto_baud(struct termios *tp);
|
|
|
5bfd05 |
+static void list_speeds(void);
|
|
|
5bfd05 |
static void output_special_char (unsigned char c, struct options *op,
|
|
|
5bfd05 |
struct termios *tp, FILE *fp);
|
|
|
5bfd05 |
static void do_prompt(struct options *op, struct termios *tp);
|
|
|
5bfd05 |
@@ -231,7 +308,8 @@ static void termio_final(struct options *op,
|
|
|
5bfd05 |
struct termios *tp, struct chardata *cp);
|
|
|
5bfd05 |
static int caps_lock(char *s);
|
|
|
5bfd05 |
static speed_t bcode(char *s);
|
|
|
5bfd05 |
-static void usage(FILE * out) __attribute__((__noreturn__));
|
|
|
5bfd05 |
+static void usage(void) __attribute__((__noreturn__));
|
|
|
5bfd05 |
+static void exit_slowly(int code) __attribute__((__noreturn__));
|
|
|
5bfd05 |
static void log_err(const char *, ...) __attribute__((__noreturn__))
|
|
|
5bfd05 |
__attribute__((__format__(printf, 1, 2)));
|
|
|
5bfd05 |
static void log_warn (const char *, ...)
|
|
|
5bfd05 |
@@ -239,13 +317,16 @@ static void log_warn (const char *, ...)
|
|
|
5bfd05 |
static ssize_t append(char *dest, size_t len, const char *sep, const char *src);
|
|
|
5bfd05 |
static void check_username (const char* nm);
|
|
|
5bfd05 |
static void login_options_to_argv(char *argv[], int *argc, char *str, char *username);
|
|
|
5bfd05 |
+static void reload_agettys(void);
|
|
|
5bfd05 |
+static void print_issue_file(struct options *op, struct termios *tp);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Fake hostname for ut_host specified on command line. */
|
|
|
5bfd05 |
static char *fakehost;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#ifdef DEBUGGING
|
|
|
5bfd05 |
+# include "closestream.h"
|
|
|
5bfd05 |
# ifndef DEBUG_OUTPUT
|
|
|
5bfd05 |
-# define DEBUG_OUTPUT "/dev/ttyp0"
|
|
|
5bfd05 |
+# define DEBUG_OUTPUT "/dev/tty10"
|
|
|
5bfd05 |
# endif
|
|
|
5bfd05 |
# define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0)
|
|
|
5bfd05 |
FILE *dbf;
|
|
|
5bfd05 |
@@ -261,8 +342,7 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
struct options options = {
|
|
|
5bfd05 |
.flags = F_ISSUE, /* show /etc/issue (SYSV_STYLE) */
|
|
|
5bfd05 |
.login = _PATH_LOGIN, /* default login program */
|
|
|
5bfd05 |
- .tty = "tty1", /* default tty line */
|
|
|
5bfd05 |
- .issue = ISSUE /* default issue file */
|
|
|
5bfd05 |
+ .tty = "tty1" /* default tty line */
|
|
|
5bfd05 |
};
|
|
|
5bfd05 |
char *login_argv[LOGIN_ARGV_MAX + 1];
|
|
|
5bfd05 |
int login_argc = 0;
|
|
|
5bfd05 |
@@ -283,8 +363,12 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#ifdef DEBUGGING
|
|
|
5bfd05 |
dbf = fopen(DEBUG_OUTPUT, "w");
|
|
|
5bfd05 |
- for (int i = 1; i < argc; i++)
|
|
|
5bfd05 |
+ for (int i = 1; i < argc; i++) {
|
|
|
5bfd05 |
+ if (i > 1)
|
|
|
5bfd05 |
+ debug(" ");
|
|
|
5bfd05 |
debug(argv[i]);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ debug("\n");
|
|
|
5bfd05 |
#endif /* DEBUGGING */
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Parse command-line arguments. */
|
|
|
5bfd05 |
@@ -311,6 +395,13 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
sigaction(SIGHUP, &sa_hup, NULL);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
tcsetpgrp(STDIN_FILENO, getpid());
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* Default is to follow the current line speed and then default to 9600 */
|
|
|
5bfd05 |
+ if ((options.flags & F_VCONSOLE) == 0 && options.numspeed == 0) {
|
|
|
5bfd05 |
+ options.speeds[options.numspeed++] = bcode("9600");
|
|
|
5bfd05 |
+ options.flags |= F_KEEPSPEED;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
/* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
|
|
|
5bfd05 |
debug("calling termio_init\n");
|
|
|
5bfd05 |
termio_init(&options, &termios);
|
|
|
5bfd05 |
@@ -337,7 +428,7 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Set the optional timer. */
|
|
|
5bfd05 |
if (options.timeout)
|
|
|
5bfd05 |
- alarm((unsigned) options.timeout);
|
|
|
5bfd05 |
+ alarm(options.timeout);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Optionally wait for CR or LF before writing /etc/issue */
|
|
|
5bfd05 |
if (serial_tty_option(&options, F_WAITCRLF)) {
|
|
|
5bfd05 |
@@ -362,7 +453,9 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
username = options.autolog;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if ((options.flags & F_NOPROMPT) == 0) {
|
|
|
5bfd05 |
+ if (options.flags & F_NOPROMPT) { /* --skip-login */
|
|
|
5bfd05 |
+ print_issue_file(&options, &termios);
|
|
|
5bfd05 |
+ } else { /* regular (auto)login */
|
|
|
5bfd05 |
if (options.autolog) {
|
|
|
5bfd05 |
/* Autologin prompt */
|
|
|
5bfd05 |
do_prompt(&options, &termios);
|
|
|
5bfd05 |
@@ -372,7 +465,7 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
debug("reading login name\n");
|
|
|
5bfd05 |
while ((username =
|
|
|
5bfd05 |
get_logname(&options, &termios, &chardata)) == NULL)
|
|
|
5bfd05 |
- if ((options.flags & F_VCONSOLE) == 0)
|
|
|
5bfd05 |
+ if ((options.flags & F_VCONSOLE) == 0 && options.numspeed)
|
|
|
5bfd05 |
next_speed(&options, &termios);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
@@ -403,9 +496,12 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
login_options_to_argv(login_argv, &login_argc,
|
|
|
5bfd05 |
options.logopt, username);
|
|
|
5bfd05 |
} else {
|
|
|
5bfd05 |
- if (fakehost && (options.flags & F_REMOTE)) {
|
|
|
5bfd05 |
- login_argv[login_argc++] = "-h";
|
|
|
5bfd05 |
- login_argv[login_argc++] = fakehost;
|
|
|
5bfd05 |
+ if (options.flags & F_REMOTE) {
|
|
|
5bfd05 |
+ if (fakehost) {
|
|
|
5bfd05 |
+ login_argv[login_argc++] = "-h";
|
|
|
5bfd05 |
+ login_argv[login_argc++] = fakehost;
|
|
|
5bfd05 |
+ } else if (options.flags & F_NOHOSTNAME)
|
|
|
5bfd05 |
+ login_argv[login_argc++] = "-H";
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
if (username) {
|
|
|
5bfd05 |
if (options.autolog)
|
|
|
5bfd05 |
@@ -418,25 +514,18 @@ int main(int argc, char **argv)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
login_argv[login_argc] = NULL; /* last login argv */
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (options.chroot) {
|
|
|
5bfd05 |
- if (chroot(options.chroot) < 0)
|
|
|
5bfd05 |
- log_err(_("%s: can't change root directory %s: %m"),
|
|
|
5bfd05 |
- options.tty, options.chroot);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- if (options.chdir) {
|
|
|
5bfd05 |
- if (chdir(options.chdir) < 0)
|
|
|
5bfd05 |
- log_err(_("%s: can't change working directory %s: %m"),
|
|
|
5bfd05 |
- options.tty, options.chdir);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- if (options.nice) {
|
|
|
5bfd05 |
- if (nice(options.nice) < 0)
|
|
|
5bfd05 |
- log_warn(_("%s: can't change process priority: %m"),
|
|
|
5bfd05 |
- options.tty);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- if (options.osrelease)
|
|
|
5bfd05 |
- free(options.osrelease);
|
|
|
5bfd05 |
+ if (options.chroot && chroot(options.chroot) < 0)
|
|
|
5bfd05 |
+ log_err(_("%s: can't change root directory %s: %m"),
|
|
|
5bfd05 |
+ options.tty, options.chroot);
|
|
|
5bfd05 |
+ if (options.chdir && chdir(options.chdir) < 0)
|
|
|
5bfd05 |
+ log_err(_("%s: can't change working directory %s: %m"),
|
|
|
5bfd05 |
+ options.tty, options.chdir);
|
|
|
5bfd05 |
+ if (options.nice && nice(options.nice) < 0)
|
|
|
5bfd05 |
+ log_warn(_("%s: can't change process priority: %m"),
|
|
|
5bfd05 |
+ options.tty);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ free(options.osrelease);
|
|
|
5bfd05 |
#ifdef DEBUGGING
|
|
|
5bfd05 |
- fprintf(dbf, "read %c\n", ch);
|
|
|
5bfd05 |
if (close_stream(dbf) != 0)
|
|
|
5bfd05 |
log_err("write failed: %s", DEBUG_OUTPUT);
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
@@ -477,7 +566,7 @@ static char *replace_u(char *str, char *username)
|
|
|
5bfd05 |
log_err(_("failed to allocate memory: %m"));
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if (p != str) {
|
|
|
5bfd05 |
- /* copy chars befor \u */
|
|
|
5bfd05 |
+ /* copy chars before \u */
|
|
|
5bfd05 |
memcpy(tp, str, p - str);
|
|
|
5bfd05 |
tp += p - str;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
@@ -527,6 +616,55 @@ static void login_options_to_argv(char *argv[], int *argc,
|
|
|
5bfd05 |
*argc = i;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+static void output_version(void)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ static const char *features[] = {
|
|
|
5bfd05 |
+#ifdef DEBUGGING
|
|
|
5bfd05 |
+ "debug",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef CRTSCTS
|
|
|
5bfd05 |
+ "flow control",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef KDGKBLED
|
|
|
5bfd05 |
+ "hints",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef ISSUE_SUPPORT
|
|
|
5bfd05 |
+ "issue",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
+ "issue.d",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef KDGKBMODE
|
|
|
5bfd05 |
+ "keyboard mode",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef USE_PLYMOUTH_SUPPORT
|
|
|
5bfd05 |
+ "plymouth",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+ "reload",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef USE_SYSLOG
|
|
|
5bfd05 |
+ "syslog",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+#ifdef HAVE_WIDECHAR
|
|
|
5bfd05 |
+ "widechar",
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+ NULL
|
|
|
5bfd05 |
+ };
|
|
|
5bfd05 |
+ unsigned int i;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ printf( _("%s from %s"), program_invocation_short_name, PACKAGE_STRING);
|
|
|
5bfd05 |
+ fputs(" (", stdout);
|
|
|
5bfd05 |
+ for (i = 0; features[i]; i++) {
|
|
|
5bfd05 |
+ if (0 < i)
|
|
|
5bfd05 |
+ fputs(", ", stdout);
|
|
|
5bfd05 |
+ printf("%s", features[i]);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ fputs(")\n", stdout);
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#define is_speed(str) (strlen((str)) == strspn((str), "0123456789,"))
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
/* Parse command-line arguments. */
|
|
|
5bfd05 |
static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
@@ -540,46 +678,50 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
HELP_OPTION,
|
|
|
5bfd05 |
ERASE_CHARS_OPTION,
|
|
|
5bfd05 |
KILL_CHARS_OPTION,
|
|
|
5bfd05 |
+ RELOAD_OPTION,
|
|
|
5bfd05 |
+ LIST_SPEEDS_OPTION,
|
|
|
5bfd05 |
};
|
|
|
5bfd05 |
const struct option longopts[] = {
|
|
|
5bfd05 |
- { "8bits", no_argument, 0, '8' },
|
|
|
5bfd05 |
- { "autologin", required_argument, 0, 'a' },
|
|
|
5bfd05 |
- { "noreset", no_argument, 0, 'c' },
|
|
|
5bfd05 |
- { "chdir", required_argument, 0, 'C' },
|
|
|
5bfd05 |
- { "delay", required_argument, 0, 'd' },
|
|
|
5bfd05 |
- { "remote", no_argument, 0, 'E' },
|
|
|
5bfd05 |
- { "issue-file", required_argument, 0, 'f' },
|
|
|
5bfd05 |
- { "flow-control", no_argument, 0, 'h' },
|
|
|
5bfd05 |
- { "host", required_argument, 0, 'H' },
|
|
|
5bfd05 |
- { "noissue", no_argument, 0, 'i' },
|
|
|
5bfd05 |
- { "init-string", required_argument, 0, 'I' },
|
|
|
5bfd05 |
- { "noclear", no_argument, 0, 'J' },
|
|
|
5bfd05 |
- { "login-program", required_argument, 0, 'l' },
|
|
|
5bfd05 |
- { "local-line", optional_argument, 0, 'L' },
|
|
|
5bfd05 |
- { "extract-baud", no_argument, 0, 'm' },
|
|
|
5bfd05 |
- { "skip-login", no_argument, 0, 'n' },
|
|
|
5bfd05 |
- { "nonewline", no_argument, 0, 'N' },
|
|
|
5bfd05 |
- { "login-options", required_argument, 0, 'o' },
|
|
|
5bfd05 |
- { "login-pause", no_argument, 0, 'p' },
|
|
|
5bfd05 |
- { "nice", required_argument, 0, 'P' },
|
|
|
5bfd05 |
- { "chroot", required_argument, 0, 'r' },
|
|
|
5bfd05 |
- { "hangup", no_argument, 0, 'R' },
|
|
|
5bfd05 |
- { "keep-baud", no_argument, 0, 's' },
|
|
|
5bfd05 |
- { "timeout", required_argument, 0, 't' },
|
|
|
5bfd05 |
- { "detect-case", no_argument, 0, 'U' },
|
|
|
5bfd05 |
- { "wait-cr", no_argument, 0, 'w' },
|
|
|
5bfd05 |
- { "nohints", no_argument, 0, NOHINTS_OPTION },
|
|
|
5bfd05 |
- { "nohostname", no_argument, 0, NOHOSTNAME_OPTION },
|
|
|
5bfd05 |
- { "long-hostname", no_argument, 0, LONGHOSTNAME_OPTION },
|
|
|
5bfd05 |
- { "version", no_argument, 0, VERSION_OPTION },
|
|
|
5bfd05 |
- { "help", no_argument, 0, HELP_OPTION },
|
|
|
5bfd05 |
- { "erase-chars", required_argument, 0, ERASE_CHARS_OPTION },
|
|
|
5bfd05 |
- { "kill-chars", required_argument, 0, KILL_CHARS_OPTION },
|
|
|
5bfd05 |
- { NULL, 0, 0, 0 }
|
|
|
5bfd05 |
+ { "8bits", no_argument, NULL, '8' },
|
|
|
5bfd05 |
+ { "autologin", required_argument, NULL, 'a' },
|
|
|
5bfd05 |
+ { "noreset", no_argument, NULL, 'c' },
|
|
|
5bfd05 |
+ { "chdir", required_argument, NULL, 'C' },
|
|
|
5bfd05 |
+ { "delay", required_argument, NULL, 'd' },
|
|
|
5bfd05 |
+ { "remote", no_argument, NULL, 'E' },
|
|
|
5bfd05 |
+ { "issue-file", required_argument, NULL, 'f' },
|
|
|
5bfd05 |
+ { "flow-control", no_argument, NULL, 'h' },
|
|
|
5bfd05 |
+ { "host", required_argument, NULL, 'H' },
|
|
|
5bfd05 |
+ { "noissue", no_argument, NULL, 'i' },
|
|
|
5bfd05 |
+ { "init-string", required_argument, NULL, 'I' },
|
|
|
5bfd05 |
+ { "noclear", no_argument, NULL, 'J' },
|
|
|
5bfd05 |
+ { "login-program", required_argument, NULL, 'l' },
|
|
|
5bfd05 |
+ { "local-line", optional_argument, NULL, 'L' },
|
|
|
5bfd05 |
+ { "extract-baud", no_argument, NULL, 'm' },
|
|
|
5bfd05 |
+ { "list-speeds", no_argument, NULL, LIST_SPEEDS_OPTION },
|
|
|
5bfd05 |
+ { "skip-login", no_argument, NULL, 'n' },
|
|
|
5bfd05 |
+ { "nonewline", no_argument, NULL, 'N' },
|
|
|
5bfd05 |
+ { "login-options", required_argument, NULL, 'o' },
|
|
|
5bfd05 |
+ { "login-pause", no_argument, NULL, 'p' },
|
|
|
5bfd05 |
+ { "nice", required_argument, NULL, 'P' },
|
|
|
5bfd05 |
+ { "chroot", required_argument, NULL, 'r' },
|
|
|
5bfd05 |
+ { "hangup", no_argument, NULL, 'R' },
|
|
|
5bfd05 |
+ { "keep-baud", no_argument, NULL, 's' },
|
|
|
5bfd05 |
+ { "timeout", required_argument, NULL, 't' },
|
|
|
5bfd05 |
+ { "detect-case", no_argument, NULL, 'U' },
|
|
|
5bfd05 |
+ { "wait-cr", no_argument, NULL, 'w' },
|
|
|
5bfd05 |
+ { "nohints", no_argument, NULL, NOHINTS_OPTION },
|
|
|
5bfd05 |
+ { "nohostname", no_argument, NULL, NOHOSTNAME_OPTION },
|
|
|
5bfd05 |
+ { "long-hostname", no_argument, NULL, LONGHOSTNAME_OPTION },
|
|
|
5bfd05 |
+ { "reload", no_argument, NULL, RELOAD_OPTION },
|
|
|
5bfd05 |
+ { "version", no_argument, NULL, VERSION_OPTION },
|
|
|
5bfd05 |
+ { "help", no_argument, NULL, HELP_OPTION },
|
|
|
5bfd05 |
+ { "erase-chars", required_argument, NULL, ERASE_CHARS_OPTION },
|
|
|
5bfd05 |
+ { "kill-chars", required_argument, NULL, KILL_CHARS_OPTION },
|
|
|
5bfd05 |
+ { NULL, 0, NULL, 0 }
|
|
|
5bfd05 |
};
|
|
|
5bfd05 |
|
|
|
5bfd05 |
while ((c = getopt_long(argc, argv,
|
|
|
5bfd05 |
- "8a:cC:d:Ef:hH:iI:Jl:LmnNo:pP:r:Rst:Uw", longopts,
|
|
|
5bfd05 |
+ "8a:cC:d:Ef:hH:iI:Jl:L::mnNo:pP:r:Rst:Uw", longopts,
|
|
|
5bfd05 |
NULL)) != -1) {
|
|
|
5bfd05 |
switch (c) {
|
|
|
5bfd05 |
case '8':
|
|
|
5bfd05 |
@@ -595,13 +737,12 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
op->chdir = optarg;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'd':
|
|
|
5bfd05 |
- op->delay = atoi(optarg);
|
|
|
5bfd05 |
+ op->delay = strtou32_or_err(optarg, _("invalid delay argument"));
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'E':
|
|
|
5bfd05 |
op->flags |= F_REMOTE;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'f':
|
|
|
5bfd05 |
- op->flags |= F_CUSTISSUE;
|
|
|
5bfd05 |
op->issue = optarg;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'h':
|
|
|
5bfd05 |
@@ -634,7 +775,7 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
else if (strcmp(optarg, "=auto") == 0)
|
|
|
5bfd05 |
op->clocal = CLOCAL_MODE_AUTO;
|
|
|
5bfd05 |
else
|
|
|
5bfd05 |
- log_err(_("unssuported --local-line mode argument"));
|
|
|
5bfd05 |
+ log_err(_("invalid argument of --local-line"));
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'm':
|
|
|
5bfd05 |
@@ -643,6 +784,9 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
case 'n':
|
|
|
5bfd05 |
op->flags |= F_NOPROMPT;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
+ case 'N':
|
|
|
5bfd05 |
+ op->flags |= F_NONL;
|
|
|
5bfd05 |
+ break;
|
|
|
5bfd05 |
case 'o':
|
|
|
5bfd05 |
op->logopt = optarg;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
@@ -650,7 +794,7 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
op->flags |= F_LOGINPAUSE;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'P':
|
|
|
5bfd05 |
- op->nice = atoi(optarg);
|
|
|
5bfd05 |
+ op->nice = strtos32_or_err(optarg, _("invalid nice argument"));
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'r':
|
|
|
5bfd05 |
op->chroot = optarg;
|
|
|
5bfd05 |
@@ -662,8 +806,7 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
op->flags |= F_KEEPSPEED;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 't':
|
|
|
5bfd05 |
- if ((op->timeout = atoi(optarg)) <= 0)
|
|
|
5bfd05 |
- log_err(_("bad timeout value: %s"), optarg);
|
|
|
5bfd05 |
+ op->timeout = strtou32_or_err(optarg, _("invalid timeout argument"));
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'U':
|
|
|
5bfd05 |
op->flags |= F_LCUC;
|
|
|
5bfd05 |
@@ -686,14 +829,19 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
case KILL_CHARS_OPTION:
|
|
|
5bfd05 |
op->killchars = optarg;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
+ case RELOAD_OPTION:
|
|
|
5bfd05 |
+ reload_agettys();
|
|
|
5bfd05 |
+ exit(EXIT_SUCCESS);
|
|
|
5bfd05 |
+ case LIST_SPEEDS_OPTION:
|
|
|
5bfd05 |
+ list_speeds();
|
|
|
5bfd05 |
+ exit(EXIT_SUCCESS);
|
|
|
5bfd05 |
case VERSION_OPTION:
|
|
|
5bfd05 |
- printf(_("%s from %s\n"), program_invocation_short_name,
|
|
|
5bfd05 |
- PACKAGE_STRING);
|
|
|
5bfd05 |
+ output_version();
|
|
|
5bfd05 |
exit(EXIT_SUCCESS);
|
|
|
5bfd05 |
case HELP_OPTION:
|
|
|
5bfd05 |
- usage(stdout);
|
|
|
5bfd05 |
+ usage();
|
|
|
5bfd05 |
default:
|
|
|
5bfd05 |
- usage(stderr);
|
|
|
5bfd05 |
+ errtryhelp(EXIT_FAILURE);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
@@ -701,26 +849,26 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if (argc < optind + 1) {
|
|
|
5bfd05 |
log_warn(_("not enough arguments"));
|
|
|
5bfd05 |
- usage(stderr);
|
|
|
5bfd05 |
+ errx(EXIT_FAILURE, _("not enough arguments"));
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Accept "tty", "baudrate tty", and "tty baudrate". */
|
|
|
5bfd05 |
- if ('0' <= argv[optind][0] && argv[optind][0] <= '9') {
|
|
|
5bfd05 |
+ if (is_speed(argv[optind])) {
|
|
|
5bfd05 |
/* Assume BSD style speed. */
|
|
|
5bfd05 |
parse_speeds(op, argv[optind++]);
|
|
|
5bfd05 |
if (argc < optind + 1) {
|
|
|
5bfd05 |
- warn(_("not enough arguments"));
|
|
|
5bfd05 |
- usage(stderr);
|
|
|
5bfd05 |
+ log_warn(_("not enough arguments"));
|
|
|
5bfd05 |
+ errx(EXIT_FAILURE, _("not enough arguments"));
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
op->tty = argv[optind++];
|
|
|
5bfd05 |
} else {
|
|
|
5bfd05 |
op->tty = argv[optind++];
|
|
|
5bfd05 |
if (argc > optind) {
|
|
|
5bfd05 |
- char *v = argv[optind++];
|
|
|
5bfd05 |
- if ('0' <= *v && *v <= '9')
|
|
|
5bfd05 |
+ char *v = argv[optind];
|
|
|
5bfd05 |
+ if (is_speed(v)) {
|
|
|
5bfd05 |
parse_speeds(op, v);
|
|
|
5bfd05 |
- else
|
|
|
5bfd05 |
- op->speeds[op->numspeed++] = bcode("9600");
|
|
|
5bfd05 |
+ optind++;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
@@ -732,45 +880,6 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
if (argc > optind && argv[optind])
|
|
|
5bfd05 |
op->term = argv[optind];
|
|
|
5bfd05 |
|
|
|
5bfd05 |
-#ifdef DO_DEVFS_FIDDLING
|
|
|
5bfd05 |
- /*
|
|
|
5bfd05 |
- * Some devfs junk, following Goswin Brederlow:
|
|
|
5bfd05 |
- * turn ttyS<n> into tts/<n>
|
|
|
5bfd05 |
- * turn tty<n> into vc/<n>
|
|
|
5bfd05 |
- * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=72241
|
|
|
5bfd05 |
- */
|
|
|
5bfd05 |
- if (op->tty && strlen(op->tty) < 90) {
|
|
|
5bfd05 |
- char dev_name[100];
|
|
|
5bfd05 |
- struct stat st;
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
- if (strncmp(op->tty, "ttyS", 4) == 0) {
|
|
|
5bfd05 |
- strcpy(dev_name, "/dev/");
|
|
|
5bfd05 |
- strcat(dev_name, op->tty);
|
|
|
5bfd05 |
- if (stat(dev_name, &st) < 0) {
|
|
|
5bfd05 |
- strcpy(dev_name, "/dev/tts/");
|
|
|
5bfd05 |
- strcat(dev_name, op->tty + 4);
|
|
|
5bfd05 |
- if (stat(dev_name, &st) == 0) {
|
|
|
5bfd05 |
- op->tty = strdup(dev_name + 5);
|
|
|
5bfd05 |
- if (!op->tty)
|
|
|
5bfd05 |
- log_err(_("failed to allocate memory: %m"));
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- } else if (strncmp(op->tty, "tty", 3) == 0) {
|
|
|
5bfd05 |
- strcpy(dev_name, "/dev/");
|
|
|
5bfd05 |
- strncat(dev_name, op->tty, 90);
|
|
|
5bfd05 |
- if (stat(dev_name, &st) < 0) {
|
|
|
5bfd05 |
- strcpy(dev_name, "/dev/vc/");
|
|
|
5bfd05 |
- strcat(dev_name, op->tty + 3);
|
|
|
5bfd05 |
- if (stat(dev_name, &st) == 0) {
|
|
|
5bfd05 |
- op->tty = strdup(dev_name + 5);
|
|
|
5bfd05 |
- if (!op->tty)
|
|
|
5bfd05 |
- log_err(_("failed to allocate memory: %m"));
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
-#endif /* DO_DEVFS_FIDDLING */
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
debug("exiting parseargs\n");
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
@@ -778,15 +887,20 @@ static void parse_args(int argc, char **argv, struct options *op)
|
|
|
5bfd05 |
static void parse_speeds(struct options *op, char *arg)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
char *cp;
|
|
|
5bfd05 |
+ char *str = strdup(arg);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (!str)
|
|
|
5bfd05 |
+ log_err(_("failed to allocate memory: %m"));
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- debug("entered parse_speeds\n");
|
|
|
5bfd05 |
- for (cp = strtok(arg, ","); cp != NULL; cp = strtok((char *)0, ",")) {
|
|
|
5bfd05 |
+ debug("entered parse_speeds:\n");
|
|
|
5bfd05 |
+ for (cp = strtok(str, ","); cp != NULL; cp = strtok((char *)0, ",")) {
|
|
|
5bfd05 |
if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
|
|
|
5bfd05 |
log_err(_("bad speed: %s"), cp);
|
|
|
5bfd05 |
if (op->numspeed >= MAX_SPEED)
|
|
|
5bfd05 |
log_err(_("too many alternate speeds"));
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
debug("exiting parsespeeds\n");
|
|
|
5bfd05 |
+ free(str);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#ifdef SYSV_STYLE
|
|
|
5bfd05 |
@@ -794,13 +908,13 @@ static void parse_speeds(struct options *op, char *arg)
|
|
|
5bfd05 |
/* Update our utmp entry. */
|
|
|
5bfd05 |
static void update_utmp(struct options *op)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
- struct utmp ut;
|
|
|
5bfd05 |
+ struct utmpx ut;
|
|
|
5bfd05 |
time_t t;
|
|
|
5bfd05 |
pid_t pid = getpid();
|
|
|
5bfd05 |
pid_t sid = getsid(0);
|
|
|
5bfd05 |
char *vcline = op->vcline;
|
|
|
5bfd05 |
char *line = op->tty;
|
|
|
5bfd05 |
- struct utmp *utp;
|
|
|
5bfd05 |
+ struct utmpx *utp;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
* The utmp file holds miscellaneous information about things started by
|
|
|
5bfd05 |
@@ -810,8 +924,8 @@ static void update_utmp(struct options *op)
|
|
|
5bfd05 |
* utmp file can be opened for update, and if we are able to find our
|
|
|
5bfd05 |
* entry in the utmp file.
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
- utmpname(_PATH_UTMP);
|
|
|
5bfd05 |
- setutent();
|
|
|
5bfd05 |
+ utmpxname(_PATH_UTMP);
|
|
|
5bfd05 |
+ setutxent();
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
* Find my pid in utmp.
|
|
|
5bfd05 |
@@ -822,7 +936,7 @@ static void update_utmp(struct options *op)
|
|
|
5bfd05 |
* FIXME: The present code is taken from login.c, so if this is changed,
|
|
|
5bfd05 |
* maybe login has to be changed as well (is this true?).
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
- while ((utp = getutent()))
|
|
|
5bfd05 |
+ while ((utp = getutxent()))
|
|
|
5bfd05 |
if (utp->ut_pid == pid
|
|
|
5bfd05 |
&& utp->ut_type >= INIT_PROCESS
|
|
|
5bfd05 |
&& utp->ut_type <= DEAD_PROCESS)
|
|
|
5bfd05 |
@@ -852,33 +966,15 @@ static void update_utmp(struct options *op)
|
|
|
5bfd05 |
if (fakehost)
|
|
|
5bfd05 |
strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host));
|
|
|
5bfd05 |
time(&t);
|
|
|
5bfd05 |
- ut.ut_time = t;
|
|
|
5bfd05 |
+ ut.ut_tv.tv_sec = t;
|
|
|
5bfd05 |
ut.ut_type = LOGIN_PROCESS;
|
|
|
5bfd05 |
ut.ut_pid = pid;
|
|
|
5bfd05 |
ut.ut_session = sid;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- pututline(&ut);
|
|
|
5bfd05 |
- endutent();
|
|
|
5bfd05 |
+ pututxline(&ut);
|
|
|
5bfd05 |
+ endutxent();
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- {
|
|
|
5bfd05 |
-#ifdef HAVE_UPDWTMP
|
|
|
5bfd05 |
- updwtmp(_PATH_WTMP, &ut);
|
|
|
5bfd05 |
-#else
|
|
|
5bfd05 |
- int ut_fd;
|
|
|
5bfd05 |
- int lf;
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
- if ((lf = open(_PATH_WTMPLOCK, O_CREAT | O_WRONLY, 0660)) >= 0) {
|
|
|
5bfd05 |
- flock(lf, LOCK_EX);
|
|
|
5bfd05 |
- if ((ut_fd =
|
|
|
5bfd05 |
- open(_PATH_WTMP, O_APPEND | O_WRONLY)) >= 0) {
|
|
|
5bfd05 |
- write_all(ut_fd, &ut, sizeof(ut));
|
|
|
5bfd05 |
- close(ut_fd);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- flock(lf, LOCK_UN);
|
|
|
5bfd05 |
- close(lf);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
-#endif /* HAVE_UPDWTMP */
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
+ updwtmpx(_PATH_WTMP, &ut);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
#endif /* SYSV_STYLE */
|
|
|
5bfd05 |
@@ -888,6 +984,9 @@ static void open_tty(char *tty, struct termios *tp, struct options *op)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
const pid_t pid = getpid();
|
|
|
5bfd05 |
int closed = 0;
|
|
|
5bfd05 |
+#ifndef KDGKBMODE
|
|
|
5bfd05 |
+ int serial;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Set up new standard input, unless we are given an already opened port. */
|
|
|
5bfd05 |
|
|
|
5bfd05 |
@@ -903,8 +1002,12 @@ static void open_tty(char *tty, struct termios *tp, struct options *op)
|
|
|
5bfd05 |
if ((gr = getgrnam("tty")))
|
|
|
5bfd05 |
gid = gr->gr_gid;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (((len = snprintf(buf, sizeof(buf), "/dev/%s", tty)) >=
|
|
|
5bfd05 |
- (int)sizeof(buf)) || (len < 0))
|
|
|
5bfd05 |
+ len = snprintf(buf, sizeof(buf), "/dev/%s", tty);
|
|
|
5bfd05 |
+ if (len < 0 || (size_t)len >= sizeof(buf))
|
|
|
5bfd05 |
+ log_err(_("/dev/%s: cannot open as standard input: %m"), tty);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* Open the tty as standard input. */
|
|
|
5bfd05 |
+ if ((fd = open(buf, O_RDWR|O_NOCTTY|O_NONBLOCK, 0)) < 0)
|
|
|
5bfd05 |
log_err(_("/dev/%s: cannot open as standard input: %m"), tty);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
@@ -913,24 +1016,20 @@ static void open_tty(char *tty, struct termios *tp, struct options *op)
|
|
|
5bfd05 |
* Linux login(1) will change tty permissions. Use root owner and group
|
|
|
5bfd05 |
* with permission -rw------- for the period between getty and login.
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
- if (chown(buf, 0, gid) || chmod(buf, (gid ? 0620 : 0600))) {
|
|
|
5bfd05 |
+ if (fchown(fd, 0, gid) || fchmod(fd, (gid ? 0620 : 0600))) {
|
|
|
5bfd05 |
if (errno == EROFS)
|
|
|
5bfd05 |
log_warn("%s: %m", buf);
|
|
|
5bfd05 |
else
|
|
|
5bfd05 |
log_err("%s: %m", buf);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- /* Open the tty as standard input. */
|
|
|
5bfd05 |
- if ((fd = open(buf, O_RDWR|O_NOCTTY|O_NONBLOCK, 0)) < 0)
|
|
|
5bfd05 |
- log_err(_("/dev/%s: cannot open as standard input: %m"), tty);
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
/* Sanity checks... */
|
|
|
5bfd05 |
- if (!isatty(fd))
|
|
|
5bfd05 |
- log_err(_("/dev/%s: not a character device"), tty);
|
|
|
5bfd05 |
if (fstat(fd, &st) < 0)
|
|
|
5bfd05 |
log_err("%s: %m", buf);
|
|
|
5bfd05 |
if ((st.st_mode & S_IFMT) != S_IFCHR)
|
|
|
5bfd05 |
log_err(_("/dev/%s: not a character device"), tty);
|
|
|
5bfd05 |
+ if (!isatty(fd))
|
|
|
5bfd05 |
+ log_err(_("/dev/%s: not a tty"), tty);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if (((tid = tcgetsid(fd)) < 0) || (pid != tid)) {
|
|
|
5bfd05 |
if (ioctl(fd, TIOCSCTTY, 1) == -1)
|
|
|
5bfd05 |
@@ -946,7 +1045,7 @@ static void open_tty(char *tty, struct termios *tp, struct options *op)
|
|
|
5bfd05 |
debug("TIOCNOTTY ioctl failed\n");
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
- * Let's close all file decriptors before vhangup
|
|
|
5bfd05 |
+ * Let's close all file descriptors before vhangup
|
|
|
5bfd05 |
* https://lkml.org/lkml/2012/6/5/145
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
close(fd);
|
|
|
5bfd05 |
@@ -1015,22 +1114,66 @@ static void open_tty(char *tty, struct termios *tp, struct options *op)
|
|
|
5bfd05 |
if (tcgetattr(STDIN_FILENO, tp) < 0)
|
|
|
5bfd05 |
log_err(_("%s: failed to get terminal attributes: %m"), tty);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+#if defined (__s390__) || defined (__s390x__)
|
|
|
5bfd05 |
+ if (!op->term) {
|
|
|
5bfd05 |
+ /*
|
|
|
5bfd05 |
+ * Special terminal on first serial line on a S/390(x) which
|
|
|
5bfd05 |
+ * is due legacy reasons a block terminal of type 3270 or
|
|
|
5bfd05 |
+ * higher. Whereas the second serial line on a S/390(x) is
|
|
|
5bfd05 |
+ * a real character terminal which is compatible with VT220.
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+ if (strcmp(op->tty, "ttyS0") == 0) /* linux/drivers/s390/char/con3215.c */
|
|
|
5bfd05 |
+ op->term = DEFAULT_TTYS0;
|
|
|
5bfd05 |
+ else if (strncmp(op->tty, "3270/tty", 8) == 0) /* linux/drivers/s390/char/con3270.c */
|
|
|
5bfd05 |
+ op->term = DEFAULT_TTY32;
|
|
|
5bfd05 |
+ else if (strcmp(op->tty, "ttyS1") == 0) /* linux/drivers/s390/char/sclp_vt220.c */
|
|
|
5bfd05 |
+ op->term = DEFAULT_TTYS1;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#if defined(__FreeBSD_kernel__)
|
|
|
5bfd05 |
+ login_tty (0);
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
* Detect if this is a virtual console or serial/modem line.
|
|
|
5bfd05 |
* In case of a virtual console the ioctl KDGKBMODE succeeds
|
|
|
5bfd05 |
* whereas on other lines it will fails.
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
- if (ioctl(STDIN_FILENO, KDGKBMODE, &op->kbmode) == 0) {
|
|
|
5bfd05 |
+#ifdef KDGKBMODE
|
|
|
5bfd05 |
+ if (ioctl(STDIN_FILENO, KDGKBMODE, &op->kbmode) == 0)
|
|
|
5bfd05 |
+#else
|
|
|
5bfd05 |
+ if (ioctl(STDIN_FILENO, TIOCMGET, &serial) < 0 && (errno == EINVAL))
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+ {
|
|
|
5bfd05 |
op->flags |= F_VCONSOLE;
|
|
|
5bfd05 |
if (!op->term)
|
|
|
5bfd05 |
op->term = DEFAULT_VCTERM;
|
|
|
5bfd05 |
} else {
|
|
|
5bfd05 |
+#ifdef K_RAW
|
|
|
5bfd05 |
op->kbmode = K_RAW;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
if (!op->term)
|
|
|
5bfd05 |
op->term = DEFAULT_STERM;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- setenv("TERM", op->term, 1);
|
|
|
5bfd05 |
+ if (setenv("TERM", op->term, 1) != 0)
|
|
|
5bfd05 |
+ log_err(_("failed to set the %s environment variable"), "TERM");
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+/* Initialize termios settings. */
|
|
|
5bfd05 |
+static void termio_clear(int fd)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ /*
|
|
|
5bfd05 |
+ * Do not write a full reset (ESC c) because this destroys
|
|
|
5bfd05 |
+ * the unicode mode again if the terminal was in unicode
|
|
|
5bfd05 |
+ * mode. Also it clears the CONSOLE_MAGIC features which
|
|
|
5bfd05 |
+ * are required for some languages/console-fonts.
|
|
|
5bfd05 |
+ * Just put the cursor to the home position (ESC [ H),
|
|
|
5bfd05 |
+ * erase everything below the cursor (ESC [ J), and set the
|
|
|
5bfd05 |
+ * scrolling region to the full window (ESC [ r)
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+ write_all(fd, "\033[r\033[H\033[J", 9);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Initialize termios settings. */
|
|
|
5bfd05 |
@@ -1038,6 +1181,28 @@ static void termio_init(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
speed_t ispeed, ospeed;
|
|
|
5bfd05 |
struct winsize ws;
|
|
|
5bfd05 |
+#ifdef USE_PLYMOUTH_SUPPORT
|
|
|
5bfd05 |
+ struct termios lock;
|
|
|
5bfd05 |
+ int i = (plymouth_command(MAGIC_PING) == 0) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
|
|
|
5bfd05 |
+ if (i)
|
|
|
5bfd05 |
+ plymouth_command(MAGIC_QUIT);
|
|
|
5bfd05 |
+ while (i-- > 0) {
|
|
|
5bfd05 |
+ /*
|
|
|
5bfd05 |
+ * Even with TTYReset=no it seems with systemd or plymouth
|
|
|
5bfd05 |
+ * the termios flags become changed from under the first
|
|
|
5bfd05 |
+ * agetty on a serial system console as the flags are locked.
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+ memset(&lock, 0, sizeof(struct termios));
|
|
|
5bfd05 |
+ if (ioctl(STDIN_FILENO, TIOCGLCKTRMIOS, &lock) < 0)
|
|
|
5bfd05 |
+ break;
|
|
|
5bfd05 |
+ if (!lock.c_iflag && !lock.c_oflag && !lock.c_cflag && !lock.c_lflag)
|
|
|
5bfd05 |
+ break;
|
|
|
5bfd05 |
+ debug("termios locked\n");
|
|
|
5bfd05 |
+ sleep(1);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ memset(&lock, 0, sizeof(struct termios));
|
|
|
5bfd05 |
+ ioctl(STDIN_FILENO, TIOCSLCKTRMIOS, &lock);
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if (op->flags & F_VCONSOLE) {
|
|
|
5bfd05 |
#if defined(IUTF8) && defined(KDGKBMODE)
|
|
|
5bfd05 |
@@ -1063,22 +1228,16 @@ static void termio_init(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
if ((tp->c_cflag & (CS8|PARODD|PARENB)) == CS8)
|
|
|
5bfd05 |
op->flags |= F_EIGHTBITS;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if ((op->flags & F_NOCLEAR) == 0) {
|
|
|
5bfd05 |
- /*
|
|
|
5bfd05 |
- * Do not write a full reset (ESC c) because this destroys
|
|
|
5bfd05 |
- * the unicode mode again if the terminal was in unicode
|
|
|
5bfd05 |
- * mode. Also it clears the CONSOLE_MAGIC features which
|
|
|
5bfd05 |
- * are required for some languages/console-fonts.
|
|
|
5bfd05 |
- * Just put the cursor to the home position (ESC [ H),
|
|
|
5bfd05 |
- * erase everything below the cursor (ESC [ J), and set the
|
|
|
5bfd05 |
- * scrolling region to the full window (ESC [ r)
|
|
|
5bfd05 |
- */
|
|
|
5bfd05 |
- write_all(STDOUT_FILENO, "\033[r\033[H\033[J", 9);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
+ if ((op->flags & F_NOCLEAR) == 0)
|
|
|
5bfd05 |
+ termio_clear(STDOUT_FILENO);
|
|
|
5bfd05 |
return;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (op->flags & F_KEEPSPEED) {
|
|
|
5bfd05 |
+ /*
|
|
|
5bfd05 |
+ * Serial line
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (op->flags & F_KEEPSPEED || !op->numspeed) {
|
|
|
5bfd05 |
/* Save the original setting. */
|
|
|
5bfd05 |
ispeed = cfgetispeed(tp);
|
|
|
5bfd05 |
ospeed = cfgetospeed(tp);
|
|
|
5bfd05 |
@@ -1097,9 +1256,6 @@ static void termio_init(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
* later on.
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- /* Flush input and output queues, important for modems! */
|
|
|
5bfd05 |
- tcflush(STDIN_FILENO, TCIOFLUSH);
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
/* The defaul is set c_iflag in termio_final() according to chardata.
|
|
|
5bfd05 |
* Unfortunately, the chardata are not set according to the serial line
|
|
|
5bfd05 |
* if --autolog is enabled. In this case we do not read from the line
|
|
|
5bfd05 |
@@ -1124,7 +1280,7 @@ static void termio_init(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
* Note that the speed is stored in the c_cflag termios field, so we have
|
|
|
5bfd05 |
- * set the speed always when the cflag se reseted.
|
|
|
5bfd05 |
+ * set the speed always when the cflag is reset.
|
|
|
5bfd05 |
*/
|
|
|
5bfd05 |
cfsetispeed(tp, ispeed);
|
|
|
5bfd05 |
cfsetospeed(tp, ospeed);
|
|
|
5bfd05 |
@@ -1150,15 +1306,10 @@ static void termio_init(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Check for terminal size and if not found set default */
|
|
|
5bfd05 |
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) {
|
|
|
5bfd05 |
- int set = 0;
|
|
|
5bfd05 |
- if (ws.ws_row == 0) {
|
|
|
5bfd05 |
+ if (ws.ws_row == 0)
|
|
|
5bfd05 |
ws.ws_row = 24;
|
|
|
5bfd05 |
- set++;
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
- if (ws.ws_col == 0) {
|
|
|
5bfd05 |
+ if (ws.ws_col == 0)
|
|
|
5bfd05 |
ws.ws_col = 80;
|
|
|
5bfd05 |
- set++;
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
if (ioctl(STDIN_FILENO, TIOCSWINSZ, &ws))
|
|
|
5bfd05 |
debug("TIOCSWINSZ ioctl failed\n");
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
@@ -1168,8 +1319,11 @@ static void termio_init(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
if (op->flags & F_RTSCTS)
|
|
|
5bfd05 |
tp->c_cflag |= CRTSCTS;
|
|
|
5bfd05 |
#endif
|
|
|
5bfd05 |
+ /* Flush input and output queues, important for modems! */
|
|
|
5bfd05 |
+ tcflush(STDIN_FILENO, TCIOFLUSH);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- tcsetattr(STDIN_FILENO, TCSANOW, tp);
|
|
|
5bfd05 |
+ if (tcsetattr(STDIN_FILENO, TCSANOW, tp))
|
|
|
5bfd05 |
+ log_warn(_("setting terminal attributes failed: %m"));
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Go to blocking input even in local mode. */
|
|
|
5bfd05 |
fcntl(STDIN_FILENO, F_SETFL,
|
|
|
5bfd05 |
@@ -1190,6 +1344,10 @@ static void reset_vc(const struct options *op, struct termios *tp)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if (tcsetattr(STDIN_FILENO, TCSADRAIN, tp))
|
|
|
5bfd05 |
log_warn(_("setting terminal attributes failed: %m"));
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* Go to blocking input even in local mode. */
|
|
|
5bfd05 |
+ fcntl(STDIN_FILENO, F_SETFL,
|
|
|
5bfd05 |
+ fcntl(STDIN_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Extract baud rate from modem status message. */
|
|
|
5bfd05 |
@@ -1273,7 +1431,7 @@ static char *xgetdomainname(void)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
#ifdef HAVE_GETDOMAINNAME
|
|
|
5bfd05 |
char *name;
|
|
|
5bfd05 |
- size_t sz = get_hostname_max() + 1;
|
|
|
5bfd05 |
+ const size_t sz = get_hostname_max() + 1;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
name = malloc(sizeof(char) * sz);
|
|
|
5bfd05 |
if (!name)
|
|
|
5bfd05 |
@@ -1285,8 +1443,9 @@ static char *xgetdomainname(void)
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
name[sz - 1] = '\0';
|
|
|
5bfd05 |
return name;
|
|
|
5bfd05 |
-#endif
|
|
|
5bfd05 |
+#else
|
|
|
5bfd05 |
return NULL;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
|
|
|
5bfd05 |
@@ -1299,10 +1458,13 @@ static char *read_os_release(struct options *op, const char *varname)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* read the file only once */
|
|
|
5bfd05 |
if (!op->osrelease) {
|
|
|
5bfd05 |
- fd = open(_PATH_OS_RELEASE, O_RDONLY);
|
|
|
5bfd05 |
+ fd = open(_PATH_OS_RELEASE_ETC, O_RDONLY);
|
|
|
5bfd05 |
if (fd == -1) {
|
|
|
5bfd05 |
- log_warn(_("cannot open: %s: %m"), _PATH_OS_RELEASE);
|
|
|
5bfd05 |
- return NULL;
|
|
|
5bfd05 |
+ fd = open(_PATH_OS_RELEASE_USR, O_RDONLY);
|
|
|
5bfd05 |
+ if (fd == -1) {
|
|
|
5bfd05 |
+ log_warn(_("cannot open os-release file"));
|
|
|
5bfd05 |
+ return NULL;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if (fstat(fd, &st) < 0 || st.st_size > 4 * 1024 * 1024)
|
|
|
5bfd05 |
@@ -1359,8 +1521,7 @@ static char *read_os_release(struct options *op, const char *varname)
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
- if (ret)
|
|
|
5bfd05 |
- free(ret);
|
|
|
5bfd05 |
+ free(ret);
|
|
|
5bfd05 |
ret = strdup(p);
|
|
|
5bfd05 |
if (!ret)
|
|
|
5bfd05 |
log_err(_("failed to allocate memory: %m"));
|
|
|
5bfd05 |
@@ -1373,20 +1534,251 @@ done:
|
|
|
5bfd05 |
return ret;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
-/* Show login prompt, optionally preceded by /etc/issue contents. */
|
|
|
5bfd05 |
-static void do_prompt(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+static void open_netlink(void)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
-#ifdef ISSUE
|
|
|
5bfd05 |
- FILE *fd;
|
|
|
5bfd05 |
-#endif /* ISSUE */
|
|
|
5bfd05 |
+ struct sockaddr_nl addr = { 0, };
|
|
|
5bfd05 |
+ int sock;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+ if (netlink_fd != AGETTY_RELOAD_FDNONE)
|
|
|
5bfd05 |
+ return;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
|
5bfd05 |
+ if (sock >= 0) {
|
|
|
5bfd05 |
+ addr.nl_family = AF_NETLINK;
|
|
|
5bfd05 |
+ addr.nl_pid = getpid();
|
|
|
5bfd05 |
+ addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
|
|
|
5bfd05 |
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
|
|
5bfd05 |
+ close(sock);
|
|
|
5bfd05 |
+ else
|
|
|
5bfd05 |
+ netlink_fd = sock;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+static int process_netlink_msg(int *changed)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ char buf[4096];
|
|
|
5bfd05 |
+ struct sockaddr_nl snl;
|
|
|
5bfd05 |
+ struct nlmsghdr *h;
|
|
|
5bfd05 |
+ int rc;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ struct iovec iov = {
|
|
|
5bfd05 |
+ .iov_base = buf,
|
|
|
5bfd05 |
+ .iov_len = sizeof(buf)
|
|
|
5bfd05 |
+ };
|
|
|
5bfd05 |
+ struct msghdr msg = {
|
|
|
5bfd05 |
+ .msg_name = &snl,
|
|
|
5bfd05 |
+ .msg_namelen = sizeof(snl),
|
|
|
5bfd05 |
+ .msg_iov = &iov,
|
|
|
5bfd05 |
+ .msg_iovlen = 1,
|
|
|
5bfd05 |
+ .msg_control = NULL,
|
|
|
5bfd05 |
+ .msg_controllen = 0,
|
|
|
5bfd05 |
+ .msg_flags = 0
|
|
|
5bfd05 |
+ };
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ rc = recvmsg(netlink_fd, &msg, MSG_DONTWAIT);
|
|
|
5bfd05 |
+ if (rc < 0) {
|
|
|
5bfd05 |
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* Failure, just stop listening for changes */
|
|
|
5bfd05 |
+ close(netlink_fd);
|
|
|
5bfd05 |
+ netlink_fd = AGETTY_RELOAD_FDNONE;
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ for (h = (struct nlmsghdr *)buf; NLMSG_OK(h, (unsigned int)rc); h = NLMSG_NEXT(h, rc)) {
|
|
|
5bfd05 |
+ if (h->nlmsg_type == NLMSG_DONE ||
|
|
|
5bfd05 |
+ h->nlmsg_type == NLMSG_ERROR) {
|
|
|
5bfd05 |
+ close(netlink_fd);
|
|
|
5bfd05 |
+ netlink_fd = AGETTY_RELOAD_FDNONE;
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ *changed = 1;
|
|
|
5bfd05 |
+ break;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ return 1;
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+static int process_netlink(void)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ int changed = 0;
|
|
|
5bfd05 |
+ while (process_netlink_msg(&changed));
|
|
|
5bfd05 |
+ return changed;
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+static int wait_for_term_input(int fd)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
|
|
|
5bfd05 |
+ fd_set rfds;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (inotify_fd == AGETTY_RELOAD_FDNONE) {
|
|
|
5bfd05 |
+ /* make sure the reload trigger file exists */
|
|
|
5bfd05 |
+ int reload_fd = open(AGETTY_RELOAD_FILENAME,
|
|
|
5bfd05 |
+ O_CREAT|O_CLOEXEC|O_RDONLY,
|
|
|
5bfd05 |
+ S_IRUSR|S_IWUSR);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* initialize reload trigger inotify stuff */
|
|
|
5bfd05 |
+ if (reload_fd >= 0) {
|
|
|
5bfd05 |
+ inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
|
|
5bfd05 |
+ if (inotify_fd > 0)
|
|
|
5bfd05 |
+ inotify_add_watch(inotify_fd, AGETTY_RELOAD_FILENAME,
|
|
|
5bfd05 |
+ IN_ATTRIB | IN_MODIFY);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ close(reload_fd);
|
|
|
5bfd05 |
+ } else
|
|
|
5bfd05 |
+ log_warn(_("failed to create reload file: %s: %m"),
|
|
|
5bfd05 |
+ AGETTY_RELOAD_FILENAME);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ while (1) {
|
|
|
5bfd05 |
+ int nfds = fd;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ FD_ZERO(&rfds);
|
|
|
5bfd05 |
+ FD_SET(fd, &rfds);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (inotify_fd >= 0) {
|
|
|
5bfd05 |
+ FD_SET(inotify_fd, &rfds);
|
|
|
5bfd05 |
+ nfds = max(nfds, inotify_fd);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ if (netlink_fd >= 0) {
|
|
|
5bfd05 |
+ FD_SET(netlink_fd, &rfds);
|
|
|
5bfd05 |
+ nfds = max(nfds, netlink_fd);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* If waiting fails, just fall through, presumably reading input will fail */
|
|
|
5bfd05 |
+ if (select(nfds + 1, &rfds, NULL, NULL, NULL) < 0)
|
|
|
5bfd05 |
+ return 1;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (FD_ISSET(fd, &rfds)) {
|
|
|
5bfd05 |
+ return 1;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ } else if (netlink_fd >= 0 && FD_ISSET(netlink_fd, &rfds)) {
|
|
|
5bfd05 |
+ if (!process_netlink())
|
|
|
5bfd05 |
+ continue;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* Just drain the inotify buffer */
|
|
|
5bfd05 |
+ } else if (inotify_fd >= 0 && FD_ISSET(inotify_fd, &rfds)) {
|
|
|
5bfd05 |
+ while (read(inotify_fd, buffer, sizeof (buffer)) > 0);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+#endif /* AGETTY_RELOAD */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifdef ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
+static int issuedir_filter(const struct dirent *d)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ size_t namesz;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifdef _DIRENT_HAVE_D_TYPE
|
|
|
5bfd05 |
+ if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG &&
|
|
|
5bfd05 |
+ d->d_type != DT_LNK)
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+ if (*d->d_name == '.')
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ namesz = strlen(d->d_name);
|
|
|
5bfd05 |
+ if (!namesz || namesz < ISSUEDIR_EXTSIZ + 1 ||
|
|
|
5bfd05 |
+ strcmp(d->d_name + (namesz - ISSUEDIR_EXTSIZ), ISSUEDIR_EXT))
|
|
|
5bfd05 |
+ return 0;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* Accept this */
|
|
|
5bfd05 |
+ return 1;
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+static FILE *issuedir_next_file(int dd, struct dirent **namelist, int nfiles, int *n)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ while (*n < nfiles) {
|
|
|
5bfd05 |
+ struct dirent *d = namelist[*n];
|
|
|
5bfd05 |
+ struct stat st;
|
|
|
5bfd05 |
+ FILE *f;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ (*n)++;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (fstatat(dd, d->d_name, &st, 0) ||
|
|
|
5bfd05 |
+ !S_ISREG(st.st_mode))
|
|
|
5bfd05 |
+ continue;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ f = fopen_at(dd, d->d_name, O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR);
|
|
|
5bfd05 |
+ if (f)
|
|
|
5bfd05 |
+ return f;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ return NULL;
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#endif /* ISSUEDIR_SUPPORT */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifndef ISSUE_SUPPORT
|
|
|
5bfd05 |
+static void print_issue_file(struct options *op, struct termios *tp __attribute__((__unused__)))
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ if ((op->flags & F_NONL) == 0) {
|
|
|
5bfd05 |
+ /* Issue not in use, start with a new line. */
|
|
|
5bfd05 |
+ write_all(STDOUT_FILENO, "\r\n", 2);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+#else /* ISSUE_SUPPORT */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+static void print_issue_file(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ const char *filename, *dirname = NULL;
|
|
|
5bfd05 |
+ FILE *f = NULL;
|
|
|
5bfd05 |
+#ifdef ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
+ int dd = -1, nfiles = 0, i;
|
|
|
5bfd05 |
+ struct dirent **namelist = NULL;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
if ((op->flags & F_NONL) == 0) {
|
|
|
5bfd05 |
/* Issue not in use, start with a new line. */
|
|
|
5bfd05 |
write_all(STDOUT_FILENO, "\r\n", 2);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
-#ifdef ISSUE
|
|
|
5bfd05 |
- if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) {
|
|
|
5bfd05 |
+ if (!(op->flags & F_ISSUE))
|
|
|
5bfd05 |
+ return;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /*
|
|
|
5bfd05 |
+ * The custom issue file or directory specified by: agetty -f <path>.
|
|
|
5bfd05 |
+ * Note that nothing is printed if the file/dir does not exist.
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+ filename = op->issue;
|
|
|
5bfd05 |
+ if (filename) {
|
|
|
5bfd05 |
+ struct stat st;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (stat(filename, &st) < 0)
|
|
|
5bfd05 |
+ return;
|
|
|
5bfd05 |
+ if (S_ISDIR(st.st_mode)) {
|
|
|
5bfd05 |
+ dirname = filename;
|
|
|
5bfd05 |
+ filename = NULL;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ } else {
|
|
|
5bfd05 |
+ /* The default /etc/issue and optional /etc/issue.d directory
|
|
|
5bfd05 |
+ * as extension to the file. The /etc/issue.d directory is
|
|
|
5bfd05 |
+ * ignored if there is no /etc/issue file. The file may be
|
|
|
5bfd05 |
+ * empty or symlink.
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+ if (access(_PATH_ISSUE, F_OK|R_OK) != 0)
|
|
|
5bfd05 |
+ return;
|
|
|
5bfd05 |
+ filename = _PATH_ISSUE;
|
|
|
5bfd05 |
+ dirname = _PATH_ISSUEDIR;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifdef ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
+ if (dirname) {
|
|
|
5bfd05 |
+ dd = open(dirname, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
|
|
|
5bfd05 |
+ if (dd >= 0)
|
|
|
5bfd05 |
+ nfiles = scandirat(dd, ".", &namelist, issuedir_filter, versionsort);
|
|
|
5bfd05 |
+ if (nfiles <= 0)
|
|
|
5bfd05 |
+ dirname = NULL;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ i = 0;
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+ if (filename)
|
|
|
5bfd05 |
+ f = fopen(filename, "r");
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (f || dirname) {
|
|
|
5bfd05 |
int c, oflag = tp->c_oflag; /* Save current setting. */
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if ((op->flags & F_VCONSOLE) == 0) {
|
|
|
5bfd05 |
@@ -1395,12 +1787,23 @@ static void do_prompt(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
tcsetattr(STDIN_FILENO, TCSADRAIN, tp);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- while ((c = getc(fd)) != EOF) {
|
|
|
5bfd05 |
- if (c == '\\')
|
|
|
5bfd05 |
- output_special_char(getc(fd), op, tp, fd);
|
|
|
5bfd05 |
- else
|
|
|
5bfd05 |
- putchar(c);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
+ do {
|
|
|
5bfd05 |
+#ifdef ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
+ if (!f && i < nfiles)
|
|
|
5bfd05 |
+ f = issuedir_next_file(dd, namelist, nfiles, &i);
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+ if (!f)
|
|
|
5bfd05 |
+ break;
|
|
|
5bfd05 |
+ while ((c = getc(f)) != EOF) {
|
|
|
5bfd05 |
+ if (c == '\\')
|
|
|
5bfd05 |
+ output_special_char(getc(f), op, tp, f);
|
|
|
5bfd05 |
+ else
|
|
|
5bfd05 |
+ putchar(c);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ fclose(f);
|
|
|
5bfd05 |
+ f = NULL;
|
|
|
5bfd05 |
+ } while (dirname);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
fflush(stdout);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
if ((op->flags & F_VCONSOLE) == 0) {
|
|
|
5bfd05 |
@@ -1409,11 +1812,36 @@ static void do_prompt(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
/* Wait till output is gone. */
|
|
|
5bfd05 |
tcsetattr(STDIN_FILENO, TCSADRAIN, tp);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
- fclose(fd);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
-#endif /* ISSUE */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+#ifdef ISSUEDIR_SUPPORT
|
|
|
5bfd05 |
+ for (i = 0; i < nfiles; i++)
|
|
|
5bfd05 |
+ free(namelist[i]);
|
|
|
5bfd05 |
+ free(namelist);
|
|
|
5bfd05 |
+ if (dd >= 0)
|
|
|
5bfd05 |
+ close(dd);
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+#endif /* ISSUE_SUPPORT */
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+/* Show login prompt, optionally preceded by /etc/issue contents. */
|
|
|
5bfd05 |
+static void do_prompt(struct options *op, struct termios *tp)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+again:
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+ print_issue_file(op, tp);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
if (op->flags & F_LOGINPAUSE) {
|
|
|
5bfd05 |
puts(_("[press ENTER to login]"));
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+ if (!wait_for_term_input(STDIN_FILENO)) {
|
|
|
5bfd05 |
+ /* reload issue */
|
|
|
5bfd05 |
+ if (op->flags & F_VCONSOLE)
|
|
|
5bfd05 |
+ termio_clear(STDOUT_FILENO);
|
|
|
5bfd05 |
+ goto again;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
getc(stdin);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
#ifdef KDGKBLED
|
|
|
5bfd05 |
@@ -1533,18 +1961,36 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
|
|
|
5bfd05 |
*bp = '\0';
|
|
|
5bfd05 |
|
|
|
5bfd05 |
while (*logname == '\0') {
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
/* Write issue file and prompt */
|
|
|
5bfd05 |
do_prompt(op, tp);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+ if (!wait_for_term_input(STDIN_FILENO)) {
|
|
|
5bfd05 |
+ /* refresh prompt -- discard input data, clear terminal
|
|
|
5bfd05 |
+ * and call do_prompt() again
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+ if ((op->flags & F_VCONSOLE) == 0)
|
|
|
5bfd05 |
+ sleep(1);
|
|
|
5bfd05 |
+ tcflush(STDIN_FILENO, TCIFLUSH);
|
|
|
5bfd05 |
+ if (op->flags & F_VCONSOLE)
|
|
|
5bfd05 |
+ termio_clear(STDOUT_FILENO);
|
|
|
5bfd05 |
+ bp = logname;
|
|
|
5bfd05 |
+ *bp = '\0';
|
|
|
5bfd05 |
+ continue;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
cp->eol = '\0';
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* Read name, watch for break and end-of-line. */
|
|
|
5bfd05 |
while (cp->eol == '\0') {
|
|
|
5bfd05 |
|
|
|
5bfd05 |
char key;
|
|
|
5bfd05 |
+ ssize_t readres;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (read(STDIN_FILENO, &c, 1) < 1) {
|
|
|
5bfd05 |
+ debug("read from FD\n");
|
|
|
5bfd05 |
+ readres = read(STDIN_FILENO, &c, 1);
|
|
|
5bfd05 |
+ if (readres < 0) {
|
|
|
5bfd05 |
+ debug("read failed\n");
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/* The terminal could be open with O_NONBLOCK when
|
|
|
5bfd05 |
* -L (force CLOCAL) is specified... */
|
|
|
5bfd05 |
@@ -1558,12 +2004,15 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
|
|
|
5bfd05 |
case ESRCH:
|
|
|
5bfd05 |
case EINVAL:
|
|
|
5bfd05 |
case ENOENT:
|
|
|
5bfd05 |
- break;
|
|
|
5bfd05 |
+ exit_slowly(EXIT_SUCCESS);
|
|
|
5bfd05 |
default:
|
|
|
5bfd05 |
log_err(_("%s: read: %m"), op->tty);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+ if (readres == 0)
|
|
|
5bfd05 |
+ c = 0;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
/* Do parity bit handling. */
|
|
|
5bfd05 |
if (eightbit)
|
|
|
5bfd05 |
ascval = c;
|
|
|
5bfd05 |
@@ -1588,8 +2037,10 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
|
|
|
5bfd05 |
switch (key) {
|
|
|
5bfd05 |
case 0:
|
|
|
5bfd05 |
*bp = 0;
|
|
|
5bfd05 |
- if (op->numspeed > 1)
|
|
|
5bfd05 |
+ if (op->numspeed > 1 && !(op->flags & F_VCONSOLE))
|
|
|
5bfd05 |
return NULL;
|
|
|
5bfd05 |
+ if (readres == 0)
|
|
|
5bfd05 |
+ exit_slowly(EXIT_SUCCESS);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case CR:
|
|
|
5bfd05 |
case NL:
|
|
|
5bfd05 |
@@ -1627,6 +2078,7 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
#ifdef HAVE_WIDECHAR
|
|
|
5bfd05 |
if ((op->flags & (F_EIGHTBITS|F_UTF8)) == (F_EIGHTBITS|F_UTF8)) {
|
|
|
5bfd05 |
/* Check out UTF-8 multibyte characters */
|
|
|
5bfd05 |
@@ -1637,7 +2089,7 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
|
|
|
5bfd05 |
if (len < 0)
|
|
|
5bfd05 |
log_err(_("%s: invalid character conversion for login name"), op->tty);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- wcs = (wchar_t *) malloc((len + 1) * sizeof(wchar_t));
|
|
|
5bfd05 |
+ wcs = malloc((len + 1) * sizeof(wchar_t));
|
|
|
5bfd05 |
if (!wcs)
|
|
|
5bfd05 |
log_err(_("failed to allocate memory: %m"));
|
|
|
5bfd05 |
|
|
|
5bfd05 |
@@ -1702,12 +2154,12 @@ static void termio_final(struct options *op, struct termios *tp, struct chardata
|
|
|
5bfd05 |
case 1:
|
|
|
5bfd05 |
/* odd parity */
|
|
|
5bfd05 |
tp->c_cflag |= PARODD;
|
|
|
5bfd05 |
- /* do not break */
|
|
|
5bfd05 |
+ /* fallthrough */
|
|
|
5bfd05 |
case 2:
|
|
|
5bfd05 |
/* even parity */
|
|
|
5bfd05 |
tp->c_cflag |= PARENB;
|
|
|
5bfd05 |
tp->c_iflag |= INPCK | ISTRIP;
|
|
|
5bfd05 |
- /* do not break */
|
|
|
5bfd05 |
+ /* fallthrough */
|
|
|
5bfd05 |
case (1 | 2):
|
|
|
5bfd05 |
/* no parity bit */
|
|
|
5bfd05 |
tp->c_cflag &= ~CSIZE;
|
|
|
5bfd05 |
@@ -1767,11 +2219,17 @@ static speed_t bcode(char *s)
|
|
|
5bfd05 |
return 0;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
-static void __attribute__ ((__noreturn__)) usage(FILE *out)
|
|
|
5bfd05 |
+static void __attribute__((__noreturn__)) usage(void)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
+ FILE *out = stdout;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
fputs(USAGE_HEADER, out);
|
|
|
5bfd05 |
- fprintf(out, _(" %1$s [options] line [baud_rate,...] [termtype]\n"
|
|
|
5bfd05 |
- " %1$s [options] baud_rate,... line [termtype]\n"), program_invocation_short_name);
|
|
|
5bfd05 |
+ fprintf(out, _(" %1$s [options] <line> [<baud_rate>,...] [<termtype>]\n"
|
|
|
5bfd05 |
+ " %1$s [options] <baud_rate>,... <line> [<termtype>]\n"), program_invocation_short_name);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ fputs(USAGE_SEPARATOR, out);
|
|
|
5bfd05 |
+ fputs(_("Open a terminal and set its mode.\n"), out);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
fputs(USAGE_OPTIONS, out);
|
|
|
5bfd05 |
fputs(_(" -8, --8bits assume 8-bit tty\n"), out);
|
|
|
5bfd05 |
fputs(_(" -a, --autologin <user> login the specified user automatically\n"), out);
|
|
|
5bfd05 |
@@ -1782,10 +2240,12 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out)
|
|
|
5bfd05 |
fputs(_(" -H, --host <hostname> specify login host\n"), out);
|
|
|
5bfd05 |
fputs(_(" -i, --noissue do not display issue file\n"), out);
|
|
|
5bfd05 |
fputs(_(" -I, --init-string <string> set init string\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" -J --noclear do not clear the screen before prompt\n"), out);
|
|
|
5bfd05 |
fputs(_(" -l, --login-program <file> specify login program\n"), out);
|
|
|
5bfd05 |
- fputs(_(" -L, --local-line[=<mode>] cotrol local line flag\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" -L, --local-line[=<mode>] control the local line flag\n"), out);
|
|
|
5bfd05 |
fputs(_(" -m, --extract-baud extract baud rate during connect\n"), out);
|
|
|
5bfd05 |
fputs(_(" -n, --skip-login do not prompt for login\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" -N --nonewline do not print a newline before issue\n"), out);
|
|
|
5bfd05 |
fputs(_(" -o, --login-options <opts> options that are passed to login\n"), out);
|
|
|
5bfd05 |
fputs(_(" -p, --login-pause wait for any key before the login\n"), out);
|
|
|
5bfd05 |
fputs(_(" -r, --chroot <dir> change root to the directory\n"), out);
|
|
|
5bfd05 |
@@ -1794,18 +2254,29 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out)
|
|
|
5bfd05 |
fputs(_(" -t, --timeout <number> login process timeout\n"), out);
|
|
|
5bfd05 |
fputs(_(" -U, --detect-case detect uppercase terminal\n"), out);
|
|
|
5bfd05 |
fputs(_(" -w, --wait-cr wait carriage-return\n"), out);
|
|
|
5bfd05 |
- fputs(_(" --noclear do not clear the screen before prompt\n"), out);
|
|
|
5bfd05 |
fputs(_(" --nohints do not print hints\n"), out);
|
|
|
5bfd05 |
- fputs(_(" --nonewline do not print a newline before issue\n"), out);
|
|
|
5bfd05 |
fputs(_(" --nohostname no hostname at all will be shown\n"), out);
|
|
|
5bfd05 |
fputs(_(" --long-hostname show full qualified hostname\n"), out);
|
|
|
5bfd05 |
fputs(_(" --erase-chars <string> additional backspace chars\n"), out);
|
|
|
5bfd05 |
fputs(_(" --kill-chars <string> additional kill chars\n"), out);
|
|
|
5bfd05 |
- fputs(_(" --help display this help and exit\n"), out);
|
|
|
5bfd05 |
- fputs(_(" --version output version information and exit\n"), out);
|
|
|
5bfd05 |
- fprintf(out, USAGE_MAN_TAIL("agetty(8)"));
|
|
|
5bfd05 |
+ fputs(_(" --chdir <directory> chdir before the login\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" --delay <number> sleep seconds before prompt\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" --nice <number> run login with this priority\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" --reload reload prompts on running agetty instances\n"), out);
|
|
|
5bfd05 |
+ fputs(_(" --list-speeds display supported baud rates\n"), out);
|
|
|
5bfd05 |
+ printf( " --help %s\n", USAGE_OPTSTR_HELP);
|
|
|
5bfd05 |
+ printf( " --version %s\n", USAGE_OPTSTR_VERSION);
|
|
|
5bfd05 |
+ printf(USAGE_MAN_TAIL("agetty(8)"));
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ exit(EXIT_SUCCESS);
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+static void list_speeds(void)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ const struct Speedtab *sp;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
|
5bfd05 |
+ for (sp = speedtab; sp->speed; sp++)
|
|
|
5bfd05 |
+ printf("%10ld\n", sp->speed);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
@@ -1855,6 +2326,13 @@ static void dolog(int priority, const char *fmt, va_list ap)
|
|
|
5bfd05 |
#endif /* USE_SYSLOG */
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+static void exit_slowly(int code)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ /* Be kind to init(8). */
|
|
|
5bfd05 |
+ sleep(10);
|
|
|
5bfd05 |
+ exit(code);
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
static void log_err(const char *fmt, ...)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
va_list ap;
|
|
|
5bfd05 |
@@ -1863,9 +2341,7 @@ static void log_err(const char *fmt, ...)
|
|
|
5bfd05 |
dolog(LOG_ERR, fmt, ap);
|
|
|
5bfd05 |
va_end(ap);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- /* Be kind to init(8). */
|
|
|
5bfd05 |
- sleep(10);
|
|
|
5bfd05 |
- exit(EXIT_FAILURE);
|
|
|
5bfd05 |
+ exit_slowly(EXIT_FAILURE);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
static void log_warn(const char *fmt, ...)
|
|
|
5bfd05 |
@@ -1877,41 +2353,70 @@ static void log_warn(const char *fmt, ...)
|
|
|
5bfd05 |
va_end(ap);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
-static void output_iface_ip(struct ifaddrs *addrs, const char *iface, sa_family_t family)
|
|
|
5bfd05 |
+static void print_addr(sa_family_t family, void *addr)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+ char buff[INET6_ADDRSTRLEN + 1];
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ inet_ntop(family, addr, buff, sizeof(buff));
|
|
|
5bfd05 |
+ printf("%s", buff);
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+/*
|
|
|
5bfd05 |
+ * Prints IP for the specified interface (@iface), if the interface is not
|
|
|
5bfd05 |
+ * specified then prints the "best" one (UP, RUNNING, non-LOOPBACK). If not
|
|
|
5bfd05 |
+ * found the "best" interface then prints at least host IP.
|
|
|
5bfd05 |
+ */
|
|
|
5bfd05 |
+static void output_iface_ip(struct ifaddrs *addrs,
|
|
|
5bfd05 |
+ const char *iface,
|
|
|
5bfd05 |
+ sa_family_t family)
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
- if (!iface)
|
|
|
5bfd05 |
+ struct ifaddrs *p;
|
|
|
5bfd05 |
+ struct addrinfo hints, *info = NULL;
|
|
|
5bfd05 |
+ char *host = NULL;
|
|
|
5bfd05 |
+ void *addr = NULL;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (!addrs)
|
|
|
5bfd05 |
return;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (addrs->ifa_name
|
|
|
5bfd05 |
- && strcmp(addrs->ifa_name, iface) == 0
|
|
|
5bfd05 |
- && addrs->ifa_addr
|
|
|
5bfd05 |
- && addrs->ifa_addr->sa_family == family) {
|
|
|
5bfd05 |
+ for (p = addrs; p; p = p->ifa_next) {
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- void *addr = NULL;
|
|
|
5bfd05 |
- char buff[INET6_ADDRSTRLEN + 1];
|
|
|
5bfd05 |
+ if (!p->ifa_name ||
|
|
|
5bfd05 |
+ !p->ifa_addr ||
|
|
|
5bfd05 |
+ p->ifa_addr->sa_family != family)
|
|
|
5bfd05 |
+ continue;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (iface) {
|
|
|
5bfd05 |
+ /* Filter out by interface name */
|
|
|
5bfd05 |
+ if (strcmp(p->ifa_name, iface) != 0)
|
|
|
5bfd05 |
+ continue;
|
|
|
5bfd05 |
+ } else {
|
|
|
5bfd05 |
+ /* Select the "best" interface */
|
|
|
5bfd05 |
+ if ((p->ifa_flags & IFF_LOOPBACK) ||
|
|
|
5bfd05 |
+ !(p->ifa_flags & IFF_UP) ||
|
|
|
5bfd05 |
+ !(p->ifa_flags & IFF_RUNNING))
|
|
|
5bfd05 |
+ continue;
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- switch (addrs->ifa_addr->sa_family) {
|
|
|
5bfd05 |
+ addr = NULL;
|
|
|
5bfd05 |
+ switch (p->ifa_addr->sa_family) {
|
|
|
5bfd05 |
case AF_INET:
|
|
|
5bfd05 |
- addr = &((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
|
|
5bfd05 |
+ addr = &((struct sockaddr_in *) p->ifa_addr)->sin_addr;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case AF_INET6:
|
|
|
5bfd05 |
- addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
|
|
5bfd05 |
+ addr = &((struct sockaddr_in6 *) p->ifa_addr)->sin6_addr;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
if (addr) {
|
|
|
5bfd05 |
- inet_ntop(addrs->ifa_addr->sa_family, addr, buff, sizeof(buff));
|
|
|
5bfd05 |
- printf("%s", buff);
|
|
|
5bfd05 |
+ print_addr(family, addr);
|
|
|
5bfd05 |
+ return;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- } else if (addrs->ifa_next)
|
|
|
5bfd05 |
- output_iface_ip(addrs->ifa_next, iface, family);
|
|
|
5bfd05 |
-}
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
-static void output_ip(sa_family_t family)
|
|
|
5bfd05 |
-{
|
|
|
5bfd05 |
- char *host;
|
|
|
5bfd05 |
- struct addrinfo hints, *info = NULL;
|
|
|
5bfd05 |
+ if (iface)
|
|
|
5bfd05 |
+ return;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+ /* Hmm.. not found the best interface, print host IP at least */
|
|
|
5bfd05 |
memset(&hints, 0, sizeof(hints));
|
|
|
5bfd05 |
hints.ai_family = family;
|
|
|
5bfd05 |
if (family == AF_INET6)
|
|
|
5bfd05 |
@@ -1919,9 +2424,6 @@ static void output_ip(sa_family_t family)
|
|
|
5bfd05 |
|
|
|
5bfd05 |
host = xgethostname();
|
|
|
5bfd05 |
if (host && getaddrinfo(host, NULL, &hints, &info) == 0 && info) {
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
- void *addr = NULL;
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
switch (info->ai_family) {
|
|
|
5bfd05 |
case AF_INET:
|
|
|
5bfd05 |
addr = &((struct sockaddr_in *) info->ai_addr)->sin_addr;
|
|
|
5bfd05 |
@@ -1930,12 +2432,8 @@ static void output_ip(sa_family_t family)
|
|
|
5bfd05 |
addr = &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr;
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
- if (addr) {
|
|
|
5bfd05 |
- char buff[INET6_ADDRSTRLEN + 1];
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
- inet_ntop(info->ai_family, (void *) addr, buff, sizeof(buff));
|
|
|
5bfd05 |
- printf("%s", buff);
|
|
|
5bfd05 |
- }
|
|
|
5bfd05 |
+ if (addr)
|
|
|
5bfd05 |
+ print_addr(family, addr);
|
|
|
5bfd05 |
|
|
|
5bfd05 |
freeaddrinfo(info);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
@@ -1974,22 +2472,25 @@ static void output_special_char(unsigned char c, struct options *op,
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
struct utsname uts;
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- uname(&uts;;
|
|
|
5bfd05 |
-
|
|
|
5bfd05 |
switch (c) {
|
|
|
5bfd05 |
case 's':
|
|
|
5bfd05 |
+ uname(&uts;;
|
|
|
5bfd05 |
printf("%s", uts.sysname);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'n':
|
|
|
5bfd05 |
+ uname(&uts;;
|
|
|
5bfd05 |
printf("%s", uts.nodename);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'r':
|
|
|
5bfd05 |
+ uname(&uts;;
|
|
|
5bfd05 |
printf("%s", uts.release);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'v':
|
|
|
5bfd05 |
+ uname(&uts;;
|
|
|
5bfd05 |
printf("%s", uts.version);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'm':
|
|
|
5bfd05 |
+ uname(&uts;;
|
|
|
5bfd05 |
printf("%s", uts.machine);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
case 'o':
|
|
|
5bfd05 |
@@ -2066,30 +2567,39 @@ static void output_special_char(unsigned char c, struct options *op,
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
char *var = NULL, varname[64];
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (get_escape_argument(fp, varname, sizeof(varname)))
|
|
|
5bfd05 |
+ /* \S{varname} */
|
|
|
5bfd05 |
+ if (get_escape_argument(fp, varname, sizeof(varname))) {
|
|
|
5bfd05 |
var = read_os_release(op, varname);
|
|
|
5bfd05 |
- else if (!(var = read_os_release(op, "PRETTY_NAME")))
|
|
|
5bfd05 |
- var = uts.sysname;
|
|
|
5bfd05 |
- if (var) {
|
|
|
5bfd05 |
- if (strcmp(varname, "ANSI_COLOR") == 0)
|
|
|
5bfd05 |
- printf("\033[%sm", var);
|
|
|
5bfd05 |
- else
|
|
|
5bfd05 |
- printf("%s", var);
|
|
|
5bfd05 |
- if (var != uts.sysname)
|
|
|
5bfd05 |
- free(var);
|
|
|
5bfd05 |
+ if (var) {
|
|
|
5bfd05 |
+ if (strcmp(varname, "ANSI_COLOR") == 0)
|
|
|
5bfd05 |
+ printf("\033[%sm", var);
|
|
|
5bfd05 |
+ else
|
|
|
5bfd05 |
+ fputs(var, stdout);
|
|
|
5bfd05 |
+ }
|
|
|
5bfd05 |
+ /* \S */
|
|
|
5bfd05 |
+ } else if ((var = read_os_release(op, "PRETTY_NAME"))) {
|
|
|
5bfd05 |
+ fputs(var, stdout);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ /* \S and PRETTY_NAME not found */
|
|
|
5bfd05 |
+ } else {
|
|
|
5bfd05 |
+ uname(&uts;;
|
|
|
5bfd05 |
+ fputs(uts.sysname, stdout);
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ free(var);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
case 'u':
|
|
|
5bfd05 |
case 'U':
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
int users = 0;
|
|
|
5bfd05 |
- struct utmp *ut;
|
|
|
5bfd05 |
- setutent();
|
|
|
5bfd05 |
- while ((ut = getutent()))
|
|
|
5bfd05 |
+ struct utmpx *ut;
|
|
|
5bfd05 |
+ setutxent();
|
|
|
5bfd05 |
+ while ((ut = getutxent()))
|
|
|
5bfd05 |
if (ut->ut_type == USER_PROCESS)
|
|
|
5bfd05 |
users++;
|
|
|
5bfd05 |
- endutent();
|
|
|
5bfd05 |
+ endutxent();
|
|
|
5bfd05 |
if (c == 'U')
|
|
|
5bfd05 |
printf(P_("%d user", "%d users", users), users);
|
|
|
5bfd05 |
else
|
|
|
5bfd05 |
@@ -2100,17 +2610,22 @@ static void output_special_char(unsigned char c, struct options *op,
|
|
|
5bfd05 |
case '6':
|
|
|
5bfd05 |
{
|
|
|
5bfd05 |
sa_family_t family = c == '4' ? AF_INET : AF_INET6;
|
|
|
5bfd05 |
+ struct ifaddrs *addrs = NULL;
|
|
|
5bfd05 |
char iface[128];
|
|
|
5bfd05 |
|
|
|
5bfd05 |
- if (get_escape_argument(fp, iface, sizeof(iface))) { /* interface IP */
|
|
|
5bfd05 |
- struct ifaddrs *addrs;
|
|
|
5bfd05 |
- int status = getifaddrs(&addrs);
|
|
|
5bfd05 |
- if (status != 0)
|
|
|
5bfd05 |
- break;
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+ open_netlink();
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (getifaddrs(&addrs))
|
|
|
5bfd05 |
+ break;
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (get_escape_argument(fp, iface, sizeof(iface)))
|
|
|
5bfd05 |
output_iface_ip(addrs, iface, family);
|
|
|
5bfd05 |
- freeifaddrs(addrs);
|
|
|
5bfd05 |
- } else /* host IP */
|
|
|
5bfd05 |
- output_ip(family);
|
|
|
5bfd05 |
+ else
|
|
|
5bfd05 |
+ output_iface_ip(addrs, NULL, family);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ freeifaddrs(addrs);
|
|
|
5bfd05 |
break;
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
default:
|
|
|
5bfd05 |
@@ -2162,7 +2677,7 @@ static void init_special_char(char* arg, struct options *op)
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
/*
|
|
|
5bfd05 |
- * Appends @str to @dest and if @dest is not empty then use use @sep as a
|
|
|
5bfd05 |
+ * Appends @str to @dest and if @dest is not empty then use @sep as a
|
|
|
5bfd05 |
* separator. The maximal final length of the @dest is @len.
|
|
|
5bfd05 |
*
|
|
|
5bfd05 |
* Returns the final @dest length or -1 in case of error.
|
|
|
5bfd05 |
@@ -2217,3 +2732,19 @@ err:
|
|
|
5bfd05 |
log_err(_("checkname failed: %m"));
|
|
|
5bfd05 |
}
|
|
|
5bfd05 |
|
|
|
5bfd05 |
+static void reload_agettys(void)
|
|
|
5bfd05 |
+{
|
|
|
5bfd05 |
+#ifdef AGETTY_RELOAD
|
|
|
5bfd05 |
+ int fd = open(AGETTY_RELOAD_FILENAME, O_CREAT|O_CLOEXEC|O_WRONLY,
|
|
|
5bfd05 |
+ S_IRUSR|S_IWUSR);
|
|
|
5bfd05 |
+ if (fd < 0)
|
|
|
5bfd05 |
+ err(EXIT_FAILURE, _("cannot open %s"), AGETTY_RELOAD_FILENAME);
|
|
|
5bfd05 |
+
|
|
|
5bfd05 |
+ if (futimens(fd, NULL) < 0 || close(fd) < 0)
|
|
|
5bfd05 |
+ err(EXIT_FAILURE, _("cannot touch file %s"),
|
|
|
5bfd05 |
+ AGETTY_RELOAD_FILENAME);
|
|
|
5bfd05 |
+#else
|
|
|
5bfd05 |
+ /* very unusual */
|
|
|
5bfd05 |
+ errx(EXIT_FAILURE, _("--reload is unsupported on your system"));
|
|
|
5bfd05 |
+#endif
|
|
|
5bfd05 |
+}
|
|
|
5bfd05 |
--
|
|
|
5bfd05 |
2.20.1
|
|
|
5bfd05 |
|