-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.c
184 lines (168 loc) · 4.39 KB
/
main.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// UCLA CS 111 Lab 1 main program
#include <errno.h>
#include <error.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "command.h"
static char const *program_name;
static char const *script_name;
static void
usage (void)
{
error (1, 0, "usage: %s [-pt] SCRIPT-FILE", program_name);
}
static int
get_next_byte (void *stream)
{
return getc (stream);
}
int compare(char** arr1, char** arr2) //assume arr1 is bigger than arr2
{
int i=0, j;
for (; arr1[i]; i++)
for (j=0; arr2[j]; j++)
if (strcmp(arr1[i], arr2[j]) == 0)
return 1;
return 0;
}
int
main (int argc, char **argv)
{
int opt;
int command_number = 1;
int print_tree = 0;
int time_travel = 0;
program_name = argv[0];
for (;;)
switch (getopt (argc, argv, "pt"))
{
case 'p': print_tree = 1; break;
case 't': time_travel = 1; break;
default: usage (); break;
case -1: goto options_exhausted;
}
options_exhausted:;
// There must be exactly one file argument.
if (optind != argc - 1)
usage ();
script_name = argv[optind];
FILE *script_stream = fopen (script_name, "r");
if (! script_stream)
error (1, errno, "%s: cannot open", script_name);
command_stream_t stream =
make_command_stream (get_next_byte, script_stream);
command_t last_command = NULL;
command_t command;
if (!time_travel)
while ((command = read_command_stream (stream)))
{
if (print_tree)
{
printf ("# %d\n", command_number++);
print_command (command);
}
else
{
last_command = command;
execute_command (command, time_travel);
}
}
else
{
//get commands as array
int len = 0;
command_stream_t* array = streamArrayFromList(stream, &len);
//make dependency graph as adjacency matrix
int** graph= malloc(len * sizeof(int*)); //like R
int* wait = calloc(len, sizeof(int)); //like W
int* need = calloc(len, sizeof(int));
int waitSum = 0;
int i = 0, j,k;
for (; i < len; i++) graph[i] = calloc(len, sizeof(int));
for (i = 0; i < len; i++)
for (j = 0; j < i; j++)
{
//row may depend on col; array[i] may depend on array[j]
// if array[i] has an input or output file that is an input or output of array[j]
//all arguments except options are input files, and options start with minus
//set graph[i][j] to 1 if dependent, else don't change
//and increment wait[i] if dependent
char** isInputs = getInputs_pub(array[i]);
char** isOutputs = getOutputs_pub(array[i]);
char** jsInputs = getInputs_pub(array[j]);
char** jsOutputs = getOutputs_pub(array[j]);
if (compare(isInputs, jsOutputs) || compare(isOutputs, jsOutputs) || compare(isInputs, jsInputs) || compare(isOutputs, jsInputs))
{
graph[i][j] = 1;
wait[i]++;
need[j]++;
waitSum++;
}
}
//then evaluate (resolve) dependency graph
do
for (i = 0; i < len; i++)
{
if (wait[i] != 0) continue; //don't start it if it's waiting on someone or if it's done
int pid = fork();
if (pid == 0)
{
execute_command(getCmd(array[i]),time_travel);
wait[i] = -1;
exit(0);
}
else if (pid > 0)
{
//when task i is done, decrement waitSum and wait[j] for tasks depending on i; if wait[j] now equals 0, start array[j] in new process
wait[i] = -1;
if (!need[i]) continue; //if noone needs me, continue;
int status; //if people need me, then wait for me to finish then signal everyone
waitpid(pid, &status, -2);
usleep(10000);
for (j = i+1; j < len; j++)
{
if (graph[j][i])
{
wait[j]--;
waitSum--;
}
if (!wait[j])
{
int pid2 = fork();
if (pid2 == 0)
{
execute_command(getCmd(array[j]),time_travel);
wait[j] = -1;
exit(0);
}
else if (pid2 > 0)
{
wait[j] = -1;
if (!need[j]) continue;
int status2;
waitpid(pid2, &status2, -2);
usleep(10000);
for (k = j+1; k < len; k++)
if (graph[k][j])
{
wait[k]--;
waitSum--;
}
}
else
error(1,0,"cannot create child process in main!");
}
}
}
else
error(1,0,"cannot create child process in main!");
}
while (waitSum);
}
return print_tree || !last_command ? 0 : command_status (last_command);
}