Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
some code
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
yanjung2
some code
Commits
83d83d5a
Commit
83d83d5a
authored
5 years ago
by
yanjung2
Browse files
Options
Downloads
Patches
Plain Diff
initial commit
parents
Branches
master
No related tags found
No related merge requests found
Pipeline
#180106
failed
5 years ago
Stage: build
Stage: test
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
shell.c
+603
-0
603 additions, 0 deletions
shell.c
shell.h
+14
-0
14 additions, 0 deletions
shell.h
with
617 additions
and
0 deletions
shell.c
0 → 100644
+
603
−
0
View file @
83d83d5a
/**
* Shell Lab
* CS 241 - Fall 2018
*/
#include
"format.h"
#include
"shell.h"
#include
"vector.h"
#include
"sstring.h"
#include
<stdlib.h>
#include
<string.h>
#include
<unistd.h>
#include
<stdio.h>
#include
<limits.h>
#include
<getopt.h>
#include
<sys/wait.h>
#include
<signal.h>
typedef
struct
process
{
char
*
command
;
char
*
status
;
pid_t
pid
;
}
process
;
static
vector
*
processes
;
void
insert_history
(
vector
*
history
,
char
*
path_h
)
{
FILE
*
f
=
fopen
(
path_h
,
"r"
);
size_t
size
=
0
;
if
(
!
f
)
{
print_history_file_error
();
return
;
}
else
{
char
*
buffer
=
NULL
;
while
(
getline
(
&
buffer
,
&
size
,
f
)
!=
-
1
)
{
int
length
=
strlen
(
buffer
);
if
(
buffer
[
length
-
1
]
==
'\n'
)
{
buffer
[
length
-
1
]
=
'\0'
;
}
vector_push_back
(
history
,
buffer
);
}
free
(
buffer
);
}
fclose
(
f
);
}
void
write_history
(
vector
*
history
,
char
*
path_h
)
{
FILE
*
f
=
fopen
(
path_h
,
"w+"
);
for
(
size_t
i
=
0
;
i
<
vector_size
(
history
);
i
++
)
{
fprintf
(
f
,
"%s
\n
"
,
vector_get
(
history
,
i
));;
}
fclose
(
f
);
}
int
handle_command
(
char
*
line
,
vector
*
history
,
vector
*
processes
)
{
sstring
*
sstr
=
cstr_to_sstring
((
const
char
*
)
line
);
vector
*
vec
=
sstring_split
(
sstr
,
' '
);
int
result
=
0
;
if
(
strcmp
(
vector_get
(
vec
,
0
),
"cd"
)
==
0
)
{
if
(
vector_size
(
vec
)
==
1
)
{
print_no_directory
(
""
);
}
else
{
if
(
chdir
(
vector_get
(
vec
,
1
))
==-
1
)
{
print_no_directory
(
vector_get
(
vec
,
1
));
}
else
{
result
=
1
;
}
}
}
else
if
(
strcmp
(
vector_get
(
vec
,
0
),
"!history"
)
==
0
)
{
for
(
size_t
i
=
0
;
i
<
vector_size
(
history
);
i
++
)
{
print_history_line
(
i
,
vector_get
(
history
,
i
));
}
}
else
if
(((
char
*
)
vector_get
(
vec
,
0
))[
0
]
==
'!'
)
{
if
(
vector_size
(
history
)
==
0
)
{
print_no_history_match
();
}
else
if
(
vector_size
(
vec
)
==
1
&&
strcmp
(
vector_get
(
vec
,
0
),
"!"
)
==
0
)
{
print_command
(
vector_get
(
history
,
vector_size
(
history
)
-
1
));
if
(
handle_command
(
vector_get
(
history
,
vector_size
(
history
)
-
1
),
history
,
processes
))
{
char
*
last
=
vector_get
(
history
,
vector_size
(
history
)
-
1
);
vector_push_back
(
history
,
last
);
}
}
else
{
int
idx
=
-
1
;
for
(
size_t
i
=
0
;
i
<
vector_size
(
history
);
i
++
)
{
char
target
[
strlen
(
line
)];
strncpy
(
target
,
vector_get
(
history
,
vector_size
(
history
)
-
i
-
1
),
strlen
(
line
)
-
1
);
if
(
strcmp
(
target
,
line
+
1
)
==
0
)
{
idx
=
vector_size
(
history
)
-
i
-
1
;
break
;
}
}
if
(
idx
==
-
1
)
{
print_no_history_match
();
}
else
{
print_command
(
vector_get
(
history
,
idx
));
if
(
handle_command
(
vector_get
(
history
,
idx
),
history
,
processes
))
{
char
*
last
=
vector_get
(
history
,
idx
);
vector_push_back
(
history
,
last
);
}
}
}
}
else
if
(((
char
*
)
vector_get
(
vec
,
0
))[
0
]
==
'#'
)
{
int
idx
=
atoi
(
line
+
1
);
if
((
unsigned
long
)
idx
>
vector_size
(
history
)
-
1
||
idx
<
0
)
{
print_invalid_index
();
}
else
{
print_command
(
vector_get
(
history
,
idx
));
if
(
handle_command
(
vector_get
(
history
,
idx
),
history
,
processes
))
{
char
*
last
=
vector_get
(
history
,
idx
);
vector_push_back
(
history
,
last
);
}
}
}
else
if
(
strcmp
(
vector_get
(
vec
,
0
),
"ps"
)
==
0
)
{
for
(
size_t
i
=
0
;
i
<
vector_size
(
processes
);
i
++
)
{
process
*
p
=
vector_get
(
processes
,
i
);
print_process_info
(
p
->
status
,
p
->
pid
,
p
->
command
);
}
result
=
1
;
}
else
if
(
strcmp
(
vector_get
(
vec
,
0
),
"kill"
)
==
0
)
{
if
(
vector_size
(
vec
)
!=
2
)
{
print_invalid_command
(
line
);
}
else
{
pid_t
found
=
0
;
process
*
p
;
for
(
size_t
i
=
0
;
i
<
vector_size
(
processes
);
i
++
)
{
p
=
vector_get
(
processes
,
i
);
if
(
p
->
pid
==
atoi
(
vector_get
(
vec
,
1
)))
{
found
=
p
->
pid
;
kill
(
found
,
SIGTERM
);
print_killed_process
(
p
->
pid
,
p
->
command
);
result
=
1
;
break
;
}
}
if
(
found
==
0
)
{
print_no_process_found
(
atoi
(
vector_get
(
vec
,
1
)));
}
}
}
else
if
(
strcmp
(
vector_get
(
vec
,
0
),
"stop"
)
==
0
)
{
if
(
vector_size
(
vec
)
!=
2
)
{
print_invalid_command
(
line
);
}
else
{
pid_t
found
=
0
;
process
*
p
;
for
(
size_t
i
=
0
;
i
<
vector_size
(
processes
);
i
++
)
{
p
=
vector_get
(
processes
,
i
);
if
(
p
->
pid
==
atoi
(
vector_get
(
vec
,
1
)))
{
found
=
p
->
pid
;
p
->
status
=
STATUS_STOPPED
;
kill
(
found
,
SIGTSTP
);
print_stopped_process
(
p
->
pid
,
p
->
command
);
result
=
1
;
break
;
}
}
if
(
found
==
0
)
{
print_no_process_found
(
atoi
(
vector_get
(
vec
,
1
)));
}
}
}
else
if
(
strcmp
(
vector_get
(
vec
,
0
),
"cont"
)
==
0
)
{
if
(
vector_size
(
vec
)
!=
2
)
{
print_invalid_command
(
line
);
}
else
{
pid_t
found
=
0
;
process
*
p
;
for
(
size_t
i
=
0
;
i
<
vector_size
(
processes
);
i
++
)
{
p
=
vector_get
(
processes
,
i
);
if
(
p
->
pid
==
atoi
(
vector_get
(
vec
,
1
)))
{
found
=
p
->
pid
;
p
->
status
=
STATUS_RUNNING
;
kill
(
found
,
SIGCONT
);
result
=
1
;
break
;
}
}
if
(
found
==
0
)
{
print_no_process_found
(
atoi
(
vector_get
(
vec
,
1
)));
}
}
}
else
if
(
line
[
strlen
(
line
)
-
1
]
==
'&'
)
{
fflush
(
stdout
);
char
newline
[
strlen
(
line
)];
strcpy
(
newline
,
line
);
newline
[
strlen
(
newline
)
-
1
]
=
'\0'
;
sstring
*
new_sstr
=
cstr_to_sstring
((
const
char
*
)
newline
);
vector
*
new_vec
=
sstring_split
(
new_sstr
,
' '
);
char
**
com
=
(
char
**
)
malloc
(
sizeof
(
char
*
)
*
(
vector_size
(
new_vec
)
+
1
));
pid_t
child
=
fork
();
if
(
child
==
-
1
)
{
print_fork_failed
();
exit
(
1
);
}
else
if
(
child
==
0
)
{
for
(
size_t
i
=
0
;
i
<
vector_size
(
new_vec
);
i
++
)
{
com
[
i
]
=
vector_get
(
new_vec
,
i
);
}
print_command_executed
(
getpid
());
execvp
(
com
[
0
],
com
);
print_exec_failed
(
newline
);
exit
(
1
);
}
else
{
if
(
setpgid
(
child
,
getpid
())
==
-
1
)
{
print_setpgid_failed
();
for
(
size_t
i
=
0
;
i
<
vector_size
(
processes
);
i
++
)
{
process
*
p
=
vector_get
(
processes
,
i
);
if
(
i
>=
1
)
{
int
status
;
waitpid
(
p
->
pid
,
&
status
,
0
);
free
(
p
->
command
);
}
free
(
p
);
}
vector_destroy
(
new_vec
);
sstring_destroy
(
new_sstr
);
free
(
com
);
sstring_destroy
(
sstr
);
vector_destroy
(
vec
);
vector_destroy
(
processes
);
vector_destroy
(
history
);
exit
(
1
);
}
process
*
bg
=
malloc
(
sizeof
(
process
));
bg
->
pid
=
child
;
bg
->
status
=
STATUS_RUNNING
;
bg
->
command
=
strdup
(
line
);
vector_push_back
(
processes
,
bg
);
result
=
1
;
}
vector_destroy
(
new_vec
);
sstring_destroy
(
new_sstr
);
free
(
com
);
}
else
{
fflush
(
stdout
);
char
**
com
=
(
char
**
)
malloc
(
sizeof
(
char
*
)
*
(
vector_size
(
vec
)
+
1
));
pid_t
child
=
fork
();
if
(
child
==
-
1
)
{
print_fork_failed
();
exit
(
1
);
}
else
if
(
child
==
0
)
{
for
(
size_t
i
=
0
;
i
<
vector_size
(
vec
);
i
++
)
{
com
[
i
]
=
vector_get
(
vec
,
i
);
}
print_command_executed
(
getpid
());
execvp
(
com
[
0
],
com
);
print_exec_failed
(
line
);
exit
(
1
);
}
else
{
int
status
=
0
;
waitpid
(
child
,
&
status
,
0
);
if
(
status
!=
0
)
{
print_wait_failed
();
}
else
{
result
=
1
;
}
}
free
(
com
);
}
sstring_destroy
(
sstr
);
vector_destroy
(
vec
);
if
(
result
==
1
)
return
1
;
else
return
0
;
}
int
seperator_idx
(
char
*
line
)
{
char
*
temp
=
line
;
int
idx
=
0
;
while
(
*
temp
)
{
if
(
*
temp
==
';'
)
{
return
idx
;
}
temp
++
;
idx
++
;
}
return
0
;
}
int
and_index
(
char
*
line
)
{
char
*
temp
=
line
;
int
idx
=
0
;
while
(
*
temp
)
{
if
(
*
temp
==
'&'
)
{
if
(
idx
+
1
<
(
int
)
strlen
(
line
))
return
idx
;
}
temp
++
;
idx
++
;
}
return
0
;
}
int
or_index
(
char
*
line
)
{
char
*
temp
=
line
;
int
idx
=
0
;
while
(
*
temp
)
{
if
(
*
temp
==
'|'
)
{
return
idx
;
}
temp
++
;
idx
++
;
}
return
0
;
}
void
handle_file
(
vector
*
history
,
char
*
path_f
,
vector
*
processes
)
{
FILE
*
f
=
fopen
(
path_f
,
"r"
);
if
(
!
f
)
{
print_script_file_error
();
return
;
}
pid_t
pid_sh
=
getpid
();
char
*
buffer
=
NULL
;
size_t
size
=
0
;
char
cwd
[
PATH_MAX
+
1
];
while
(
getline
(
&
buffer
,
&
size
,
f
)
!=
-
1
)
{
int
length
=
strlen
(
buffer
);
if
(
buffer
[
length
-
1
]
==
'\n'
)
{
buffer
[
length
-
1
]
=
'\0'
;
}
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
print_command
((
const
char
*
)
buffer
);
if
(
strlen
(
buffer
)
==
0
)
{
continue
;
}
sstring
*
str
=
cstr_to_sstring
(
buffer
);
int
idx
=
seperator_idx
(
buffer
);
if
(
idx
>
0
)
{
char
*
com1
=
sstring_slice
(
str
,
0
,
idx
);
char
*
com2
=
sstring_slice
(
str
,
idx
+
2
,
strlen
(
buffer
));
handle_command
(
com1
,
history
,
processes
);
handle_command
(
com2
,
history
,
processes
);
free
(
com1
);
free
(
com2
);
vector_push_back
(
history
,
buffer
);
sstring_destroy
(
str
);
continue
;
}
idx
=
and_index
(
buffer
);
if
(
idx
>
0
)
{
char
*
a
=
sstring_slice
(
str
,
0
,
idx
);
char
*
b
=
sstring_slice
(
str
,
idx
+
3
,
strlen
(
buffer
));
if
(
handle_command
(
a
,
history
,
processes
)
>
0
)
{
handle_command
(
b
,
history
,
processes
);
}
free
(
a
);
free
(
b
);
vector_push_back
(
history
,
buffer
);
sstring_destroy
(
str
);
continue
;
}
idx
=
or_index
(
buffer
);
if
(
idx
>
0
)
{
char
*
c
=
sstring_slice
(
str
,
0
,
idx
);
char
*
d
=
sstring_slice
(
str
,
idx
+
3
,
strlen
(
buffer
));
if
(
handle_command
(
c
,
history
,
processes
)
==
0
)
{
handle_command
(
d
,
history
,
processes
);
}
free
(
c
);
free
(
d
);
vector_push_back
(
history
,
buffer
);
sstring_destroy
(
str
);
continue
;
}
int
result
=
handle_command
(
buffer
,
history
,
processes
);
if
(
result
==
1
)
{
vector_push_back
(
history
,
buffer
);
}
sstring_destroy
(
str
);
}
free
(
buffer
);
fclose
(
f
);
}
void
sig_chld
(
int
signal
)
{
if
(
vector_size
(
processes
)
>
1
)
{
pid_t
pid
;
int
status
;
while
((
pid
=
waitpid
(
-
1
,
&
status
,
WNOHANG
))
>
0
)
{
for
(
size_t
i
=
1
;
i
<
vector_size
(
processes
);
i
++
)
{
process
*
p
=
vector_get
(
processes
,
i
);
if
(
p
->
pid
==
pid
)
{
free
(
p
->
command
);
free
(
p
);
vector_erase
(
processes
,
i
);
break
;
}
}
}
}
}
void
sig_int
(
int
signal
)
{
while
(
vector_size
(
processes
)
>
1
)
{
process
*
p
=
vector_get
(
processes
,
1
);
kill
(
p
->
pid
,
SIGTERM
);
}
}
int
shell
(
int
argc
,
char
*
argv
[])
{
// TODO: This is the entry point for your shell.
if
(
argc
>
5
||
argc
==
4
||
argc
==
2
)
{
print_usage
();
exit
(
1
);
}
if
(
argc
==
3
&&
strcmp
(
argv
[
1
],
"-h"
)
!=
0
&&
strcmp
(
argv
[
1
],
"-f"
)
!=
0
)
{
print_usage
();
exit
(
1
);
}
processes
=
shallow_vector_create
();
process
*
p_sh
=
malloc
(
sizeof
(
process
));
p_sh
->
command
=
"./shell"
;
p_sh
->
status
=
STATUS_RUNNING
;
p_sh
->
pid
=
getpid
();
vector_push_back
(
processes
,
p_sh
);
vector
*
history
=
string_vector_create
();
signal
(
SIGINT
,
sig_int
);
signal
(
SIGCHLD
,
sig_chld
);
if
(
argc
==
3
&&
strcmp
(
argv
[
1
],
"-f"
)
==
0
)
{
char
*
path_f
=
get_full_path
((
char
*
)
argv
[
2
]);
handle_file
(
history
,
path_f
,
processes
);
free
(
path_f
);
}
else
if
(
argc
==
5
)
{
if
(
strcmp
(
argv
[
1
],
"-h"
)
==
0
&&
strcmp
(
argv
[
3
],
"-f"
)
==
0
)
{
char
*
path_h
=
get_full_path
((
char
*
)
argv
[
2
]);
insert_history
(
history
,
path_h
);
free
(
path_h
);
char
*
path_f
=
get_full_path
((
char
*
)
argv
[
4
]);
handle_file
(
history
,
path_f
,
processes
);
free
(
path_f
);
}
else
if
(
strcmp
(
argv
[
1
],
"-f"
)
==
0
&&
strcmp
(
argv
[
3
],
"-h"
)
==
0
)
{
char
*
path_h
=
get_full_path
((
char
*
)
argv
[
4
]);
insert_history
(
history
,
path_h
);
free
(
path_h
);
char
*
path_f
=
get_full_path
((
char
*
)
argv
[
2
]);
handle_file
(
history
,
path_f
,
processes
);
free
(
path_f
);
}
else
{
print_usage
();
vector_destroy
(
processes
);
vector_destroy
(
history
);
exit
(
1
);
}
}
else
{
if
(
argc
==
3
)
{
char
*
path_h
=
get_full_path
((
char
*
)
argv
[
2
]);
insert_history
(
history
,
path_h
);
free
(
path_h
);
}
size_t
size
=
0
;
char
*
buffer
=
NULL
;
char
cwd
[
PATH_MAX
+
1
];
pid_t
pid_sh
=
getpid
();
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
while
(
getline
(
&
buffer
,
&
size
,
stdin
)
!=
-
1
)
{
int
length
=
strlen
(
buffer
);
if
(
buffer
[
length
-
1
]
==
'\n'
)
{
buffer
[
length
-
1
]
=
'\0'
;
}
if
(
strlen
(
buffer
)
==
0
)
{
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
continue
;
}
if
(
strcmp
(
buffer
,
"exit"
)
==
0
)
{
break
;
}
sstring
*
str
=
cstr_to_sstring
(
buffer
);
int
idx
=
seperator_idx
(
buffer
);
if
(
idx
>
0
)
{
char
*
com1
=
sstring_slice
(
str
,
0
,
idx
);
char
*
com2
=
sstring_slice
(
str
,
idx
+
2
,
strlen
(
buffer
));
handle_command
(
com1
,
history
,
processes
);
handle_command
(
com2
,
history
,
processes
);
free
(
com1
);
free
(
com2
);
vector_push_back
(
history
,
buffer
);
sstring_destroy
(
str
);
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
continue
;
}
idx
=
and_index
(
buffer
);
if
(
idx
>
0
)
{
char
*
a
=
sstring_slice
(
str
,
0
,
idx
);
char
*
b
=
sstring_slice
(
str
,
idx
+
3
,
strlen
(
buffer
));
if
(
handle_command
(
a
,
history
,
processes
)
>
0
)
{
handle_command
(
b
,
history
,
processes
);
}
free
(
a
);
free
(
b
);
vector_push_back
(
history
,
buffer
);
sstring_destroy
(
str
);
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
continue
;
}
idx
=
or_index
(
buffer
);
if
(
idx
>
0
)
{
char
*
c
=
sstring_slice
(
str
,
0
,
idx
);
char
*
d
=
sstring_slice
(
str
,
idx
+
3
,
strlen
(
buffer
));
if
(
handle_command
(
c
,
history
,
processes
)
==
0
)
{
handle_command
(
d
,
history
,
processes
);
}
free
(
c
);
free
(
d
);
vector_push_back
(
history
,
buffer
);
sstring_destroy
(
str
);
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
continue
;
}
int
result
=
handle_command
(
buffer
,
history
,
processes
);
if
(
result
==
1
)
{
vector_push_back
(
history
,
buffer
);
}
getcwd
(
cwd
,
sizeof
(
cwd
));
print_prompt
(
cwd
,
pid_sh
);
sstring_destroy
(
str
);
}
free
(
buffer
);
}
while
(
vector_size
(
processes
)
>
1
)
{
process
*
p
=
vector_get
(
processes
,
1
);
kill
(
p
->
pid
,
SIGTERM
);
}
process
*
p
=
vector_get
(
processes
,
0
);
free
(
p
);
if
(
argc
==
3
)
{
if
(
strcmp
(
argv
[
1
],
"-h"
)
==
0
)
{
char
*
pa
=
get_full_path
((
char
*
)
argv
[
2
]);
write_history
(
history
,
pa
);
free
(
pa
);
}
}
if
(
argc
==
5
)
{
if
(
strcmp
(
argv
[
3
],
"-h"
)
==
0
)
{
char
*
pa
=
get_full_path
((
char
*
)
argv
[
4
]);
write_history
(
history
,
pa
);
free
(
pa
);
}
}
vector_destroy
(
processes
);
vector_destroy
(
history
);
return
0
;
}
This diff is collapsed.
Click to expand it.
shell.h
0 → 100644
+
14
−
0
View file @
83d83d5a
/**
* Shell Lab
* CS 241 - Fall 2018
*/
/**
* this file exists so that we can provide a main method which does a variety of
* handy things.
*
* DO NOT EDIT THIS FILE!
*/
// entry point for student code
int
shell
(
int
argc
,
char
**
argv
);
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment