What do /proc/fd file descriptors show? - c++

Learning about the /proc/ directory today, in particular I'm interested in the security implications of having all the information about a process semi-publicly available, so I wrote a simple program that does some simple whatnot that allows me to explore some properties of the /proc/ directory:
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
extern char** environ;
void is_linux() {
#ifdef __linux
cout << "this is running on linux" << endl;
#endif
}
int main(int argc, char* argv[]) {
is_linux();
cout << "hello world" << endl;
int fd = open("afile.txt", O_RDONLY | O_CREAT, 0600);
cout << "afile.txt open on: " << fd << endl;
cout << "current pid: " << getpid() << endl;;
cout << "launch arguments: " << endl;
for (int index = 0; index != argc; ++index) {
cout << argv[index] << endl;
}
cout << "program environment: " << endl;
for (char** entry = environ; *entry; ++entry) {
cout << *entry << endl;
}
pause();
}
Interestingly though (to me anyway), when I check the file-descriptors folder (/pid/<PID#>/fd), I see this:
root#excalibur-VirtualBox:/proc/1546/fd# ls -l
total 0
lrwx------ 1 root root 64 Nov 7 09:12 0 -> /dev/null
lrwx------ 1 root root 64 Nov 7 09:12 1 -> /dev/null
lrwx------ 1 root root 64 Nov 7 09:12 2 -> /dev/null
lrwx------ 1 root root 64 Nov 7 09:12 3 -> socket:[11050]
why do the file descriptors point to /dev/null? Is that to prevent user's from being able to inject content into a file without actually being the process itself, or am I off base on that? And even more curious, why does the file descriptor to an open file point to a socket? That seems really odd. If anyone can shed some light on this for me, I would really appreciate it. Thanks!

You are definitely looking at the wrong /proc directory (for other PID or on another computer). The contents of /proc/<pid>/fd for your program should look like here:
lrwx------ 1 user group 64 Nov 7 22:15 0 -> /dev/pts/4
lrwx------ 1 user group 64 Nov 7 22:15 1 -> /dev/pts/4
lrwx------ 1 user group 64 Nov 7 22:15 2 -> /dev/pts/4
lr-x------ 1 user group 64 Nov 7 22:15 3 -> /tmp/afile.txt
Here we can see that file descriptors 0, 1, and 2 are shown as symbolic links to the pseudo terminal in which the program is running. It could be /dev/null if you started your program with input, output, and error redirection. The file descriptor #3 points to the file afile.txt which is currently opened.

Related

CMD cannot read input characters correctly

I tried to use system function to run a cmd command, but I can't get the command output, Because My Windows is Italian When I type / in my system() function to call cmd its getting actually - and not getting / I tried this in my cmd and is receiving this - instead / ,I tried to use chcp 437 for English cmd but , it didn't work
example :
system("net user xxx xxxx /add");
the command is getting :
net user xxx xxxx -add
I just do not want to do this to work in Italian Windows and work for other languages actually, how to solve this problem?
You should never use system(). You are programming in C++. There is no need to use system() since you have access to everything in the, well, system :D. system() was written in C after all.
And there is the security risk: someone could replace system() or the command you are trying to run using system() in your machine and make not-nice-things in your system.
you can change the code page in your code before calling system() using
SetConsoleOutputCP(); that lives in windows.h
1252 is the Latin codepage and should do ok in Italian. Also 65001 is the utf-8 codepage and should also work well
to run your program on the "new" Windows Terminal is also an option since it is Unicode
pass a string to system() and not a literal. this way you can be sure it has what you want, before the call.
it is a good practice to save the codepage in use before change and restore it on exit
A C++ Example
This program
takes an array of commands
const char* command[] =
{
"DIR .\\*.* /O:D",
"NET USER /Add /?"
};
and runs on the console. The commands uses slashes and backslashes and outputs text so you can test a bit more. And you can just edit the array and add new commands to test
You can try alternative codepages. Here I used 65001, the one for Unicode
int originalOCP = GetConsoleOutputCP();
std::cout << "Original CodePage: " << originalOCP << "\n";
SetConsoleOutputCP(65001);
std::cout << "CodePage now is " << GetConsoleOutputCP() << "\n";
The command is written on the console before being passed to system()
std::cout <<
"\n\n\t==> command " <<
i << " is '" <<
command[i] << "'\n\n";
system(command[i]);
The output in Portuguese Windows
Original CodePage: 850
CodePage now is 65001
==> command 0 is 'DIR .\*.* /O:D'
O volume na unidade C não tem nome.
O Número de Série do Volume é 7E52-1BF2
Pasta de C:\Users\toninho\source\repos\ConsoleApplication8\ConsoleApplication8
29/10/2020 10:21 168 ConsoleApplication8.vcxproj.user
29/10/2020 10:38 974 ConsoleApplication8.vcxproj.filters
29/10/2020 10:38 7.199 ConsoleApplication8.vcxproj
29/10/2020 10:59 676 a.cpp
29/10/2020 10:59 <DIR> ..
29/10/2020 10:59 <DIR> .
29/10/2020 10:59 <DIR> Debug
4 arquivo(s) 9.017 bytes
3 pasta(s) 128.838.795.264 bytes disponíveis
==> command 1 is 'NET USER /Add /?'
A sintaxe deste comando é:
NET USER
[nome de usuário [senha | *] [opções]] [/DOMAIN]
nome de usuário {senha | *} /ADD [opções] [/DOMAIN]
nome de usuário [/DELETE] [/DOMAIN]
nome de usuário [/TIMES:{horários | ALL}]
nome de usuário [/ACTIVE: {YES | NO}]
CodePage now is 850
The code
#include <iostream>
#include <windows.h>
int main(int argc, char** argv)
{
const char* command[] =
{
"DIR .\\*.* /O:D",
"NET USER /Add /?"
};
int originalOCP = GetConsoleOutputCP();
std::cout << "Original CodePage: " << originalOCP << "\n";
SetConsoleOutputCP(65001);
std::cout << "CodePage now is " << GetConsoleOutputCP() << "\n";
for (int i = 0; i < sizeof(command) / sizeof(char*); i += 1)
{
std::cout <<
"\n\n\t==> command " <<
i << " is '" <<
command[i] << "'\n\n";
system(command[i]);
};
SetConsoleOutputCP(originalOCP);
std::cout << "CodePage now is " << GetConsoleOutputCP() << "\n";
return 0;
}

Check all files sizes in a path (C++)

I'm trying to loop so that my program can get the weight of all files in a folder, and if the weight of any of these is equal to X, it will do an action, I need to know how I can loop like this, and i have a func to know whats the file size
std::ifstream::pos_type filesize(const char* filename)
{
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
}
Here's a short example program that demonstrates how to use C++17's <filesystem> library to iterate over a directory. If your compiler is fairly up-to-date, it should support C++17 without issue.
#include <filesystem>
#include <iostream>
int main() {
namespace fs = std::filesystem;
fs::path pwd(""); // Current directory program was executed from
pwd = fs::absolute(pwd);
for (auto& i : fs::directory_iterator(pwd)) {
try {
if (fs::file_size(i.path()) / 1024 > 2048) {
std::cout << i.path() << " is larger than 2MB\n";
}
} catch (fs::filesystem_error& e) {
std::cerr << e.what() << '\n';
}
}
}
This was the contents of the directory:
.
├── a.out
├── fiveKB
├── fourMB
├── main.cpp
└── oneMB
0 directories, 5 files
And information about the files:
drwxr-xr-x 7 user staff 224B Jul 29 22:11 ./
drwxr-xr-x 13 user staff 416B Jul 29 21:59 ../
-rwxr-xr-x 1 user staff 47K Jul 29 22:10 a.out*
-rw-r--r-- 1 user staff 5.0K Jul 29 21:58 fiveKB
-rw-r--r-- 1 user staff 4.0M Jul 29 21:59 fourMB
-rw-r--r-- 1 user staff 450B Jul 29 22:11 main.cpp
-rw-r--r-- 1 user staff 1.0M Jul 29 21:59 oneMB
And finally, the output:
"/Users/user/Documents/tmp/test/fourMB" is larger than 2MB

execlp() is not properly working after fork()

I'm writing function that takes in the value in a linked list, then forks the process and execs a new process using the parameters passed into the command line. Here is the code I have for prog2b.cc:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cplist.h"
#include <sys/time.h>
#include <iostream>
#include <sys/wait.h>
#include <errno.h>
struct timeval start, end;
char *key;
int launch_children(cplist *head){
pid_t cpid;
double execution_times = 0;
if(cpid = fork() < 0 ){ // Important to trap errors
std::cerr << "ARGH I'm likely in trouble, get me out of here!" << std::endl;
exit(1); // Important to exit on errors
}else if (cpid == 0 ){
std::cout << "Child process "<< getpid() << ". Running grep on " << key << head->path << std::endl;
execlp("prog2b", "prog2b", "grep", "-R", key, head->path, NULL);
std::cerr << "Exec failed.. Why?" << std::endl;
exit(1); // VERY IMPORTANT - DON'T LET CHILD KEEP RUNNING
} else { // parent
head->cpid = cpid;
wait(NULL);
std::cout << "Child "<< cpid << "has terminated in " << execution_times;
}
}
int main(int argc, char *argv[]){
int i;
int j = 0;
cplist *head = (cplist*) malloc(sizeof(cplist));
head->path = NULL;
head->next = NULL;
if(strcmp(argv[1], "-v") == 0){
key = argv[2];
for(i = 3; i < argc; i++){
cpl_add(head, argv[i]);
j++;
}
} else {
key = argv[1];
for(i = 2; i < argc; i++){
cpl_add(head, argv[i]);
j++;
}
}
printf("key: %s\n", key);
launch_children(head);
return(0);
}
My program is supposed to take in the key and path values from the command line, then the child process should execlp using 'grep' '-r', and the values passed in. I'm struggling to get the exec to work properly. I've spent a lot of time on the man page for execs trying to understand them better and test out other execs but I've gotten stuck. The exec process won't run. Here is an example to show how it works right now:
When I run: ./prog2b 5678 /hw1/02/ from the command line my output is:
key: 5678
Child process 70788. Running grep on 5678 /hw1/02
Exec failed.. Why?
key: 5678
Child process 70789. Running grep on 5678 /hw1/02
Exec failed.. Why?
The correct out put should be:
key: 5678
Child process nnnnn. Running grep -R 5678 hw1/02
../../hw1/02/nYyLimCI:5678
../../hw1/02/ANFGmj97:5678
../../hw1/02/oFrtX8Sy:5678
../../hw1/02/UrYt9aBz:5678
../../hw1/02/wE1AMVeh:5678
../../hw1/02/F6TGJEiJ:5678
../../hw1/02/v1HG6zmh:5678
../../hw1/02/YyOSKcJG:5678
Child process nnnnn has terminated in a.bbbbbb seconds
I know the exec is failing and I've tried to use errno and it outputted "No such file or directory". I've figured out it referred to the first prog2b but when changed to ./prog2b I believe it causes a fork bomb. I also haven't quite grasped how to grep in the exec and I feel that could be the issue. Hopefully this will help clear up my troubles with fork and exec. I have a header file and linked list function class to _add and _dump but I don't believe those are what's causing the bug
The fact that errno is set to ENOENT (no such file or directory) tells you that execlp() was not able to find the executable.
From the manual page:
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".)
Your current working directory is most likely not in your PATH, and therefore the executable is not found. A simple solution is to just prepend a ./ in front of its name:
execlp("./prog2b", "prog2b", "grep", "-R", "key","head->path", NULL);
// here ^^
Tip for the future: you can see exactly where exec*() tries to look using strace:
$ strace -f -e execve ./prog2b 5678 /hw1/02/
execve("./prog2b ", ["./prog2b", "5678", "/hw1/02/"], [/* 40 vars */]) = 0
key: 5678
Child process 70788. Running grep on 5678 /hw1/02
execve("/usr/local/bin/prog2b", ["prog2b", "grep", "-R", "key","head->path"], [/* 40 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/bin/prog2b", ["prog2b", "grep", "-R", "key","head->path"], [/* 40 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/prog2b", ["prog2b", "grep", "-R", "key","head->path"], [/* 40 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/games/prog2b", ["prog2b", "grep", "-R", "key","head->path"], [/* 40 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/games/prog2b", ["prog2b", "grep", "-R", "key","head->path"], [/* 40 vars */]) = -1 ENOENT (No such file or directory)
Exec failed.. Why?
+++ exited with 1 +++

std::filesystem::exists function doesn't work properly on windows 10

I write some code as below with c++17 msvc:
#include <filesystem>
#include <iostream>
int main()
{
using namespace std::filesystem;
std::wstring s = L"c:\\windows\\system32\\applicationframehost.exe";
path p(s);
std::cout << absolute(p) << std::endl;
std::cout << exists(p) << std::endl;
std::cin.get();
return 0;
}
and run it on windows 10.
the application prints 0 -> means that file does not exist.
But it really exists and when I try with Cygwin ls -l command, it shows a good result:
#myuser> ls -l c:\windows\system32\applicationframehost.exe
-rwxr-xr-x 2 cody.nguyen 1049089 69800 Apr 12 2018 'c:\windows\system32\applicationframehost.exe'
Could you please explain me why and how to solve this issue from code?
thanks,
P/S: the function exists(p) works perfectly with almost other files except some in C:\Windows\System32\. I just tried to run my application with admin/system/user rights but got same results.
With ls -l command I just run it with user privilege only.

trying to connect to postgresql via c++ program

Background
I'm running linux... and I'm trying to write a basic little c++ program that connects to a postgresql database.
I'm trying to follow this article
http://www.tutorialspoint.com/postgresql/postgresql_c_cpp.htm
Problem
I've been able to compile the library... and I can see now that I have the following folder on my computer
/usr/local/include/pqxx
But when i try to write some basic code and compile it, I get the following error:
devbox2:/var/abus# g++ testdb.cpp -lpqxx -lpq
testdb.cpp:2:22: fatal error: pqxx/pqxx: No such file or directory
#include <pqxx/pqxx>
^
compilation terminated.
Source Code
Here's what the code looks like:
1 #include <iostream>
2 #include <pqxx/pqxx>
3
4 using namespace std;
5 using namespace pqxx;
6
7 int main(int argc, char* argv[])
8 {
9 try{
10 connection C("dbname=testdestination user=testuser password=testpassword \
11 hostaddr=127.0.0.1 port=5432");
12 if (C.is_open()) {
13 cout << "Opened database successfully: " << C.dbname() << endl;
14 } else {
15 cout << "Can't open database" << endl;
16 return 1;
17 }
18 C.disconnect ();
19 }catch (const std::exception &e){
20 cerr << e.what() << std::endl;
21 return 1;
22 }
23 }
What I've tried so far:
I've been poking around the /usr/local/include/pqxx folder and I can see that there is a file called pqxx... but it doesn't have any extension on it.
Here's a snippet from the ls -lah command for that folder:
-rw-r--r-- 1 root root 637 Dec 8 21:42 pipeline
-rw-r--r-- 1 root root 7.5K Dec 8 21:42 pipeline.hxx
-rw-r--r-- 1 root root 1.1K Dec 8 21:42 pqxx
-rw-r--r-- 1 root root 728 Dec 8 21:42 prepared_statement
-rw-r--r-- 1 root root 8.2K Dec 8 21:42 prepared_statement.hxx
I've also made sure that my PATH includes the /usr/local/include/pqxx folder. This is what my PATH looks like:
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/gcc:/usr/local/include/pqxx:/usr/local/include'
I'm not sure what else I should check. Any suggestions would be appreciated.
Thanks.
To find the include files, you must add an -I option, e.g.
g++ -I/usr/local/include testdb.cpp -lpqxx -lpq
Adding directories to PATH doesn't help here, PATH is for locating executables from the shell.