I'm developing a script that checks the version of some installed C programs. The version check is performed with the --version option. However, this option may not be implemented in all the checked programs. When the option is implemented I use:
version=$(./$program_name --version)
But when it's not, the program just starts executing.
If I just execute the program in the background and the stop it if continues running, I can never get the version number. Is there a way to check whether the option is implemented without letting the program run?
Not completely waterproof but I nice start is using strings:
strings /usr/bin/git | grep -- --version
If you are referring to any arbitrary C program, no there is currently no way to reliably check if a program supports an option. You can try guessing with a mixture of ./program --help, ./program --usage, ./program -h and ./program --this-option-is-a-lie-or-some-other-bogus-option-to-give-usage-information. However, it all ultimately boils down to guesswork.
On RedHat and derivates using yum and rpm you can ask the rpm package manager:
$ rpm -q --whatprovides /bin/cat
coreutils-8.4-31.el6_5.1.i686
On Debian and derivated using apt-get you can ask the APT package manager:
$ dpkg-query -S /bin/bash
bash: /bin/bash
Back in the day we always included a what string with version info. Actually part of SCCS, if the program contained strings starting with "#(#)", it is displayed by the what command. C code would like like this:
static char prog_id[] = "#(#) my_program version 1.0 - 3/26/2014";
Anyway try doing a what on the program and see what you get. heh.
Related
I'm trying to count the syscalls in my Go program on OS X Yosemite. I've tried using dtruss and dtrace, but both cause my program to crash with the following error, followed by a stack trace:
fatal error: runtime: bsdthread_register error
The two commands I've used are:
sudo dtruss "./my_program my_arg"
sudo dtrace -c "powerset 2" -n 'syscall:::entry { #num[probefunc] = count(); }'
Things I've Tried
The main takeaway from my Google-foo has been to unset DYLD_INSERT_LIBRARIES, which I have done numerous times to no avail.
./my_program is a binary that I created with go install. I've written an equivalent C program and both of the above commands work fine with that.
If you want to use dtrace on macOS, you will need to use the external linker to build your program
-ldflags -linkmode=external
I need to develop a utility that will take command line arguments as follows:
$ lsm -g <group> -t <type> -d <device>
My project manager wants that when we type any argument like lsm -g and press Tab, then a function will be called to run a database query and fetch help for the user about the value of the option.
Similar to how terminal behaves in this case:
$ cd <tab>
.bash_history .local/
.bash_logout .log-report.log.swp
.bash_profile .macromedia/
.bashrc .mozilla/
.cache/ Music/
.config/ .mysql_history
.dbus/ .nautilus/
Desktop/ .opera/
Documents/ .orc/
Downloads/ .p2/
.eclipse/ Pictures/
I have tried these approaches:
Use fork() to create a child to call the help function.
Use execv() to run a help function using a seperate binary.
But both require that lsm be running.
I'm not sure how to proceed further.
As various commentators have noted, tab-completion is implemented in the shell, not in the program which is about to be executed.
Most shells have frameworks for implementing custom tab-completion. In the case of bash, it is implemented with the help of the readline library. There is extensive documentation in the bash manual and there are a variety of tutorials kicking around the internet, such as this one from Debian (not an endorsement, just the result of a quick Google search).
I'm on a Mac and in terminal I'm compiling my program
gcc -Wall -g -o example example.c
it compiles (there are no errors), but when I try to provide command line arguments
example 5 hello how are you
terminal responds with "-bash: example: command not found"
how am supposed to provide the arguments I want to provide after compiling?
Run it like this with path:
./example 5 hello how are you
Unless the directory where the example binary is part of the PATH variable, what you have won't work even if the binary you are running is in the current directory.
It is not a compilation issue, but an issue with your shell. The current directory is not in your PATH (look with echo $PATH and use which to find out how the shell uses it for some particular program, e.g. which gcc).
I suggest testing your program with an explicit file path for the program like
./example 5 hello how are you
You could perhaps edit your ~/.bashrc to add . at the end of your PATH. There are pro and conses (in particular some possible security issues if your current directory happens to be sometimes a "malicious" one like perhaps /tmp might be : bad guys might put there a gcc which is a symlink to /bin/rm so you need to add . at the end of your PATH if you do).
Don't forget to learn how to use a debugger (like gdb). This skill is essential when coding in C (or in C++). Perhaps consider also upgrading your gcc (Apple don"t like much its current GPLv3 license so don't distribute the recent one; try just gcc -v and notice that the latest released GCC is today 4.8.1).
./example 5 Hello how are you is the syntax you're looking for.
This article lends a good explanation as to why this is important.
Basically, when you hit Enter, the shell checks to see if the first set of characters is an absolute path. If it's not, it checks the PATH variable to find executables with the name of the command you are trying to run. If it's found, it will be run, but otherwise it will crash and burn and you will become very sad.
I need to make some modifications to the the C standard library (glibc) in order to get some performance improvements. Specifically, I am going to be writing some specialized versions of some of the locale-dependent functions (which in glibc perform poorly), such as strcoll.
I have checked out the glibc source from here, into ~/Desktop/glibc. I then ran the following sequence of commands without error.
$ cd ~/Desktop
$ mkdir bglibc
$ cd bglibc
$ ./../glibc/configure --prefix=~/Desktop/bglibc
$ make
$ make install
At this point, I have successfully compiled and installed glibc into ~/Desktop/bglibc. I then created the following test program (ct.c) in the bglibc directory:
#include <stdio.h>
#include <locale.h>
int main ()
{
char *locale = NULL;
locale = "en_US.utf8";
char *result = setlocale(LC_COLLATE, locale);
if (result == NULL) {
printf("locale not set\n");
}
printf("strcoll: %d\n", strcoll("some", "string"));
return 0;
}
I then build it with this script:
iSYSROOT=~/Desktop/bglibc
gcc -o ct ct.c \
--sysroot=${SYSROOT} \
-Wl,-rpath=${SYSROOT}/lib \
-Wl,--dynamic-linker=${SYSROOT}/lib/ld.so.1
Which builds it properly. I then run it with this script:
#!/bin/sh
builddir=`dirname "$0"`
GCONV_PATH="${builddir}/iconvdata" \
exec "${builddir}"/elf/ld-linux-x86-64.so.2 --library-path "${builddir}":"${builddir}"/*:"${builddir}"/*/*:"${builddir}"/*/*/* ${1+"$#"}
Which is names testrun.sh. To run it on the program I previously compiled (ct), I run ./testrun.sh ./ct.
This successfully runs the program, however the program prints out locale not set, meaning that it was unable to set the locale to "en_US.utf8". Thus, the locale keeps the default ("C"), in which case strcoll simply returns the result of strcmp. However, I need this call to run the strcoll code in order to run tests on its performance, and then tune it to run faster for specific locales.
I know that "en_US.utf8" is a valid locale for my system (Ubuntu 12.04 lts), because I see this:
$ locale -a | grep US
en_US.utf8
I have also tried running this program but setting the locale variable to other strings such as "en_US.UTF-16", "", "en_US.UTF-8", etc. all with no luck.
I imagine this isn't the first issue I will run into when trying to get locale stuff to work with my modified version of glibc, but its the first.
Any ideas On what I can do to get the locale functions (specifically setlocale) to work right?
My guess: You forgot to "make" some locales. Try:
$ make
$ make install
$ make localedata/install-locales
see also GNU libc make manual
After installation you might want to configure the timezone and locale
installation …
Try to use the strace to find out where the glibc tries to read the locales from. I suspect that since you set the prefix glibc tries to find them in ~/Desktop/bglibc/share/locale/ or something similar. And certainly UTF-16 will not work with 8 bit string types...
hello everyone
i try to debug a program, which have been installed by makefile.
it have a binary file of OpenDPI_demo.o and a shell shellscript OpenDPI_demo.
when i gdb OpenDPI_demo.o,i have a problem. i can't run it. the error is:
Starting program: /home/lx/ntop/test/opendpi/src/examples/OpenDPI_demo/OpenDPI_demo.o
/bin/bash: /home/lx/ntop/test/opendpi/src/examples/OpenDPI_demo/OpenDPI_demo.o:can't execute the binary file.
please tell me why. actually i can run the program by ./OpenDPI_demo.
thank you.
Based on the extension, the file is an object file. It is used by the linker (alongside other object files) to produce an executable. It's the real executable the one you want to run/debug.
This is another example of difficulties encountered with programs using libtool.
the file OpenDPI_demo alongside OpenDPI_demo.o is actually, as you said, a shell script which wraps the execution of the real compiled file, probably in .libs/OpenDPI_demo.
libtool needs this wrapper to adjust the runtime library paths and such so that you can execute the program transparently, as if it was actually installed on your system.
The way to correctly debug this application is not
/home/lx/ntop/test/opendpi $ gdb src/examples/OpenDPI_demo/.libs/OpenDPI_demo
but rather using libtool --mode=execute on the shell script, like the following (it's an example):
/home/lx/ntop/test/opendpi $ ./libtool --mode=execute gdb --args \
src/examples/OpenDPI_demo/OpenDPI_demo -f capture.pcap
Suggest you use
gdb OpenDPI_demo
instead
In your makefile if it depens on the object, make it depend on OpenDPI_demo, e.g.