/*
 * Copyright © 2002  Networks Associates Technology, Inc.
 * All rights reserved.
 *
 * myrerun.c
 * This program uses priv_rerun to print 0 through 5.  Each execution
 * should be as a different user (mail, news, ftp, rpc, nobody).  This
 * program should help demonstrate the use of priv_rerunas(), a less
 * than-obvious Privman method.
 *
 * $Id: myrerun.c,v 1.7 2002/11/01 05:39:58 dougk Exp $
 */

#include "../config.h"

#include "privman.h"

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>

/* Needs to be global so that rerun_fn and main can both see it. */
int state = 0;

void rerun_fn(char * const args[])
{
    /* This function will run before we drop out of priv_init the second
     * through fifth times.  Futz with global state so we can recognize
     * the situation.  args comes from the priv_rerunas call, and is a 
     * null-terminated array of strings.  Don't try and pass pointers via
     * args, it won't work.
     */
    state = atoi(args[0]);
}

int main(void) {
    const char *users[5];
    struct passwd *pw;
    int i = 0;

    while (i < 5 && (pw = getpwent()) != NULL) {
        if (pw->pw_uid > 10) {
	    users[i++] = strdup(pw->pw_name);
	}
    } 
    /* Do this before priv_init so that children can see it. */
    
    priv_init("myrerun");

    /* Nothing up my sleeve... */
    pw = getpwuid(getuid());
    printf("state = %d, uid = %d/%d (%s)\n", state,
		    getuid(), geteuid(), pw->pw_name);
    if (state < 5) {
        char **arg;
        arg = (char**)malloc(sizeof(char *) * 2);
        arg[0] = malloc(5);
        arg[1] = 0;
        /* Create a string to pass the state to the next iteration. */
        snprintf(arg[0], 4, "%d", state + 1);

        /* setuid to user, don't chroot, call rerun_fn(arg) before dropping
         * out of priv_init again.
         */
        if ( priv_rerunas(rerun_fn, arg, users[state], NULL, 0) < 0)
            fprintf(stderr,"priv_rerunas failed.\n");
        _exit(0);
    }

    exit(EXIT_SUCCESS);
}



syntax highlighted by Code2HTML, v. 0.9.1