execl command to write on file - c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXLINE 512
main(int argc,char* argv[]){
int k;
for (k=0; k<argc; k++) {
if (k%2==0) {
if (fork()==0){
execl("/user/bin/rev","rev",argv[k],">",argv[k],NULL);
exit(1);
}
}
else
{
if (fork()==0){
execl("/usr/bin/awk","awk","-f","ouk.awk",argv[k],">",argv[k],NULL);
exit(1);
}
wait(0);
}
}
}
awk script
{ for (i=NF;i>=1;i--){ if(s){s=s" "$i} else{s=$i }}{print s;s=""}}
Could someone please tell why this does not work? What I am trying to do is modify
the file argv[i] using the awk script or the rev command
Thanks

To have piping (>) work a shell needs to be involved. The OP's code does not call a shell but starts the awk process directly.
You might like to replace this line:
execl("/usr/bin/awk","awk","-f","ouk.awk",argv[k],">",argv[k],NULL);
by those:
char cmd[PATHMAX] = "";
sprintf(cmd, "\"/usr/bin/awk -f out.awk %s > %s\"", argv[k], argv[k]);
execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
/* As execl() does not return if successful, getting here indicates an error! */
perror("execl() failed");
(This implies that the strings referenced by argv[k]do not contain spaces.)
For details please see your shell's man pages. Note that /bin/sh commonly is linked to some other shell program like bash.

Related

Why does the system call system() not work as intended in this C program?

This is a C program that connects two prcoesses (the parent and child) to a pipe. The child process runs a python script that filters a phrase (String) in an RSS feed and the parent process captures the URL and opens it in a browser. This is the source code
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
void open_url(char *url)
{
char launch[255];
sprintf(launch, "cmd /c start %s", url);
system(launch);
}
void error_msg(char *msg)
{
printf("msg: %s\n", msg);
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(1);
}
int main(int argc, char* argv[])
{
char *phrase = argv[1];
char *vars[] = {"RSS_FEED=https://rss.app/feeds/tUpJh41L1MCpL3dl.xml", NULL};
int fd[2];
if(pipe(fd) == -1)
error_msg("Can't open a pipe");
pid_t pid;
pid = fork();
if (pid == -1)
error_msg("Can't fork process");
if (!pid)
{
dup2(fd[1], 1);
close(fd[0]);
if (execle(
"C:/Users/LENOVO/AppData/Local/Programs/Python/Python310/python",
"C:/Users/LENOVO/AppData/Local/Program/Python/Python310/python",
"./rssgossip.py", "-u", phrase, NULL, vars) == -1
)
error_msg("Can't run script");
}
dup2(fd[0], 0);
close(fd[1]);
char line[255];
while(fgets(line, 255, stdin))
{
if (line[0] == '\t')
open_url(line + 1);
}
return (0);
}
The program compiles without any errors, but when the parent calls system(launch) in open_url(), here's the issue. It surprisingly executes only the first part of the command stored in launch which is "cmd /c start" and ignores the url. More surprisingly is when I debugged the program through a simple printf statement, printf("%s", launch), I replaced the same output of the printf statement with the launch variable so instead of system(launch) -> system("cmd /c start 'url'") and it executed the url in a browser as intended.
EDIT: This is the direct downloading link of the python script (rssgossip.py) used in this program if you would like to try it to get what I'm trying to do clearer.
I recommend you running the script as a Python script first (with Python interpreter) to understand what actually this script does. To run it as a Python script, you would need to define RSS_FEED environment variable and assign an rss feed to it RSS_FEED=<rss_feed_url> (you can use the rss_feed_url used in this program) and finally run it as python rssgossip.py '<any_phrase>'
when i tried this code and it ran fine
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
void open_url(char *url)
{
char launch[255];
sprintf(launch, "cmd /c start "" %s", url);
printf("%s",launch);
system(launch);
}
int main()
{
char url[] = "C:/emu8086/emu8086.exe";
open_url(url);
}
may be the problem at parameter which you input

How to define system()

So I want to define system() function! Here is my function:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
void mySystem (char *command)
{
execlp (command, command, (char*) 0);
}
int main (int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
char command[50];
strcpy(command, argv[i]);
mySystem(command);
}
return 0;
}
And then I try it and it is like that:
gcc exe6.c;
./a.out ls ls
In this case it only does one ls.
./a.out "ls -l"
In this case doesn't do anything. What am I doing wrong?
The man page actually tells you how to do it:
The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
system() returns after the command has been completed.

Attempting to call execvp to run programname supplied through stdin, but call fails each time

Good evening
I have found a few similar questions, but nothing that suffices based on this specific question.
I am forking a child process, and attempting to call execvp to run a simple program which outputs 3 chars to stdout. The program name to be run comes from user input.
For some reason every call to execvp fails for simpleO:
I compile file simpleO.c into simpleO, and then compile and run fork.c. I type simpleO into the prompt when requested to attempt to run, but each time I get the error. Here is the code.
The error message printed by perror is "No such file or directory"
--
fork.c
#include <stdio.h>
#include <unistd.h>/*fork, exec*/
#include <errno.h>/*errno*/
#include <string.h> /*strerror*/
#include <stdlib.h>/*EXIT_FAILURE*/
#define BUFFERSIZE 100
int main(int argc, char *argv[]){
int i = 0;
pid_t pid;
int status;
char buffer[BUFFERSIZE];
fgets(buffer, BUFFERSIZE, stdin);
argv[0] = strtok(buffer, " ");
while (buffer[i] != '\0') {/*analyze each char*/
if (buffer[i] == ' ')/*based on how many spaces there are*/
argv[i] = strtok(NULL, " ");/*tokenize, populate argv*/
i++;
}
if((pid = fork()) == -1){
fprintf(stderr, "fork error: %s\n", strerror(errno));
return EXIT_FAILURE;}
else if (pid==0) {
int e = execvp(argv[0],argv);
if (e==-1) {
perror("Exec failed");
printf("Process %s\n",argv[0]);
perror("Process did not run");
exit(1);
}
}
else{
wait(&status);}
return 0;
}
--
simpleO.c
#include <stdio.h>
int main(int argc, char **argv){
printf("%c",'c');
printf("%c",'2');
printf("%c",'1');
return 0;
}
Addl ref: perror prints "No such file or directory"
Okay, look: a key lesson in programming is that when an error message tells you something, you should believe it. So, your program is saying "no such file or directory", and it means the file you're trying to run doesn't exist at whatever path you're trying to use.
You now know that it's not at the default path, so the next thing to try is to use the absolute path of the executable. Now, given the rest of this, I'd suggest you write a very simple C program that does nothing whatsoever besides trying to fork/exec your child program. No argv vector or anything, just fork and then execvp in the child with the executable path an absolute parth.

running pico using execvp after dup2 in C

What I want to do is basically make standard out of the child process write in the write end of the pipe using dup2 and run pico using execvp and the parent would read the read end of the file and do something with it and write it out in the standard out and display it in pico. This is run under a Linux machine.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc,char* argv[])
{
char* arguments[] = {"pico", "a.txt", NULL};
int my_pipe[2];
if(pipe(my_pipe)==-1)
fprintf(stderr,"Error\n");
pid_t child_id;
child_id = fork();
if(child_id == -1)
{
fprintf(stderr, "Fork error\n");
}
if(child_id==0)
{
close(my_pipe[0]);
dup2(my_pipe[1],1); /*make standard out write in the write end of the pipe?*/
close(my_pipe[1]);
execvp("pico",arguments);
fprintf(stderr, "Exec failed\n");
exit(0);
}
close(my_pipe[1]);
char reading_buf[1];
char r[] = "S";
while(read(my_pipe[0], reading_buf,1)>0)/*read something in the pipe*/
{
write(1,r,1);/*display "S" in pico*/
}
close(my_pipe[0]);
return 0;
} /* end main */
the problem I'm having is that when I try to do the write() in standard out, pico wouldnt show in the terminal and I got this weird output of continuous "S" (from r) like this:
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
and it would add more "S" 's whenever I try to press any key. I'm pretty new to all of this and any help would be appreciated.
I think I know what's going on here: because stdout is redirected to the pipe, when pico tries to print to stdout it's actually printing to the pipe and nothing shows up on the screen. You have to manually print to stdout in the parent. Try changing "write(1,r,1)" to "write(1, reading_buf, 1)" and pico will display normally.

Unix Processes - compile and run c program

Create a parent process that gets from the command line n arguments arg1, arg2, ... , argn. arg1 is the name to a source C, arg2 is the name of the executable file results from compile arg1, and arg3, ... , argn are arguments to start.
The parent compiles arg1 and creates the executable arg2, after that runs it into a son process.
I tried to solve the problem, using some examples, but I didn't really understand them, so the program is not working. I really need some help...
#include<unistd.h>
#include<stdio.h>
#include<sys/wait.h>
#include<string.h>
int main(int argc, char* argv[]){
char com[200];
int p;
p=fork();
strcpy(com,"gcc -o prog.c");
strcat(com,argv[1]);
if(p==0){
if(WEXITSTATUS(system(com))==0)
execl("./prog.c","./prog.c",argv[3],argv[4],argv[5],NULL);
}
wait(0);
exit(0);
return 0;
}
The C program I want to use, reads some input data from two files and stores data into another file.
This code more or less does what you say your program should do. In particular, it uses argv[2] as the program name. It uses snprintf() to avoid overflows with long arguments (but doesn't verify that it didn't overrun). It prints various status messages — partly as a debugging aid, partly to give meaning to the various parts of the program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
int p;
if (argc != 6)
{
fprintf(stderr, "Usage: %s source program file1 file2 file3\n", argv[0]);
return(1);
}
if ((p = fork()) == 0)
{
char com[200];
snprintf(com, sizeof(com), "gcc -o %s %s", argv[2], argv[1]);
if (system(com) == 0)
{
printf("Compilation of %s successful\n", argv[2]);
fflush(0);
execl(argv[2], argv[2], argv[3], argv[4], argv[5], (char *)NULL);
fprintf(stderr, "Failed to execute %s\n", argv[2]);
return(1);
}
fprintf(stderr, "Compilation of %s from %s failed\n", argv[2], argv[1]);
return(1);
}
int status;
wait(&status);
printf("Compilation and execution of %s yielded status %d\n",
argv[2], WEXITSTATUS(status));
return 0;
}
When this file is named gc.c and is compiled to make gc, it can be run as:
$ ./gc gc.c ./gc2 gc.c gc.c gc.c
Compilation of ./gc2 successful
Usage: ./gc2 source program file1 file2 file3
Compilation and execution of ./gc2 yielded status 1
$
The usage message from gc2 is correct; the program expects 6 arguments, not the 4 it is given by the program.
You should look into the manual of exec which will tell you how to run exec to fork another process that behaves according to the specification. This code can help you how to pass on variables to a child process:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for fork */
#include <sys/types.h> /* for pid_t */
#include <sys/wait.h> /* for wait */
int main()
{
/*Spawn a child to run the program.*/
pid_t pid=fork();
if (pid==0) { /* child process */
static char *argv[]={"echo","Foo is my name.",NULL};
execv("/bin/echo",argv);
exit(127); /* only if execv fails */
}
else { /* pid!=0; parent process */
waitpid(pid,0,0); /* wait for child to exit */
}
return 0;
}

Resources