Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
Cs283
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
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Joey Le
Cs283
Commits
4143e2cd
Commit
4143e2cd
authored
3 months ago
by
Joey Le
Browse files
Options
Downloads
Patches
Plain Diff
Fixed a bunch of the functions. Hopefully it works now
parent
52c21eea
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
Assignment-06/starter/dshlib.c
+56
-70
56 additions, 70 deletions
Assignment-06/starter/dshlib.c
Assignment-06/starter/rsh_cli.c
+59
-19
59 additions, 19 deletions
Assignment-06/starter/rsh_cli.c
Assignment-06/starter/rsh_server.c
+90
-63
90 additions, 63 deletions
Assignment-06/starter/rsh_server.c
with
205 additions
and
152 deletions
Assignment-06/starter/dshlib.c
+
56
−
70
View file @
4143e2cd
...
...
@@ -263,58 +263,40 @@ static void start_server() {
* fork(), execvp(), exit(), chdir()
*/
int
exec_remote_cmd_loop
(
char
*
address
,
int
port
)
{
char
cmd_buff
[
RDSH_COMM_BUFF_SZ
];
char
rsp_buff
[
RDSH_COMM_BUFF_SZ
];
int
cli_socket
;
ssize_t
recv_bytes
;
int
is_eof
;
int
exec_local_cmd_loop
()
{
char
cmd_buff
[
SH_CMD_MAX
];
int
rc
=
OK
;
while
(
1
)
{
printf
(
"%s"
,
SH_PROMPT
);
if
(
fgets
(
cmd_buff
,
SH_CMD_MAX
,
stdin
)
==
NULL
)
{
printf
(
"
\n
"
);
break
;
// Connect to the server
cli_socket
=
start_client
(
address
,
port
);
if
(
cli_socket
<
0
)
{
perror
(
"start client"
);
return
client_cleanup
(
cli_socket
,
NULL
,
NULL
,
ERR_RDSH_CLIENT
);
}
cmd_buff
[
strcspn
(
cmd_buff
,
"
\n
"
)]
=
'\0'
;
if
(
strlen
(
cmd_buff
)
==
0
)
{
printf
(
"%s
\n
"
,
CMD_WARN_NO_CMD
);
rc
=
WARN_NO_CMDS
;
continue
;
while
(
1
)
{
printf
(
"rsh> "
);
if
(
!
fgets
(
cmd_buff
,
RDSH_COMM_BUFF_SZ
,
stdin
))
{
break
;
// Exit on input error or EOF
}
if
(
strstr
(
cmd_buff
,
"|"
)
!=
NULL
)
{
command_list_t
cmd_list
;
if
(
parse_pipeline
(
cmd_buff
,
&
cmd_list
)
!=
OK
)
{
fprintf
(
stderr
,
"%s
\n
"
,
CMD_ERR_PIPE_LIMIT
);
rc
=
ERR_TOO_MANY_COMMANDS
;
continue
;
// Remove the newline character from the command
size_t
cmd_len
=
strlen
(
cmd_buff
);
if
(
cmd_len
>
0
&&
cmd_buff
[
cmd_len
-
1
]
==
'\n'
)
{
cmd_buff
[
cmd_len
-
1
]
=
'\0'
;
}
// Execute the pipeline
execute_pipeline
(
&
cmd_list
);
// Free memory for each command's buffer
for
(
int
i
=
0
;
i
<
cmd_list
.
num
;
i
++
)
{
free
(
cmd_list
.
commands
[
i
].
_cmd_buffer
);
}
}
else
{
// Handle local commands (e.g., cd, exit)
if
(
strncmp
(
cmd_buff
,
"cd"
,
2
)
==
0
)
{
// Handle cd locally
cmd_buff_t
cmd
;
if
(
build_cmd_buff
(
cmd_buff
,
&
cmd
)
!=
OK
)
{
fprintf
(
stderr
,
"%s
\n
"
,
CMD_ERR_PIPE_LIMIT
);
rc
=
ERR_MEMORY
;
continue
;
}
if
(
strcmp
(
cmd
.
argv
[
0
],
EXIT_CMD
)
==
0
)
{
free
(
cmd
.
_cmd_buffer
);
break
;
}
if
(
strcmp
(
cmd
.
argv
[
0
],
"cd"
)
==
0
)
{
if
(
cmd
.
argc
==
1
)
{
chdir
(
getenv
(
"HOME"
));
}
else
if
(
cmd
.
argc
==
2
)
{
...
...
@@ -326,31 +308,35 @@ int exec_local_cmd_loop() {
}
free
(
cmd
.
_cmd_buffer
);
continue
;
}
else
if
(
strncmp
(
cmd_buff
,
"exit"
,
4
)
==
0
)
{
break
;
// Exit the remote shell
}
pid_t
pid
=
fork
();
if
(
pid
<
0
)
{
perror
(
"fork failed"
);
rc
=
ERR_MEMORY
;
}
else
if
(
pid
==
0
)
{
execvp
(
cmd
.
argv
[
0
],
cmd
.
argv
);
perror
(
"execvp failed"
);
exit
(
EXIT_FAILURE
);
}
else
{
int
status
;
wait
(
&
status
);
if
(
WIFEXITED
(
status
))
{
if
(
WEXITSTATUS
(
status
)
!=
0
)
{
fprintf
(
stderr
,
"Command failed with exit code %d
\n
"
,
WEXITSTATUS
(
status
));
// Send the command to the server
ssize_t
sent_bytes
=
send
(
cli_socket
,
cmd_buff
,
strlen
(
cmd_buff
),
0
);
if
(
sent_bytes
<
0
)
{
perror
(
"send"
);
return
client_cleanup
(
cli_socket
,
NULL
,
NULL
,
ERR_RDSH_COMMUNICATION
);
}
// Receive the server's response
is_eof
=
0
;
while
((
recv_bytes
=
recv
(
cli_socket
,
rsp_buff
,
RDSH_COMM_BUFF_SZ
,
0
))
>
0
)
{
printf
(
"%.*s"
,
(
int
)
recv_bytes
,
rsp_buff
);
if
(
rsp_buff
[
recv_bytes
-
1
]
==
RDSH_EOF_CHAR
)
{
is_eof
=
1
;
break
;
}
}
free
(
cmd
.
_cmd_buffer
);
if
(
recv_bytes
<
0
)
{
perror
(
"recv"
);
return
client_cleanup
(
cli_socket
,
NULL
,
NULL
,
ERR_RDSH_COMMUNICATION
);
}
else
if
(
recv_bytes
==
0
)
{
printf
(
"Server closed the connection
\n
"
);
break
;
}
}
return
r
c
;
return
c
lient_cleanup
(
cli_socket
,
NULL
,
NULL
,
OK
)
;
}
This diff is collapsed.
Click to expand it.
Assignment-06/starter/rsh_cli.c
+
59
−
19
View file @
4143e2cd
...
...
@@ -92,32 +92,49 @@
*/
int
exec_remote_cmd_loop
(
char
*
address
,
int
port
)
{
char
*
cmd_buff
;
char
*
rsp_buff
;
char
cmd_buff
[
RDSH_COMM_BUFF_SZ
];
// Use the buffer size from rshlib.h
char
rsp_buff
[
RDSH_COMM_BUFF_SZ
]
;
int
cli_socket
;
ssize_t
io_size
;
ssize_t
recv_bytes
;
int
is_eof
;
// TODO set up cmd and response buffs
// Connect to the server
cli_socket
=
start_client
(
address
,
port
);
if
(
cli_socket
<
0
)
{
perror
(
"start client"
);
return
client_cleanup
(
cli_socket
,
cmd_buff
,
rsp_buff
,
ERR_RDSH_CLIENT
);
return
client_cleanup
(
cli_socket
,
NULL
,
NULL
,
ERR_RDSH_CLIENT
);
}
while
(
1
)
{
// TODO print prompt
while
(
1
)
{
printf
(
"rsh> "
);
if
(
!
fgets
(
cmd_buff
,
RDSH_COMM_BUFF_SZ
,
stdin
))
{
break
;
}
// TODO fgets input
if
(
send
(
cli_socket
,
cmd_buff
,
strlen
(
cmd_buff
),
0
)
<
0
)
{
perror
(
"send"
);
return
client_cleanup
(
cli_socket
,
NULL
,
NULL
,
ERR_RDSH_COMMUNICATION
);
}
// TODO send() over cli_socket
is_eof
=
0
;
while
((
recv_bytes
=
recv
(
cli_socket
,
rsp_buff
,
RDSH_COMM_BUFF_SZ
,
0
))
>
0
)
{
printf
(
"%.*s"
,
(
int
)
recv_bytes
,
rsp_buff
);
// Print the received data
if
(
rsp_buff
[
recv_bytes
-
1
]
==
RDSH_EOF_CHAR
)
{
is_eof
=
1
;
// Check for EOF character
break
;
}
}
// TODO recv all the results
if
(
recv_bytes
<
0
)
{
perror
(
"recv"
);
return
client_cleanup
(
cli_socket
,
NULL
,
NULL
,
ERR_RDSH_COMMUNICATION
);
}
// TODO break on exit command
if
(
strncmp
(
cmd_buff
,
"exit"
,
4
)
==
0
||
strncmp
(
cmd_buff
,
"stop-server"
,
11
)
==
0
)
{
break
;
}
}
return
client_cleanup
(
cli_socket
,
cmd_buff
,
rsp_buff
,
OK
);
}
...
...
@@ -151,6 +168,29 @@ int start_client(char *server_ip, int port){
int
ret
;
// TODO set up cli_socket
cli_socket
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
cli_socket
<
0
)
{
perror
(
"socket"
);
return
ERR_RDSH_CLIENT
;
}
// Set up the server address structure
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
sin_family
=
AF_INET
;
addr
.
sin_port
=
htons
(
port
);
if
(
inet_pton
(
AF_INET
,
server_ip
,
&
addr
.
sin_addr
)
<=
0
)
{
perror
(
"inet_pton"
);
close
(
cli_socket
);
return
ERR_RDSH_CLIENT
;
}
// Connect to the server
ret
=
connect
(
cli_socket
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
if
(
ret
<
0
)
{
perror
(
"connect"
);
close
(
cli_socket
);
return
ERR_RDSH_CLIENT
;
}
return
cli_socket
;
...
...
This diff is collapsed.
Click to expand it.
Assignment-06/starter/rsh_server.c
+
90
−
63
View file @
4143e2cd
...
...
@@ -302,73 +302,109 @@ int boot_server(char *ifaces, int port){
*/
int
exec_client_requests
(
int
cli_socket
)
{
char
*
io_buff
;
int
io_size
;
command_list_t
cmd_list
;
char
cmd_buff
[
RDSH_COMM_BUFF_SZ
];
ssize_t
recv_bytes
;
int
rc
=
OK
;
// Allocate a buffer for I/O operations
io_buff
=
malloc
(
RDSH_COMM_BUFF_SZ
);
if
(
io_buff
==
NULL
)
{
return
ERR_RDSH_SERVER
;
// Return server error if allocation fails
}
while
(
1
)
{
// Receive input from the client
io_size
=
recv
(
cli_socket
,
io_buff
,
RDSH_COMM_BUFF_SZ
,
0
);
if
(
io_size
<
0
)
{
perror
(
"recv"
);
free
(
io_buff
);
return
ERR_RDSH_COMMUNICATION
;
// Return communication error
}
else
if
(
io_size
==
0
)
{
// Client disconnected
free
(
io_buff
);
return
OK
;
// Return OK to accept another client
recv_bytes
=
recv
(
cli_socket
,
cmd_buff
,
RDSH_COMM_BUFF_SZ
,
0
);
if
(
recv_bytes
<=
0
)
{
close
(
cli_socket
);
printf
(
"Client disconnected
\n
"
);
return
OK
;
}
// Null-terminate the received data
io_buff
[
io_size
]
=
'\0'
;
cmd_buff
[
recv_bytes
]
=
'\0'
;
// Check for special commands
if
(
strncmp
(
io_buff
,
"exit"
,
strlen
(
"exit"
))
==
0
)
{
// Client sent the `exit` command
free
(
io_buff
);
return
OK
;
// Return OK to accept another client
}
else
if
(
strncmp
(
io_buff
,
"stop-server"
,
strlen
(
"stop-server"
))
==
0
)
{
// Client sent the `stop-server` command
free
(
io_buff
);
return
OK_EXIT
;
// Return OK_EXIT to stop the server
}
// Parse the input into a command list
rc
=
parse_pipeline
(
io_buff
,
&
cmd_list
);
if
(
rc
!=
OK
)
{
// Handle parsing error
send_message_string
(
cli_socket
,
CMD_ERR_RDSH_EXEC
);
cmd_buff
[
strcspn
(
cmd_buff
,
"
\n
"
)]
=
'\0'
;
if
(
strlen
(
cmd_buff
)
==
0
)
{
send_message_string
(
cli_socket
,
CMD_WARN_NO_CMD
);
send_message_eof
(
cli_socket
);
continue
;
// Continue to the next iteration
rc
=
WARN_NO_CMDS
;
continue
;
}
// Execute the command pipeline
rc
=
rsh_execute_pipeline
(
cli_socket
,
&
cmd_list
);
if
(
rc
<
0
)
{
// Handle execution error
send_message_string
(
cli_socket
,
CMD_ERR_RDSH_EXEC
);
if
(
strstr
(
cmd_buff
,
"|"
)
!=
NULL
)
{
command_list_t
cmd_list
;
if
(
parse_pipeline
(
cmd_buff
,
&
cmd_list
)
!=
OK
)
{
send_message_string
(
cli_socket
,
CMD_ERR_PIPE_LIMIT
);
send_message_eof
(
cli_socket
);
continue
;
// Continue to the next iteration
rc
=
ERR_TOO_MANY_COMMANDS
;
continue
;
}
// Free memory for each command's buffer
rc
=
rsh_execute_pipeline
(
cli_socket
,
&
cmd_list
);
for
(
int
i
=
0
;
i
<
cmd_list
.
num
;
i
++
)
{
free
(
cmd_list
.
commands
[
i
].
_cmd_buffer
);
}
}
else
{
cmd_buff_t
cmd
;
if
(
build_cmd_buff
(
cmd_buff
,
&
cmd
)
!=
OK
)
{
send_message_string
(
cli_socket
,
CMD_ERR_PIPE_LIMIT
);
send_message_eof
(
cli_socket
);
rc
=
ERR_MEMORY
;
continue
;
}
if
(
strcmp
(
cmd
.
argv
[
0
],
EXIT_CMD
)
==
0
)
{
free
(
cmd
.
_cmd_buffer
);
send_message_string
(
cli_socket
,
"Exiting...
\n
"
);
send_message_eof
(
cli_socket
);
return
OK
;
}
else
if
(
strcmp
(
cmd
.
argv
[
0
],
"stop-server"
)
==
0
)
{
free
(
cmd
.
_cmd_buffer
);
send_message_string
(
cli_socket
,
"Stopping server...
\n
"
);
send_message_eof
(
cli_socket
);
return
OK_EXIT
;
}
else
if
(
strcmp
(
cmd
.
argv
[
0
],
"cd"
)
==
0
)
{
if
(
cmd
.
argc
==
1
)
{
chdir
(
getenv
(
"HOME"
));
}
else
if
(
cmd
.
argc
==
2
)
{
if
(
chdir
(
cmd
.
argv
[
1
])
!=
0
)
{
char
error_msg
[
256
];
snprintf
(
error_msg
,
sizeof
(
error_msg
),
"cd: %s
\n
"
,
strerror
(
errno
));
send_message_string
(
cli_socket
,
error_msg
);
}
}
else
{
send_message_string
(
cli_socket
,
CMD_ERR_PIPE_LIMIT
);
}
send_message_eof
(
cli_socket
);
free
(
cmd
.
_cmd_buffer
);
continue
;
}
pid_t
pid
=
fork
();
if
(
pid
<
0
)
{
perror
(
"fork failed"
);
rc
=
ERR_MEMORY
;
}
else
if
(
pid
==
0
)
{
execvp
(
cmd
.
argv
[
0
],
cmd
.
argv
);
perror
(
"execvp failed"
);
exit
(
EXIT_FAILURE
);
}
else
{
int
status
;
wait
(
&
status
);
if
(
WIFEXITED
(
status
))
{
if
(
WEXITSTATUS
(
status
)
!=
0
)
{
char
error_msg
[
256
];
snprintf
(
error_msg
,
sizeof
(
error_msg
),
"Command failed with exit code %d
\n
"
,
WEXITSTATUS
(
status
));
send_message_string
(
cli_socket
,
error_msg
);
}
}
}
free
(
cmd
.
_cmd_buffer
);
}
send_message_eof
(
cli_socket
);
}
// Clean up (this will never be reached due to the while(1) loop)
free
(
io_buff
);
return
WARN_RDSH_NOT_IMPL
;
// Default return value
return
rc
;
}
/*
* send_message_eof(cli_socket)
* cli_socket: The server-side socket that is connected to the client
...
...
@@ -384,25 +420,16 @@ int exec_client_requests(int cli_socket) {
* we were unable to send the EOF character.
*/
int
send_message_string
(
int
cli_socket
,
char
*
buff
)
{
int
bytes_sent
;
// Send the message
bytes_sent
=
send
(
cli_socket
,
buff
,
strlen
(
buff
),
0
);
if
(
bytes_sent
<
0
)
{
int
send_message_eof
(
int
cli_socket
)
{
if
(
send
(
cli_socket
,
&
RDSH_EOF_CHAR
,
1
,
0
)
<
0
)
{
perror
(
"send"
);
return
ERR_RDSH_COMMUNICATION
;
}
// Send the EOF character
if
(
send_message_eof
(
cli_socket
)
!=
OK
)
{
return
ERR_RDSH_COMMUNICATION
;
}
return
OK
;
}
/*
* send_message_string(cli_socket, char *buff)
* cli_socket: The server-side socket that is connected to the client
...
...
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