execlp time doesn't show anything - c

int main(int argc, char* argv[]){
execlp("time", "time", NULL);
return 0;
}
Nevertheless, if I add an argument to time like ls, it does work:
int main(int argc, char* argv[]){
execlp("time", "time", "ls", NULL);
return 0;
}
Output:
LICENCIA main.c msh parser.y prueba.c scanner.o y.tab.h
Makefile main.o parser.o prueba scanner.l tempCodeRunnerFile.c
0,00 real 0,00 user 0,00 sys
Any idea?

This works as expected. execlp("time", "time", NULL); is equivalent to executing /usr/bin/time (assuming that is what it resolves to; it could be different environments different from mine), and executing /usr/bin/time (again on my system, macOS 10.14.6) with no arguments does not print anything. I suppose other implementations of the time utility could print a message that no command to time was given and/or exit with an error code.
In contrast, execlp("time", "time", "ls", NULL); is equivalent to executing /usr/bin/time ls, in which case the time program executes ls and reports its times.
in the linux terminal if you type time it shows you the shell and child processes times…
When you type time in a command-line shell, it executes the shell’s built-in time function, not the system time program. To reproduce this using execlp, you must use execlp to start a shell, not time, and you must pass the shell arguments to give it a time command to execute.

Related

How to execute a code whose main function looks like this?

The code is like (real noob question) :
int main(int argc, char **argv){
//some code
}
I know, it means I have to give some arguments while executing in the terminal, but the code does not require any arguments or information from the user. I don't know what to give as the argument?
For example:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello World\n");
}
Compile with GCC,
$gcc prog.c -o prog
$./prog
Hello World
So, If you do not use agave in your code, then, there is no need to provide an argument.
I have to give some arguments while executing in the terminal,
No, you don't have to. You may give some arguments. There are conventions regarding program arguments (but these are just conventions, not requirements).
It is perfectly possible to write some C code with a main without argument, or with ignored arguments. Then you'll compile your program into some executable myprog and you just type ./myprog (or even just myprog if your PATH variable mentions at the right place the directory containing your myprog) in your terminal.
The C11 standard n1570 specifies in §5.1.2.2.1 [Program startup] that
The function called at program startup is named main. The implementation declares no
prototype for this function. It shall be defined with a return type of int and with no
parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be
used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent) or in some other implementation-defined manner.
The POSIX standard specifies further the relation between the command line, the execve function, and the main of your program. See also this.
In practice I strongly recommend, in any serious program running on a POSIX system, to give two argc & argv arguments to main and to parse them following established conventions (In particular, I hate serious programs not understanding --help and --version).
You can always pass some number of arguments or pass nothing unless you are checking for the number of arguments and arguments passed (or forcing compiler to do so). Your command interpreter has no idea what your program is going to do with the passed argument or whether the program need any argument. It's your program which takes care of all these things.
For example,
int main(void){
return 0;
}
you can pass any number of arguments to the above program
$ gcc hello.c -o hello
$ ./hello blah blah blah
In case of
int main(int argc, char **argv){
return 0;
}
you can pass no arguments.
$ gcc hello.c -o hello
$ ./hello
For
int main(int argc, char **argv){
if(argc < 3){
printf("You need to pass two arguments to print those on the terminal\n");
exit(0);
}
else{
printf("%s %s\n", argv[1], arv[2]);
}
return 0;
}
You have to pass two arguments because the program checking the number of arguments passed and using them
$ gcc hello.c -o hello
$ ./hello Hello world

run linux command using execlp with more than one argument as string in c

I am trying to run ls using system calls in C with more than one argument, for example -l -a. The arguments and their number is changing depending on the user input. The input is concatenated "-l" + "-a" == "-l -a". The code I'm using is:
execlp("ls","ls",arguments,NULL) //arguments = "-l -a"
The user input is from Terminal:
-l
-a
if you want to executes more than one argument , then you should use execvp() instead of execlp.
#include<stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
execvp(argv[1],argv+1);// argv+1 means whatever arguments after argv[1] it will take & executes it
return 0;
}
for e.g your input like that
xyz#xyz-PC:~$ ./a.out ps -el
I hope it helps.

Relation between PATH env and argv[0]

Generally argv[0] is as same as exec file name. For example:
If I execute program with ./my_program then argv[0] is ./my_program
If I execute program with /home/username/my_program then argv[0] is /home/username/my_program.
My question is, if PATH=/home/username why I can't see argv[0] value?
This is my real situation
PATH=/home/knight/bin:/home/knight/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/knight
My test program source is:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("%s\n", argv[0]);
}
My home directory is /home/knight so I can execute program directly.
knight#knight-desktop:~$ test
knight#knight-desktop:~$ ./test
./test
I can't understand, why doesn't the knight#knight-desktop:~$ test command print any result?
Because test is a shell builtin command.
And there is a big difference between ./test(it is an executable file) while test is a command passed direct to the shell of which if typed incorrect, it could have been not recognised for example lets say you use the command tst the result will be -bash: tst: command not found
To check if any word is a builtin command/reserved keyword for shell,use command type.
on terminal,
$type test
test is a shell builtin
$type if
if is a shell keyword

executing a program in C linux using fork and exec

I want to execute a C program in Linux using fork and exec system calls.
I have written a program msg.c and it's working fine. Then I wrote a program msg1.c.
When I do ./a.out msg.c, it's just printing msg.c as output but not executing my program.
#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(int argc,char** argv)
{
/*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;
}
argv[0] contains your program's name and you are Echo'ing it.
Works flawlessly ;-)
/bin/echo msg.c will print msg.c as output if you need to execute your msg binary then you need to change your code to execv("path/msg");
your exec executes the program echo which prints out whatever argv's value is;
furthermore you cannot "execute" msg.c if it is a sourcefile, you have to compile (gcc msg.c -o msg) it first, and then call something like exec("msg")
C programs are not executables (unless you use an uncommon C interpreter).
You need to compile them first with a compiler like GCC, so compile your msg.c source file into a msg-prog executable (using -Wall to get all warnings and -g to get debugging info from the gcc compiler) with:
gcc -Wall -g msg.c -o msg-prog
Take care to improve the msg.c till you get no warnings.
Then, you might want to replace your execv in your source code with something more sensible. Read execve(2) and execl(3) and perror(3). Consider using
execl ("./msg-prog", "msg-prog", "Foo is my name", NULL);
perror ("execl failed");
exit (127);
Read Advanced Linux Programming.
NB: You might name your executable just msg instead of msg-prog ....

Calling execve bash on bash scripts can't find arguments

I have two (Ubuntu Linux) bash scripts which take input arguments. They need to be run simultaneously. I tried execve with arguments e.g.
char *argv[10] = { "/mnt/hgfs/F/working/script.sh", "file1", "file2", NULL };
execve(argv[0], argv, NULL)
but the bash script can't seem to find any arguments at e.g. $0, $1, $2.
printf "gcc -c ./%s.c -o ./%s.o\n" $1 $1;
gcc -c ./$1.c -o ./$1.o -g
exit 0;
output is gcc -c ./main.c -o ./main.o
and then a lot of errors like /usr/include/libio.h:53:21: error: stdarg.h: No such file or directory
What's missing?
Does your script start with the hashbang line? I think that's a must, something like:
#!/bin/bash
For example, see the following C program:
#include <stdio.h>
#include <unistd.h>
char *argv[10] = { "./qq.sh", "file1", NULL };
int main (void) {
int rc = execve (argv[0], argv, NULL);
printf ("rc = %d\n", rc);
return 0;
}
When this is compiled and run with the following qq.sh file, it outputs rc = -1:
echo $1
when you change the file to:
#!/bin/bash
echo $1
it outputs:
file1
as expected.
The other thing you need to watch out for is with using these VMWare shared folders, evidenced by /mnt/hgfs. If the file was created with a Windows-type editor, it may have the "DOS" line endings of carriage-return/line-feed - that may well be causing problems with the execution of the scripts.
You can check for this by running:
od -xcb /mnt/hgfs/F/working/script.sh
and seeing if any \r characters appear.
For example, if I use the shell script with the hashbang line in it (but appen a carriage return to the line), I also get the rc = -1 output, meaning it couldn't find the shell.
And, now, based on your edits, your script has no trouble interpreting the arguments at all. The fact that it outputs:
gcc -c ./main.c -o ./main.o
is proof positive of this since it's seeing $1 as main.
The problem you actually have is that the compiler is working but it cannot find strdarg.h included from your libio.h file - this has nothing to do with whether bash can see those arguments.
My suggestion is to try and compile it manually with that command and see if you get the same errors. If so, it's a problem with what you're trying to compile rather than a bash or exec issue.
If it does compile okay, it may be because of the destruction of the environment variables in your execve call.

Resources