Finding path of Builtins and executables for commands in Linux - c

I am trying to implement 'whereis' command in C. But I was able to implement it partially. When I ever I try 'whereis' in Linux shell, lets say for e.g. whereis ls .. I get the following results
$ whereis ls
/bin/ls
/usr/share/man/man1p/ls.1p.gz
/usr/share/man/man1/ls.1.gz
I am able to get the first path using the PATH env.variable. But I have no clue how to find the other two paths. Any pointers how to find those paths.

On Linux (but not on all systems, e.g. Mac OS), whereis searches in $MANPATH (or some other default places) for matching files, which for ls are something like this:
$MANPATH/man(.+)/ls\.\1(\.gz)?
If you really need to know how whereis works, you can simply look at its source....

man whereis (Ubuntu 11.04) mentions the following paths:
/{bin,sbin,etc}
/usr/{lib,bin,old,new,local,games,include,etc,src,man,sbin,X386,TeX,g++-include}
/usr/local/{X386,TeX,X11,include,lib,man,etc,bin,games,emacs}

Another option generally available is which. It will return the fully-qualified path and executable name for the executable. For example:
$ which ls
/usr/bin/ls
It may help you in your whereis endevour and is also useful for portability in scripts to set the executable where it may be located in different places on different distributions:
my_ls=$(which ls 2>/dev/null)
[ -x "$my_ls" ] || {
echo "ls not found"
exit 1
}

Related

C script doesn't works globaly

I write test script in C, compiled it and put to /usr/bin directory, to execute it from anywhere like mkdir or ls. But then I wrote $ test nothing happen, if i wrote $ /usr/bin/test it works well. What I did wrong? I got Ubuntu 14.
In shells (such as bash), there's a shell builtin named test. So, when you execute test, shell builtin test is executed even though you have test in /usr/bin/ assuming you have /usr/bin/ in your PATH. When you give full path, there's no ambiguity there (like other binaries namedtest which might be there in PATH or builtins).
You can test this by running:
$type test
Name your binary to something else that doesn't interfere with system binaries or shell builtins. It's generally recommended to put your binaries in designated locations such as usr/local/bin/ even if your binary is uniquely named.

How can I count syscalls in a Go program on OS X?

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

Using pg_config with waf

I use waf as my build system and I want to compile a small C program using Postgres. I have included postgres.h in my program so I need to find the path to it in my wscript file. I know that I can get the path I need by running:
pg_config --includedir-server
which gives me:
/usr/include/postgresql/9.3/server
So I thought I could use something like this:
cfg.check_cfg(
path='pg_config',
package='',
uselib_store='PG',
args='--includedir-server',
)
And then build my program by:
bld.program(
source=['testpg.c'],
target='testpg',
includes=['.', '../src'],
use=['PQ', 'PG'],
)
But this fails with postgres.h: No such file or directory. I ran ./waf -v and confirmed that the proper -I flag is not being passed to gcc. My guess is this happens because pg_config does not add a -I prefix to the path it returns. Is there a way I can make waf to add the prefix, or make pg_config to add it?
Should pg_config had the standard output of pkg_config like programs (ie outputs something like -Ixxx -Iyyy), your code would work, has check_cfg parse this kind of output.
As there is no complicated parsing, you can go for:
import subprocess
includes = subprocess.check_output(["pg_config", "--includedir-server"])
includes.replace("\n", "")
conf.env.INCLUDES_PG = [includes]
And then use it:
bld.program(
source=['testpg.c'],
target='testpg',
use=['PG'],
)
See the library integration in the waf book. It explains the naming rule that make it works.
You can write a small plugin to ease the use :)

C - program compiling, but unable to provide arguments

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.

gdb and makefile

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.

Resources