Browse Source

Change how text login generally works so getty can die and reboot after login session ends

K. Lange 3 years ago
parent
commit
4b50fd324d
7 changed files with 104 additions and 67 deletions
  1. 1 1
      Makefile
  2. 39 34
      apps/getty.c
  3. 9 3
      apps/init.c
  4. 23 0
      apps/login-loop.c
  5. 30 27
      apps/login.c
  6. 1 1
      apps/terminal-vga.c
  7. 1 1
      apps/terminal.c

+ 1 - 1
Makefile

@@ -258,7 +258,7 @@ fast: image.iso
 .PHONY: headless
 headless: image.iso
 	@qemu-system-i386 -cdrom $< ${QEMU_ARGS} \
-	  -nographic \
+	  -nographic -no-reboot \
 	  -fw_cfg name=opt/org.toaruos.bootmode,string=headless
 
 .PHONY: efi64

+ 39 - 34
apps/getty.c

@@ -6,6 +6,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <pty.h>
+#include <sys/wait.h>
 #include <sys/fswait.h>
 
 int main(int argc, char * argv[]) {
@@ -17,51 +18,55 @@ int main(int argc, char * argv[]) {
 		return 1;
 	}
 
-	if (!fork()) {
-
-		if (argc > 1) {
-			file = argv[1];
-		}
+	if (argc > 1) {
+		file = argv[1];
+	}
 
-		openpty(&fd_master, &fd_slave, NULL, NULL, NULL);
-		fd_serial = open(file, O_RDWR);
+	openpty(&fd_master, &fd_slave, NULL, NULL, NULL);
+	fd_serial = open(file, O_RDWR);
 
-		if (!fork()) {
-			dup2(fd_slave, 0);
-			dup2(fd_slave, 1);
-			dup2(fd_slave, 2);
+	pid_t child = fork();
 
-			system("ttysize -q");
+	if (!child) {
+		dup2(fd_slave, 0);
+		dup2(fd_slave, 1);
+		dup2(fd_slave, 2);
 
-			char * tokens[] = {"/bin/login",NULL};
-			execvp(tokens[0], tokens);
-			exit(1);
-		} else {
+		system("ttysize -q");
 
-			int fds[2] = {fd_serial, fd_master};
+		char * tokens[] = {"/bin/login",NULL};
+		execvp(tokens[0], tokens);
+		exit(1);
+	} else {
 
-			while (1) {
-				int index = fswait2(2,fds,200);
-				char buf[1024];
-				int r;
-				switch (index) {
-					case 0: /* fd_serial */
-						r = read(fd_serial, buf, 1);
-						write(fd_master, buf, 1);
-						break;
-					case 1: /* fd_master */
-						r = read(fd_master, buf, 1024);
-						write(fd_serial, buf, r);
-						break;
-					default: /* timeout */
-						break;
-				}
+		int fds[2] = {fd_serial, fd_master};
 
+		while (1) {
+			int index = fswait2(2,fds,200);
+			char buf[1024];
+			int r;
+			switch (index) {
+				case 0: /* fd_serial */
+					r = read(fd_serial, buf, 1);
+					write(fd_master, buf, 1);
+					break;
+				case 1: /* fd_master */
+					r = read(fd_master, buf, 1024);
+					write(fd_serial, buf, r);
+					break;
+				default: /* timeout */
+					{
+						int result = waitpid(child, NULL, WNOHANG);
+						if (result > 0) {
+							/* Child login shell has returned (session ended) */
+							return 0;
+						}
+					}
+					break;
 			}
 
 		}
 
-		return 1;
 	}
 
 	return 0;

+ 9 - 3
apps/init.c

@@ -6,7 +6,7 @@
 #include <unistd.h>
 
 void set_console(void) {
-	int _stdin  = syscall_open("/dev/null", 0, 0);
+	int _stdin  = syscall_open("/dev/ttyS0", 0, 0);
 	int _stdout = syscall_open("/dev/ttyS0", 1, 0);
 	int _stderr = syscall_open("/dev/ttyS0", 1, 0);
 
@@ -36,8 +36,8 @@ void set_hostname(void) {
 }
 
 int start_options(char * args[]) {
-	int pid = syscall_fork();
-	if (!pid) {
+	int cpid = syscall_fork();
+	if (!cpid) {
 		char * _envp[] = {
 			"LD_LIBRARY_PATH=/lib:/usr/lib",
 			"PATH=/bin:/usr/bin",
@@ -51,8 +51,14 @@ int start_options(char * args[]) {
 		int pid = 0;
 		do {
 			pid = wait(NULL);
+			if (pid == cpid) {
+				break;
+			}
 		} while ((pid > 0) || (pid == -1 && errno == EINTR));
 	}
+
+	syscall_reboot();
+
 	return 0;
 }
 

+ 23 - 0
apps/login-loop.c

@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+int main(int argc, char * argv[]) {
+	while (1) {
+		pid_t f = fork();
+		if (!f) {
+			char * args[] = {
+				"login",
+				NULL
+			};
+			execvp(args[0], args);
+		} else {
+			int result;
+			do {
+				result = waitpid(f, NULL, 0);
+			} while (result < 0);
+		}
+	}
+
+	return 1;
+}

+ 30 - 27
apps/login.c

@@ -43,6 +43,8 @@ void sig_segv(int sig) {
 
 int main(int argc, char ** argv) {
 
+	int uid;
+
 	printf("\n");
 	system("uname -a");
 	printf("\n");
@@ -52,8 +54,9 @@ int main(int argc, char ** argv) {
 	signal(SIGSEGV, sig_segv);
 
 	while (1) {
-		char * username = malloc(sizeof(char) * 1024);
-		char * password = malloc(sizeof(char) * 1024);
+
+		char username[1024] = {0};
+		char password[1024] = {0};
 
 		/* TODO: gethostname() */
 		char _hostname[256];
@@ -94,7 +97,7 @@ int main(int argc, char ** argv) {
 		tcsetattr(fileno(stdin), TCSAFLUSH, &old);
 		fprintf(stdout, "\n");
 
-		int uid = toaru_auth_check_pass(username, password);
+		uid = toaru_auth_check_pass(username, password);
 
 		if (uid < 0) {
 			sleep(2);
@@ -102,31 +105,31 @@ int main(int argc, char ** argv) {
 			continue;
 		}
 
-		system("cat /etc/motd");
-
-		pid_t pid = getpid();
-
-		pid_t f = fork();
-		if (getpid() != pid) {
-			setuid(uid);
-			toaru_auth_set_vars();
-			char * args[] = {
-				getenv("SHELL"),
-				NULL
-			};
-			execvp(args[0], args);
-			return 1;
-		} else {
-			child = f;
-			int result;
-			do {
-				result = waitpid(f, NULL, 0);
-			} while (result < 0);
-		}
-		child = 0;
-		free(username);
-		free(password);
+		break;
+	}
+
+	system("cat /etc/motd");
+
+	pid_t pid = getpid();
+
+	pid_t f = fork();
+	if (getpid() != pid) {
+		setuid(uid);
+		toaru_auth_set_vars();
+		char * args[] = {
+			getenv("SHELL"),
+			NULL
+		};
+		execvp(args[0], args);
+		return 1;
+	} else {
+		child = f;
+		int result;
+		do {
+			result = waitpid(f, NULL, 0);
+		} while (result < 0);
 	}
+	child = 0;
 
 	return 0;
 }

+ 1 - 1
apps/terminal-vga.c

@@ -1061,7 +1061,7 @@ int main(int argc, char ** argv) {
 			fprintf(stderr, "Failed to launch requested startup application.\n");
 		} else {
 			if (_login_shell) {
-				char * tokens[] = {"/bin/login",NULL};
+				char * tokens[] = {"/bin/login-loop",NULL};
 				execvp(tokens[0], tokens);
 				exit(1);
 			} else {

+ 1 - 1
apps/terminal.c

@@ -1996,7 +1996,7 @@ int main(int argc, char ** argv) {
 			fprintf(stderr, "Failed to launch requested startup application.\n");
 		} else {
 			if (_login_shell) {
-				char * tokens[] = {"/bin/login",NULL};
+				char * tokens[] = {"/bin/login-loop",NULL};
 				execvp(tokens[0], tokens);
 				exit(1);
 			} else {