setenv() to update PATH environment variable - c

i want to write a C program to append a string to PATH Environment variable.
something like "export PATH=$PATH:$HOME/mylib"
i have C code like this
setenv("PATH", "$PATH:$HOME/mylib",1); //which does not work.
other work arround i thought was get PATH and HOME using getenv() and create a memory in heap then append them using strcat().
I might have to update PATH many times in my code: so this is a tiresome process.
is there any alternative?
Thanks

The $FOO syntax, which expands to the value of the environment variable with the name FOO, is a feature of the shell; it's not directly available in C.
Your system may provide the wordexp() function, which gives you similar functionality in C.
But since you're just expanding two environment variables with fixed names ("HOME" and "PATH"), it makes more sense to use the portable getenv() function and a little string processing. (You might consider using sprintf or snprintf rather than strcat.)
NOTE: If you're only using the updated $PATH internally in your program, you can stop reading here.
Hopefully you're not expecting any changes to $PATH to be available on the command line after your program finishes running. Your running C program is most likely a child process of your interactive shell. Environment variables are inherited by child processes; they don't propagate back to parent proceses.
If that's what you're trying to do, you can have your program print the new PATH value to stdout, and then have the shell evaluate it:
PATH=`your-program`
Or it can print the command(s) to set one or more environment variables:
eval `your-program`
(In bash, you can use $(your-program) as well as `your-program`.)

No there is no alternative. You have to build the literal string and pass it to setenv.

There is no other option immediately available. You can write a separate function to handle this, if you need to do it several times.

Related

Stata: Call a do file containing loop from a program in the other do file

I am trying to call a do file which has loops from a program in other do file. I am getting an error.
Now, if I use do instead of include, it runs fine but I don't get to use local macros created. I used include so I can use the macros further in the program. I don't want to use global.
First do file (test.do).
forval i = 1/5 {
local val`i' = `i'
}
Second do file(call-test.do)
capture program drop test
program test
include "test.do"
di `val1'
end
test
I got error r(9611);
I using version 16.1
Response from Stata support
The -include- is designed to let you share definitions. It will not
work correctly within a program as documented in -help include-
The short answer is that -include- is usually ok to use in programs,
but not with looping commands, and if you use -include- in a program,
it probably isn't working the way you think it is.
Here's the long version of exactly what is going on:
When you use -include- in a program, your program literally includes
the -include- command in it. The program does NOT have the contents
of the include file substituted in place. That's the start of the
problem for looping commands.
In any case, when a program executes the -include- command, Stata gets
confused about whether to define a loop program on the behalf of a
looping command globally or within the program, and things go downhill
from there. Given how the code is structured, it is unlikely we could
fix -include- to behave differently, so our documentation really
should simply recommend against using -include- in programs. In
addition, at the point at which the failure occurs, Stata simply knows
that it cannot call a program that it thinks should already be in
memory, hence the 9611 return code. It has no idea at that point that
this was because it was called with -include-, unfortunately.
We could in the future introduce a true C-like "#include" for use in
programs which would simply substitute in-line the lines from whatever
was included into your program

fopen() function with a dynamic location in C

I just want to learn that how can I open a file with fopen() function from a dynamic location. I mean, for example it will be a system file and in another computer, this file can be in another location. So if I will set my location in my code not dynamically, my program will not work in another computer. So how Can I set the location dynamically for my program will find this file wherever it is?
You can (and often should) pass program arguments to your main, thru the conventional int argc, char**argv formal arguments of your main. See also this.
(I am focusing on Linux, but you could adapt my answer to other OSes and platforms)
So you would use some convention to pass that file path (not a location, that word usually refers to memory addresses) to your program (often thru the command line starting your program). See also this answer.
You could use (at least on Linux) getopt_long(3) to parse program arguments. But there are other ways, and you can process the arguments of main explicitly.
You could also use some environment variable to pass that information. You'll query it with getenv(3). Read also environ(7).
Many programs have configuration files (whose path is wired into the program but often can be given by program arguments or by environment variables) and are parsing them to find relevant file paths.
And you could even consider some other inter-process communication to pass a file path to your program. After all, a file path is just some string (with restrictions and interpretations explained in path_resolution(7)). There are many ways to pass some data to a program.
Read also about globbing, notably glob(7). On Unix, the shell is expanding the program arguments. You may want to use functions like glob(3) or wordexp(3) on something obtained elsewhere (e.g. in some configuration file) to get similar expansion.
BTW, be sure, when using fopen, to check against its failure. You'll probably use perror like here.
Look also into the source code of several free software projects (perhaps on github) for inspiration.
I would suggest you to use the environment variables, In a PC set your file location as environment variable. then read the environment variable value in your program, then open the file. This idea works both in linux and windows however you have adopt the code based on the OS to read the environment variables.
Besides specifying file location at runtime through command line arguments, environment variables or configuration files, you can implement a PATH-like logic:
Possible locations for your file are set in an environment variable:
export MY_FILE_PATH=/usr/bin:/bin:/opt/bin:$HOME/bin
Your program reads that environment variable, parses its contents and checks existence of file in each specified path, with fopen() return status.

Determine which binary will run via execlp in advance

Edit #1
The "Possible duplicates" so far are not duplicates. They test for the existence of $FILE in $PATH, rather than providing the full path to the first valid result; and the top answer uses bash command line commands, not pure c.
Original Question
Of all the exec family functions, there are a few which do $PATH lookups rather than requiring an absolute path to the binary to execute.
From man exec:
The execlp(), execvp(), and execvpe() functions duplicate the actions
of the shell in searching for an executable file if the specified
filename does not contain a slash
(/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If
this variable isn't defined, the path
list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3)
call typically returns the value
"/bin:/usr/bin".)
Is there a simple, straightforward way, to test what the first "full path to execute" will evaluate to, without having to manually iterate through all the elements in the $PATH environment variable, and appending the binary name to the end of the path? I would like to use a "de facto standard" approach to estimating the binary to be run, rather than re-writing a task that has likely already been implemented several times over in the past.
I realize that this won't be a guarantee, since someone could potentially invalidate this check via a buggy script, TOCTOU attacks, etc. I just need a decent approximation for testing purposes.
Thank you.
Is there a simple, straightforward way, to test what the first "full path to execute" will evaluate to, without having to manually iterate through all the elements in the $PATH environment variable
No, you need to iterate thru $PATH (i.e. getenv("PATH") in C code). Some (non standard) libraries provide a way to do that, but it is really so simple that you should not bother. You could use strchr(3) to find the "next" occurrence of colon :, so coding that loop is really simple. As Jonathan Leffler commented, they are subtleties (e.g. permissions, hanging symbolic links, some other process adding some new executable to a directory mentionned in your $PATH) but most programs ignore them.
And what is really relevant is the PATH value before running execvp. In practice, it is the value of PATH when starting your program (because outside processes cannot change it). You just need to be sure that your program don't change PATH which is very likely (the corner case, and difficult one, would be some other thread -of the same process- changing the PATH environment variable with putenv(3) or setenv(3)).
In practice the PATH won't change (unless you have some code explicitly changing it). Even if you use proprietary libraries and don't have time to check their source code, you can expect PATH to stay the same in practice during execution of your process.
If you need some more precise thing, and assuming you use execp functions on program names which are compile time constants, or at least constant after your program initialization reading some configuration files, you could do what many shells are doing: "caching" the result of searching the PATH into some hash table, and using execve on that. Still, you cannot avoid the issue of some other process adding or removing files into directories mentioned in your PATH; but most programs don't care (and are written with the implicit hypothesis that this don't happen, or is notified to your program: look at the rehash builtin of zsh as an example).
But you always need to test against failure of exec (including execlp(3) & execve(2)) and fork functions. They could fail for many reasons, even if the PATH has not changed and directories and files mentioned in it have not been changed.

Which environment variables the app is using

I have binary executable file compiled from C-source and I know that it uses some of UNIX system environment variables. Unfortunately I have no documentation and decompiling/reverse-engineering is very difficult.
Is there a way to find which env variables the app tries to read in runtime?
I mean, if C's getenv reads some file to get variable values or does a system call, it is possible. So, can I do it?
strings(1) might help you to identify the names of the envrionment variables.
– Blagovest Buyukliev
One can use a debugger, set a breakpoint on getenv, and inspect the function argument. This is possible even without debug information (albeit more difficult, since it requires knowledge of the calling convention).

Trying to call C program from Ruby script

I am trying to call a C program from my Ruby script, parsing it an argument (file object) and then store some variables the C program would return.
The idea is that my Ruby script allows me to easily cycle through the files & folders of a parent folder but it is way too slow to efficiently process all the files in that folder. Hence the use of a C program that I want to call to process each file.
My problem is that I can't find a method to call that C program from Ruby (and how to parse it the file argument, I'm not even sure it is possible as I don't know if Ruby files objects and C streams are "compatible")
Thank you in advance for your help !
You say you are trying to call a program so I assume you are not trying to statically or dynamically load a library and call a function. (If you are trying to load a library to call a function then look to the DL::Importer module.)
As for calling an external program from Ruby and receiving its result (from stdout, in this case), regardless of whether it was written in C or not, an easy way to do it is:
value = `program arg1 arg2 ...`
e.g. if the program you want to call compresses a given file and outputs the compressed size.
size = `mycompressionprogram filename.txt`
puts "compressed result is: #{size}"
Note those are back ticks " ` ".
So this is one easy way to code your computationally heavy stuff in C and wrap it up in a Ruby script.
One simple traditional way for a Ruby process to interact with unrelated C code is popen, which will allow your Ruby process to invoke the (compiled) code as a separate process, passing your choice of arguments into the traditional space the operating system allocates for that (accessible in argv in your process's int main(int argc, char** argv)), and then interacting with its standard input and standard output over a pipe. However, this technique launches another process and requires that you serialize/deserialize any ongoing interprocess communication so that it can run over the pipe, which may be an impediment.
So you can also write the C code as a Ruby extension, which will allow you to return values more readily, and moreover avoids the overhead associated with having a separate process involved. However, note that if you perform extensive work with Ruby objects in your C code you may still incur the performance penalties you'd hoped to avoid. The canonical document on how to write Ruby extensions is README.EXT.

Resources