I'm a beginner programmer to C and I'm trying to write a basic shell. I'm trying to use the fork() function, but it simply doesn't seem to work. I get caught in an endless loop of just my shell's prompt taking input and then seemingly doing nothing with it.
I ran the debugger and set the breakpoint to where the program forks, and at that point, I got an error message of
Can't find a source file at "/build/glibc-Cl5G7W/glibc-2.23/posix/../sysdeps/nptl/fork.c"
Locate the file or edit the source lookup path to include its location.
What I think is happening is that I either messed up with my #include headers or that when I tried to compile, I left some library out. I've just been compiling with the standard
gcc -o shell custom_shell.c
and I recall my teacher saying something about compiling with libraries, but I thought my #include headers would cover that and I can't find anything else on the topic online.
The parts of my code I'm wary over are
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
...
pid_t pid = fork();
if (pid < 0){ //error
perror("fork");
exit(1);
}
else if (pid == 0){ //child
execvp(args[0], args);
}
else{ //parent
wait(0);
}
Related
I have a C program. I noticed that you can't put 2 execl's in it.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t fork(void);
int system(const char *command);
execl("/bin/sh", "sh", "-c", "kdialog --warningcontinuecancel
\"Make sure to include: \n \n 1. py_lcd folder \n 2. 4x20
Raspberry Pi LCD Display \n 3. Python 2.7.12 to be installed \n
\n If you are missing something, kill the program process and
get them.\"", (char *) 0);
sleep(1);
execl("/bin/sh", "sh", "-c", "kdialog --msgbox \"Setting up files...\" --title \"Installing...\"", (char *) 0);
return(0);
}
Can someone help me if there is a way to bypass this or if i am making a mistake???
The exec family of functions don't return when they succeed. They replace the running process with the one being execed. If you want to run a program in a child process (with full control, unlike system), you need to use fork + exec + wait (or perhaps posix_spawn).
Anything written after execl is a deadcode. The main purpose of execl is to re-use the current process information for a new process to improve performance. You will be using sharing the same structures of process information(pid, stack, heap etc.) of the current process where execl is executed.
I found an answer myself. There is a system() command which works the exact same but you are able to insert it anywhere in the code without problems
I'm trying to debug a linux user-space application, which creates a process group with setpgid(0,0). When launched on terminal, it returns no error and work as expected. But when debugging with gdb, it returns EPERM.
I suspect that it is because the gdb attaches my process as a child. So it is not possible to set my process as parent with setpgid(0,0). Is that correct? If so, isn't there a way to debug this case with gdb?
Edit:
Environment:
Ubuntu 12.04 Kernel 3.11.0-15-generic
Using the simple code below, if launched on terminal, I get success!!. If I debug with gdb (configured on Eclipse Luna), I get setpgid: Operation not permitted.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int err = setpgid((pid_t)0, (pid_t) 0);
if (err < 0)
perror("setpgid");
else
printf("success!! \n");
exit(err);
}
i have a question:
exists any system call for generate a core dump?
I know which a core dump could be generated by a signal, but i want know if it's possible generated from system call
void createdump(void)
{
if(!fork()) { //child process
// Crash the app
abort() || (*((void*)0) = 42);
}
}
What ever place you wan't to dump call the function. This will create a child and crash it. So you can get dump even without exiting your program
You can also raise the SIGABRT signal to get the core dump.
raise(SIGABRT);
*this is equivalent to calling abort() directly.
Same idea as code hacker's answer, but compilable, with error handling, and without the zombie:
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int
coredump(void)
{
pid_t p,r;
if(0>(p=fork()))
return -1;
if(0==p)
abort() /*child*/;
/*reap zombie*/
do r=waitpid(p,0,0); while(0>r && EINTR==errno);
if(0>r) {
perror("waitpid shouldn't have failed");
abort();
}
return 0;
}
This still has the rather obvious deficiency in that that it won't work with multithreaded processes.
I was working on my project when I needed to use "curl" to obtain some data from www. Now firstly I tried direct system() function but it didn't worked, strangely everytime it corrupted the whole source code file while compiling with gcc. Luckily I was testing it separately.
Then I tested execl() function, this code compiles OK and gcc gives me a .exe file to run, but nothing happens when I run it,blank windows appears. CODE:
int main(){
execl("curl","curl","http://livechat.rediff.com/sports/score/score.txt",">blahblah.txt",NULL);
getch();
return 0;
}
Includes are not shown properly but I have included stdio,conio,stdlib and unistd.h.
How can I get output of program to store in text file? Also running the above command creates and stores text file in My Documents, I want it to be in local directory from where I run the program. How can I do that?
You need to provide the path of curl, and you cannot use redirection because the application will not be executed through bash. Instead use the -o flag and specify the filename. Also, execl does not return when successful:
#include <unistd.h>
#include <stdio.h>
int main(){
execl("/usr/bin/curl",
"curl","http://livechat.rediff.com/sports/score/score.txt",
"-oblahblah.txt",NULL
);
printf("error\n");
return 0;
}
If you want your code to return, you should fork a child process to run the command. This way you can check the return code.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define CURL "/usr/bin/curl"
int main()
{
pid_t pid;
int status;
pid = fork();
if (pid == 0)
{
execl(CURL, CURL, arg1, NULL);
}
else if (pid < 0)
{
printf("Fork failed\n");
exit (1);
}
else
{
if (waitpid(pid, &status, 0) != pid)
status = -1;
}
return status;
}
arg1 is whatever argument you want to use with curl or if you aren't using any than you obviously can omit it.
I've been using a combination of fork() and exec() to execute some external command on linux, however, the code seems to fail whenever I try to execute /usr/bin/firefox which is a symbolic link to a real binary.
Does anyone know how to solve this problem? I've tested with other programs (which really are executable binaries and not symlinks to them) and it works.
Here's the code from the program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv) {
pid_t pid;
// this was the old line:
// char *parmList[] = {"", "index.html", NULL};
// and this is the one that solves the problem:
char *parmList[] = {"firefox", "index.html", NULL};
int a;
if ((pid = fork()) == -1)
perror("fork failed");
if (pid == 0) {
a = execvp("/usr/bin/firefox", parmList);
fprintf(stdout, "execvp() returned %d\n", a);
fprintf(stdout, "errno: %s (%d).\n", strerror(errno), errno);
}
else {
waitpid(pid, 0, 0);
}
return 0;
}
Edit: I updated the code to include the answer and changed the topic's title because the problem really didn't seem to be due to symbolic links at all. Thanks everyone.
You might want to add some code right after the execvp to output some diagnostic (i.e. check errno, print something meaningful ;)).
You could also try to analyze it w/o source modification using strace or gdb for that matter.
See also: execve.
Update as follow-up from the comments
Firefox is not happy with argv[0] being empty, which is what argList looked like, unfortunately.
Lessons learned: Be thoroughly aware of what you pass as argv to the program you execute. :)
Does Firefox insist on having a non-empty argv[0]? You should normally pass the name of the command (either just "firefox" or "/usr/bin/firefox") to the command, but you are not doing so.
[...going to check the deeper comments above - and it seems this is the correct diagnosis, but 21 minutes or so late...]