In my code, I am using execve() to execute a file at a particular location.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FILE "newFolder/program"
int main() {
char *n[] = { FILE, NULL };
execve(FILE, n, NULL);
perror("execve");
exit(1);
}
I do not have the complete source code of FILE but I know that it ends in the following:
execl("/bin/sh", "/bin/sh", NULL);
Is there a way for me, through my code which calls FILE, to execute shell commands (i.e. ls -la) on the bin/sh that FILE opened?
Related
I have the following code(there's a bunch of extra headers that were used in other parts of the code that I removed since they don't have anything to do with my issue). I have also removed the error checking for fork and pipe for brevity:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
void compile(char *fullname)
{
int pid = fork();
int pipe_send_output[2];
pipe(pipe_send_output);
if (pid == 0)
{
close(pipe_send_output[0]);
dup2(pipe_send_output[1], STDERR_FILENO); // redirect output of gcc to the pipe
execlp("gcc", "gcc", "-Wall", fullname, NULL);
printf("execlp error");
}
else
{
close(pipe_send_output[1]);
dup2(STDIN_FILENO, pipe_send_output[0]); // redirect from pipe to stdin
close(pipe_send_output[0]);
exit(0);
}
}
int main(){
compile("folder/small.c");
}
The compile function is supposed to create a new process which compiles some c file using gcc, and then sends the output(errors and warnings) to the parent process, to be printed. To do this I redirected STDERR to the write end of the pipe, and then in the parent process redirected the read end to stdin. I can't for the life of me figure out why it's not displaying anything. If I remove the redirection of stderr to the pipe, then plenty of stuff it outputed, so the issue isn't gcc not outputting anything. I tried to replace the redirection to stdin with reading from the pipe and then printing it, but that has the same result. A couple of time this did print one or 2 characters, which is even more confusing. This is the code that replaces the second call to dup2 for printing:
char buffer[1024];
while(read(pipe_send_output[0], buffer, 1024)) printf("%s", buffer);
I've looked everywhere on google and on the man page and still don't have a clue what's wrong.
Disclaimer:This is part of a project for a lab at university. The code that I wrote follows the blueprint from the materials my professor provided, and makes perfect sense to me. Any hint on what the issue may be is appreciated.
More specifically, the program is supposed to emulate the bash command cat file| grep $keyword > file.
What I've done is: In the parent I read every character from the file and format them into lines which I then send to the named pipe, then in the child write the lines containing the keyword into the original file.
However, I receive a segmentation fault error when attempting to read the second character from the original file, which I assume is because the parent is waiting for the child to write in the original file instead of instead of reading the contents of said file.
Any help with the implementation/explanation of why exactly the error occurs would be great.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
char key[20], *c,line[40];
int fd,fd_r,fd_w,fd_fr,fd_fw,counter=0;
int main(){
pid_t pid;
mkfifo("fifo1",0777);
fgets(key,10,stdin);
int k=0;
if ((pid=fork()) < 0)
perror("err_fork");
if(pid){ //PARENT
printf("%d\n",fd_r=open("prog.c",O_RDONLY));
printf("%d\n",fd_fw=open("fifo1",O_WRONLY));
while(read(fd_r,c,1)){
line[k++]=(*c);
while(read(fd_r,c,1) && ((*c)!='\n'))
line[k++]=(*c);
line[k]=0;
write(fd_fw,line,strlen(line)+1);
memset(line,0,sizeof(line));
}
close(fd_r);
close(fd_fw);
}
else{ //CHILD
printf("%d\n",fd_w=open("prog.c",O_WRONLY));
printf("%d\n",fd_fr=open("fifo1",O_RDONLY));
while(read(fd_fr,line,sizeof(line))){
c=strstr(line,key);
if(c)
write(fd_w,line,strlen(line)+1);
}
close(fd_w);
close(fd_fr);
}
unlink("fifo1");
}
You're segfaulting because you're trying to read a byte into c. However, c is an uninitialized global pointer and thus it's equal to NULL. Trying to read data at that location is therefore an invalid use of memory.
What you do instead is declare
char c;
and then
read(fd_r,&c,1)
I'm trying to make a named pipe on c under linux using the mkfifo command. But when I run the program, I either get a "no such file or directory" error or absolutely nothing (console doesn't display anything)
Here is my code :
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define MAX_LINE 80
int main(int argc, char** argv) {
int create;
//mkfifo("/tmp/myfifo", 0666);
create = mkfifo("tmp/myfifo", 0666);
if (create==-1)
{
printf("error%s", strerror(errno));
}
char line[MAX_LINE];
int pipe;
pipe = open("/tmp/myfifo", O_WRONLY);
if (pipe==-1)
{printf("error");
}
printf("Enter line: ");
fgets(line, MAX_LINE, stdin);
write(pipe, line, strlen(line));
sleep (100);
close(pipe);
return 0;
}
I am still learning, and I don't understand what i'm doing wrong. Thanks for your help.
For a named pipe to be useful, somebody has to read it and somebody has to write it. Usually this will be 2 separate programs. Your program is the writer. Where is the reader?
If there is no reader, it is normal for the program to block on the O_WRONLY open. So when your program appears to be doing nothing, it's really just doing this:
pipe = open("/tmp/myfifo", O_WRONLY);
which waits for a reader to show up.
In another terminal, run cat /tmp/myfifo. The presence of a reader will allow the writer to make progress. Your program will wake up and move on to the Enter line prompt, and what you enter will be read by the cat and written to the second terminal.
The other problem is an inconsistency in your filenames. In one place you wrote "tmp/myfifo" without a leading slash, so you are trying to create the named pipe in a tmp directory that is inside the current working directory. If that tmp directory doesn't exist, No such file or directory will be the result.
I stumbled upon a problem in a program I was working on. The following reproduces my issue:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int fd, ret_fd;
DIR *dirp;
fd = open("./", O_RDONLY);
#if 1
if ((dirp = fdopendir(fd)) == NULL) {
perror("dirp");
return 1;
}
closedir(dirp);
#endif
ret_fd = openat(fd, "Makefile", O_RDONLY);
if (ret_fd == -1) {
perror("ret_fd");
return 1;
}
return 0;
}
Basically, the call to openat(), which has been preceeded by fdopendir(), fails with: Bad file descriptor. However, this does not happen if fdopendir() is omitted.
I know that fdopendir() makes internal use of the file descriptor, but shouldn't it revert any changes to it after calling closedir()?
What can I do to prevent openat() from failing in this case?
The POSIX description of fdopendir() says:
Upon calling closedir() the file descriptor shall be closed.
So the descriptor is likely to be closed by the time you call openat().
And this is from a typical Linux man page for fdopendir():
After a successful call to fdopendir(), fd is used internally by the
implementation, and should not otherwise be used by the application.
I need to work with multiple displays in execlp calls (). I'm trying this:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("calling to execlp:\n\n");
execlp("DISPLAY=:0 /usr/bin/qtdisplay","qtdisplay", "-r", NULL);
execlp("DISPLAY=:1 /usr/bin/qtdisplay","qtdisplay", "-r", NULL);
printf("fail!");
exit(0);
}
But this fails, with the following message: execlp: No such file or directory
Is there any way to work with the displays?
Try system() instead, it'll start a new child process and call exec() from there. Also, it handles shell command-line constructs by calling a shell and handing your shell construct to that shell, like this:
system("DISPLAY=:0; /usr/bin/qtdisplay -r");
Also, learn to check return codes from functions like this, and do some sane action (like print an error message):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int rc;
rc = system("DISPLAY=:0; /usr/bin/qtdisplay -r");
if (rc == -1) {
perror("error starting qtdisplay on :0");
exit(1);
}
rc = system("DISPLAY=:1; /usr/bin/qtdisplay -r");
if (rc == -1) {
perror("error starting qtdisplay on :1");
exit(1);
}
exit(0);
}
If you want these two commands to be run in parallel (not one after the other), you should use command-lines like this:
system("DISPLAY=:0; /usr/bin/qtdisplay -r &");