Browse Source

kernel: getpgid; esh: fixups

K. Lange 3 years ago
parent
commit
35c29e9b4d

+ 40 - 5
apps/sh.c

@@ -71,9 +71,32 @@ static int current_line = 0;
 static char * current_file = NULL;
 
 int pid; /* Process ID of the shell */
+int my_pgid;
 
 int is_subshell = 0;
 
+struct semaphore {
+	int fds[2];
+};
+
+struct semaphore create_semaphore(void) {
+	struct semaphore out;
+	pipe(out.fds);
+	return out;
+}
+
+void raise_semaphore(struct semaphore s){
+	close(s.fds[0]);
+	close(s.fds[1]);
+}
+
+void wait_semaphore(struct semaphore s) {
+	close(s.fds[1]);
+	char buf;
+	read(s.fds[0], &buf, 1);
+	close(s.fds[0]);
+}
+
 void set_pgid(int pgid) {
 	if (shell_interactive == 1) {
 		setpgid(0, pgid);
@@ -88,7 +111,7 @@ void set_pgrp(int pgid) {
 
 void reset_pgrp() {
 	if (shell_interactive == 1 && !is_subshell) {
-		tcsetpgrp(STDIN_FILENO, pid);
+		tcsetpgrp(STDIN_FILENO, my_pgid);
 	}
 }
 
@@ -783,9 +806,11 @@ int wait_for_child(int pgid, char * name) {
 	int waitee = (shell_interactive == 1 && !is_subshell) ? -pgid : pgid;
 	int outpid;
 	int ret_code = 0;
+	int e;
 
 	do {
 		outpid = waitpid(waitee, &ret_code, WSTOPPED);
+		e = errno;
 		if (WIFSTOPPED(ret_code)) {
 			suspended_pgid = pgid;
 			if (name) {
@@ -797,7 +822,7 @@ int wait_for_child(int pgid, char * name) {
 			suspended_pgid = 0;
 			hashmap_remove(job_hash, (void*)pgid);
 		}
-	} while (outpid != -1 || (outpid == -1 && errno != ECHILD));
+	} while (outpid != -1 || (outpid == -1 && e != ECHILD));
 	reset_pgrp();
 	handle_status(ret_code);
 	return WEXITSTATUS(ret_code);
@@ -1244,10 +1269,13 @@ _nope:
 	if (cmdi > 0) {
 		int last_output[2];
 		pipe(last_output);
+
+		struct semaphore s = create_semaphore();
 		child_pid = fork();
 		if (!child_pid) {
 			set_pgid(0);
-			set_pgrp(getpid());
+			if (!nowait) set_pgrp(getpid());
+			raise_semaphore(s);
 			is_subshell = 1;
 			dup2(last_output[1], STDOUT_FILENO);
 			close(last_output[0]);
@@ -1294,16 +1322,20 @@ _nope:
 		close(last_output[0]);
 		close(last_output[1]);
 
+		wait_semaphore(s);
+
 		/* Now execute the last piece and wait on all of them */
 	} else {
 		shell_command_t func = shell_find(*arg_starts[0]);
 		if (func) {
 			return func(argcs[0], arg_starts[0]);
 		} else {
+			struct semaphore s = create_semaphore();
 			child_pid = fork();
 			if (!child_pid) {
 				set_pgid(0);
-				set_pgrp(getpid());
+				if (!nowait) set_pgrp(getpid());
+				raise_semaphore(s);
 				is_subshell = 1;
 				if (output_files[cmdi]) {
 					int fd = open(output_files[cmdi], file_args[cmdi], 0666);
@@ -1316,6 +1348,9 @@ _nope:
 				}
 				run_cmd(arg_starts[0]);
 			}
+
+			wait_semaphore(s);
+
 			pgid = child_pid;
 			last_child = child_pid;
 		}
@@ -1519,7 +1554,7 @@ int main(int argc, char ** argv) {
 
 	shell_interactive = 1;
 
-	signal(SIGTSTP, SIG_IGN);
+	my_pgid = getpgid(0);
 	signal(SIGTTOU, SIG_IGN);
 	signal(SIGTTIN, SIG_IGN);
 

+ 1 - 0
base/usr/include/syscall.h

@@ -119,6 +119,7 @@ DECL_SYSCALL1(pipe,  int *);
 DECL_SYSCALL3(readlink, char *, char *, int);
 DECL_SYSCALL0(setsid);
 DECL_SYSCALL2(setpgid,int,int);
+DECL_SYSCALL1(getpgid,int);
 
 _End_C_Header
 

+ 1 - 0
base/usr/include/syscall_nums.h

@@ -52,3 +52,4 @@
 #define SYS_CHOWN 61
 #define SYS_SETSID 62
 #define SYS_SETPGID 63
+#define SYS_GETPGID 64

+ 1 - 0
base/usr/include/unistd.h

@@ -85,5 +85,6 @@ extern int sethostname(const char * name, size_t len);
 
 extern pid_t setsid(void);
 extern int setpgid(pid_t, pid_t);
+extern pid_t getpgid(pid_t);
 
 _End_C_Header

+ 16 - 0
kernel/sys/syscall.c

@@ -986,6 +986,21 @@ static int sys_setpgid(pid_t pid, pid_t pgid) {
 	return 0;
 }
 
+static int sys_getpgid(pid_t pid) {
+	process_t * proc;
+	if (pid == 0) {
+		proc = (process_t*)current_process;
+	} else {
+		proc = process_from_pid(pid);
+	}
+
+	if (!proc) {
+		return -ESRCH;
+	}
+
+	return proc->job;
+}
+
 /*
  * System Call Internals
  */
@@ -1043,6 +1058,7 @@ static int (*syscalls[])() = {
 	[SYS_CHOWN]        = sys_chown,
 	[SYS_SETSID]       = sys_setsid,
 	[SYS_SETPGID]      = sys_setpgid,
+	[SYS_GETPGID]      = sys_getpgid,
 };
 
 uint32_t num_syscalls = sizeof(syscalls) / sizeof(*syscalls);

+ 5 - 0
libc/unistd/setpgid.c

@@ -4,8 +4,13 @@
 #include <errno.h>
 
 DEFN_SYSCALL2(setpgid, SYS_SETPGID, int, int);
+DEFN_SYSCALL1(getpgid, SYS_GETPGID, int);
 
 int setpgid(pid_t pid, pid_t pgid) {
 	__sets_errno(syscall_setpgid((int)pid,(int)pgid));
 }
 
+pid_t getpgid(pid_t pid) {
+	__sets_errno(syscall_getpgid((int)pid));
+}
+