Portable way to get user name - c++

For C/C++ there seems to be no portable function to get the user name in Linux/Posix and Windows.
What would be the least cumbersome and yet robust portable code to achieve this ?
In Linux the USER environment variable seems always to be defined, whereas Windows seems to define the USERNAME variable. Relying on getenv one could avoid including windows.h and minimize preprocessor statements:
char * user_name = getenv("USER");
if (!user_name) {
user_name = getenv("USERNAME");
}
But is this approach halfway robust ? Or am I ignorant to another solution ? And I was also ignorant towards iOS ...

Using environment variables to find the username is very unreliable:
I expanded your code to this:
#include <iostream>
int main()
{
char * user_name = getenv("USER");
std::cout << user_name << std::endl;
}
and did this:
$ whoami
MatsP
$ g++ -Wall -std=c++0x getenv.cpp
$ ./a.out
MatsP
$ export USER=DonaldDuck
$ ./a.out
DonaldDuck
So, I would definitely suggest that if the username is of any importance to your code, then you should use a system-specific function to get the username. If it's not important to your code, ask at install time or some such, and don't try to use any system function to fetch the username.
(In answer to your actual question, yes, I would think that an iOS has the same functionality of a USER environment variable - although I'm not sure there is a meaningful user on an iPhone).

There is no portable solution.
Under Linux (and Unix in general), a "user" is a number, and can
have several different names. Use getuid to get the id, then
getpwuid to get one of the names. Or use getlogin to get
the name the user used to login (but this will only work if the
process has a controlling terminal). If you want to get all
of the names the user is known under, you'll have to iterate
using getpwent, checking the pw_uid field for each entry
returned.
The use of an environment variable is not guaranteed. In many
contexts, the environment variable won't be set, and even if it
is, it's not guaranteed to be correct.
Windows has a function GetUserName; I don't know too much
about it, however.

The user concept is related to the operating system or even system, not the language.
As there are a myriad of different systems around, the only feasable approach is to limit yourself to a list of systems you want to support.
There exists software that can help you to achieve portability, like the GNU autotools for Unix like systems (and to a certain degree Windows).

You are right - there is no portable way to do it.
There are two solutions for that: use proper set of ifdef's to use one code on window, and another on linux.
the other way is to do it with factory which would return you an abstract object or pointer to function which would be system specific. Factory should detect system and return proper function/class

Related

Can a function access args passed to main()?

Is there a way I could access program's args outside of main() without storing references to them?
Program arguments are stored within preserved space of the program, so I see no reason for not being able to access them. Maybe there is something like const char** get_program_arguments() and int get_program_arguments_count() but I cannot find it...
My problem comes from the fact that I am rewriting a library that is used now in many programs within the company, and I need to access these programs common arguments without changing them. For example I need program name, but I cannot use ::getenv("_") as they can be executed from various shells. I cannot use GNU extension because this needs to work on Linux, AIX, SunOS using gcc, CC and so on.
Some systems do provide access to the argument list, or at least argv[0]. But it’s common practice for main to mutate argc and argv during option processing, so there is no reliably correct answer as to what a global interface for them should return.
Add to that the general undesirability of global state, and the fact that it harms debugging to have whatever low-level functions attempt to analyze the arguments to a program they might know nothing about, and you end up with don’t do that. It’s not hard to pass arguments (or, better, meaningful flags that result from decoding them) to a library.

Can SDL_GetBasePath() and SDL_GetPrefPath() be called before SDL_Init()?

In my application I would like to use a configuration file. However I have the chicken and egg problem here: the configuration file can even describe how SDL (and other things) should be init'ed. Thus, I would need to call SDL_GetPrefPath() before even SDL_Init() to get the common place where configuration for my application is stored as per-user basis. I'm not sure if it's possible. I also need SDL_GetBasePath() for similar (fall-back) purpose, I know that's ugly but some users would like that optionally for trying to find the configuration file. Reading the configuration file itself is not a problem, as I don't use SDL related functions for that, though I need to get the directory where configuration file can be found.
Surely, I can test if it's work, but it's not the best, it may fail in different SDL versions, on other architecture, or who knows. I would like to know it's safe "by design" (and "future-proof"), or not.
On the SDL-2 wiki, some functions like SDL_ShowSimpleMessageBox() is noted, that it's safe to be used even before SDL_Init(), but I am not sure if this is the situation in this case. I'm not sure if SDL-2 wiki is detailed enough to always show the situation like this (as with SDL_ShowSimpleMessageBox()), since this information is not mentioned on the pages of the functions I'm talking about now.
Note, my application is intended to run on Linux, MacOS and Windows, so it would be hard to judge by myself where SDL will put its preference directory after initialization, and also an ugly, redundant stuff then ...
Maybe it's useful for others too, so this is what I could figure out:
https://bugzilla.libsdl.org/show_bug.cgi?id=3796
I've submitted an SDL bugzilla ticket about this. The answer, that it's basically platform dependent, and not safe for these functions to be used without SDL_Init(). May work on some platforms, may not on others (or in the future). However, I got a tip, to use SDL_Init(0) and SDL_Quit() around the call. So, with my own ideas added as well, something like this:
char *my_pref_dir_path = NULL;
if (!SDL_Init(0)) {
char *p = SDL_GetPrefPath(app_org, app_name);
if (p) {
my_pref_dir_path = strdup(p);
SDL_free(p);
}
SQL_Quit();
}
if (!my_pref_dir_path) {
/* ... panic or exit or whatever ... */
}
SDL_Init(0) won't initialize too much (not even video or other subsystems, so it won't interfere with the plan that I may not need SDL at all later), but it should be safe now to use the desired functions. After that, SQL_Quit() would make SDL "go away". Later, of course, you can have a "proper" SDL initialization, for example: SDL_Init(SDL_INIT_EVERYTHING), just like if this code hasn't been in your program at all before.
Since, I am not sure, if the pointer returned by SDL_GetPrefPath() is valid after SQL_Quit(), I would strdup() it or such, and I use SDL_free() before SQL_Quit() on the pointer returned by SDL_GetPrefPath() since it's recommended by the documentation too anyway. Maybe I'm just too careful here, but I think, it's a safer bet then, if I play tricks like this.
After this code, my_pref_dir_path will hold a pointer to the SDL preferences directory string, or NULL, if an error occured.

C++: Can function pointers be traced back to the original function before compilation without looking at the function name?

I want to set up a server on which students can upload and run code for a course. However, I don't want them to access various functions, like system(), which could allow bad access to my server. I can search the pre-processor output for an explicit function call, but if the user makes a function pointer like this:
int (*syst)(const char*) = system;
syst("rm *");
I'm still open to the threat. However, I can't just search for the string "system", for example, since it's otherwise a valid name - if the student didn't include cstdlib, they could use that name as a variable name. Since this is a beginning programming course, having a blacklist of variable names ten miles long is a bad idea.
Is there a way to define the functions other than by name and allow me to search for that other designation before compiling their code?
By far the easiest solution is to compile the code - that's pretty harmless - and then look at the actual library imports. Users may have defined their own system, but that wouldn't cause system to be imported from glibc.
Showing imported symbols
The main reason you can't look at the raw source code is because #define allows malicious users to hide the blacklisted symbol names. But there are plenty of other possibilities to do that, including
auto hidden = &sys\
tem;
So you need some processing of the source, and it's probably easiest just to fully process the whole source.
I would also suggest running this inside a chroot as a non-privileged user. It's lighter weight than a VM.
Alas, it's not possible (easily) to get a functions name from a pointer
How to get function's name from function's pointer in C? That question is from a C perspective, but it's the same problem, essentially.

How to implement Python function exec() in C++?

The Python function exec() is a very good tool for programming.
For example:
/******************************************************
* we have array names={"ali","hamed"}
* goal is declare string ali="ali" and hamed="hamed"
******************************************************/
Python code:
# used for command
# below line is a syntax python
# in python we dont declare variable
list=["ali","hamed"] #python syntax
#in python we dont wite {
#python work with tab insteed of {}
for i in list:
temp = i + ' = "' + i + '"' #temp is a string
exec(temp)
My question: Is there a similar function exists in C++? If not, how to implement it in C++?
Python's exec, and similar features in other languages (i.e. eval in JavaScript) only work because those are interpreted languages where variables are defined at run time.
You can't do what you're asking in directly C++ because it's a compiled language that requires that all variables and their names are known at compile time.
You can do it, but it's not trivial, and it will only work on
systems where a C++ compiler is installed. Basically, C++ is
compiled, so if you want to execute some string which is C++,
you'll have to compile it: write it to a file (probably with
additional boilerplate like some includes), invoke the compiler
(with system) to build a DLL, and then load the DLL.
In practice, even if you went to all that effort, you'd probably
find it less useful than you think. Because C++ requires static
declarations for just about everything, it's much harder to
write small snippets like that and have them usable. (You
would, for example, have to wrap it in a function, and generate
extern for all of the variables it uses.) C++ doesn't support
this sort of thing for software engineering reasons; the very
features which make languages like Python so flexible for small,
quickly written programs, cause severe maintenance problems when
used in large scale robust software. Different languages are
designed for different purposes. It's very easy to create
a mixed language system using Python for the top level glue
(where you would want a facility such as you describe), and
calling into C++ for the heavy work (where such a facility would
allow the user to trigger core dumps at will).
Alternatively, you can implement a small language in C++. For
keeping user defined variables, for example, use std::map,
rather than declaring the variables. (That is, after all, what
Python does under the hood.)
If you are planning to use strings as parameters,it is NOT a good idea!
you can simply use an id generator function and give an id to every string that you are gonna use ,or if you are using a class you can put that function in the constructor.
no need to that exec() at all!!

Set system variable from C++

This shell script
#!/bin/csh
set VAR=12345
echo $VAR
will peacefully give the output 12345 at shell.
I need to use C++ to do the same in some part of the code:
string str = "12345";
retValue="set var1= "+str;
system(retValue1.c_str());
system("echo $var1");
This doesn't create a system variable var1 and echos null which is understandable as each system function would create a child process with different environment variables. So I combine them as follows using just one system function...but it echos null again.
retValue="set var1= "+str;
retValue1=retValue+";\n echo $var1";
system(retValue1.c_str());
Can someone please guide me to set up the system variable thru C++.
Thanks a lot in advance!
Look at setenv in <cstdlib>:
#include <cstdlib>
setenv("VAR", "12345", true);
You basically can't do that.
You could call putenv to change environment variables in your own process and in all future children processes, but there is no way (and this is good) to change the environment of the parent shell process.
You could have a use convention for your C++ program that e.g. it is outputting some shell commands to be sourced (or eval-ed) by the user. An example of this is ssh-agent -s.
You can use putenv().
#include <cstdlib>
...
putenv("VAR=12345");
This is very convenient, but the string is not copied by putenv. This means that if you modify it later, then you modify the environment. That's not an issue for a literal, but the way you are forming your strings, using std::string is not readily compatible with putenv().
The alternative then is to use setenv()
#include <cstdlib>
...
setenv("VAR", "12345", true);
With setenv(), copies of the input are made and you are safe to dispose of the strings after calling setenv().
The function you want is probably putenv(). You didn't specify which OS you are on, so I'll assume Linux because that's the man page I have handy:
int putenv(char *string);
The putenv() function adds or changes the value of environment
variables. The argument string is of the form name=value. If name
does not already exist in the environment, then string is added to the
environment. If name does exist, then the value of name in the
environment is changed to value. The string pointed to by string
becomes part of the environment, so altering the string changes the
environment.
IIRC, there is a putenv on win32 as well. Finally you might try looking at this question, possibly a dup
Above answers explains correctly as to how to set environment variable from a C++ program which is basically setenv()
The only other point i wanted to make is that why your approach doesn't work? The reason is, that when a process is loaded, the system command is loaded with new context - an equivalent of a new shell. Actually your environment variable is getting set but when you comeback it is lost.
Refer to this http://pubs.opengroup.org/onlinepubs/007904975/functions/setenv.html.
Infact, the setenv() sets the env variables of parent process! Which is why it works for you.
Note that the otherwise excellent CPPreference site does not seem to mention setenv among the functions available in the <cstdlib> header, only getenv. This may not be a problem though as I could use setenv by #include-ing <cstdlib> on a Centos 7 system with GCC 9.1. I suspect in most cases <cstdlib> is just a thin wrapper around <stdlib.h>.
Another small thing to note is that setenv takes C-style character arguments (also for the value of the environment variable to be set). If you use C++ strings (as you should), don't forget to convert them using their .c_str() method.