Check if environment has passed to execv - c

I try to do some homework exercise about creating a process with execv in linux.
I need to take an input string from the user, and check if there is a program with same name on the machine.
I need to try to execute the given program string with the PATH variable directories
I have to use the execv function ONLY to execute the program.
The input seperated by space when the first word is the file of the program and the other words are the arguments.
And they also ask me to validate that the environment has passed to the execv.
How do i check that?
I found out that I need to use the environ variable and fill it
I Have tried this so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MYCOMMAND_LEN 1000
#define MYNUM_OF_PARAMS 500
extern char **environ;
int main()
{
int i = 0, j, pid, stat, amountOfLib;
char command[MYCOMMAND_LEN];
char *params[MYNUM_OF_PARAMS];
char *path, *lastStr;
char *libs[100];
int numberOflib = 0, numOfParams;
char *commandPath;
//cut path
path = getenv("PATH");
lastStr = strtok(path, ":");
libs[0] = (char*)malloc(sizeof(char)*strlen(lastStr) + 1);
strcpy(libs[0], lastStr);
i = 1;
while (lastStr = strtok(NULL, ":")) {
libs[i] = (char*)malloc(sizeof(char)*strlen(lastStr) + 1);
strcpy(libs[i], lastStr);
i++;
numberOflib = i;
}
numberOflib = i;
puts("Please Enter Command: ");
gets(commandPath);
//loop until leave {
while (strcmp(command, "leave") != 0) {
//cut command
lastStr = strtok(command, " ");
params[0] = (char*)malloc(sizeof(char)*(strlen(lastStr) + 1));
strcpy(params[0], lastStr);
i = 1;
while ((lastStr = strtok(NULL, " ")) != NULL)
{
params[i] = (char*)malloc(sizeof(char)*(strlen(lastStr) + 1));
strcpy(params[i], lastStr);
i++;
}
params[i] = NULL;
numOfParams = i;
//check if first is relative
if ((pid = fork()) == 0) {
if (params[0][0] == '/' ||
(strlen(params[0]) >= 2 &&
params[0][0] == '.' &&
params[0][1] == '/'
) ||
(strlen(params[0]) >= 3 &&
params[0][0] == '.' &&
params[0][1] == '.' &&
params[0][2] == '/'
)
) execv(params[0], params);
// if command like "man ls"
else {
for (i = 0; i < amountOfLib; i++) {
commandPath = libs[i];
strcat(commandPath, "/");
strcat(commandPath, params[0]);
for (j = 0; j < numOfParams; j++) {
environ[j] = params[j]; //last environ also get the null
}
execv(commandPath, NULL);
}
puts("command not found in PATH");
exit(1);
}
} else {
wait(&stat);
}
puts("Please Enter Command: ");
gets(commandPath);
}
//}
}
some inputs like 'ls' reply that the argv vector is empty.

Related

How can I input a word, read through a dictionary, and print the word's translation?

My objective is to input a string "sana" which will at the end print only one corresponding result. Ie: if I enter the word "sana" it would print "Word sana is in English word" and if the user enters "word" it prints "Word word is in Finnish sana". So the code is not working at all so I wanted to ask how should I continue. if-else doesn't work at all but I thought it would help me visualize where to go there.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Read file line by line
split lines using ; as delimiter
store first/second part in some array
ask user to input and search the word in that array
*/
int main()
{
FILE *fp;
char sana[30];
char *p;
void *tmp;
int lasku = 0;
int pal = 1;
int i;
char **vars = NULL;
char **vals = NULL;
fp = fopen("dictionary.txt", "r");
printf("Word: ");
scanf("%s", sana);
while (fgets(sana, sizeof(sana), fp)) {
sana[strcspn(sana, "\n")] = 0;
if (!(p = strchr(sana, ';')))
continue;
*p++ = 0; //poistaa ;
if (!strlen(sana) || !strlen(p))
continue;
if (!(tmp = realloc(vars, (lasku + 1) * sizeof(char*))))
goto out;
vars = (char**)tmp;
if (!(tmp = realloc(vals, (lasku + 1) * sizeof(char*))))
goto out;
vals = (char**)tmp;
vars[lasku] = strdup(sana);
vals[lasku] = strdup(p);
lasku++;
if (!vars[lasku-1] || ! vals[lasku-1])
goto out;
}
pal = 0;
if (i == 0 || i == 2 || i == 4)
printf("Word %s is in English %s\n", vars[i], vals[i]);
else
if (i == 1 || i == 3 || i == 5)
printf("Word %s is in Finnish %s\n", vals[i], vars[i]);
else
printf("Word can't be found in the dictionary");
out:
fclose(fp);
if (vars)
for (i = 0; i < lasku; i++)
free(vars[i]);
if (vals)
for (i = 0; i < lasku; i++)
free(vals[i]);
free(vars);
free(vals);
return pal;
}
The code does not work because:
you overwrite the word in sana when you read the dictionary.
you never set i.
testing the value of uninitialized variable i has undefined behavior.
You should first local the dictionary in memory, then read words from the user and search them in the dictionary for matches.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Read file line by line
split lines using ; as delimiter
store first/second part in some array
ask user to input and search the word in that array
*/
int main() {
FILE *fp;
char sana[30];
char **tmp;
int lasku = 0, i, found, error = 0;
char **vars = NULL;
char **vals = NULL;
fp = fopen("dictionary.txt", "r");
while (fgets(sana, sizeof(sana), fp)) {
sana[strcspn(sana, "\n")] = '\0';
if (!(p = strchr(sana, ';')))
continue;
*p++ = '\0';
if (!*sana || !*p)
continue;
if (!(tmp = realloc(vars, (lasku + 1) * sizeof(*vars)))) {
error = 1;
break;
}
vars = tmp;
if (!(tmp = realloc(vals, (lasku + 1) * sizeof(*vals)))) {
error = 1;
break;
}
vals = tmp;
vars[lasku] = strdup(sana);
vals[lasku] = strdup(p);
lasku++;
if (!vars[lasku-1] || !vals[lasku-1]) {
error = 1;
break;
}
}
fclose(fp);
if (!error) {
for (;;) {
printf("Word: ");
if (scanf("%29s", sana) != 1)
break;
found = 0;
for (i = 0; i < lasku; i++) {
if (!strcmp(sana, vars[i]) {
printf("Word %s is in English %s\n", vars[i], vals[i]);
found = 1;
}
if (!strcmp(sana, vals[i]) {
printf("Word %s is in Finnish %s\n", vals[i], vars[i]);
found = 1;
}
}
if (!found) {
printf("Word can't be found in the dictionary");
}
}
}
for (i = 0; i < lasku; i++) {
free(vars[i]);
free(vals[i]);
}
free(vars);
free(vals);
return error;
}

How to find words with capital letters in a char using c?

I'm trying to find all the words with capital letters in a string, but am unable to process my data structure. i seem to be able to print out fileContent, indicating that it is loading in successfully, but my second function is not working on the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* loadFile(char* fileName)
{
FILE *inputFile;
inputFile = fopen(fileName, "r");
//finds the end of the file
fseek(inputFile, 0, SEEK_END);
//stores the size of the file
int size = ftell(inputFile);
//Sets the scan to the start of the file
fseek(inputFile, 0, SEEK_SET);
char *documentStore = (char*)malloc(size);
int i = 0, c;
while((c = fgetc(inputFile)) != EOF)
{
documentStore[i] = c;
i++;
}
return documentStore;
}
void countImportantWords(char* fileContent, char** importantWords, int* frequencyWords)
{
int uniqueWordCount = 0;
int lengthWordStore = 10;
int i = 0;
int recording = 0;
char wordBuffer[50];
int wordBufferCount = 0;
int isWordPresent = 0;
while(fileContent[i] != EOF)
{
//To allocate more memory incase the structure is full
if(uniqueWordCount == lengthWordStore)
{
lengthWordStore += 10;
char** newWordStore = realloc(importantWords, lengthWordStore * sizeof(char*));
int* newFrequencyStore = realloc(frequencyWords, sizeof(int));
importantWords = newWordStore;
frequencyWords = newFrequencyStore;
}
printf("%s", wordBuffer);
//Conditions to fill if its a word
if(fileContent[i] >= 'A' && fileContent[i] <= 'Z' && recording == 0)
{
wordBuffer[0] = fileContent[i];
recording = 1;
}else if(fileContent[i] >= 'a' && fileContent[i] <= 'z' && recording == 1)
{
//each if is to check if the end of word is reached. Any character that is non alphabetical is considered end of word
wordBufferCount += 1;
wordBuffer[wordBufferCount] = fileContent[i];
} else if (fileContent[i] >= 'A' && fileContent[i] <= 'Z' && recording == 1)
{
wordBufferCount += 1;
wordBuffer[wordBufferCount] = fileContent[i];
} else {
//Adding a terminating character so that it strcpy only copies until that point
wordBuffer[wordBufferCount + 1] = '\0';
recording = 0;
//check to see if that word is in the array already, and if it is, it will just increment the frequency
for(int j = 0; j < uniqueWordCount; j++){
if(strcmp(wordBuffer, importantWords[j]) == 0)
{
frequencyWords[j] += 1;
isWordPresent = 1;
}
}
//if its not present, it should assign it to the structure
if(isWordPresent == 0)
{
char* wordStore = (char*)malloc(wordBufferCount * sizeof(char));
strcpy(wordStore, wordBuffer);
uniqueWordCount += 1;
importantWords[uniqueWordCount] = wordStore;
frequencyWords[uniqueWordCount] = 1;
}
}
i++;
}
}
int main() {
char fileName[50];
char *fileContent;
char **importantWords = (char**)malloc(10*sizeof(char**));
int *frequencyWords = (int*)malloc(10*sizeof(int));
printf("Please input the full file path: ");
scanf("%s", fileName);
fileContent = loadFile(fileName);
countImportantWords(fileContent, importantWords, frequencyWords);
int i = 0;
while(importantWords[i] != '\0')
{
printf("%s %d", importantWords[i], frequencyWords[i]);
i++;
}
return 0;
}
I've put in the full file so you can see how the structure was created incase that it is the issue, but ideally what would happen is that the final loop would print out all the words that are important and they're frequency. Currently i'm getting exit code 11, which i'm not sure what it means, but may be worth mentioning. I'd really appreciate any help :)
You can simplify the process dramatically but utilising functions and learning to manage your memory. I wrote a short example which does not take punctuation into account. It just assumes every word is separated by a space, which you can customise to your discretion.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char* readfile(char* filename){
char* data = NULL;
FILE* file = fopen(filename, "r");
if(file == NULL){
return NULL;
}
fseek(file, 0, SEEK_END);
long size = ftell(file)+1;
fseek(file, 0, SEEK_SET);
data = (char*)malloc(size);
if(data == NULL){
return NULL;
}
fgets(data, (int)size, file);
return data;
}
typedef struct uppercase_t{
char** word;
int count;
}uppercase;
void copy(uppercase* u,char* token){
size_t length = strlen(token);
u->word[u->count] = (char*)malloc(length+1);
if(u->word[u->count] == NULL){
return;
}
strcpy(u->word[u->count], token);
++u->count;
}
void createuppercasedata(uppercase* u, char* data){
const char delimeter[] = " ";
char* token = strtok(data, delimeter);
if(token == NULL){
return;
}
u->word = (char**)malloc(u->count+1);
if(u->word == NULL){
return;
}
if(isupper(token[0])){
copy(u,token);
}
while(token != NULL){
token = strtok(0, delimeter);
if(token != NULL)
if(isupper(token[0])) {
char** reallocated = (char**)realloc(u->word, u->count+1);
if(reallocated == NULL){
return;
}
u->word = reallocated;
copy(u, token);
}
}
}
void destroyuppercasedata(uppercase* u){
for(int index = 0; index < u->count; ++index){
free(u->word[index]);
}
free(u->word);
}
int main(){
char filename[] = "textfile";
char* data = readfile(filename);
if(data == NULL){
return -1;
}
uppercase u = {0};
createuppercasedata(&u, data);
printf("found %i uppercase words\n",u.count);
for(int index = 0; index < u.count; ++index){
printf("%s\n", u.word[index]);
}
destroyuppercasedata(&u);
free(data);
}
The code will allocate a new pointer for each uppercase and memory for the word to be copied too. It will free all the memory it allocated in the structure with destroyuppercasedata and it will free the initial data that was read from file. Error checking and memory management in C is really important. So utilise those properly.
This was the test file I used.
textfile
How many Uppercase words can Be Found In this text File the answer should be Seven
And this was the output to the terminal:
How
Uppercase
Be
Found
In
File
Seven

Problems of History for my own Shell in C

As a project, I have to make my own shell. I did it but I have some problems with the history feature.
Here's piece of my code:
int main(int argc, char* argv[])
{
char saisie[300], cwd[1024];
char* nom = getenv("USER");
char* backup[MAXCMD];
int boucle = 1, n = 0, i, u = 0, b = 0;
for(i = 0; i < MAXCMD; i++)
{
backup[i] = NULL;
}
for(i = 0; i < MAX_INPUT_SZ; i++)
{
saisie[i] = 0;
}
char* cmd[MAXPARAMS]; //MAXPARAMS is 20
while( boucle == 1)
{
printf("%s#sam:~ %s> ", nom, (getcwd(cwd, sizeof(cwd))));
fgets(saisie,MAX_INPUT_SZ,stdin);
printf("\n");
split_input(saisie, cmd);
free(backup[u]);
backup[u] = strdup(saisie);
u = (u + 1) % MAXCMD;
b = switchcmd(cmd,backup,b,u);
start(cmd,b);
b = 0; //débloquage fonction start
}
return 0;
}
I print the history with this fonction:
int historique(char* backup[], int u)
{
int i = u;
int place = 1;
do
{
if (backup[i])
{
printf("%4d: %s\n", place, backup[i]);
place++;
}
i = (i + 1) % MAXCMD;
} while (i != u);
return 0;
}
B is used to block the execution fonction (start) when user enter "cd" or "history", because it will generate an error.
Here's the fonction triggered when user enters "cd", "history", or "exit":
int switchcmd(char** cmd,char** backup, int b,int u)
{
int i, n = 3, switch_value = 0;
char* error;
char* listcmd[n];
listcmd[0] = "cd";
listcmd[1] = "exit";
listcmd[2] = "history";
for (i = 0; i < n; ++i)
{
if(strcmp(cmd[0], listcmd[i]) == 0)
{
switch_value = i + 1;
break;
}
}
switch (switch_value)
{
case 1:
chdir(cmd[1]);
b = 1;
error = strerror(errno);
if (*error != 0)
{
printf("sam: %s: %s\n", cmd[0], error);
}
break;
case 2:
printf("Bye bye\n");
exit(0);
case 3:
historique((char**)backup,u);
b = 1;
break;
}
return b;
}
When I execute my shell, and enter these commands successively, they work. °i1
> clear
> ls -a -l
> ls -a
> cd ..
> man chdir
Then "history" for printing the history, I have this : °i2
1: clear
2: ls
3: ls
4: cd
5: man
6: history
and I want this output, with all parameters: °i3
1: clear
2: ls -a -l
3: ls -a
4: cd ..
5: man chdir
6: history`
I dont know why, and I don't understand why strdup does not duplicate my cmd in backup at it should.
Any help please?
When the user command is store in ' saisie ', this command is duplicate and split in array of parameters. And I use ' cmd ' in the execution fonction, with execvp.
Then there is your big problem, cmd has a fixed length of 1, if you use that to stored the command arguments for execvp, then you can only store one thing: NULL.
You have two options:
Use a large fixed size, for example char *cmd[100] where you can store up
to 99 arguments and no more. This is the easiest solution but it is not flexible
enough. Although some systems have a limit on the number of arguemnts you can
pass to a new process, I don't know if there is a limit for all systems,
this and this might help you there.
Dynamically create an array of char pointers depending on the command line.
This is more work but this is also the more flexible solution. Assuming that
your command line does not have support for pipes (|) and redirections (<,
<<, >, >>), then split_input could look like this:
char **split_input(const char *cmd)
{
if(cmd == NULL)
return NULL;
char **argv = NULL, **tmp;
char *line = strdup(cmd);
if(line == NULL)
return NULL;
const char *delim = " \t\n";
char *token = strtok(line, delim);
if(token == NULL)
{
free(line);
return NULL;
}
size_t len = 0;
do {
char *arg = strdup(token);
if(arg == NULL)
{
free_argv(argv);
free(line);
return NULL;
}
tmp = realloc(argv, (len + 2) * sizeof *argv);
if(tmp == NULL)
{
free_argv(argv);
free(line);
return NULL;
}
argv = tmp;
argv[len++] = arg;
argv[len] = NULL; // argv must be NULL terminated
} while(token = strtok(NULL, delim));
free(line);
return argv;
}
void free_argv(char **argv)
{
if(argv == NULL)
return;
for(size_t i = 0; argv[i]; ++i)
free(argv[i]);
free(argv);
}
Now you can use it like this:
while( boucle == 1)
{
printf("%s#sam:~ %s> ", nom, (getcwd(cwd, sizeof(cwd))));
fgets(saisie,MAX_INPUT_SZ,stdin);
printf("\n");
char **argv = split_input(saisie);
if(argv == NULL)
{
fprintf(stderr, "Cannot split command line, not enough memory\n");
continue;
}
free(backup[u]);
backup[u] = strdup(argv[0]); // <-- passing argv[0], not argv
// but perhaps what you really want
// is strdup(saisie)
u = (u + 1) % MAXCMD;
b = switchcmd(argv,backup,b,u);
start(argv,b);
b = 0; //débloquage fonction start
free_argv(argv);
}
You are also doing
backup[u] = strdup(cmd);
but the problem is that cmd is an array of char pointers, strdup expects a
const char*, you are passing the wrong type. It should be strdup(cmd[0]) or
strdup(saisie) if you want to store the whole command.

Expanding on a C-Shell program and chdir() isn't working properly

My instructor gave us a basic shell in C to expand upon, and I'm currently working on getting the shell to change directories whenever the user enters 'cd [directory]' into the command line. I've gotten it to stop seg faulting, but it won't change directories. Can anyone tell me why it isn't working?
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
/* Array holds arguments: args[0] is the command. */
static char *args[512];
pid_t pid;
int command_pipe[2];
#define READ 0
#define WRITE 1
int chdir(const char* path);
static int
command (int input, int first, int last)
{
int pipettes[2];
/* Invoke pipe */
pipe (pipettes);
pid = fork ();
if (pid == 0)
{
if (first == 1 && last == 0 && input == 0)
{
// 1st cmd
dup2 (pipettes[WRITE], STDOUT_FILENO);
}
else if (first == 0 && last == 0 && input != 0)
{
// Mid cmd
dup2 (input, STDIN_FILENO);
dup2 (pipettes[WRITE], STDOUT_FILENO);
}
else
{
// Last cmd
dup2 (input, STDIN_FILENO);
}
if (execvp (args[0], args) == -1)
_exit (EXIT_FAILURE); // If child fails
}
if (input != 0)
close (input);
close (pipettes[WRITE]);
// If last command, nothing more needs to be read
if (last == 1)
close (pipettes[READ]);
return pipettes[READ];
}
static void
cleanup (int n)
{
int i;
for (i = 0; i < n; ++i)
wait (NULL);
}
static int go (char *cmd, int input, int first, int last);
static char line[1024];
static int n = 0;
int
main (int argc, char* argv[])
{
while (1)
{
/* Initial Prompt */
printf ("?> ");
fflush (NULL);
/* Read in command */
if (!fgets (line, 1024, stdin))
return 0;
int input = 0;
int first = 1;
char *cmd = line;
char *next = strchr (cmd, '|'); /* Find initial '|' */
char *also = strchr (cmd, ';'); /* Find initial ';' */
char *directory = argv[1];
while (next != NULL)
{
/* 'next' points to '|' */
*next = '\0';
input = go (cmd, input, first, 0);
cmd = next + 1;
next = strchr (cmd, '|'); /* Find next '|' */
first = 0;
}
if(argv[0] == "cd"){
chdir(directory);
}
input = go (cmd, input, first, 1);
cleanup (n);
n = 0;
}
return 0;
}
static char *
skip_white_space (char *s)
{
while (isspace (*s))
++s;
return s;
}
static void
parse (char *cmd)
{
cmd = skip_white_space (cmd);
char *next = strchr (cmd, ' ');
int i = 0;
while (next != NULL)
{
next[0] = '\0';
args[i] = cmd;
++i;
cmd = skip_white_space (next + 1);
next = strchr (cmd, ' ');
}
if (cmd[0] != '\0')
{
args[i] = cmd;
next = strchr (cmd, '\n');
next[0] = '\0';
++i;
}
args[i] = NULL;
}
static int
go (char *cmd, int input, int first, int last)
{
parse (cmd);
if (args[0] != NULL)
{
if (strcmp (args[0], "exit") == 0)
exit (0);
n += 1;
return command (input, first, last);
}
return 0;
}
Your immediate problem seems to lie here:
if(argv[0] == "cd"){
chdir(directory);
I think you'll find that argv[0] is the implementation's representation of your program name, not the command you just entered, which is probably in args. Or cmd. Or somewhere.
Even once you fix that, you shouldn't be using == for string comparisons in C. One of the strcmp family is the correct way to do it.

having trouble with my cd and history function

My results for cd and history:
sgraham#myshell:/home/class/sgraham/proj1>cd .. (works fine)
sgraham#myshell:/home/class/sgraham>cd .. (not working)
sgraham#myshell:/home/class/sgraham>cd .. (not working)
cd: Too many arguments
sgraham#myshell:/home/class/sgraham>history
sgraham#myshell:/home/class/sgraham> (not printing out history)
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_COMMAND_SIZE 80
#define MAX_ARGS 9
#define HIS_SIZE 100
typedef struct
{
int argument; // userCom arguments
char *arg[MAX_ARGS + 1]; // userCom arguments array
char *history[HIS_SIZE]; //history array
char *input; // hold input file
char *output; // hold output file
} Command;
int main()
{
Command userCom = {0}; //holds userCom struct
const char *whitespace = " \n\r\t\v\f"; // userCom delimiting chars
char* username = getenv("USER"); //Get user name
char* curDirect = getenv("HOME"); //get cwd
char* token[MAX_ARGS];
char* cwd;
char* buf;
char* cmd;
char buffer[MAX_COMMAND_SIZE + 1]; //hold userCom line
//char history[HIS_SIZE][MAX_ARGS +1]; //2D array for history
int tok = 0;
int new;
int i;
int limit;
int last = 0;
int hist = 0; //initialize history size to 0
long size;
struct stat buff; //holds file information
//gets current working directory and also changes buffer if necessary
size = pathconf(".", _PC_PATH_MAX);
if ((buf = (char *)malloc((size_t)size)) != NULL)
cwd = getcwd(buf, (size_t)size);
while(1){
//prints users prompt
printf("\n%s#myshell:%s>", username,cwd);
//gets string from userCom line
fgets(buffer, MAX_COMMAND_SIZE + 1, stdin);
buffer[strlen(buffer)-1] = 0 ;//set null
//set-up history function
userCom.history[last% HIS_SIZE] = cmd;
last++;
//parses tokens and looks for delimiters
token[tok] = strtok(buffer,whitespace);
while(token[tok])
{
++tok;
if(tok == MAX_ARGS)
printf("Reached MAX userCom arguments");
break;
token[tok] = strtok(NULL, whitespace);
}
i =0;
//sort tokens based on special characters
for (;i<tok;++i)
{
if(!strcmp(token[i], "<"))
{
userCom.output = token[++i];
}
else if(!strcmp(token[i], ">"))
{
userCom.input = token[++i];
}
else if (token[i][0] == '$')
{
char* toktok = getenv((const char*)&token[i][1]);
if (!toktok)
{
printf("%s: ERROR: variable.\n", token[i]);
return 0;
}
else
{
userCom.arg[userCom.argument] = toktok;
++(userCom.argument);
}
}
else
{
userCom.arg[userCom.argument] = token[i];
++(userCom.argument);
}
}
tok = 0;
userCom.arg[userCom.argument] = 0;
//handles the "cd" command
if((strcmp(userCom.arg[0],"cd") == 0))
{
if (userCom.argument > 2)
printf("cd: Too many arguments\n");
// change directories if valid target and update cwd
else if (userCom.argument == 1)
{
new = chdir(cwd);
if (new != 0)
printf("%s: No such file or directory\n");
// if no argument is given, new directory should be $HOME
else
{
new = chdir(curDirect);
// get the new current working directory
size = pathconf(".", _PC_PATH_MAX);
if ((buf = (char *)malloc((size_t)size)) != NULL)
cwd = getcwd(buf, (size_t)size);
}
}
}//end "cd" function
//handles the echo command
else if(strcmp(userCom.arg[0], "echo") == 0)
{
int p;
for(p=1;p < userCom.argument; ++p)
printf("%s ", userCom.arg[p]);
}//ends echo function
//handles exit
else if(strcmp(userCom.arg[0], "exit") == 0)
{
exit(0);
}
//handles history functions
else if(strcmp(userCom.arg[0], "history") == 0)
{
int j;
for(j = last, limit = 0; userCom.history[j] != NULL && limit != HIS_SIZE ; j = (j -1)% HIS_SIZE, limit++)
printf(" %s ",userCom.history[j]);
}
else {
break;
}
}//end while 1 loop
return 0;
}//End int main
while(token[tok])
{
++tok;
if(tok == MAX_ARGS)
printf("Reached MAX userCom arguments");
break;
token[tok] = strtok(NULL, whitespace);
}
This loop breaks at the first time. Probably the if should be like
if(tok == MAX_ARGS) {
printf("Reached MAX userCom arguments");
break;
}
Also userCom.argument is never set back to zero, which causes the cd .. to work first time.

Resources