I'm trying write a shell scrip on linux to detect a string on output steam.
This is my shell script
#!/bin/bash
./binary
binary file is compiled from source file as below:
gcc-4.6 main.c -o binary
//main.c
#include "stdio.h"
void main(){
int i;
for (i=0; i<100; i++){
printf("data: %d\n", i);
sleep(1); // delay 1s
}
}
Could you let me know how to detect "data: 10" from output ./binary?
When stdout is not connected to a terminal, it's fully buffered by default. So if you want to be able to detect output immediately (as suggested by the sleep(1); in the code) you need to flush the buffer after printing.
#include "stdio.h"
void main(){
int i;
for (i=0; i<100; i++){
printf("data: %d\n", i);
fflush(stdout);
sleep(1); // delay 1s
}
}
Then you can pipe the output of the program to something in the script and it will detect the output without waiting for the program to finish.
Related
I am new to coding and I saved my firstprog.c in a file <C:\Users\chinm\Desktop\S\Codes Book>
my code in firstprog goes as follows
#include <stdio.h>
int main()
{
int i;
for(i=0; i<10; i++)
{
printf("Hello!\n");
}
return 0;
}
But when i type this in cmd i dont get a desired output
OUTPUT:
C:\Users\chinm\Desktop\S\Codes Book>gcc firstprog.c
C:\Users\chinm\Desktop\S\Codes Book>
With the gcc firstprog.c, you only compile the program. You might see that after running gcc firstprog.c, you'll get a file called a.out.
You need to run that file with:
./a.out
See https://web.stanford.edu/class/archive/cs/cs107/cs107.1212/resources/gcc for more details
My Code
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
char * arg_list[3];
arg_list[0] = "ls";
arg_list[1] = "-l";
arg_list[2] = 0;
char *arg_list2[3];
arg_list2[0] = " ps";
arg_list2[1] = "-ef";
arg_list2[2] = 0;
for(int i=0;i<5;i++){ // loop will run n times (n=5)
if(fork() == 0) {
if (i == 0){
execvp("ls", arg_list);
}else if(i==1){
execvp("ps" , arg_list2);
}else if(i>1){
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
}
for(int i=0;i<5;i++) // loop will run n times (n=5)
wait(NULL);
}
ME trying to modify it
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
for(int i=0;i<5;i++){ // loop will run n times (n=5)
if(fork() == 0) {
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
execlp(argv[i],argv[i],argv[i+1],(char*)NULL);
exit(0);
}
}
for(int i=0;i<5;i++) // loop will run n times (n=5)
wait(NULL);
}
-- NEED GUIDANCE AND UNDERSTANDING
I am trying to make my own tiny little shell program. When I run my first code works fine, runs all commands on the command line. But I cannot know and define all commands the user might enter. So i am trying to get a base code which could run any commands single or multiple entered by user. I tried using execlp where it does not compile saying argv is not defined which is true as i don't want to specifically define it.
I am trying to make my own tiny little shell program. When I run my first code works fine, runs all commands on the command line. But I cannot know and define all commands the user might enter.
For sure.... A shell program purpose is basically:
Read user input
Execute user input
Return result of execution.
There's nothing in your code that read user input....
So i am trying to get a base code which could run any commands single or multiple entered by user.
So read user input ;-)
I tried using execlp where it does not compile saying argv is not defined which is true as i don't want to specifically define it.
For sure ... but how would GCC guessed that `argv[]̀ must be automaticallty filled with user input ?
There's nothing automatic when coding in C language. You have to manage this manually.
Also, note that argc, argv et envp are usually reserved for main() function:
main(int argc, char **argv, char **envp)
So you may use something else to build your command array.
In pseudo code, what you must implement is:
quit=0
while (quit = 0) {
command_to_run = read_user_input();
if (command_to_run == "exit") {
quit = 1;
} else {
execute(command_to_run);
}
}
Some advices:
Try to use more functions. For example, implement a fork_and_run(char **cmd) function to fork and then execute command provided by the user. Il will make your code more readable and easy to maintain.
Read carefully manpages: everything you should know (like, for example, the fact that array provided to execvp() must be NULL-terminated) is written in it.
Your debugging messages should be printed to stderr. The result of the command run must be printed to stdin, so use fprintf() instead of printf() to write to the correct stream.
I would use a #define debug(x) fprintf(stderr, x) or something similar for debugging output so that you can easily disable later ;-)
I'm trying to simulate a pipe behavior on Ubuntu's Terminal, for example the command:
"echo hello | wc".
Please assume I got the tokens from stdin, handled everything correctly and now These are the commands I "received" from the user who typed them in the shell for me to handle.
I'm trying to create two processes. Using a pipe, in the first process, I point the file descriptor of the writing edge of the pipe to stdout. The second process should read into stdin with the reading edge of the pipe what execvp(..) returned.?
Here is the code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
char* fcmd[] = {"echo", "hello", NULL};
char* scmd[] = {"wc", NULL};
pid_t pid;
int pipe_des[2];
int i;
pipe(pipe_des);
for(i = 0; i < 2; i++)
{
pid = fork();
if (pid ==0)
{
switch (i)
{
case 0: // FIRST CHILD
{
dup2(pipe_des[1], STDOUT_FILENO);
close(pipe_des[0]);
execvp(fcmd[0], fcmd);
exit(0);
}
case 1: //SECOND CHILD
{
dup2(pipe_des[0], STDIN_FILENO);
close(pipe_des[1]);
execvp(scmd[0], scmd);
exit(0);
}
}
}
else if (pid < 0)
exit(EXIT_FAILURE);
return EXIT_SUCCESS;
}
I get: " amirla#ubuntu:~/Desktop/os/class/ex4$ 1 1 6 "
Like it should, but why he's printing the bash cwd first? The pipe seems to work because I get what I should, according to the length of the word I'm sending with the echo command(in the main()). After that the cursor just waits on the line below for another command without showing me the bash pwd. (maybe stdin is waiting?)
I've looked in many posts on here as well as on other websites and I still can't seem to find a solution to my problem. Any help would be appreciated. Thanks in advance.
Note: Please Ignore checking for errors, I've delete them to make the code shorter so assume they exist.
Why do I get a prompt before the output?
Your main process doesn't wait for the children to finish. What you see is:
Main starts
Main creates children
Main exits
BASH prints prompt
Children start their work
To prevent this, you need to wait for the children. See How to wait until all child processes called by fork() complete?
In your case, it's enough to add
waitpid(-1, NULL, 0);
after the loop.
The Program which has many forks as below did not finish.
#include <unistd.h>
#include <iostream>
int main() {
static int fork_cnt = 0;
const unsigned kCnt = 4;
for (int i = 0; i < kCnt; ++i) {
fork();
}
std::cout << "fork_cnt=" << fork_cnt << std::endl;
return 0;
}
When I ran it, It stop as below. It seems that The main fork is finished, but other program is waitting for something.
fork_cnt=0
qingfeng#ubuntu:~$ fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
...
Actually the program is not waiting for anything. What happens here is that you create child processes, that detach from your current stdin (at least I believe they do given their behavior). When your original process returns, sh regains the control over your stdin and prompts you for input - hence the qingfeng#ubuntu:~$ in the second line of your second listing. Anyway, your child processes keep writing to stdout, therefor the fork_cnt=0are output after the qingfeng#ubuntu:~$. When all processes have ended sh sees no reason for prompting you again for an input, therefor it seems to you as if the program's still running, but if you entered some command (or just hit Enter) you'd see it did.
To test this, please try the following: Create an infinite loop in each child process right after its creation.
#include <unistd.h>
#include <iostream>
int main() {
static int fork_cnt = 0;
const unsigned kCnt = 4;
for (int i = 0; i < kCnt; ++i) {
int pid = fork();
while(pid == 0);
}
std::cout << "fork_cnt=" << fork_cnt << std::endl;
return 0;
}
Now fork_cnt=0 is output only once and you regain the control over the terminal.
paul#www:~/Programming/playground/fork# ./a.out
fork_cnt=0
paul#www:~/Programming/playground/fork#
Anyway, the child processes are still running, which you can easily verify by entering ps in your shell.
I'm looking to pipe some String input to a small C program in Windows's command prompt. In bash I could use
$ printf "AAAAA\x86\x08\x04\xed" | ./program
Essentially, I need something to escape those hexadecimal numbers in command prompt.
Is there an equivalent or similar command for printf in command prompt/powershell?
Thanks
In PowerShell, you would do it this way:
"AAAAA{0}{1}{2}{3}" -f 0x86,0x08,0x04,0xed | ./program
I recently came up with the same question myself and decided that for someone developing Windows exploits it is worth installing cygwin :)
Otherwise one could build a small C program mimicking printf's functionality:
#include <string.h>
int main(int argc, char *argv[])
{
int i;
char tmp[3];
tmp[2] = '\0';
if (argc > 1) {
for (i = 2; i < strlen(argv[1]); i += 4) {
strncpy(tmp, argv[1]+i, 2);
printf("%c", (char)strtol(tmp, NULL, 16));
}
}
else {
printf("USAGE: printf.exe SHELLCODE\n");
return 1;
}
return 0;
}
The program only handles "\xAB\xCD" strings, but it shouldn't be difficult to extend it to handle "AAAAA\xAB\xCD" strings if one needs it.