Reputation: 278
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
extern int errno;
void parseArgs(char *path, char *argv[]) {
while (*path != '\0') {
while (*path == ' ' || *path == '\t' || *path == '\n') {
*path++ = '\0';
}
*argv++ = path;
while (*path != '\0' && *path != ' ' && *path != '\t' && *path != '\n') {
path++;
}
}
*argv = '\0';
}
int execArgs(char *argv[], int amp) {
pid_t process;
int check;
if ((process = fork()) < 0) {
fprintf(stderr, "Forking child failed\n%s\n", strerror(errno));
errno = 0;
return EXIT_FAILURE;
} else if (process == 0) {
if (execvp(*argv, argv) < 0) {
fprintf(stderr, "Execution failed\n%s\n", strerror(errno));
errno = 0;
return EXIT_FAILURE;
}
} else {
while (wait(&check) != process) {
//do nothing
}
}
return EXIT_SUCCESS;
}
int main (void) {
char path[1024];
char *argv[64];
//int amp = 0;
while (1) {
printf("[root@localhost]$ ");
fgets(path, 1024, stdin);
puts("");
parseArgs(path, argv);
if (strcmp(argv[0], "exit") == 0) {
return EXIT_SUCCESS;
}
execArgs(argv, 0);
}
}
I'm having an issue here. The problem seems to be a parse error, because whenever I try to ls
a directory, I get ls: cannot access : No such file or directory
. The odd thing is, if I go ls ..
I get:
ls: cannot access : No such file or directory
..:
cat cat.c cat.c~ m4
Furthermore - and I suspect the issues are linked - I cannot cd
into directories, however I'm not 100% sure of this as it does not throw anything like directory does not exist; I just get a blank space (but my cwd does not update).
Any help would be appreciated!
For Reference, some test inputs
[thanasi@localhost m4]$ ./cli
[root@localhost /home/thanasi/Systems Programming/m4]$ ls
ls: cannot access : No such file or directory
[root@localhost /home/thanasi/Systems Programming/m4]$ ls ..
ls: cannot access : No such file or directory
..:
cat cat.c cat.c~ m4
[root@localhost /home/thanasi/Systems Programming/m4]$ cd test
[root@localhost /home/thanasi/Systems Programming/m4]$ cd /test
/usr/bin/cd: line 2: cd: /test: No such file or directory
[root@localhost /home/thanasi/Systems Programming/m4]$ ^C
And confirmation dir 'test' does exist:
[thanasi@localhost m4]$ ls -al
total 36
drwxrwxr-x. 3 thanasi thanasi 4096 Mar 17 22:00 .
drwxrwxr-x. 3 thanasi thanasi 4096 Mar 17 20:36 ..
-rwxrwxr-x. 1 thanasi thanasi 13175 Mar 17 22:00 cli
-rw-rw-r--. 1 thanasi thanasi 1222 Mar 17 22:00 cli.c
-rw-rw-r--. 1 thanasi thanasi 1221 Mar 17 22:00 cli.c~
drwxr-xr-x. 2 root root 4096 Mar 17 21:32 test
Upvotes: 1
Views: 3046
Reputation: 183978
Typically, the input you got from fgets
ends with a newline. Say you got {'l', 's', '\n', '\0'}
as the first four bytes in path
. Then, when parseArgs
has set argv[0]
to point to the first character in path
, the next iteration overwrites the newline with '\0'
, and sets argv[1] = &path[2];
:
void parseArgs(char *path, char *argv[]) {
while (*path != '\0') {
while (*path == ' ' || *path == '\t' || *path == '\n') {
*path++ = '\0';
}
*argv++ = path;
while (*path != '\0' && *path != ' ' && *path != '\t' && *path != '\n') {
path++;
}
}
*argv = '\0';
}
so your argv
array contains a pointer to an empty string between the last real argument and the NULL
terminating the array. Thus ls
tries to list the contents of ""
- which doesn't exist.
Since you can't be certain that the input you got from fgets
ends with a newline, guard the assignment
if (*path) *argv++ = path;
to avoid that.
Upvotes: 3