This question already has an answer here:
How can I use chdir function in Linux?
(1 answer)
Closed 6 years ago.
When I try to run ./shell cd includes/
I don't actually change into the includes directory. Here's my code:
int cd(char *path) {
printf("i got there at least\n");
if(path == NULL) {
printf("dont waork\n");
print_usage();
} else {
printf("print please\n");
int dir_change = chdir(path);
if(dir_change != 0)
print_no_directory(path);
}
return 1;
}
int shell(int argc, char *argv[]) {
pid_t pid;
int status;
pid = fork();
if(pid == 0) {
execl("cd", argv[0], argv[1], argv[2], (char*)NULL);
printf("argv[1]: %s\n", argv[1]);
if(!strcmp(argv[1], "cd")) {
cd(argv[2]);
}
} else if(pid > 0) {
waitpid(pid, &status, WUNTRACED);
} else {
print_fork_failed();
}
return 0;
}
I don't see what's wrong with my code.
You can't run a program to change the directory of another program (your shell).
What happens is
A new process is spawned to run your program
That program calls chdir(), to change its current directory
The program end, causing the process to die
The shell is still where it was
That's why cd in the shell is a built-in command.
you cannot create a cd command like this unless you develop your own shell.
The chdir command works, but only inside your program. Once you exit it, you're back to the parent shell current directory.
Related
I wrote 2 programs.
The first one gets 2 strings through argv and prints the program process id and the smallest string (by dictionary order).
int main(int argc,char **argv) {
int cmp;
if (argc != 3){
perror("Wrong arguments");
exit(EXIT_FAILURE);
}
printf("my ID: %d\n",getpid());
cmp = strcmp(argv[1],argv[2]);
if (cmp < 0)
puts(argv[1]);
else if (cmp > 0)
puts(argv[2]);
else puts(argv[1]);
exit(EXIT_SUCCESS);
}
I have compiled the code via terminal with:
gcc -Wall my_cmp.c -o my_cmp
The second program creates a child process and performs execvp() with my_cmp sending "abc" "de".
void do_sun(char **argv);
int main() {
pid_t status;
char *args[] = { "my_cmp", "abc","de", NULL };
status = fork();
if (status < 0){
perror("Cannot fork");
exit(EXIT_FAILURE);
}
if (status == 0){
char *args[] = { "my_cmp", "abc","de", NULL };
do_sun(args);
exit(EXIT_SUCCESS);
}
if (status > 0){
wait(&status);
if (execvp(args[0],args) != 0 )
perror("error");
exit(EXIT_SUCCESS);
}
exit(EXIT_SUCCESS);
}
void do_sun(char **args){
if (execvp(args[0],args) == -1 )
perror("error");
exit(EXIT_SUCCESS);
}
When I run the program I am getting this message:
error: No such file or directory
error: No such file or directory
I have tried to switch directory to the my_cmp file with no success.
On some systems it won't search working directory for executable binary files by default.
You should use ./my_cmp instead of my_cmp to have it work on such systems.
If you use execvp, you are saying that the executable will be found "in the path"; that is, in one of the directories listed in $PATH. Few directories are on this path, and while it is possible to add . to $PATH, that's generally regarded to be asecurity vulnerability.
If you want to specify the path to the executable (in which case you can put it in whatever directory you want), use the non-path execv.
I am writing a function to my shell where I need to redirect output to file. For example user write: ls -l >> file and ls -l should be written to file. Almost all things are correct but after first calling my function program stop and I can't write anything else. Below I present my function and I would appreciate any clues to resolve the problem:
void execute2(char *command, char **argv, char **argv2)
{
pid_t pid;
int status;
if ((pid = fork()) < 0)
{
printf("*** ERROR ***\n");
exit(1);
}
else if (pid == 0)
{
close(1);
parse(command, argv, argv2);
int output = open(*argv2, O_APPEND | O_WRONLY);
dup2(output,1);
if (strcmp(argv[0], "exit") == 0)
exit(0);
if (execvp(*argv, argv) < 0)
{
printf("*** ERROR ***\n");
exit(1);
}
close(output);
}
else
{
while (wait(&status) != pid);
}
}
command is command getting from user, argv is part of instruction and parameters and argv2 is the output file.
#Jonathan Leffler I checked this and I think it doesn 't resolve problem. I suggest that when I call first time execute2 it works as well as I want but I never finish that proces. Or I don 't undestand something
I'm trying to create a simple program that will allow to execute basic
shell commands. Problem is execve just hangs everytime.
Heres the code:
char* arglist[]={"ls","-l",NULL};
char* env[]={NULL};
int status;
while (1)
{
if (fork() != 0)
{
waitpid(-1, &status, 0);
}
else
{
execve(arglist[0],arglist,env);
}
}
return 0;
}
The first arguments should be a full path to the binary you execute:
char* arglist[]={"/bin/ls", "-l", NULL};
So I am programming pipes in C (to support multiple pipes). Currently I am testing it with hardcoded commands. I tried to execute cd command to change current working directory and pwd command to display new directory. But it does not work for me: cd does not change working directory and pwd display old directory of my Debug folder in project root. I will be very thankful if you clarify the cause of this problem to me. Thank you!
Here is the code
int main(int argc, const char * argv[]) {
char *cd[] = {"cd", "/Users/user01/Desktop", NULL};
char *pwd[] = {"pwd", NULL};
char **cmd [] = {cd, pwd, NULL};
loop_pipe(cmd);
return 0;
}
void loop_pipe(char ***cmd){
int p[2];
pid_t pid;
int fd_in = 0;
while (*cmd != NULL)
{
pipe(p);
if ((pid = fork()) == -1){
exit(EXIT_FAILURE);
}else if (pid == 0){
dup2(fd_in, 0); //change the input according to the old one
if (*(cmd + 1) != NULL)
dup2(p[1], 1);
close(p[0]);
execvp((*cmd)[0], *cmd);
exit(EXIT_FAILURE);
}else{
wait(NULL);
close(p[1]);
fd_in = p[0]; //save the input for the next command
cmd++;
}
}
}
cd is not a program. In the shell, it is implemented as a built-in.
Think about what would happen if that were not the case: The new child process would change directory and then promptly exit, effecting no persistent change. Parent and child processes do not share working directories.
I doubt your goal actually is to change directories per se, but if that were what you wanted, you would have to do it "manually" in your parent process, using a chdir() call.
This question already has answers here:
implementing a shell in C
(2 answers)
Closed 9 years ago.
im trying to implement a shell using C.
I'm currently trying to deal with the pipes of the program with no luck yet. I was wondering how could i process a command such as
SHELL$: sort < txtFile | grep key
i parsed the command line so that i have sort < txtFile in one char* array, and grep key in another char* array
any help would be greatly appreciated.
this is the code i have so far:
PS: i didnt include the code that deals with the redirects
pid = fork();
if(pid == 0)
{
/* child process */
if( PIPE_FLAG )
{
close(c2p[0]);
if(dup2(c2p[1], STDOUT_FILENO) == -1){
perror("dup2() failed");
exit(2);
}
}
/* Execute command */
execvp(cmd_args[0], cmd_args);
perror("exec failed 1. "); /* return only when exec fails */
exit(-1);
}
else if(pid > 0)
{
/* parent process */
if(!async)
waitpid(pid, NULL, 0);
else
printf("this is an async call\n");
if(PIPE_FLAG)
{
close(c2p[1]);
if(dup2(c2p[0], STDIN_FILENO) == -1){
perror("dup2() failed");
exit(-1);
}
execvp(nxt_args[0], nxt_args);
perror("exec failed 2. ");
exit(-1);
}
}
else
{
/* error occurred */
perror("fork failed");
exit(1);
}
this is my main:
int main (int argc, char* argv [])
{
char commands[BUFSIZ];
for(;;)
{
printf("MYSHELL$ ");
if(fgets(commands, BUFSIZ, stdin) == NULL)
{
perror("fgets failed");
exit(1);
}
execute(commands) ;
}
return 0;
}
so after the call to the above command, my shell loop terminates.
How could i solve this issue?
It looks like your problem is you exec() in the parent process too when piping. exec() replaces the current process with the new one, so when you call it in the parent, your shell is replaced, so the loop doesn't even exist anymore.
For every exec() in your shell, you should fork() first, to ensure that the parent shell process remains alive.