Serenity Operating System
1/*
2 * Copyright (c) 2020, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "Job.h"
8#include "AST.h"
9#include "Shell.h"
10#include <inttypes.h>
11#include <stdio.h>
12#include <sys/wait.h>
13
14namespace Shell {
15
16bool Job::print_status(PrintStatusMode mode)
17{
18 int wstatus;
19 auto rc = waitpid(m_pid, &wstatus, WNOHANG);
20 auto status = "running";
21
22 if (rc > 0) {
23 if (WIFEXITED(wstatus))
24 status = "exited";
25
26 if (WIFSTOPPED(wstatus))
27 status = "stopped";
28
29 if (WIFSIGNALED(wstatus))
30 status = "signaled";
31 } else {
32 // if rc < 0, We couldn't waitpid() it, probably because we're not the parent shell.
33 // Otherwise, the information we have is already correct,
34 // so just use the old information.
35 if (exited())
36 status = "exited";
37 else if (m_is_suspended)
38 status = "stopped";
39 else if (signaled())
40 status = "signaled";
41 }
42
43 char background_indicator = '-';
44
45 if (is_running_in_background())
46 background_indicator = '+';
47
48 const AST::Command& command = *m_command;
49
50 switch (mode) {
51 case PrintStatusMode::Basic:
52 outln("[{}] {} {} {}", m_job_id, background_indicator, status, command);
53 break;
54 case PrintStatusMode::OnlyPID:
55 outln("[{}] {} {} {} {}", m_job_id, background_indicator, m_pid, status, command);
56 break;
57 case PrintStatusMode::ListAll:
58 outln("[{}] {} {} {} {} {}", m_job_id, background_indicator, m_pid, m_pgid, status, command);
59 break;
60 }
61 fflush(stdout);
62
63 return true;
64}
65
66Job::Job(pid_t pid, unsigned pgid, DeprecatedString cmd, u64 job_id, AST::Command&& command)
67 : m_pgid(pgid)
68 , m_pid(pid)
69 , m_job_id(job_id)
70 , m_cmd(move(cmd))
71{
72 m_command = make<AST::Command>(move(command));
73
74 set_running_in_background(false);
75 m_command_timer.start();
76}
77
78void Job::set_has_exit(int exit_code)
79{
80 if (m_exited)
81 return;
82 m_exit_code = exit_code;
83 m_exited = true;
84 if (on_exit)
85 on_exit(*this);
86}
87
88void Job::set_signalled(int sig)
89{
90 if (m_exited)
91 return;
92 m_exited = true;
93 m_exit_code = 126;
94 m_term_sig = sig;
95 if (on_exit)
96 on_exit(*this);
97}
98
99void Job::unblock()
100{
101 if (!m_exited && on_exit)
102 on_exit(*this);
103}
104
105}