run rsync through execvp: StrictHostKeyChecking=no: unknown option - c++

I am trying to run rsync through execvp with StrictHostKeyChecking option.
This is my code:
#include <unistd.h>
int main() {
char *argv[] = {"rsync",
"remote_user#1.2.4.5:/tmp",
"/home/tmp/",
"-e 'ssh -o StrictHostKeyChecking=no'",
0};
execvp("rsync", argv);
}
I am getting this error:
rsync: -e '-o StrictHostKeyChecking=no': unknown option
rsync error: syntax or usage error (code 1) at main.c(1422) [client=3.0.6]
I have tried another way:
#include <unistd.h>
int main() {
char *argv[] = {"rsync",
"remote_user#1.2.4.5:/tmp",
"/home/tmp/",
"-e",
"'ssh -o StrictHostKeyChecking=no'",
0};
execvp("rsync", argv);
}
But now it is failing with error:
rsync: Failed to exec ssh -o StrictHostKeyChecking=no: No such file or directory (2) rsync error: error in IPC code (code 14) at pipe.c(84) [sender=3.0.6]
Why it don't understand StrictHostKeyChecking option?

rsync expects to receive the options first, followed by the hosts. You're doing it backwards: first you need to specify -e and -o.
You also shouldn't be single-quoting the -o option: that is needed when invoking it from bash, to prevent bash from interpreting the arguments and splitting them into separate argv[] entries. Think about it: when bash sees '-o StrictHostKeyChecking=no', it passes -o StrictHostKeyChecking=no as a single argv[] entry, without the single quotes (because the single quotes is your way to tell the shell that you don't want argument splitting).
Last, but not least, you should check that execvp(3) didn't fail.
So, this is what you need:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char *argv[] = {
"rsync",
"-e",
"ssh -o StrictHostKeyChecking=no",
"remote_user#1.2.4.5:/tmp",
"/home/tmp/",
NULL
};
if (execvp("rsync", argv) < 0) {
perror("rsync(1) error");
exit(EXIT_FAILURE);
}
return 0;
}

Related

How to compile a c++ code using libtorrent?

I am testing the example code posted on the official libtorrent website (https://www.libtorrent.org/tutorial-ref.html). I pasted the code here:
#include <libtorrent/session.hpp>
#include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/magnet_uri.hpp>
int main(int argc, char const* argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s <magnet-url>\n");
return 1;
}
lt::session ses;
lt::add_torrent_params atp = lt::parse_magnet_uri(argv[1]);
atp.save_path = "."; // save in current dir
lt::torrent_handle h = ses.add_torrent(atp);
// ...
}
I have already installed the libtorrent:
ldconfig -v | grep libtorrent
libtorrent-rasterbar.so.9 -\> libtorrent-rasterbar.so.9.0.0
I used the following command to compile the code:
g++ main.cpp -o run -ltorrent-rasterbar -lboost_filesystem-mt
However, I got errors:
main.cpp: In function 'int main(int, const char\*\*)':
main.cpp:12:3: error: 'lt' has not been declared
lt::session ses;
I also saw another solution, but it does not resolve the issue I am facing: How to compile a libtorrent(rasterbar) code ?
Does anyone know what caused this failure?

How can i give command line arguments without using out extension ,not ./a.out 3 4 but like ./a 3 4

int main(int argc, char *argv[])
{
if (argc < 2) {
printf("missing argument\n");
exit(-1);
}
printf("%s %s %s", argv[1], argv[2]);
return 0;
}
Just want to give command line arguments like ./a 3 4 without using .out in linux terminal thanks!!
Assuming your source file was a.c, just use the -o ("output") flag when you compile it, like this:
cc -o a a.c
Or, if you already did
cc a.c
meaning it left it in a.out by default, you can always rename it:
mv a.out a
Of course you can call it anything you want:
cc -o mytestprogram a.c

How to use QCommandLineParser for arguments with multiple params?

I wonder, how can I use multiple- or sub-arguments with QCommandLineParser?
For example:
/home/my_app --my_option_with_two_params first_param second_param --my-option-with-one-param param?
Try this which has the analogy of -I /my/include/path1 -I /my/include/path2:
--my_option_with_two_params first_param --my_option_with_two_params second_param
... and then you can use this method to have access to the values:
QStringList QCommandLineParser::values(const QString & optionName) const
Returns a list of option values found for the given option name optionName, or an empty list if not found.
The name provided can be any long or short name of any option that was added with addOption().
Here you can find a simple test case that works:
main.cpp
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName("multiple-values-program");
QCoreApplication::setApplicationVersion("1.0");
QCommandLineParser parser;
parser.setApplicationDescription("Test helper");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption targetDirectoryOption(QStringList() << "t" << "target-directory",
QCoreApplication::translate("main", "Copy all source files into <directory>."),
QCoreApplication::translate("main", "directory"));
parser.addOption(targetDirectoryOption);
parser.process(app);
qDebug() << parser.values(targetDirectoryOption);
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build
qmake && make
Output when --help is used
Usage: main [options]
Test helper
Options:
-h, --help Displays this help.
-v, --version Displays version information.
-t, --target-directory <directory> Copy all source files into <directory>.
Run and Output
./main -t foo -t bar -> ("foo", "bar")
./main -t foo bar -> ("foo")

Error when running program with sharing library

There is such code:
#include <cstdlib>
#include <clang-c/Index.h>
using namespace std;
int main(int argc, char** argv)
{
CXIndex Index = clang_createIndex(0, 0);
CXTranslationUnit TU = clang_parseTranslationUnit(Index, 0, argv, argc, 0, 0, CXTranslationUnit_None);
for (unsigned I = 0, N = clang_getNumDiagnostics(TU); I != N; ++I)
{
CXDiagnostic Diag = clang_getDiagnostic(TU, I);
CXString String = clang_formatDiagnostic(Diag,
clang_defaultDiagnosticDisplayOptions());
fprintf(stderr, "%s\n", clang_getCString(String));
clang_disposeString(String);
}
clang_disposeTranslationUnit(TU);
clang_disposeIndex(Index);
return 0;
}
And it's compiled with following flags:
g++ main.cpp -g -fno-rtti `llvm-config --cxxflags --ldflags --libs` -lclang -o main
However when I want to run main:
./main
then there is following error:
./main: error while loading shared libraries: libclang.so: cannot open shared object file: No such file or directory
However:
$ sudo find / -name libclang.so
/usr/local/lib/libclang.so
Library seems to be on place. How to run this program?
ldconfig creates the necessary links and cache to the most recent
shared libraries found in the directories specified on the command
line, in the file /etc/ld.so.conf, and in the trusted directories
(/lib and /usr/lib)
Try running /sbin/ldconfig and then if that doesn't work try appending the file /etc/ld.so.conf with "/usr/local/lib" and then run /sbin/ldconfig
Commands:
Run the following command and then try compiling/running again
/sbin/ldconfig
If that doesn't work then do this and then try compiling/running again
echo "/usr/local/lib" >> /etc/ld.so.conf
/sbin/ldconfig

Run C or C++ file as a script

So this is probably a long shot, but is there any way to run a C or C++ file as a script? I tried:
#!/usr/bin/gcc main.c -o main; ./main
int main(){ return 0; }
But it says:
./main.c:1:2: error: invalid preprocessing directive #!
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$#"
int main(){
return 0;
}
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit from the shell script before the interpreter reaches the C/C++ code, or invoke exec magic.
Run with chmod +x main.c; ./main.c.
A shebang like #!/usr/bin/tcc -run isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main() {
for (auto i: {1, 2, 3})
std::cout << i << std::endl;
return 0;
}
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main() {
return 0;
}
Of course you can cache the executable:
#if 0
EXEC=${0%.*}
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main() {
return 0;
}
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "${0%.*}")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "${CLASS_PATH}" ${CLASS_NAME}
rm -f "${CLASS_PATH}/${CLASS_NAME}.class"
exit
*/
class Main {
public static void main(String[] args) {
return;
}
}
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main(){}
See:
https://unix.stackexchange.com/a/373229/23567
https://stackoverflow.com/a/12296348/199332
For C, you may have a look at tcc, the Tiny C Compiler. Running C code as a script is one of its possible uses.
$ cat /usr/local/bin/runc
#!/bin/bash
sed -n '2,$p' "$#" | gcc -o /tmp/a.out -x c++ - && /tmp/a.out
rm -f /tmp/a.out
$ cat main.c
#!/bin/bash /usr/local/bin/runc
#include <stdio.h>
int main() {
printf("hello world!\n");
return 0;
}
$ ./main.c
hello world!
The sed command takes the .c file and strips off the hash-bang line. 2,$p means print lines 2 to end of file; "$#" expands to the command-line arguments to the runc script, i.e. "main.c".
sed's output is piped to gcc. Passing - to gcc tells it to read from stdin, and when you do that you also have to specify the source language with -x since it has no file name to guess from.
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $# -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[]) {
bar();
return EXIT_SUCCESS;
}
#endif
#ifdef BAR_C
void bar() {
puts("bar!");
}
#endif
The #if 0 #endif pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
CINT:
CINT is an interpreter for C and C++
code. It is useful e.g. for situations
where rapid development is more
important than execution time. Using
an interpreter the compile and link
cycle is dramatically reduced
facilitating rapid development. CINT
makes C/C++ programming enjoyable even
for part-time programmers.
You might want to checkout ryanmjacobs/c which was designed for this in mind. It acts as a wrapper around your favorite compiler.
#!/usr/bin/c
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
return 0;
}
The nice thing about using c is that you can choose what compiler you want to use, e.g.
$ export CC=clang
$ export CC=gcc
So you get all of your favorite optimizations too! Beat that tcc -run!
You can also add compiler flags to the shebang, as long as they are terminated with the -- characters:
#!/usr/bin/c -Wall -g -lncurses --
#include <ncurses.h>
int main(void) {
initscr();
/* ... */
return 0;
}
c also uses $CFLAGS and $CPPFLAGS if they are set as well.
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && { ./a.out "$#"; e="$?"; rm ./a.out; exit "$e"; }
#include <stdio.h>
int main(int argc, char const* argv[]) {
printf("Hello world!\n");
return 0;
}
This properly forwards the arguments and the exit code too.
Quite a short proposal would exploit:
The current shell script being the default interpreter for unknown types (without a shebang or a recognizable binary header).
The "#" being a comment in shell and "#if 0" disabling code.
#if 0
F="$(dirname $0)/.$(basename $0).bin"
[ ! -f $F -o $F -ot $0 ] && { c++ "$0" -o "$F" || exit 1 ; }
exec "$F" "$#"
#endif
// Here starts my C++ program :)
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char **argv) {
if (argv[1])
clog << "Hello " << argv[1] << endl;
else
clog << "hello world" << endl;
}
Then you can chmod +x your .cpp files and then ./run.cpp.
You could easily give flags for the compiler.
The binary is cached in the current directory along with the source, and updated when necessary.
The original arguments are passed to the binary: ./run.cpp Hi
It doesn't reuse the a.out, so that you can have multiple binaries in the same folder.
Uses whatever c++ compiler you have in your system.
The binary starts with "." so that it is hidden from the directory listing.
Problems:
What happens on concurrent executions?
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^\/\/code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$#"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main() {
printf("Hi\n");
return 0;
}
Here's yet another alternative:
#if 0
TMP=$(mktemp -d)
cc -o ${TMP}/a.out ${0} && ${TMP}/a.out ${#:1} ; RV=${?}
rm -rf ${TMP}
exit ${RV}
#endif
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello world\n");
return 0;
}
I know this question is not a recent one, but I decided to throw my answer into the mix anyways.
With Clang and LLVM, there is not any need to write out an intermediate file or call an external helper program/script. (apart from clang/clang++/lli)
You can just pipe the output of clang/clang++ to lli.
#if 0
CXX=clang++
CXXFLAGS="-O2 -Wall -Werror -std=c++17"
CXXARGS="-xc++ -emit-llvm -c -o -"
CXXCMD="$CXX $CXXFLAGS $CXXARGS $0"
LLICMD="lli -force-interpreter -fake-argv0=$0 -"
$CXXCMD | $LLICMD "$#" ; exit $?
#endif
#include <cstdio>
int main (int argc, char **argv) {
printf ("Hello llvm: %d\n", argc);
for (auto i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
return 3==argc;
}
The above however does not let you use stdin in your c/c++ script.
If bash is your shell, then you can do the following to use stdin:
#if 0
CXX=clang++
CXXFLAGS="-O2 -Wall -Werror -std=c++17"
CXXARGS="-xc++ -emit-llvm -c -o -"
CXXCMD="$CXX $CXXFLAGS $CXXARGS $0"
LLICMD="lli -force-interpreter -fake-argv0=$0"
exec $LLICMD <($CXXCMD) "$#"
#endif
#include <cstdio>
int main (int argc, char **argv) {
printf ("Hello llvm: %d\n", argc);
for (auto i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
for (int c; EOF != (c=getchar()); putchar(c));
return 3==argc;
}
There are several places that suggest the shebang (#!) should remain but its illegal for the gcc compiler. So several solutions cut it out. In addition it is possible to insert a preprocessor directive that fixes the compiler messages for the case the c code is wrong.
#!/bin/bash
#ifdef 0
xxx=$(mktemp -d)
awk 'BEGIN
{ print "#line 2 \"$0\""; first=1; }
{ if (first) first=0; else print $0 }' $0 |\
g++ -x c++ -o ${xxx} - && ./${xxx} "$#"
rv=$?
\rm ./${xxx}
exit $rv
#endif
#include <iostream>
int main(int argc,char *argv[]) {
std::cout<<"Hello world"<<std::endl;
}
As stated in a previous answer, if you use tcc as your compiler, you can put a shebang #!/usr/bin/tcc -run as the first line of your source file.
However, there is a small problem with that: if you want to compile that same file, gcc will throw an error: invalid preprocessing directive #! (tcc will ignore the shebang and compile just fine).
If you still need to compile with gcc one workaround is to use the tail command to cut off the shebang line from the source file before piping it into gcc:
tail -n+2 helloworld.c | gcc -xc -
Keep in mind that all warnings and/or errors will be off by one line.
You can automate that by creating a bash script that checks whether a file begins with a shebang, something like
if [[ $(head -c2 $1) == '#!' ]]
then
tail -n+2 $1 | gcc -xc -
else
gcc $1
fi
and use that to compile your source instead of directly invoking gcc.
Just wanted to share, thanks to Pedro's explanation on solutions using the #if 0 trick, I have updated my fork on TCC (Sugar C) so that all examples can be called with shebang, finally, with no errors when looking source on the IDE.
Now, code displays beautifully using clangd in VS Code for project sources. Samples first lines look like:
#if 0
/usr/local/bin/sugar `basename $0` $# && exit;
// above is a shebang hack, so you can run: ./args.c <arg 1> <arg 2> <arg N>
#endif
The original intention of this project always has been to use C as if a scripting language using TCC base under the hood, but with a client that prioritizes ram output over file output (without the of -run directive).
You can check out the project at: https://github.com/antonioprates/sugar
I like to use this as the first line at the top of my programs:
For C (technically: gnu C as I've specified it below):
///usr/bin/env ccache gcc -Wall -Wextra -Werror -O3 -std=gnu17 "$0" -o /tmp/a -lm && /tmp/a "$#"; exit
For C++ (technically: gnu++ as I've specified it below):
///usr/bin/env ccache g++ -Wall -Wextra -Werror -O3 -std=gnu++17 "$0" -o /tmp/a -lm && /tmp/a "$#"; exit
ccache helps ensure your compiling is a little more efficient. Install it in Ubuntu with sudo apt update && sudo apt install ccache.
For Go (golang) and some explanations of the lines above, see my other answer here: What's the appropriate Go shebang line?