/*
* Copyright ©2026 Soham Pardeshi. All rights reserved.
* Permission is hereby granted to students registered for University of
* Washington CSE 333 for use solely during Summer Quarter 2026 for
* purposes of the course. No other use, copying, distribution, or
* modification is permitted without prior written consent. Copyrights
* for third-party components of this work must be honored. Instructors
* interested in reusing these course materials should contact the author.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
// A fork()-based server calls accept() to get client_fd, then forks: the
// child handles that one client and does not accept new ones, so it
// closes listen_fd; the parent goes back to accepting and does not
// handle this client, so it closes client_fd. This program uses a pipe
// in place of an accepted connection, so it can show that same
// close-what-you-do-not-use pattern without a real client attached.
int main(void) {
int pipe_fds[2];
if (pipe(pipe_fds) != 0) {
perror("pipe");
return EXIT_FAILURE;
}
int read_fd = pipe_fds[0];
int write_fd = pipe_fds[1];
pid_t pid = fork();
if (pid < 0) {
perror("fork");
return EXIT_FAILURE;
}
if (pid == 0) {
// Child: stands in for the worker that handles the client. It only
// reads from the connection, so it closes the write end, just as a
// fork()-based server's child closes listen_fd.
close(write_fd);
char buffer[64];
ssize_t bytes_read = read(read_fd, buffer, sizeof(buffer) - 1);
if (bytes_read > 0) {
buffer[bytes_read] = '\0';
printf("child: received \"%s\"\n", buffer);
}
close(read_fd);
_exit(EXIT_SUCCESS);
}
// Parent: stands in for the acceptor that goes back to accepting new
// clients. It does not read from this connection, so it closes the
// read end, just as a fork()-based server's parent closes client_fd.
close(read_fd);
const char* message = "hello from parent";
write(write_fd, message, strlen(message));
close(write_fd);
int status;
waitpid(pid, &status, 0);
return EXIT_SUCCESS;
}