summaryrefslogtreecommitdiffstats
path: root/term-utils/agetty.c
diff options
context:
space:
mode:
authorKarel Zak2012-09-13 12:54:36 +0200
committerKarel Zak2012-09-13 12:59:46 +0200
commit2b945eda3da145c7434cd7cc9ebc6392dcbea15d (patch)
tree23431331bb866afb91808e1f020d8b2d9ae6bd39 /term-utils/agetty.c
parentbuild-sys: simplify usrlib_execdir initialization (diff)
downloadkernel-qcow2-util-linux-2b945eda3da145c7434cd7cc9ebc6392dcbea15d.tar.gz
kernel-qcow2-util-linux-2b945eda3da145c7434cd7cc9ebc6392dcbea15d.tar.xz
kernel-qcow2-util-linux-2b945eda3da145c7434cd7cc9ebc6392dcbea15d.zip
agetty: add \4 and \6 issue file sequences to print IP addresses
Based on Andrea Bonomi <a.bonomi@endian.com> ideas. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'term-utils/agetty.c')
-rw-r--r--term-utils/agetty.c116
1 files changed, 113 insertions, 3 deletions
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 43243f92a..4e2313592 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -31,6 +31,9 @@
#include <netdb.h>
#include <langinfo.h>
#include <grp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ifaddrs.h>
#include "strutils.h"
#include "all-io.h"
@@ -242,7 +245,8 @@ static void open_tty(char *tty, struct termios *tp, struct options *op);
static void termio_init(struct options *op, struct termios *tp);
static void reset_vc (const struct options *op, struct termios *tp);
static void auto_baud(struct termios *tp);
-static void output_special_char (unsigned char c, struct options *op, struct termios *tp);
+static void output_special_char (unsigned char c, struct options *op,
+ struct termios *tp, FILE *fp);
static void do_prompt(struct options *op, struct termios *tp);
static void next_speed(struct options *op, struct termios *tp);
static char *get_logname(struct options *op,
@@ -1240,7 +1244,7 @@ static void do_prompt(struct options *op, struct termios *tp)
while ((c = getc(fd)) != EOF) {
if (c == '\\')
- output_special_char(getc(fd), op, tp);
+ output_special_char(getc(fd), op, tp, fd);
else
putchar(c);
}
@@ -1696,8 +1700,97 @@ static void log_warn(const char *fmt, ...)
va_end(ap);
}
+static void output_iface_ip(struct ifaddrs *addrs, const char *iface, sa_family_t family)
+{
+ if (!iface)
+ return;
+
+ if (addrs->ifa_name
+ && strcmp(addrs->ifa_name, iface) == 0
+ && addrs->ifa_addr
+ && addrs->ifa_addr->sa_family == family) {
+
+ void *addr = NULL;
+ char buff[INET6_ADDRSTRLEN + 1];
+
+ switch (addrs->ifa_addr->sa_family) {
+ case AF_INET:
+ addr = &((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
+ break;
+ }
+ if (addr) {
+ inet_ntop(addrs->ifa_addr->sa_family, addr, buff, sizeof(buff));
+ printf("%s", buff);
+ }
+
+ } else if (addrs->ifa_next)
+ output_iface_ip(addrs->ifa_next, iface, family);
+}
+
+static void output_ip(sa_family_t family)
+{
+ char host[MAXHOSTNAMELEN + 1];
+ struct addrinfo hints, *info = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ if (family == AF_INET6)
+ hints.ai_flags = AI_V4MAPPED;
+
+ if (gethostname(host, sizeof(host)) == 0
+ && getaddrinfo(host, NULL, &hints, &info) == 0
+ && info) {
+
+ void *addr = NULL;
+ char buff[INET6_ADDRSTRLEN + 1];
+
+ switch (info->ai_family) {
+ case AF_INET:
+ addr = &((struct sockaddr_in *) info->ai_addr)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr;
+ break;
+ }
+ inet_ntop(info->ai_family, (void *) addr, buff, sizeof(buff));
+ printf("%s", buff);
+
+ freeaddrinfo(info);
+ }
+}
+
+/*
+ * parses \x{argument}, if not argument specified then returns NULL, the @fd
+ * has to point to one char after the sequence (it means '{').
+ */
+static char *get_escape_argument(FILE *fd, char *buf, size_t bufsz)
+{
+ size_t i = 0;
+ int c = fgetc(fd);
+
+ if (c == EOF || (unsigned char) c != '{') {
+ ungetc(c, fd);
+ return NULL;
+ }
+
+ do {
+ c = fgetc(fd);
+ if (c == EOF)
+ return NULL;
+ if ((unsigned char) c != '}' && i < bufsz - 1)
+ buf[i++] = (unsigned char) c;
+
+ } while ((unsigned char) c != '}');
+
+ buf[i] = '\0';
+ return buf;
+}
+
static void output_special_char(unsigned char c, struct options *op,
- struct termios *tp)
+ struct termios *tp, FILE *fp)
{
struct utsname uts;
@@ -1808,6 +1901,23 @@ static void output_special_char(unsigned char c, struct options *op,
printf((users == 1) ? _("user") : _("users"));
break;
}
+ case '4':
+ case '6':
+ {
+ sa_family_t family = c == '4' ? AF_INET : AF_INET6;
+ char iface[128];
+
+ if (get_escape_argument(fp, iface, sizeof(iface))) { /* interface IP */
+ struct ifaddrs *addrs;
+ int status = getifaddrs(&addrs);
+ if (status != 0)
+ break;
+ output_iface_ip(addrs, iface, family);
+ freeifaddrs(addrs);
+ } else /* host IP */
+ output_ip(family);
+ break;
+ }
default:
putchar(c);
break;