How to transfer parameters from execl to scanf? - c

I want to transfer some parameters from one program to another.
For example, here are two programs. a.c compiled as a
#include <stdio.h>
int main() {
char a[10];
scanf("%s", a);
printf("%s\n", a);
return 0;
}
and e.c compiled as e:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main() {
char *input = "here it is";
execl("./a", "a", "a", NULL);
return 0;
}
Actually, I would like to transfer the parameter "a" from the e.c to a.c so that once I execute the program "e", it will print out
a
a
However, I find out that excel cannot pass the parameters to the specified program.
If I cannot modify the program a.c, how can I execute this program using another program using standard input?

If you can't modify a.c, then you'll need to write the data to some file, then reset stdin to read from that file:
FILE *fp = fopen("somefile", "w");
if (fp == NULL)
// handle error
fputs(input, fp);
fclose(fp);
if (freopen("somefile", "r", stdin) == NULL)
// handle error
unlink("somefile");
execl("./a", "a", NULL);
The unlink system call makes sure the file disappears when a is done with it.
Note: you might be able to use a pipe instead of a file, because the message is so small that it will fit inside a pipe's buffer. That's not a reliable solution for larger messages, though -- if you want to use a pipe, you need to fork.

Related

How to write a file, then make it executable in C?

I am trying to write a program that writes a file with some text in it, then makes that file executable. This is what I have:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
char name[] = "foo";
FILE * fp;
fp = fopen(name, "w");
fprintf(fp, "This file should be executable.\n");
execl("/usr/bin/chmod", "/usr/bin/chmod", "+x", name, NULL);
return 0;
}
The problem I am having that running execl seems to remove the contents of the file I wrote. If I remove the execl, it works as expected, and writes a file with the desired text. But when I leave in the execl, it writes a file, makes it executable, but the file is blank. How do I make it so the file still has the text in it, and is executable?
The problem is that output to the file is buffered. When you call execl(), you replace the process with chmod, but never write the stdio buffer to the file.
You need to call fclose(fp) before execl() to force everything to be written. You could also use fflush(fp), but fclose() more complete.
Creating the file with the wrong permissions and then changing them is not what you want to do. Just create the file with the desired permissions in the first place. If you want the file to be executable you can (with one caveat mentioned below) run:
/* CAUTION: all error checking omitted for clarity */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void)
{
char name[] = "foo";
FILE * fp;
int fd = open(name, O_RDWR | O_CREAT, 0777);
fp = fdopen(fd, "w");
fprintf(fp, "This file should be executable.\n");
return 0;
}
This will create the file with mode 0777 (modified by the umask) when executed. (eg, if umask is 111, the executable bits will not be set)
But, if you do want to create the file with the wrong permissions and then change them, don't exec out to /usr/bin/chmod. Just use chmod(2). eg chmod(name, 0777);
+x is convenient if you are just adding a permission, but since you are creating the file you are in complete control and you know what the permissions are.

Execute hello.c file by using file handlers in C

I'm trying my luck with C lately and I came across to this question where I'm stuck.
I've a hello.c file
CODE 1
#include<stdio.h>
#include<stdlib.h>
int main(){
printf("Hello World");
return 0;
}
I open this file and display the content using the following C program (CODE 2)
CODE 2
#include<fcntl.h>
#include<stdio.h>
int main() {
FILE *fd;
char ch;
fd = fopen("/home/hello.c","r");
if( fd != NULL ) {
while((ch = getc( fd )) != EOF){
putchar(ch);
}
}
return 0;
}
However, I want the output of this code to be Hello World, i.e output of the hello.c file which is read.
How can that be done?
In order to run a c file, first you need to compile it into machine code then execute it.
To compile it: run gcc source-file -o executable-file
To run, execute: executable-file
In order to to the same things in C, use system() function from <stdlib.h>
const char* tempFile = "./tempfile";
const char* sourceFile = "hello.c";
const char compileCommand[255];
sprintf(compileCommand, "gcc %s -o %s", sourceFile, tempFile);
system(compileCommand);
system(tempFile);
This code hasn't been tested.
Currently, in the second program, you are reading hello.c file. So the output of CODE2 will be the contents of hello.c. i.e. #include<stdio.h>...
For what you need, in CODE1, you need to write the output of the program into a separate file (say a.txt) and then read a.txt in CODE2.
Hope this is a sufficient hint for you to solve further.
Your "CODE 2" would have to invoke a C-compiler to compile "CODE 1" and then run it using system() or a function provided by your operating system.
BTW: It is either int main(void) or int main(int argc, char** argv), NOT int main().
As general solution, you may try also to have a look to a C interpreter, like Cling, and try to include it in your project.

execv vs execvp, why just one of them require the exact file's path?

I have two files in the same directory.
directory/
| a.c
| b.c
a.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid;
int status;
int wret;
if ((pid = fork()) < 0)
printf("error");
else if(pid == 0)
{
printf("%s", argv[1]);
execv(argv[1], &argv[1]);
}
else
{
/* respawn */
if ((wret = wait(&status)) != -1)
execv(argv[1], &argv[1]);
}
return 0;
}
b.c is just a simple program that print "hello".
I want to run ./a b from the command line to make the a program call exexXX to execute the b program.
I don't understand why if I use execv I can write just ./a b in the command line, instead if I use execvp I have to write ./a ./b.
The man exec page is not clear because it reports
"The initial argument for these functions is the name of a file that
is to be executed."
Thanks
If the program name argument contains no slashes, the execvp() function looks for the program to execute in the directories listed on your PATH environment variable. If you don't have . (the current directory) on your PATH and you aren't in one of the directories listed on your path, a plain name like b will not be executed, even if b is in the current directory. If the name contains a slash, it can be relative (./b) or absolute (/home/someone/src/programs/b) and it will be interpreted as a file name to be executed without consulting the PATH environment variable.
By contrast, execv() treats a plain b in the program name argument as ./b — the name of the file in the current directory and executes it if it is present, and fails if it is located somewhere else.
At one time, there was a comment that asked:
Are you saying if you have an executable b in . and you do execv("b", b_args), it will get executed?
On a normal Unix box, yes.
Code b.c:
#include <stdio.h>
int main(void)
{
puts("Hello");
return 0;
}
Code a.c:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char *argv[] = { "b", 0 };
execv(argv[0], argv);
fprintf(stderr, "failed to execute '%s'\n", argv[0]);
return 1;
}
Running these:
$ (PATH=$(clnpath "$PATH" ".:$PWD"); echopath PATH; ./a)
/Users/jleffler/bin
/opt/informix/12.10.FC6/bin
/Users/jleffler/oss/bin
/Users/jleffler/oss/rcs/bin
/usr/local/mysql/bin
/opt/gcc/v7.3.0/bin
/Users/jleffler/perl/v5.24.0/bin
/usr/local/bin
/usr/bin
/bin
/opt/gnu/bin
/usr/sbin
/sbin
Hello
$
The clnpath script modifies the string provided as its first argument ("$PATH") by removing any occurrences of any of the directory names listed in its second path-like argument (".:$PWD") — it's how I edit my PATH on the fly when I need to. The echopath script echoes the directories on PATH (or any other path-like variable, or it will process the result of expanding a pathlike variable, such as "$PATH"), one per line — the output shows that neither . nor /Users/jleffler/soq (which is where I run the program) is on $PATH in the sub-shell. The ./a runs the code from a.c (it would not be executed without that ./ in front), which in turn runs the code from b.c, which produces the Hello. (If there is some system where this does not work, please identify it.)
I could also arrange for b.c to be:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
puts("Hello");
const char *env = "PATH";
char *val = getenv(env);
if (val == 0)
val = "<nothing>";
printf("%s=%s\n", env, val);
return 0;
}
which would print the value of $PATH directly from the executable (to verify that neither . nor the value of the current working directory is listed).

C - fprintf isn't writing to file

C - fprintf isn't writing to file, any idea why?
#include <stdio.h>
#include <stdlib.h>
int main(void){
FILE* pfile=fopen("/home/user-vlad/Programming/C-other/meme.txt","r");
if(pfile==NULL){
printf("ERROR: Stream is equal to NULL\n");
exit(1);
}
fprintf(pfile,"Hello");
fclose(pfile);
return 0;
}
Compiler: clang, OS: FreeBSD
Assuming the file opens can be because you called fopen() with the argument "r", that means read.
To write you can use the argument "w"
fopen("/home/user-vlad/Programming/C-other/meme.txt","w");
Or if the file already exists "r+"
fopen("/home/user-vlad/Programming/C-other/meme.txt","r+");
Or if the file already exists and you want to append you can use "a"
fopen("/home/user-vlad/Programming/C-other/meme.txt","a");
You can learn more on fopen() here.

How to use System(const char*) in TC++

Today , When i coding, met a question..my Code as follow:
#include<stdlib.h>
void main()
{
system("dir");
getch();
}
The question : The user Screen is nothing..Why ? where is my result?
If you want the output when using system, at least into something you can read in your application, you need to pipe the output:
system("dir > /tmp/output.txt");
FILE *f = fopen("/tmp/output.txt", "r");
char text[1024]; // max sizeof of 1 kb, any more and I'd consider using `malloc()` instead.
fread(text, 1, 1024, f);
printf("%s\n", text);
fclose(f);
There are some problems in your program, at least one of which has already been mentioned.
void main() should be int main(void).
As I recall, the Windows/DOS getch function is declared in <conio.h>; you should have a #include directive for it. Be aware that both <conio.h> and getch are non-standard.
Since main returns int, you should return an int result.
But none of these problems explain the problem you're seeing.
With these changes:
#include <stdlib.h>
#include <conio.h>
int main(void)
{
system("dir");
getch();
return 0;
}
This should work; it should show a directory listing of whatever directory your program runs in (which is determined by TC; I don't know the details).
It's possible that the program is running in an empty directory, which means the dir command wouldn't show any files, but it should still produce some output.
Try commenting out the system() call and adding a printf call (note the added #include <stdio.h>):
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main(void)
{
printf("Hello, world\n");
getch();
return 0;
}
This should open a console window, print "Hello, world" in it, and wait for you to type Enter.
If you still don't see any output (either no console window, or a console window with nothing in it), then you have a problem that's not related to the system() call. Most likely the problem has to do with the way you're using Turbo C (I presume that's what "TC" stands for).
The main function in every C program is supposed to return an int you are returning void
Change void to int:
#include<stdlib.h>
int main()
{
system("dir");
getch();
}
When I tested, the dir command ran in my console and printed to standard out.
May be he is the running the program directly in the Turbo C IDE and hence his output is not visible. If he runs the program directly from cmd line it works. I remember you need to run Alt - F5 or some other combination to see the output window in Turbo C++

Resources