1

If I understand correctly, /etc/issue will be shown in the console by agetty

I would like to see /etc/issue, as parsed by agetty - but I do not want to start any login session or anything related. I just want a text dump of /etc/issue - with parsed commands.

Is this possible? How?

3 Answers 3

2

I don't think there is a utility that will do what you want. Looking at the agetty source code the function do_prompt(...) basically opens the /etc/issue file and reads it character by character and either displays the character read or if it's a \ it reads the next char and then enters a switch statement to display the relevant information. It wouldn't be too hard to convert this to a script ... anyway here's the relevant code

void
do_prompt(op, tp)
     struct options *op;
     struct termios *tp;
{
#ifdef  ISSUE
    FILE    *fd;
    int     oflag;
    int     c;
    struct utsname uts;

    (void) uname(&uts);
#endif

    (void) write(1, "\r\n", 2);         /* start a new line */
#ifdef  ISSUE                   /* optional: show /etc/issue */
    if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) {
    oflag = tp->c_oflag;            /* save current setting */
    tp->c_oflag |= (ONLCR | OPOST);     /* map NL in output to CR-NL */
    (void) tcsetattr(0, TCSADRAIN, tp);


    while ((c = getc(fd)) != EOF)
    {
        if (c == '\\')
          {
        c = getc(fd);

        switch (c)
          {
          case 's':
            (void) printf ("%s", uts.sysname);
            break;

          case 'n':
            (void) printf ("%s", uts.nodename);
            break;

          case 'r':
            (void) printf ("%s", uts.release);
            break;

          case 'v':
            (void) printf ("%s", uts.version);
            break;

          case 'm':
            (void) printf ("%s", uts.machine);
            break;

          case 'o':
           {
             char domainname[MAXHOSTNAMELEN+1];
#ifdef HAVE_GETDOMAINNAME
             if (getdomainname(domainname, sizeof(domainname)))
#endif
             strcpy(domainname, "unknown_domain");
             domainname[sizeof(domainname)-1] = '\0';
             printf ("%s", domainname);
           }
          break;

          case 'O':
           {
            char *dom = "unknown_domain";
            char host[MAXHOSTNAMELEN+1];
            struct addrinfo hints, *info = NULL;

            memset(&hints, 0, sizeof(hints));
            hints.ai_flags = AI_CANONNAME;

            if (gethostname(host, sizeof(host)) ||
                getaddrinfo(host, NULL, &hints, &info) ||
                info == NULL)
                fputs(dom, stdout);
            else {
                char *canon;

                if (info->ai_canonname &&
                    (canon = strchr(info->ai_canonname, '.')))
                    dom = canon + 1;
                fputs(dom, stdout);
                freeaddrinfo(info);
            }
           }
          break;

          case 'd':
          case 't':
            {
              /* TODO: use nl_langinfo() */
              char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
                      "Fri", "Sat" };
              char *month[] = { "Jan", "Feb", "Mar", "Apr", "May",
                    "Jun", "Jul", "Aug", "Sep", "Oct",
                    "Nov", "Dec" };
              time_t now;
              struct tm *tm;

              (void) time (&now);
              tm = localtime(&now);

              if (c == 'd')
            (void) printf ("%s %s %d  %d",
                weekday[tm->tm_wday], month[tm->tm_mon],
                tm->tm_mday, 
                tm->tm_year < 70 ? tm->tm_year + 2000 :
                tm->tm_year + 1900);
              else
            (void) printf ("%02d:%02d:%02d",
                tm->tm_hour, tm->tm_min, tm->tm_sec);

              break;
            }

          case 'l':
              (void) printf ("%s", op->tty);
              break;

          case 'b':
            {
            int i;

            for (i = 0; speedtab[i].speed; i++) {
                if (speedtab[i].code == cfgetispeed(tp)) {
                printf("%ld", speedtab[i].speed);
                break;
                }
            }
            break;
            }
          case 'u':
          case 'U':
            {
              int users = 0;
              struct utmp *ut;
              setutent();
              while ((ut = getutent()))
                if (ut->ut_type == USER_PROCESS)
              users++;
              endutent();
              printf ("%d ", users);
              if (c == 'U')
                printf ((users == 1) ? _("user") : _("users"));
              break;
            }
          default:
            (void) putchar(c);
          }
          }
        else
          (void) putchar(c);
    }
    fflush(stdout);

    tp->c_oflag = oflag;            /* restore settings */
    (void) tcsetattr(0, TCSADRAIN, tp); /* wait till output is gone */
    (void) fclose(fd);
    }
#endif
    {
    char hn[MAXHOSTNAMELEN+1];
    if (gethostname(hn, sizeof(hn)) == 0)
        write(1, hn, strlen(hn));
    }
    (void) write(1, LOGIN, sizeof(LOGIN) - 1);  /* always show login prompt */
}
2

This specific functionality was requested in util-linux#828.
util-linux 2.35 (released 2020-01-21) introduced a flag for this:

$ agetty --show-issue
Debian GNU/Linux bookworm/sid tabasco tty0

$

If you're on an older version of util-linux, you can do this instead:

$ agetty -N8nl /bin/true -f <(sed "s@\\l@$(tty |sed 's:^/dev/::')@g" /etc/issue) -

This suppresses the login, though agetty sees a username of -, so we're intercepting the issue file and replacing \l with the current TTY (which comes from the tty command after we remove the leading /dev/) so it doesn't display as -. -N suppresses the leading linebreak, -8 disables tty parity detection, -n suppresses the login (but doesn't suppress the login command's error), and -l /bin/true sets a dummy executable in place of /bin/login.

0

You may try

agetty -8n - linux
  • -8 disables parity detection, assuming the tty is 8-bit clean
  • -n suppresses the login prompt

For more details, man agetty.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .