/*
 * 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;
}