/*
 *   This program is free software;  you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program;  if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*
 * NAME
 *	so2.c
 *
 * DESCRIPTION
 *	so2 - tests setpriority
 *
 * CALLS
 *	setpriority()
 *
 * RESTRICTIONS
 *	none
 */

#include "test.h"
#include "usctest.h"

#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>

#include <sys/wait.h>

void cleanup(void);
void setup(void);

char *TCID= "dobry_test";
int TST_TOTAL = 1;
extern int Tst_count;


int dotest(int base_priority, int new_priority1, int new_priority2, int setpgid){
    int cpid;
    int pgid = 0;
    int new_priority;
    int user_priority, new_user_priority;
    int group_priority, new_group_priority;
    int process_priority, new_process_priority;
    int ret = 0;
    int ret2;

    if(setpgid)
        pgid = getpgrp();

    TEST(setpriority(PRIO_PGRP, pgid, base_priority));

    if (TEST_RETURN != 0) {
        tst_resm(TFAIL, "call failed - errno = %d - "
                "%s", TEST_ERRNO, strerror(TEST_ERRNO));
        return -1;
    }

    if (STD_FUNCTIONAL_TEST) {
        errno = 0;
        user_priority = getpriority(PRIO_USER, 0);
        if(errno){
            tst_resm(TFAIL, "getpriority failed %d - %s", errno, strerror(errno));
            return -1;
        }

        group_priority = getpriority(PRIO_PGRP, 0);
        if(errno < 0){
            tst_resm(TFAIL, "getpriority failed %d - %s", errno, strerror(errno));
            return -1;
        }

        process_priority = getpriority(PRIO_PROCESS, 0);
        if(errno < 0){
            tst_resm(TFAIL, "getpriority failed %d - %s", errno, strerror(errno));
            return -1;
        }

        if(process_priority != base_priority){
            tst_resm(TFAIL, "process_priority should be %d", base_priority);
            return -1;
        }
        if(group_priority != base_priority){
            tst_resm(TFAIL, "group_priority should be %d", base_priority);
            return -1;
        }
    }

    cpid = fork();
    if(cpid<0){
        tst_resm(TFAIL, "fork failed", errno, strerror(errno));
        return -1;
    }

    setpgrp();

    if(setpgid)
        pgid = getpgrp();

    new_priority = cpid?new_priority1:new_priority2;
    TEST(setpriority(PRIO_PGRP, pgid, new_priority));

    if (TEST_RETURN != 0) {
        tst_resm(TFAIL, "call failed - errno = %d - "
                "%s", TEST_ERRNO, strerror(TEST_ERRNO));
        ret=-1;
        goto out;
    }

    if (STD_FUNCTIONAL_TEST) {
        errno = 0;
        new_user_priority = getpriority(PRIO_USER, 0);
        if(errno){
            tst_resm(TFAIL, "getpriority failed %d - %s", errno, strerror(errno));
            ret=-1;
            goto out;
        }

        new_group_priority = getpriority(PRIO_PGRP, 0);
        if(errno < 0){
            tst_resm(TFAIL, "getpriority failed %d - %s", errno, strerror(errno));
            ret=-1;
            goto out;
        }

        new_process_priority = getpriority(PRIO_PROCESS, 0);
        if(errno < 0){
            tst_resm(TFAIL, "getpriority failed %d - %s", errno, strerror(errno));
            ret=-1;
            goto out;
        }

        if(new_process_priority != new_priority){
            tst_resm(TFAIL, "new_process_priority should be %d", new_priority);
            ret=-1;
            goto out;
        }
        if(new_group_priority != new_priority){
            tst_resm(TFAIL, "new_group_priority should be %d", new_priority);
            ret=-1;
            goto out;
        }
    }

out:
    if(cpid){
        cpid = wait(&ret2);
        if(WEXITSTATUS(ret2))
            ret = -ret2;
        if(cpid<0){
            tst_resm(TFAIL, "wait failed", errno, strerror(errno));
            return -1;
        }
    }else{
        exit(ret);
    }
    return ret;
}


int tests[][3] = {
    /* base, new1, new2 */
    {   0,   0,   0 },
    {   0,   1,   1 },
    {   1,   0,   0 },
    {   0,   1,   2 },
    {   2,   1,   0 },
    {  19,  19,  19 },
    { -20, -20, -20 },
};

int main(int ac, char **av)
{
    int lc;				/* loop counter */
    char *msg;			/* message returned from parse_opts */
    int setpgid;
    int n;

    if (geteuid() != 0) {
        tst_brkm(TBROK, tst_exit, "Test must be run as root");
    }

    /* parse standard options */
    if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){
        tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
    }

    setup();			/* global setup */

    /* The following loop checks looping state if -i option given */

    for (lc = 0; TEST_LOOPING(lc); lc++) {
        /* reset Tst_count in case we are looping */
        Tst_count = 0;

        for(n=0; n<sizeof(tests)/sizeof(tests[0]); n++){
            for(setpgid=0; setpgid<2; setpgid++){
                if(!dotest(tests[n][0], tests[n][1], tests[n][2], setpgid)){
                    if(STD_FUNCTIONAL_TEST){
                        tst_resm(TPASS, "functionality is correct");
                    }else{
                        tst_resm(TPASS, "call succeeded");
                    }
                }
            }
        }

    }

    cleanup();

    /*NOTREACHED*/

    return(0);

}

/*
 * setup() - performs all the ONE TIME setup for this test.
 */
    void
setup(void)
{
    /* capture signals */
    //tst_sig(NOFORK, DEF_HANDLER, cleanup);
    tst_sig(FORK, DEF_HANDLER, cleanup);

    /* Pause if that option was specified */
    TEST_PAUSE;
}

/*
 * cleanup() - performs all the ONE TIME cleanup for this test at completion
 * 	       or premature exit.
 */
    void
cleanup(void)
{
    /*
     * print timing stats if that option was specified.
     * print errno log if that option was specified.
     */
    TEST_CLEANUP;

    /* exit with return code appropriate for results */
    tst_exit();
}



syntax highlighted by Code2HTML, v. 0.9.1