Commit e47ab545 authored by Son Pham's avatar Son Pham

Lab 10 Completed

parent a7172371
No preview for this file type
......@@ -5,6 +5,28 @@
* Lab 10 - UNIX Shell
* Chosen feature 1:
* Execute with $PATH environment variable
* For example: We can just type 'ls' instead of full path '/bin/ls'
* WHY:
* As of now, full path to the program has to be specified (such as /bin/ls
* instead of just ls). This makes the shell tremendously unhelpful.
* HOW:
* Use envp as the third variable for the main function. This variable is the
* pointer to the list of strings indicating all the environment variables that
* are currently existing. I will find the $PATH environment variable and for
* each command, I will repeatedly try to match each path with the command and
* see if the command success.
* + If the command failed: Try the next path
* + If every single path failed: The program returns -1 indicating the
* execution is unsuccessful
* + Simply use 'ls' instead of '/bin/ls' and enjoy the program!
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -16,7 +38,10 @@
void execute_command(char* s);
void read_and_execute_commands(char* s);
int main(int argc, char* argv[]) {
// Globally accessible list of environment variables
char **env_variables;
int main(int argc, char* argv[], char** envp) {
// Print the fun ASCII shell image
pid_t pid;
......@@ -30,7 +55,38 @@ int main(int argc, char* argv[]) {
printf("by Son Pham\n");
// Find the PATH environment variable first
char** env;
char* thisEnv;
for (env = envp; *env != 0; env++)
thisEnv = *env;
if ((thisEnv[0] == 'P') && (thisEnv[1] == 'A') && (thisEnv[2] == 'T') && (thisEnv[3] == 'H')) break;
// Copy the PATH string (because we don't want to modify the existing PATH)
size_t path_length = strlen(thisEnv);
char path[path_length+1];
strncpy(path, thisEnv, path_length+1);
// Parse all the possible PATH:
char ** path_list = NULL;
char * pathline = strtok(path, ":=");
int n_paths = 0; // Count the number of paths
pathline = strtok(NULL, ":\n"); // Ignore the first path, it's just PATH
while(pathline) {
path_list = realloc(path_list, sizeof(char*) *++n_paths);
path_list[n_paths-1] = pathline;
pathline = strtok(NULL, ":\n");
// Allocate one extra element for the last NULL */
path_list = realloc(path_list, sizeof (char*) * (n_paths+1));
path_list[n_paths] = 0;
env_variables = path_list;
// Set up string for input from the user
char s[256];
int newline_count; // Count the newline
......@@ -110,7 +166,22 @@ void execute_command(char* s) {
pid = Fork();
if (pid == 0) { // child process exec
int value = execv(param_list[0], param_list); // TODO: WRAPPER for execv
char path[1000];
// First path
// Check if the path exist
int i = 0;
char slash[1] = "/";
while ( access(path, F_OK) != 0 ) {
strcpy(path, env_variables[i]);
strcat(path, slash);
strcat(path, param_list[0]);
// After the command is found, execute it.
} else { // Parent process
waitpid(pid, &status, WEXITSTATUS(status));
if (status == 0) {
No preview for this file type
# Name: Son Pham
# Class: CSCI 315
# Prof: Luiz Felipe Perrone
# Lab 10
Problem 1: Works to specification. Makefile runs perfectly
Problem 2: Works to specification.
Problem 3: Can execute TWO OR MORE commands sequentially
Problem 4: [Enter][Enter] prints the current working directory
Problem 5: Use that PATH environment variable to allow convenient syntax.
WHY: Typing /bin/ls is inconvenient and painful and make the shell less valuable
WHAT I DID: I automatically search the appropriate path for the command of the user
based on the PATH environment variable.
HOW TO TEST: You can now type any file as long as they belong to the current directory
or in one of the directories in the PATH environment variables.
Example: You can now type 'ls' instead of '/bin/ls'
The function is working perfectly.
......@@ -263,3 +263,15 @@ ssize_t Recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
* Execv wrapper
int Execv(const char* path, char* const argv[]) {
int ret = execv(path,argv);
if (ret == -1) {
char error_mes[] = "Command failed";
......@@ -28,4 +28,6 @@ void ReadXBytes(int sockfd, unsigned int x, void* buffer);
int Socket(int domain, int type, int protocol);
ssize_t Sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t Recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
int Execv(const char* path, char* const argv[]);
No preview for this file type
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment