login: Support /etc/issue through login-loop
This commit is contained in:
parent
4bc652365f
commit
9d6ed3feb5
|
@ -1,18 +1,199 @@
|
|||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
/**
|
||||
* @brief Repeatedly invoke `login` in a loop.
|
||||
*
|
||||
* This is more closely related to the 'getty' command in Linux
|
||||
* than our actual 'getty' command as it is also where we process
|
||||
* and display /etc/issue.
|
||||
*
|
||||
* @copyright
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2018 K. Lange
|
||||
*
|
||||
* login-loop - Continuously call `login`
|
||||
*
|
||||
* Used by the VGA terminal to provide interactive login sessions.
|
||||
* Copyright (C) 2018-2021 K. Lange
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/time.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
struct colorNames {
|
||||
const char * name;
|
||||
const char * output;
|
||||
} ColorNames[] = {
|
||||
{"black", "\033[30m"},
|
||||
{"blue", "\033[34m"},
|
||||
{"bold", "\033[1m"},
|
||||
{"brown", "\033[33m"},
|
||||
{"cyan", "\033[36"},
|
||||
{"darkgray", "\033[90m"},
|
||||
{"gray", "\033[37m"},
|
||||
{"green", "\033[32m"},
|
||||
{"lightblue", "\033[94m"},
|
||||
{"lightcyan", "\033[96m"},
|
||||
{"lightgray", "\033[97m"},
|
||||
{"lightgreen", "\033[92m"},
|
||||
{"lightmagenta", "\033[95m"},
|
||||
{"lightred", "\033[91m"},
|
||||
{"magenta", "\033[35m"},
|
||||
{"red", "\033[31m"},
|
||||
{"reset", "\033[0m"},
|
||||
{"reverse", "\033[7m"},
|
||||
{"yellow", "\033[93m"},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
char * get_arg(FILE * f) {
|
||||
static char buf[32];
|
||||
int n = fgetc(f);
|
||||
if (n == '{') {
|
||||
int count = 0;
|
||||
do {
|
||||
int x = fgetc(f);
|
||||
if (x == '}') break;
|
||||
if (x < 0) break;
|
||||
buf[count++] = x;
|
||||
buf[count] = '\0';
|
||||
} while (count < 31);
|
||||
if (count) return buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * get_ipv4_address(char * arg) {
|
||||
if (arg) {
|
||||
char if_path[1024];
|
||||
snprintf(if_path, 300, "/dev/net/%s", arg);
|
||||
int netdev = open(if_path, O_RDWR);
|
||||
if (netdev >= 0) {
|
||||
uint32_t ip_addr = 0;
|
||||
if (!ioctl(netdev, SIOCGIFADDR, &ip_addr)) {
|
||||
return inet_ntoa((struct in_addr){ntohl(ip_addr)});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Read /dev/net for interfaces */
|
||||
DIR * d = opendir("/dev/net");
|
||||
if (d) {
|
||||
struct dirent * ent;
|
||||
while ((ent = readdir(d))) {
|
||||
if (ent->d_name[0] == '.') continue;
|
||||
closedir(d);
|
||||
return get_ipv4_address(ent->d_name);
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
}
|
||||
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
void print_issue(void) {
|
||||
printf("\033[H\033[2J");
|
||||
fflush(stdout);
|
||||
|
||||
FILE * f = fopen("/etc/issue","r");
|
||||
if (!f) return;
|
||||
|
||||
/* Parse and display /etc/issue with support
|
||||
* for some escape sequences that fill in
|
||||
* dynamic information... */
|
||||
|
||||
struct utsname u;
|
||||
uname(&u);
|
||||
|
||||
struct tm * timeinfo;
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
timeinfo = localtime((time_t *)&now.tv_sec);
|
||||
|
||||
static char buf[1024];
|
||||
|
||||
while (!feof(f)) {
|
||||
int c = fgetc(f);
|
||||
|
||||
if (c < 0) break; /* Probably EOF */
|
||||
|
||||
if (c == '\\') {
|
||||
int next = fgetc(f);
|
||||
switch (next) {
|
||||
case '\n':
|
||||
/* A linefeed we should quietly skip. */
|
||||
continue;
|
||||
case '\\':
|
||||
/* A literal backslash */
|
||||
printf("\\");
|
||||
continue;
|
||||
|
||||
/* Various things from uname */
|
||||
case 'n':
|
||||
printf("%s", u.nodename);
|
||||
continue;
|
||||
case 's':
|
||||
printf("%s", u.sysname);
|
||||
continue;
|
||||
case 'r':
|
||||
printf("%s", u.release);
|
||||
continue;
|
||||
case 'm':
|
||||
printf("%s", u.machine);
|
||||
continue;
|
||||
case 'v':
|
||||
printf("%s", u.version);
|
||||
continue;
|
||||
|
||||
/* Various other useful things */
|
||||
case '4':
|
||||
printf("%s", get_ipv4_address(get_arg(f)));
|
||||
continue;
|
||||
case 'l':
|
||||
printf("%s", ttyname(STDIN_FILENO));
|
||||
continue;
|
||||
case 't':
|
||||
strftime(buf,1024,"%T %Z",timeinfo);
|
||||
printf("%s", buf);
|
||||
continue;
|
||||
case 'd':
|
||||
strftime(buf,1024,"%a %b %d %Y",timeinfo);
|
||||
printf("%s", buf);
|
||||
continue;
|
||||
|
||||
/* Formatting stuff listed in Linux's getty(8) manpage */
|
||||
case 'e': {
|
||||
char * arg = get_arg(f);
|
||||
if (arg) {
|
||||
for (struct colorNames * cn = ColorNames; cn->name; cn++) {
|
||||
if (!strcmp(arg,cn->name)) {
|
||||
printf("%s", cn->output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("\033");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%c", c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
while (1) {
|
||||
print_issue();
|
||||
pid_t f = fork();
|
||||
if (!f) {
|
||||
char * args[] = {
|
||||
|
|
|
@ -69,10 +69,6 @@ int main(int argc, char ** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
system("uname -a");
|
||||
printf("\n");
|
||||
|
||||
signal(SIGINT, sig_pass);
|
||||
signal(SIGWINCH, sig_pass);
|
||||
signal(SIGSEGV, sig_segv);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
\e{bold}\t\e{reset} on \e{bold}\d\e{reset}
|
||||
\e{yellow}\l\e{reset} on \e{lightblue}\n\e{reset} - \e{bold}\s \r\e{reset}
|
||||
|
||||
This live CD has two available user accounts: \e{bold}local\e{reset} is listed in /etc/sudoers
|
||||
and \e{bold} guest\e{reset} is not. For both accounts, the password is the same as the account
|
||||
name. The \e{bold}root\e{reset} account can also be accessed directly with the password \e{bold}toor\e{reset}.
|
||||
You may also type \e{bold}restart\e{reset} at the login prompt to reboot. Please note that
|
||||
VGA text mode and serial terminal access provides only a limited subset of the
|
||||
available functionality of ToaruOS.
|
||||
|
Loading…
Reference in New Issue