I'm currently writing a program that will run multiple commands (in one line) in the CLI using C.
The first command that I need to run is sudo -s. So I run this command alone to test if the program is running, but the program hangs while running this command. I wanted to know if the problem is the program or the command, so I run ls. The program works perfectly when I run the ls command so I assume that something is wrong with sudo -s command, maybe I need to do something with that command so that it will run in the CLI.
Here's the function that accepts the command:
int executeCommand(char *command, char *result)
{
/*This function runs a command./*/
/*The return value is the output of command*/
int nSuccess = -1;
FILE * fp = NULL;
char buffer[1035];
if (command == NULL)
render("Command is null");
if (result == NULL)
render("result is null");
if (command!=NULL && result!=NULL)
{
fp=popen(command,"r");
if(fp!=NULL)
{
strcpy(result,"\0");
while(fgets(buffer, sizeof(buffer)-1,fp)!=NULL)
{
strcat(result,buffer);
}
pclose(fp);
} nSuccess=0;
}
return nSuccess;
}
BTW, I'm doing a web app, the user will write the command that he wants to execute. The input will be sent to server via ajax using a POST request. And the server runs on Linux.
sudo -s
will require the password so the program running this command may wait for password to be entered
sudo -s will prompt for a password and won't return a result immediately.
Related
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.
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 have a custom shell, which runs in one process. I want to use the inbuilt ssh available in Linux. I want to redirect the user I/O from the custom CLI to the actual linux shell.
Here is what I have done to do ssh:
INT4 do_ssh(tCliHandle CliHandle, CHR1 *destIp)
{
FILE *writePipe = NULL;
char readbuff[1024];
char cmd[1024];
memset(cmd,'\0',sizeof(cmd));
sprintf(cmd,"/usr/bin/ssh %s",destIp);
printf("cmd = %s\r\n",cmd);
writePipe = popen(cmd,"w");
if(writePipe == NULL)
{
return -1;
}
while( fgets(readbuff,sizeof(readbuff) - 1, writePipe) != NULL)
{
CliPrintf(CliHandle,"%s\r\n", readbuff);
//printf("%s",readbuff);
}
printf("Closing writePipe\r\n");
pclose(writePipe);
return 0;
}
The problem, which I see is that after doing ssh I can't see the session anymore.
Here is the output:
cust# ssh 192.168.10.42
cmd = /usr/bin/ssh 192.168.10.42
Closing writePipe
Pseudo-terminal will not be allocated because stdin is not a terminal.
Could not create directory '/root/.ssh'.
root#192.168.10.42's password:
ssh 192.168.10.42
My expectation is to keep the session alive and let the user keep sending the command from the terminal and it should get printed on the terminal.
But, I see that after ssh the session is closed. I want to keep it open.
I want to close only when the window is closed or exit is passed.
What I should do? Any hints will be helpful.
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?