#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/sysctl.h>
#include <string.h>
#include <sys/wait.h>

#define EXIT_FAILURE	1
#define EXIT_SUCCESS	0

static int mygetresuid(uid_t* ruid, uid_t* euid, uid_t* suid)
{
  int retval, mib[4];
  struct kinfo_proc kp;
  size_t len;

  len = sizeof(kp);

  mib[0] = CTL_KERN;
  mib[1] = KERN_PROC;
  mib[2] = KERN_PROC_PID;
  mib[3] = getpid();

  retval = sysctl(mib, 4, &kp, &len, NULL, 0);
  if (retval == -1)
    return -1;

  if (len <= 0)
    return -1;

  *suid = (kp.kp_eproc.e_pcred.p_svuid);
  *ruid = getuid();
  *euid = geteuid();
  return 0;
}

int main(){
	uid_t ruid, euid, suid;
	int fd1 = -1;
	int fd2 = -1;
	int cpid = -1;
	bool privilegedOp = false;
	char *buf1 = "write to unprivileged file1.";
	char *buf2 = "sensitive information in file2.";

	mygetresuid(&ruid, &euid, &suid);
	/* drop privilege for unprivileged operation */
	/* set effective uid to real uid*/
	seteuid(ruid);

	/* Open, read, close unprivileged file */
	fd1 = open("file_unpriv.txt", O_WRONLY);
	seteuid(suid);
	/* Open, read, close unprivileged file */
	fd2 = open("file_priv.txt", O_WRONLY);

	if(fd2>0){
		privilegedOp = true;
	}
	seteuid(ruid);
	cpid = fork();
	if(cpid == 0){
		/* Results of reads above determine value of privilegedOp */
		if(privilegedOp){
			// seteuid(suid);
			/* Perform privileged operation */
			write(fd2, buf2, strlen(buf2));
			if(fd2>0) close(fd2);  
			// seteuid(ruid);
			return EXIT_SUCCESS;     
		}
	}
	write(fd1, buf1, strlen(buf1));
	if(fd1>0) close(fd1);
	wait(NULL);
	execlp("/bin/date", "/bin/date", (char*) 0);
	return EXIT_SUCCESS;
}