-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsystem_command.c
140 lines (134 loc) · 4.76 KB
/
system_command.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "header.h"
#include "system_command.h"
#include <signal.h>
#include "jobs.h"
void execute_sys_command(int arg_count, char *argument[])
{
bool is_background_proc = false;
if (arg_count == 0)
{
perror(ERROR "Invalid Argument Called, give atleast one command to execute\n");
return;
}
if (arg_count >= 2 && strcmp(argument[arg_count - 1], "&") == 0)
{
is_background_proc = true;
argument[arg_count - 1] = NULL;
arg_count--;
}
else if (arg_count >= 1 && argument[arg_count - 1][strlen(argument[arg_count - 1]) - 1] == '&')
{
is_background_proc = true;
argument[arg_count - 1][strlen(argument[arg_count - 1]) - 1] = '\0';
argument[arg_count] = NULL;
}
// we execute the system commands in foreground mode
if (is_background_proc == false)
{
// not a background process , wait parent till child finish
// printf(ERROR "%d \n", getpid());
// should be NULL terminated
argument[arg_count] = NULL;
pid_t proc_fork = fork();
if (proc_fork < 0)
{
perror(ERROR "Failed To Execute Command ");
return;
}
else if (proc_fork == 0)
{
// printf(ERROR "CHILD %d \n", getpid());
// in child
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
setpgid(0, 0);
// set the child process group id to child ka pid ( creating a new group )
int exec_flag = execvp(argument[0], argument);
if (exec_flag < 0)
{
perror(ERROR "Failed To Execute Command ");
fprintf(stderr, RESET);
exit(EXIT_FAILURE);
}
}
else
{
// IN PARENT PROCESS , control passed on to the child
// wait for the child to execute using wait();
dup2(copy_stdin_fileno, 0);
dup2(copy_stdout_fileno, 1);
signal(SIGTTIN, SIG_IGN);
// stop the terminal input for the parent //
signal(SIGTTOU, SIG_IGN);
// stop the terminal output to the terminal for the parent, ignore any input/output interrupts from parent //
int st_wait;
// set the group id of parent process as the pid of the parent, the child sets it's group as child ka pid
setpgid(proc_fork, 0);
// tcsetpgrp set the terminal display permission to the parent process
tcsetpgrp(STDIN_FILENO, proc_fork);
waitpid(proc_fork, &st_wait, WUNTRACED); // wait till the child proc dies of
// st_wait contains the error code
pid_t pgid_parent = getpgrp();
// printf(WHITE "PROCFORK %d : %d \n", proc_fork, pgid_parent);
// printf(ERROR "PARENT %d \n", getpid());
tcsetpgrp(STDIN_FILENO, pgid_parent);
signal(SIGTTIN, SIG_DFL);
// can continue for taking input
signal(SIGTTOU, SIG_DFL);
// can continue for taking output
// printf(WHITE "PROCESS EXECUTED\n");
if (WIFSTOPPED(st_wait))
{
add_node(argument[0], proc_fork);
printf("Process %s with pid %d stopped .... \n", argument[0], proc_fork);
}
}
}
else
{
// background process hoga
// no need for backgrounfd to give permission for read and write from parent
pid_t proc_fork = fork();
if (proc_fork < 0)
{
perror(ERROR "Failed To Execute Command");
fprintf(stderr, RESET);
return;
}
else if (proc_fork == 0)
{
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
setpgid(0, 0);
int exec_flag = execvp(argument[0], argument);
if (exec_flag < 0)
{
perror(ERROR "Failed To Execute Command");
fprintf(stderr, RESET);
exit(EXIT_FAILURE);
}
}
else
{
// in parent
// no need to wait
dup2(copy_stdin_fileno, 0);
dup2(copy_stdout_fileno, 1);
char *command = (char *)malloc(sizeof(char) * name_len);
strcpy(command, argument[0]);
for (int i = 1; i < arg_count && argument[i] != NULL; i++)
{
strcat(command, " ");
strcat(command, argument[i]);
}
add_node(command, proc_fork);
free(command);
pid_t pgid_parent = getpgrp();
setpgid(proc_fork, 0);
print_WHITE();
printf("%d\n", proc_fork);
print_RESET();
tcsetpgrp(STDIN_FILENO, pgid_parent);
}
}
}