Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
U
uva
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
uva
Commits
04b26d4e
Commit
04b26d4e
authored
Jan 07, 2011
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
OS: executing binaries is now supported.
parent
511058ba
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
187 additions
and
9 deletions
+187
-9
os/extra/src/input.l
os/extra/src/input.l
+2
-2
os/extra/src/input.l.h
os/extra/src/input.l.h
+1
-0
os/extra/src/main.c
os/extra/src/main.c
+184
-7
No files found.
os/extra/src/input.l
View file @
04b26d4e
...
@@ -70,7 +70,7 @@ cd {
...
@@ -70,7 +70,7 @@ cd {
return CD;
return CD;
}
}
/* Identifiers: source */
/* Identifiers: source
, cat, echo
*/
{id} {
{id} {
column_no += yyleng;
column_no += yyleng;
yylval.str = strdup(yytext);
yylval.str = strdup(yytext);
...
@@ -97,7 +97,7 @@ cd {
...
@@ -97,7 +97,7 @@ cd {
}
}
/* Argument (filenames and such): hello.txt, .config */
/* Argument (filenames and such): hello.txt, .config */
{id}[^\t\n ]+ {
{id}[^\t\n
|
]+ {
column_no += yyleng;
column_no += yyleng;
yylval.str = strdup(yytext);
yylval.str = strdup(yytext);
return ARGUMENT;
return ARGUMENT;
...
...
os/extra/src/input.l.h
View file @
04b26d4e
...
@@ -61,6 +61,7 @@ void shell_help();
...
@@ -61,6 +61,7 @@ void shell_help();
void
shell_pipe
();
void
shell_pipe
();
void
shell_repeat
(
int
prev
);
void
shell_repeat
(
int
prev
);
void
shell_exec
(
shell_args
*
args
);
void
shell_exec
(
shell_args
*
args
);
void
shell_exec_process
(
shell_args
*
args
);
/*
/*
* Doubly linked list containing all executed commands.
* Doubly linked list containing all executed commands.
...
...
os/extra/src/main.c
View file @
04b26d4e
...
@@ -12,6 +12,8 @@
...
@@ -12,6 +12,8 @@
#include <unistd.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdarg.h>
#include <math.h>
#include <math.h>
#include <signal.h>
#include <sys/wait.h>
#include "input.yacc.h"
#include "input.yacc.h"
#include "input.lex.h"
#include "input.lex.h"
...
@@ -133,18 +135,135 @@ shell_args *shell_pop_args() {
...
@@ -133,18 +135,135 @@ shell_args *shell_pop_args() {
void
shell_exec
(
shell_args
*
args
)
{
void
shell_exec
(
shell_args
*
args
)
{
assert
(
args
&&
args
->
arg
);
assert
(
args
&&
args
->
arg
);
shell_debug
(
"exec
%s
"
,
args
->
arg
);
shell_debug
(
"exec
`%s'
"
,
args
->
arg
);
// TODO: handle arguments.
// TODO: handle arguments.
shell_args
*
cur
=
args
->
next
;
shell_args
*
cur
=
args
->
next
;
while
(
cur
)
{
while
(
cur
)
{
assert
(
cur
->
arg
);
shell_debug
(
"argument: `%s'"
,
cur
->
arg
);
shell_debug
(
"argument: %s"
,
cur
->
arg
);
cur
=
cur
->
next
;
cur
=
cur
->
next
;
}
}
// Append to command history.
// Fork the process and handle forking error.
shell_history_append
(
FN_EXEC
,
args
);
pid_t
pid
=
fork
();
switch
(
pid
)
{
case
-
1
:
shell_error
(
"Error when forking"
);
exit
(
EXIT_FAILURE
);
case
0
:
shell_debug
(
"Child process #%d is ready."
,
getpid
());
shell_exec_process
(
args
);
break
;
default:
shell_debug
(
"Parent launched child process #%d."
,
pid
);
shell_history_append
(
FN_EXEC
,
args
);
}
}
/*
* Helper function for shell_exec(), which executes the process using execv()
* and handles all occurred errors caused by execv().
*/
void
shell_exec_process
(
shell_args
*
args
)
{
assert
(
args
&&
args
->
arg
);
char
*
bin
=
malloc
((
5
+
strlen
(
args
->
arg
)
+
1
)
*
sizeof
(
char
));
bin
=
strcpy
(
strcpy
(
bin
,
"/bin/"
)
+
5
,
args
->
arg
)
-
5
;
// Count the arguments.
int
argc
=
0
;
for
(
shell_args
*
arg
=
args
;
arg
;
arg
=
arg
->
next
,
argc
++
);
// Convert argument structure to list of strings. And add a NULL pointer as
// a marker for the end of the list. The first string should point to the
// binary being executed.
char
**
argv
=
malloc
((
argc
+
1
)
*
sizeof
(
char
*
));
argv
[
0
]
=
bin
;
shell_args
*
cur
=
args
+
sizeof
(
shell_args
*
);
for
(
int
a
=
0
;
a
<
argc
&&
cur
;
cur
=
args
->
next
,
a
++
)
argv
[
a
]
=
strdup
(
cur
->
arg
);
argv
[
argc
]
=
NULL
;
// Function execvp() searches in PATH-environment, which is more flexible
// (user can set its own preferences), but the assignment states execv()
// should be used, because only binaries in /bin should be loaded.
shell_debug
(
"execv(%s, [...]) called.
\n
"
,
bin
);
execv
(
bin
,
argv
);
// If the execv() call returns, an error occurred and errno contains the
// error number corresponding with the error occurred.
switch
(
errno
)
{
case
E2BIG
:
shell_error
(
"The total number of bytes in the environment (envp)"
" and argument list (argv) is too large."
);
break
;
case
EACCES
:
shell_error
(
"Search permission is denied on a component of the"
" path prefix of filename or the name of a script "
" interpreter. The file or a script interpreter is not a"
" regular file. Execute permission is denied for the file"
" or a script or ELF interpreter. The file system is"
" mounted noexec."
);
break
;
case
EFAULT
:
shell_error
(
"Filename points outside accessible address space."
);
break
;
case
EINVAL
:
shell_error
(
"An ELF executable had more than one PT_INTERP segment"
" (i.e., tried to name more than one interpreter)."
);
break
;
case
EIO
:
shell_error
(
"An I/O error occurred."
);
break
;
case
EISDIR
:
shell_error
(
"An ELF interpreter was a directory."
);
break
;
case
ELIBBAD
:
shell_error
(
"An ELF interpreter was not in a recognized format."
);
break
;
case
ELOOP
:
shell_error
(
"Too many symbolic links were encountered in resolving"
" filename or the name of a script or ELF interpreter."
);
break
;
case
EMFILE
:
shell_error
(
"The process has the maximum number of files open."
);
break
;
case
ENAMETOOLONG
:
shell_error
(
"Filename is too long."
);
break
;
case
ENFILE
:
shell_error
(
"The system limit on the total number of open files"
" has been reached."
);
break
;
case
ENOENT
:
shell_error
(
"The file filename or a script or ELF interpreter does"
" not exist, or a shared library needed for file or"
" interpreter cannot be found."
);
break
;
case
ENOEXEC
:
shell_error
(
"An executable is not in a recognized format, is for"
" the wrong architecture, or has some other format error"
" that means it cannot be executed."
);
break
;
case
ENOMEM
:
shell_error
(
"Insufficient kernel memory was available."
);
break
;
case
ENOTDIR
:
shell_error
(
"A component of the path prefix of filename or a"
" script or ELF interpreter is not a directory."
);
break
;
case
EPERM
:
shell_error
(
"The file system is mounted nosuid, the user is"
" not the superuser, and the file has the set-user-ID or"
" set-group-ID bit set. The process is being traced, the"
" user is not the superuser and the file has the "
" set-user-ID or set-group-ID bit set."
);
break
;
case
ETXTBSY
:
shell_error
(
"Executable was open for writing by one or more"
" processes."
);
break
;
}
}
}
void
shell_pipe
()
{
void
shell_pipe
()
{
...
@@ -165,6 +284,12 @@ void shell_exit() {
...
@@ -165,6 +284,12 @@ void shell_exit() {
void
shell_help
()
{
void
shell_help
()
{
// TODO: implement help text.
// TODO: implement help text.
puts
(
"Builtin commands / macros:"
);
puts
(
" cd PATH - Change current working directory to PATH."
);
puts
(
" exit - Exit this shell (also CTRL + D)."
);
puts
(
" help - This help text."
);
puts
(
" !! - Repeat previous shell command."
);
puts
(
" !N - Repeat Nth previous shell command."
);
// Append to command history.
// Append to command history.
shell_history_append
(
FN_HELP
,
NULL
);
shell_history_append
(
FN_HELP
,
NULL
);
...
@@ -173,7 +298,7 @@ void shell_help() {
...
@@ -173,7 +298,7 @@ void shell_help() {
/*
/*
* Change the current working directory of the shell. This function handles
* Change the current working directory of the shell. This function handles
* absolute and relative paths and will return 0 when the directory is
* absolute and relative paths and will return 0 when the directory is
* successfully changed, or otherwise 1 in case of an error (e.g.
path does not
* successfully changed, or otherwise 1 in case of an error (e.g. path does not
* exist).
* exist).
*/
*/
void
shell_change_dir
(
const
char
*
path
)
{
void
shell_change_dir
(
const
char
*
path
)
{
...
@@ -249,10 +374,13 @@ shell_cmd *shell_history_get(int prev) {
...
@@ -249,10 +374,13 @@ shell_cmd *shell_history_get(int prev) {
assert
(
cur
);
assert
(
cur
);
assert
(
cur
->
cmd
);
assert
(
cur
->
cmd
);
assert
(
cur
->
cmd
->
args
);
assert
(
cur
->
cmd
->
args
);
printf
(
"skipping [%d]: %s
\n
"
,
prev
,
cur
->
cmd
->
args
->
arg
);
shell_debug
(
"skipping [%d]: %s
\n
"
,
prev
,
cur
->
cmd
->
args
->
arg
);
cur
=
cur
->
prev
;
cur
=
cur
->
prev
;
}
}
if
(
cur
)
shell_debug
(
"found [%d]: %s
\n
"
,
prev
,
cur
->
cmd
->
args
->
arg
);
return
cur
?
cur
->
cmd
:
NULL
;
return
cur
?
cur
->
cmd
:
NULL
;
}
}
...
@@ -302,7 +430,56 @@ void shell_repeat(int prev) {
...
@@ -302,7 +430,56 @@ void shell_repeat(int prev) {
shell_history_add
(
cmd
);
shell_history_add
(
cmd
);
}
}
/*
* Process number of the parent shell.
*/
pid_t
parent_pid
;
/*
* Signal handler for SIGINT, SIGTERM and SIGCHLD.
*/
void
signal_handler
(
int
signum
)
{
char
*
sig
=
"TERM"
;
pid_t
pid
;
// TODO: implement signal handling
switch
(
signum
)
{
case
SIGINT
:
sig
=
"INT"
;
case
SIGTERM
:
if
(
(
pid
=
getpid
())
==
parent_pid
)
printf
(
"Parent process received SIG%s and will exit.
\n
"
,
sig
);
else
printf
(
"Process #%d received SIG%s and will exit.
\n
"
,
pid
,
sig
);
exit
(
1
);
case
SIGCHLD
:
puts
(
"Parent process received SIGCHLD."
);
pid
=
wait
(
NULL
);
printf
(
"Child with id %d exited.
\n
"
,
pid
);
break
;
default:
puts
(
"This handler does not understand this type of signal."
);
}
}
/*
* Main function, initiates the program.
*/
int
main
(
void
)
{
int
main
(
void
)
{
struct
sigaction
action
=
{.
sa_handler
=
signal_handler
};
parent_pid
=
getpid
();
// Bind signal handlers
if
(
sigaction
(
SIGINT
,
&
action
,
NULL
)
||
sigaction
(
SIGTERM
,
&
action
,
NULL
)
||
sigaction
(
SIGCHLD
,
&
action
,
NULL
)
)
{
perror
(
"An error occured while binding the signal handlers.
\n
"
);
exit
(
1
);
}
// Detect if terminal is attached.
// Detect if terminal is attached.
struct
stat
stats
;
struct
stat
stats
;
fstat
(
0
,
&
stats
);
fstat
(
0
,
&
stats
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment