Understanding unix fork - unix

Can anyone explain why the line containing "here" is executed 5 times and how exactly the program runs because I don't seem to understand how I get this output
Output:
12958: 0 here
12959: 0
12958: 0 here
12958: 1 here
12960: 1
12958: 0 here
12958: 1 here
Code:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(){
int i;
for(i=0; i<2; i++){
printf("%d: %d here\n", getpid(), i);
if(fork()==0){
printf("%d: %d\n", getpid(), i);
exit(0);
}
}
for(i=0; i<2; i++){
wait(0);
}
return 0;
}
Edit: because I'm running windows on my computer I used this website link to check the code, could that be a problem?

Fork creates an almost identical process, including the output buffers. If these are not flushed before the fork, both processes can end up printing the contents. Try putting a fflush(stdout); after the parent's printf.

It is not supposed to get the output you mentioned. As I tested your code my output was the following
11194: 0 here
11194: 1 here
11195: 0
11196: 1
Maybe you should recompile it and try again?

Related

3rd argument is ignored when I use memcpy in C

I'm a beginner in C and try to use memcpy to send byte in order to transfer data to server. It seems like no matter what I choose for 3rd argument. It's always the same.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char myChar[100] = "Hello world! ABC is an online sandbox that makes it easy to try out";
char myChar2[100];
memcpy(myChar2, myChar, 3);
printf("%s", myChar);
return 0;
}
This is the result.
Hello world! ABC is an online sandbox that makes it easy to try out
memcpy is working correctly.
The problem with your code is that you are printing myChar instead of myChar2.
printf("%s", myChar2); // Hel
Working example

How can I guarantee one #define is larger than another?

#define MY_CONST 20
#define OTHER_CONST 10
My code only makes sense if MY_CONST > OTHER_CONST. How can I guarantee this with the preprocessor? Is there any command like this?
#assert MY_CONST < OTHER_CONST
Is there any command like this?
#assert MY_CONST < OTHER_CONST
#if OTHER_CONST >= MY_CONST
#error "Error, OTHER_CONST >= MY_CONST"
#endif
as #attersson said #if will do it.
(as a good habbit try to parenthesize your macros to guarantee order of evaluation for more complex expressions. this answer shows why.)
#include <stdio.h>
#define A 10
#define B 11
#if (A) > (B)
#define RES "yes"
#else
#define RES "no"
#endif
int
main(int argc, char *argv[])
{
printf("is A larger? %s\n", RES);
return 0;
}

In-memory file to intercept stdout on function call

I've inherited this function that I have to call from my code. The function is
from a bizzare library in an arcane programming language -- so I cannot assume
almost anything about it, except for the fact that it prints some useful
infomation to stdout.
Let me simulate its effect with
void black_box(int n)
{
for(int i=0; i<n; i++) std::cout << "x";
std::cout << "\n";
}
I want to intercept and use the stuff it outputs. To that end I redirect stdout
to a temporary file, call the black_box, then restore the stdout and read the
stuff from the temporary file:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
int main(void){
int fd = open( "outbuff", O_RDWR | O_TRUNC | O_CREAT, 0600);
// Redirect stdout to fd
int tmp = dup(1);
dup2( fd, 1);
// Execute
black_box(100);
std::cout << std::flush;
// Restore old stdout
dup2(tmp, 1);
// Read output from the outbuff flie
struct stat st;
fstat(fd, &st);
std::string buf;
buf.resize(st.st_size);
lseek(fd, 0, SEEK_SET);
read(fd, &buf[0], st.st_size);
close(fd);
std::cout << "Captured: " << buf << "\n";
return 0;
}
This works. But creating a file on disk for such a task is not something I'm
proud of. Can I make something like a file, but in-memory?
Before suggesting a pipe, please consider what would happen if
black_box overflows its buffer. And no, I need it single-threaded --
starting an extra process/thread defeats the whole purpose ot what I'm trying
to achieve.
I want to intercept and use the stuff it outputs.
[...] please consider what would happen if black_box overflows its buffer.
I see two alternatives.
If you know the maximum size of the output, and the size is not too excessive, use the socketpair instead of pipe. Unlike pipes, sockets allow to change the size of the egress/ingress buffers.
Use a temporary file on /tmp. In normal case it will not touch disk (unless system is swapping). There are few functions for the purpose, for example mkstemp (or tmpfile).

How to Implement a single program in C that replicates the following Unix command(s): ps -ef | grep YOUR_USER_id | wc [duplicate]

This question already has answers here:
Connecting n commands with pipes in a shell?
(2 answers)
Learning pipes, exec, fork, and trying to chain three processes together
(1 answer)
Closed 8 years ago.
My teacher gave us a practice assignment for studying in my Operating Systems class. The assignment was to pipe three processes together and implement the commands in the title all at once. We are only allowed to use these commands when implementing it:
dup2()
one of the exec()
fork()
pipe()
close()
I can pipe two together but I don't know how to do three. Could someone either show me how to do it or at least point me in the right direction?
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pfd[2];
int pfdb[2];
int pid;
if (pipe(pfd) == -1) {
perror("pipe failed");
exit(-1);
}
if ((pid = fork()) < 0) {
perror("fork failed");
exit(-2);
}
if (pid == 0) {
close(pfd[1]);
dup2(pfd[0], 0);
close(pfd[0]);
execlp("ps", "ps", "-ef", (char *) 0);
perror("ps failed");
exit(-3);
}
else {
close(pfd[0]);
dup2(pfd[1], 1);
close(pfd[1]);
execlp("grep", "grep", "darrowr", (char *) 0);
perror("grep failed");
exit(-4);
}
exit(0);
}
Any help would be appreciated. Heck a tutorial on how to complete it would be wondrous!
You're going to need 3 processes and 2 pipes to connect them together. You start with 1 process, so you are going to need 2 fork() calls, 2 pipe() calls, and 3 exec*() calls. You have to decide which of the processes the initial process will end up running; it is most likely either the ps or the wc. You can write the code either way, but decide before you start.
The middle process, the grep, is going to need a pipe for its input and a pipe for its output. You could create one pipe and one child process and have it run ps with its output going to a pipe; you then create another pipe and another child process and fix its pipes up before running grep; the original process would have both pipes open and would close most of the file descriptors before running wc.
The key thing with pipes is to make sure you close enough file descriptors. If you duplicate a pipe to standard input or standard output, you should almost always close both of the original file descriptors returned by the pipe() call; in your example, you should close both. And with two pipes, that means there are four descriptors to close.
Working code
Note the use of an error report and exit function; it simplifies error reporting enormously. I have a library of functions that do different error reports; this is a simple implementation of one of those functions. (It's overly simple: it doesn't include the program name in the messages.)
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void err_syserr(const char *fmt, ...);
int main(void)
{
int p1[2];
int p2[2];
pid_t pid1;
pid_t pid2;
if (pipe(p1) == -1)
err_syserr("failed to create first pipe");
if ((pid1 = fork()) < 0)
err_syserr("failed to fork first time");
if (pid1 == 0)
{
dup2(p1[1], STDOUT_FILENO);
close(p1[0]);
close(p1[1]);
execlp("ps", "ps", "-ef", (char *)0);
err_syserr("failed to exec 'ps'");
}
if (pipe(p2) == -1)
err_syserr("failed to create second pipe");
if ((pid2 = fork()) < 0)
err_syserr("failed to fork second time");
if (pid2 == 0)
{
dup2(p1[0], STDIN_FILENO);
close(p1[0]);
close(p1[1]);
dup2(p2[1], STDOUT_FILENO);
close(p2[0]);
close(p2[1]);
execlp("grep", "grep", "root", (char *)0);
err_syserr("failed to exec 'grep'");
}
else
{
close(p1[0]);
close(p1[1]);
dup2(p2[0], STDIN_FILENO);
close(p2[0]);
close(p2[1]);
execlp("wc", "wc", (char *)0);
err_syserr("failed to exec 'wc'");
}
/*NOTREACHED*/
}
#include <stdarg.h>
#include <errno.h>
#include <string.h>
static void err_syserr(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
putc('\n', stderr);
exit(EXIT_FAILURE);
}
Sample output:
234 2053 18213
My machine is rather busy running root-owned programs, it seems.

How can I get the current mouse (pointer) position co-ordinates in X

This can either be some sample C code or a utility that will show me either gui or on the console it doesn't matter, but I have to be able to "command" it to grab the co-ordinates at an exact time which makes xev not very useful (that I could figure out).
I'm not a C programmer by any means but I looked at a couple of online tutorials and think this is how you are supposed to read the current mouse position. This is my own code and I'd done nothing with Xlib before so it could be completely broken (for example, the error handler shouldn't just do nothing for every error) but it works. So here is another solution:
#include <X11/Xlib.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
static int _XlibErrorHandler(Display *display, XErrorEvent *event) {
fprintf(stderr, "An error occured detecting the mouse position\n");
return True;
}
int main(void) {
int number_of_screens;
int i;
Bool result;
Window *root_windows;
Window window_returned;
int root_x, root_y;
int win_x, win_y;
unsigned int mask_return;
Display *display = XOpenDisplay(NULL);
assert(display);
XSetErrorHandler(_XlibErrorHandler);
number_of_screens = XScreenCount(display);
fprintf(stderr, "There are %d screens available in this X session\n", number_of_screens);
root_windows = malloc(sizeof(Window) * number_of_screens);
for (i = 0; i < number_of_screens; i++) {
root_windows[i] = XRootWindow(display, i);
}
for (i = 0; i < number_of_screens; i++) {
result = XQueryPointer(display, root_windows[i], &window_returned,
&window_returned, &root_x, &root_y, &win_x, &win_y,
&mask_return);
if (result == True) {
break;
}
}
if (result != True) {
fprintf(stderr, "No mouse found.\n");
return -1;
}
printf("Mouse is at (%d,%d)\n", root_x, root_y);
free(root_windows);
XCloseDisplay(display);
return 0;
}
xdotool might be the best tool for this.
For C, you can use libxdo.
Actually, xev is very useful if you supply it with the window id grabbed using xwininfo, then it can easily perform this task for you. There are no doubt much more elegant solutions but it works.
xinput can be used to print the full device state of any input device.
First you need to discover your device id:
$ xinput --list | grep -i mouse
⎜ ↳ Logitech USB Receiver Mouse id=11 [slave pointer (2)]
then you can ask for state:
$ xinput --query-state 11;
2 classes :
ButtonClass
button[1]=up
button[2]=up
button[3]=up
button[4]=up
button[5]=up
button[6]=up
button[7]=up
button[8]=up
button[9]=up
button[10]=up
button[11]=up
button[12]=up
button[13]=up
button[14]=up
button[15]=up
button[16]=up
button[17]=up
button[18]=up
button[19]=up
button[20]=up
ValuatorClass Mode=Relative Proximity=In
valuator[0]=274
valuator[1]=886
valuator[2]=0
valuator[3]=675
Or just a loop:
while sleep .2; do xinput --query-state $(xinput --list | grep -i mouse | cut -d= -f2 | cut -f1| head -1); done

Resources