Convert shell script to C code using wrapper [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to execute a shell script when loading a .php in a web-server, I've already been struggling with this for a while so I will ask for help.
What I've tried so far is to make a wrapper as explained in this post: Execute root commands via PHP
But I couldn't really get it to work making the wrapper execute a shell script, even when the script worked when being executed from the console with root privileges.
So the only solution I could found is to convert the shell code to a C code using "system ("") as using system(" ")
I don't really know if it's possible, what the shell script used to do is check the PID of the process running in the port 12321 and then kill it.
The shell script alone worked, so I am asking if anyone knows if it's possible to convert to C, here is the shell script I want to convert:
#!/bin/sh
pid=$(/bin/fuser -n tcp 12321 | /usr/bin/awk '{print $1}');
/bin/kill -9 $pid;
And here is the wrapper.c being used, that used to execute the code above called in my machine (testversion.sh), but I don't know why, isn't working.
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
setuid (0);
system ("/bin/bash /var/www/html/scrip/debugport/testversion.sh");
return 0;
}
As this doesn't seem to work, someone got a way of executing it all in the C code?

Try this. This code would only be able to kill a process owned by the same user unless run as root.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#define PORT_TO_LOOK_FOR "12321"
#define DO_NOT_KILL_BELOW 2 /* I am just putting 2 here, you can increase this */
int main(void) {
FILE *fp;
char buf[11] = {0};
pid_t pid;
/* Open the command for reading. */
fp = popen("lsof -t -i tcp:" PORT_TO_LOOK_FOR, "r");
if (fp == NULL) {
printf("Could not run lsof.\n");
exit(1);
}
else {
fgets(buf, sizeof(buf)-1, fp);
pclose(fp);
pid = (pid_t)atoi(buf);
if( pid < 1) {
printf("Either no one is listening on port "
PORT_TO_LOOK_FOR " or u don't have the "
"necessary permission.\n" );
exit(1);
}
else if( pid < DO_NOT_KILL_BELOW ) {
printf("The PID we got was not safe to kill.\n");
exit(1);
}
if( kill(pid, SIGKILL) != 0 ) {
perror("kill");
}
}
return 0;
}

Related

Creating a filesystem in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 months ago.
Improve this question
I want to create a ext4 filesystem in C
For example, my C code currently runs
system("mkfs.ext4 /dev/sdc1")
The problem is using system is not recommended and we don't want to have mkfs.ext4 utility in the root file system.
I saw mke2fs.c file in e2fsprog package, Do we need to copy directly the code understanding the implementation or is there any better way of using some library
That command mkfs.ext4 formats a filesystem on a partition, it does not create a partition. If you need to format a filesystem, the best way to do it is to run the mkfs.ext4 tool. It's not a good idea to copy code from e2fsprogs into your own program.
Why don't you want to have the utility there in the filesystem? If you need to use a certain utility, it should be there.
The system call is potentially unsafe because it passes a string to the shell, and it's difficult to safely escape dynamic arguments to avoid the possibility of shell attacks. If you are using a fixed device or a limited set of devices, and not accepting user input for the device, it should be okay to use system.
If you want to avoid using system, you can do something similar with fork and exec. This does not use the shell, so it is safer. But the code is more complex. I included a safer reusable "systemv" function.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
char *mkfs_ext4_prog = "/sbin/mkfs.ext4";
int systemv(const char *pathname, char *const argv[])
{
int wstatus;
pid_t pid;
pid = fork();
if (pid == -1) {
perror("fork failed");
exit(EXIT_FAILURE);
} else if (pid == 0) {
execv(pathname, argv);
exit(EXIT_FAILURE);
}
if (waitpid(pid, &wstatus, 0) == -1) {
perror("waitpid");
}
if (WIFEXITED(wstatus)) {
return WEXITSTATUS(wstatus);
}
if (WIFSIGNALED(wstatus)) {
fprintf(stderr, "%s killed by signal %d\n", mkfs_ext4_prog, WTERMSIG(wstatus));
}
exit(EXIT_FAILURE);
}
int mkfs_ext4(char *device)
{
char *const argv[] = { mkfs_ext4_prog, "--", device, NULL };
return systemv(mkfs_ext4_prog, argv);
}
int main(void)
{
int status;
char *device;
device = "/dev/sdc1";
status = mkfs_ext4(device);
exit(status);
}

how to write the console output to a file in c [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
hi i have the following code
int main()
{
system("netsh interface ip show addresses");
}
and the output in the console to be written to a text file or else to a variable. pleaase help me out with this. THANKS in ADVANCE
if you use Linux, try this:
system("netsh interface ip show addresses > /path/to/file 2>&1 ");
void do_popen()
FILE *pf;
char command[200];
// Execute a process listing
sprintf(command, "netsh interface ip show addresses");
// Setup our pipe for reading and execute our command.
if(!(pf= popen(command, "r"))){
exit(EXIT_FAILURE);
}
if (pclose(pf) != 0)
fprintf(stderr," Error: Failed to close command stream \n");
return;
}
Here we are using popen which internally creates a process and run the command given to it. It returns an I/O stream from where the data can be fetched later. read and write system calls are being used while reading from the given command buffer or writing into the file back
To make it more generic, you can pass the command in the function parameter and return the data stored into the file in a dynamic array.
Although it is done nicely using popen but it creates a separate process where it run these commands as sh commands,and then put it in the file and before returning the file pointer, it closes all the process.
I would rather implement my own child process using fork() and then use exec and implement my own SIGCHILD handler to remove it from zombie and keep on processing other work in parallel instead of blocking the process
Hope the below code will help to solve your issue. Look at the man pages for the details of popen and pclose APIs.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *in;
char buff[512];
if(!(in = popen("netsh interface ip show addresses", "r"))){
return -1;
}
while(fgets(buff, sizeof(buff), in)!=NULL){
printf("%s", buff);
}
pclose(in);
return 0;
}

Can I get executed commands not using history or ~/.bash_history?

My code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("entering main process---\n");
int ret;
char *argv[] = {"history",NULL};
ret = execvp("history",argv);
if(ret == -1)
perror("execl error");
printf("exiting main process ----\n");
return 0;
}
Output:
entering main process---
execl error: No such file or directory
exiting main process ----
Question:
Can I get executed commands not using history or ~/.bash_history?
It seems that something is wrong using function like execvp .
I've tried system function.
Code:
#include <stdio.h>
int main()
{
system("history");
return 0 ;
}
Nothing output.
If you try a man history you will get into the BASH_BUILTINS(1) General Commands Manual page. This means history is part of the bash shell internals. In order to have something executed via execvp() you need to have an actual executable somewhere in your PATH.
It's unclear why reading ~/.bash_history is not enough. Is it perhaps because you want the history of the currently running shell?
The short answer is no, you can't get it.
The long answer is you could attach with ptrace or through /proc/pid/mem, find the history in memory, and print it.
Probably not worth the effort.
You can pipe the output of the history builtin if you wish, by running your program with
history | ./myprog

execute less with execv?

I have the following c code. I want to display my file with less by calling execv()
however the following seems never work. The program terminates and noting pop out.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(void){
int pid;
if(pid=fork()>0){
//read in from stdin and pass to pipe
}else if(pid==0){
//read from pipe
//write to out.txt
//everything up to here works fine
char* para[]={"less","/Desktop/out.txt"};
execv("/bin/less",para);
}
return 0;
}
(The original code contained execv("bin/less", para);.) Unless the current directory is the root directory, /, or unless there is a program less in the subdirectory ./bin/less, then one of your problems is that you have a probable typo in the name of the executable. That assumes the program is /bin/less and not /usr/bin/less. You might even use execvp() to do a PATH-based search for the program.
There's an additional problem: you need to include a null pointer to mark the end of the argument list.
Finally, you can print an error message after the execv() returns. The mere fact that it returns tells you it failed.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int pid;
if ((pid = fork()) != 0)
{
// read in from stdin and pass to pipe
// Need to test for fork() error here too
}
else
{
// read from pipe
// write to out.txt
// everything up to here works fine
char *para[] = { "/bin/less", "Desktop/out.txt", 0 };
execv(para[0], para);
fprintf(stderr, "Failed to execute %s\n", para[0]);
exit(1);
}
return 0;
}
Or:
char *para[] = { "less", "Desktop/out.txt", 0 };
execvp(para[0], para);
fprintf(stderr, "Failed to execute %s\n", para[0]);
The remarks in the code about pipes are puzzling since there is no sign of pipes other than in the comments. As it stands, less will read the file it is told to read. Note that less will not paginate its output if the output is not going to a terminal. Since we can see no I/O redirection, we have to assume, then, that less will ignore anything the program tries to write to it, and will not send any data back to the program.
char* para[]={"less","/Desktop/out.txt"};
execv("/bin/less",para);
How does execv know when to stop reading parameters?
I think if you'd put code in there to handle execv() returning an error you'd have found this. You're also not testing for errors from fork().

Linux: write a C program that 'controls' a shell

Suppose we have a shell running on terminal, let's say, /dev/pts/1. The shell is already running and we can't restart it.
Now we want to write a C program that will 'control' the shell, i.e. which will itself provide a shell-like interface to the user, read user's input, pass it on to the real shell on /dev/pts/1, have it execute it, read shell's output and print it back to the user.
I know how to do half of this task: I know how to gather user's input and inject this input to the 'real shell' :
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#define SIZE 100
int main(int argc, char** argv)
{
if( argc>1 )
{
int tty = open( argv[1], O_WRONLY|O_NONBLOCK);
if( tty!=-1 )
{
char *buf,buffer[SIZE+1];
while(1)
{
printf("> ");
fgets( buffer, SIZE, stdin );
if( buffer[0]=='q' && buffer[1]=='u' && buffer[2]=='i' && buffer[3]=='t' ) break;
for(buf=buffer; *buf!='\0'; buf++ ) ioctl(tty, TIOCSTI, buf);
}
close(tty);
}
else printf("Failed to open terminal %s\n", argv[1]);
}
return 0;
}
The above will pass on your input to shell running in terminal ( give its name in the first argument ) and have the shell execute it. However, I don't know how to read the shell's output now.
Any tips?
You can use pipes for that. Linux shells allow redirection.
I used pipes to control tty's.
There are programs that allow you to change the controlling terminal for a process: reptyr and injcode are two such programs.
I do believe that they sever the other terminal, however, so depending on your needs this may or may not fit exactly.
please take a look at libpipeline. maybe this will help you...

Resources