Reputation: 166
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
char *getdir() /*find working directory*/
{
char *buffer;/*buffer is going to be used in getcwd function to get the current directory*/
char *path_buffer;//path_buffer is going to contain the directory//
long maxsize = pathconf(".", _PC_PATH_MAX);/* we set maxsize as the maximum pathname length*/
if((buffer=(char*) malloc((size_t)maxsize))!=NULL)
{
path_buffer=getcwd(buffer,maxsize); /*get the current directory*/
printf("\nMy working directory = %s",path_buffer);
return path_buffer;
}
else{
exit(-1);
}
}
char * getcmline() /*get command from stdin by the user*/
{
int bytes_read;
int nchars=200;/*max possible number for the input of the user*/
int nbytes=(sizeof(char))*nchars; /*size of chars in bytes*/
char *line=(char*) malloc(nbytes+1);
bytes_read=getline(line,&nbytes,stdin);/*read line from stdin*/
if(bytes_read == -1){
printf("Read line error");
exit(-1);
} /*error handling for bytes_read*/
else{
if(line[strlen(line)-1]=='\n')
{
line[strlen(line)-1]='\0'; /*change new line character in the end of the line of stdin*/
}
}
return line;
}
int main(void)
{
pid_t pid,child_pid;
int rv=0;
char* exit_string="exit";
char *path_buffer=NULL;
int nchars=200;
int nbytes=(sizeof(char))*nchars;
char *line=malloc(nbytes+1);
char *commands[2];
while(1){
switch(pid = fork())
{
case -1:
perror("fork"); /* something went wrong */
exit(1);
case 0:
printf(" CHILD: This is the child process!\n");
child_pid=getpid();
printf(" CHILD: My PID is %d\n", child_pid);
path_buffer=getdir();/*get the directory path*/
line=getcmline();/*get a command by the user*/
if(strcmp(line,exit_string)==0)
{
rv=3;
exit(rv);
}
commands[0]=line;
commands[1]=NULL;
execvp(commands[0],commands);
perror("Execution error");
exit(-1);
default:
waitpid(-1, &rv, 0);
if(WIFEXITED(rv)){
printf("Child exited normally and child's exit status is: %d\n", WEXITSTATUS(rv));
if((WEXITSTATUS(rv))==3){
exit(1);
}
}
}
}
return 0;
}
I made the changes in getline
, rv
and I created a proper variable for execvp
. But now the error that occurs is that after I type for example "ls". It says:
execution error: no such file or directory.
thanks again for the help and my lack of knowledge.
the error seems to be in the line variable but i cannot understand whats the problem!
The solution was given here.it should be line[(strlen)-1] and not line[(strlen-1)]
Upvotes: 1
Views: 678
Reputation: 67713
So, for the warnings: you know what lines those numbers refer to, and I'm having to guess: you could make this easier!
int rv=NULL;
initialization makes integer from pointer without a cast [enabled by default] line 42
NULL is a pointer value, rv is an integer. Set it to 0
if that's what you mean.
execvp(line[0],line);
passing argument 1 of ‘execv’ makes pointer from integer without a cast [enabled by default] line 64 passing argument 2 of ‘execv’ from incompatible pointer type [enabled by default] line 64
If you're calling execv
, the code you're compiling is not what you posted. However ... line
is a char *
, so line[0]
is a char
. The first argument of either execv
or execvp
is const char *
.
What is execv trying to accomplish? It needs a program name to run (first argument, const char *) and an array of arguments (these will form the argv[]
array passed to the new program's main
function, and the last item in the array must be NULL).
char *line=(char*) malloc(nbytes+1);
bytes_read=getline(&line,&nbytes,stdin);/*read line from stdin*/
passing argument 2 of ‘getline’ from incompatible pointer type [enabled by default] line 29
getline
needs the address of a buffer to put characters in ... line
is such an address. &line
however, is the address of a pointer. Just take out the &
.
There are more problems in your code, but these warnings all have some things in common:
You need to understand this before you start trying to write multi-process programs. Learn it with something easy, learn to read the documentation, and understand the compiler warnings.
Upvotes: 1
Reputation: 183873
default:
waitpid(child_pid, &status, 0);
//wait(&rv);
printf("PARENT:My child's exit status is: %d\n", WEXITSTATUS(rv));
if((WEXITSTATUS(rv))==3){exit(1);}
You're passing the uninitialised variable child_pid
to waitpid
, that variable is only set in the child process. You should pass pid
. Using the uninitialised variable causes undefined behaviour, so there's no predicting what will happen. Also you call WEXITSTATUS
with another uninitialised variable, rv
, you should pass status
there.
The child doesn't do anything much here because
path_buffer=getcwd(buffer,sizeof(buffer));
the size argument passed to getcwd
is the size of a char*
, usually four or eight bytes, which is too short for the absolute path of most directories, path_buffer is set to
NULLand the child immediately exits. You should pass the size of the buffer,
maxsize` there.
Upvotes: 0
Reputation: 329
The parent never gets the child's pid therefore waitpid is not waiting on it. waitpid(-1,...) will wait for any child processes to finish before continuing.
I would also suggest indenting cases and ending each case statement with a break;
Upvotes: 4