#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

// For the syntax of 'fork' and 'execvp', see 'man 3 fork' and 'man 3 execvp'

void print_string();
void fork_a_command(char *cmd);

int main(int argc, char *argv[]) {

  print_string();
  printf("\n");
  fork_a_command("ls");
  return 0;
}

void print_string() {
  char str[] = "abc";
  printf("string: %s\n", str);
}

void fork_a_command(char *cmd) {
  printf("*** The child will be created and execute 'ls'\n");
  int childpid = fork(); // create new process in process table
                 // The new child process will look like clone of this process.

  if (childpid == 0) { // if this is a child
    char *args[] = {cmd, NULL};
    execvp(cmd, args);
  } else { // else this is the original parent process that ran 'main'.
    sleep(2);  // wait 2 seconds and then print.
    printf("*** The child should now have executed 'ls'\n");
  }
}

/************************************************************
 * GDB EXAMPLE
 * LOGIN-STUDENTS:tmp% gdb ./a.out 
 * ...
 * Reading symbols from /tmp/hw1/a.out...done.
 * (gdb) break main
 * Breakpoint 1 at 0x4006ac: file fork-exec-example.c, line 12.
 * (gdb) where
 * No stack.
 * (gdb) run
 * Starting program: /tmp/hw1/./a.out 
 * 
 * Breakpoint 1, main (argc=1, argv=0x7fffffffdc78) at fork-exec-example.c:12
 * 12	  print_string();
 * Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
 * (gdb) where
 * #0  main (argc=1, argv=0x7fffffffdc78) at fork-exec-example.c:12
 * (gdb) list
 * 7	void print_string();
 * 8	void fork_a_command(char *cmd);
 * 9	
 * 10	int main(int argc, char *argv[]) {
 * 11	
 * 12	  print_string();
 * 13	  printf("\n");
 * 14	  fork_a_command("ls");
 * 15	  return 0;
 * 16	}
 * (gdb) echo Try ^Xa to temporarily switch to listing-mode, and then ^Xa\n
 * Try ^Xa to temporarily switch to listing-mode, and then ^Xa
 * (gdb) next
 * string: abc
 * 13	  printf("\n");
 * (gdb) next
 * 
 * 14	  fork_a_command("ls");
 * (gdb) step
 * fork_a_command (cmd=0x4007f0 "ls") at fork-exec-example.c:24
 * 24	  printf("*** The child will be created and execute /bin/ls\n");
 * (gdb) list
 * 19	  char str[] = "abc";
 * 20	  printf("string: %s\n", str);
 * 21	}
 * 22	
 * 23	void fork_a_command(char *cmd) {
 * 24	  printf("*** The child will be created and execute /bin/ls\n");
 * 25	  int childpid = fork(); // create new process in process table
 * 26	                 // The new child process will look like clone of this process.
 * 27	
 * 28	  if (childpid == 0) { // if this is a child
 * (gdb) next
 * *** The child will be created and execute 'ls'
 * 25	  int childpid = fork(); // create new process in process table
 * (gdb) next
 * [Detaching after fork from child process 29178]
 * 28	  if (childpid == 0) { // 'childpid == 0' if this is a child
 * (gdb) a.out  fork-exec.c  fork-exec-example.c  fork-exec.in  hw1.txt	Makefile
 * list
 * 23	void fork_a_command(char *cmd) {
 * 24	  printf("*** The child will be created and execute /bin/ls\n");
 * 25	  int childpid = fork(); // create new process in process table
 * 26	                 // The new child process will look like clone of this process.
 * 27	
 * 28	  if (childpid == 0) { // if this is a child
 * 29	    char *args[] = {cmd, NULL};
 * 30	    execvp(cmd, args);
 * 31	  } else { // else this is the original parent process that ran 'main'.
 * 32	    sleep(2);  // wait 2 seconds and then print.
 * (gdb) where
 * #0  fork_a_command (cmd=0x4007f0 "ls") at fork-exec-example.c:28
 * #1  0x00000000004006ca in main (argc=1, argv=0x7fffffffdc78)
 *     at fork-exec-example.c:14
 * (gdb) ptype cmd
 * type = char *
 * (gdb) ptype childpid
 * type = int
 * (gdb) print childpid
 * $1 = 29178
 * (gdb) next
 * 32	    sleep(2);  // wait 2 seconds and then print.
 * (gdb) next
 * 33	    printf("*** The child should now have executed /bin/ls\n");
 * (gdb) next
 * *** The child should now have executed 'ls'
 * 35	}
 * (gdb) next
 * main (argc=1, argv=0x7fffffffdc78) at fork-exec-example.c:15
 * 15	  return 0;
 * (gdb) next
 * 16	}
 * (gdb) next
 * 0x00007ffff7a2f555 in __libc_start_main () from /lib64/libc.so.6
 * (gdb) quit
 * A debugging session is active.
 * 
 * 	Inferior 1 [process 29085] will be killed.
 * 
 * Quit anyway? (y or n) y
 ************************************************************/
