]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
agetty: add \4 and \6 issue file sequences to print IP addresses
authorKarel Zak <kzak@redhat.com>
Thu, 13 Sep 2012 10:54:36 +0000 (12:54 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 13 Sep 2012 10:59:46 +0000 (12:59 +0200)
Based on Andrea Bonomi <a.bonomi@endian.com> ideas.

Signed-off-by: Karel Zak <kzak@redhat.com>
term-utils/agetty.8
term-utils/agetty.c

index ebfdb961b18734476d1192c3867917e3d9b0c8ff..e400ec855d586bad347159a916137ca97c7b1310 100644 (file)
@@ -268,6 +268,14 @@ may contain certain escape codes to display the system name, date and
 time etc. All escape codes consist of a backslash (\\) immediately
 followed by one of the letters explained below.
 
+.TP
+4 or 4{interface}
+Insert the IPv4 address of the machine hostname or IPv4 address the configured
+network interface if the interface argument is specified (e.g. \\4{eth0}).
+.TP
+6 or 6{interface}
+Insert the IPv6 address of the machine hostname or IPv6 address the configured
+network interface if the interface argument is specified (e.g. \\6{eth0}}
 .TP
 b
 Insert the baudrate of the current line.
index 43243f92ad87e396d493f53c984fd16dd7c54dd6..4e23135929ae523a1f33c336a1aef9b9acb4b65e 100644 (file)
@@ -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;