Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
uva
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
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
Taddeüs Kroes
uva
Commits
04b26d4e
Commit
04b26d4e
authored
14 years ago
by
Sander Mathijs van Veen
Browse files
Options
Downloads
Patches
Plain Diff
OS: executing binaries is now supported.
parent
511058ba
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
os/extra/src/input.l
+2
-2
2 additions, 2 deletions
os/extra/src/input.l
os/extra/src/input.l.h
+1
-0
1 addition, 0 deletions
os/extra/src/input.l.h
os/extra/src/main.c
+184
-7
184 additions, 7 deletions
os/extra/src/main.c
with
187 additions
and
9 deletions
os/extra/src/input.l
+
2
−
2
View file @
04b26d4e
...
...
@@ -70,7 +70,7 @@ cd {
return CD;
}
/* Identifiers: source */
/* Identifiers: source
, cat, echo
*/
{id} {
column_no += yyleng;
yylval.str = strdup(yytext);
...
...
@@ -97,7 +97,7 @@ cd {
}
/* Argument (filenames and such): hello.txt, .config */
{id}[^\t\n ]+ {
{id}[^\t\n
|
]+ {
column_no += yyleng;
yylval.str = strdup(yytext);
return ARGUMENT;
...
...
This diff is collapsed.
Click to expand it.
os/extra/src/input.l.h
+
1
−
0
View file @
04b26d4e
...
...
@@ -61,6 +61,7 @@ void shell_help();
void
shell_pipe
();
void
shell_repeat
(
int
prev
);
void
shell_exec
(
shell_args
*
args
);
void
shell_exec_process
(
shell_args
*
args
);
/*
* Doubly linked list containing all executed commands.
...
...
This diff is collapsed.
Click to expand it.
os/extra/src/main.c
+
184
−
7
View file @
04b26d4e
...
...
@@ -12,6 +12,8 @@
#include
<unistd.h>
#include
<stdarg.h>
#include
<math.h>
#include
<signal.h>
#include
<sys/wait.h>
#include
"input.yacc.h"
#include
"input.lex.h"
...
...
@@ -133,18 +135,135 @@ shell_args *shell_pop_args() {
void
shell_exec
(
shell_args
*
args
)
{
assert
(
args
&&
args
->
arg
);
shell_debug
(
"exec %s"
,
args
->
arg
);
shell_debug
(
"exec
`
%s
'
"
,
args
->
arg
);
// TODO: handle arguments.
shell_args
*
cur
=
args
->
next
;
while
(
cur
)
{
assert
(
cur
->
arg
);
shell_debug
(
"argument: %s"
,
cur
->
arg
);
shell_debug
(
"argument: `%s'"
,
cur
->
arg
);
cur
=
cur
->
next
;
}
// Append to command history.
shell_history_append
(
FN_EXEC
,
args
);
// Fork the process and handle forking error.
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
()
{
...
...
@@ -165,6 +284,12 @@ void shell_exit() {
void
shell_help
()
{
// 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.
shell_history_append
(
FN_HELP
,
NULL
);
...
...
@@ -173,7 +298,7 @@ void shell_help() {
/*
* Change the current working directory of the shell. This function handles
* 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).
*/
void
shell_change_dir
(
const
char
*
path
)
{
...
...
@@ -249,10 +374,13 @@ shell_cmd *shell_history_get(int prev) {
assert
(
cur
);
assert
(
cur
->
cmd
);
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
;
}
if
(
cur
)
shell_debug
(
"found [%d]: %s
\n
"
,
prev
,
cur
->
cmd
->
args
->
arg
);
return
cur
?
cur
->
cmd
:
NULL
;
}
...
...
@@ -302,7 +430,56 @@ void shell_repeat(int prev) {
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
)
{
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.
struct
stat
stats
;
fstat
(
0
,
&
stats
);
...
...
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