| /* |
| * Copyright (c) International Business Machines Corp., 2001 |
| * 03/2001 Written by Wayne Boyer |
| * 11/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com> |
| * |
| * 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, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /* |
| * Verify that setpriority(2) succeeds set the scheduling priority of |
| * the current process, process group or user. |
| */ |
| |
| #define _GNU_SOURCE |
| #include <errno.h> |
| #include <pwd.h> |
| #include <stdlib.h> |
| #include <sys/resource.h> |
| |
| #include "tst_test.h" |
| |
| static const char *username = "ltp_setpriority01"; |
| static int pid, uid, user_added; |
| |
| static struct tcase { |
| int which; |
| int *who; |
| } tcases[] = { |
| {PRIO_PROCESS, &pid}, |
| {PRIO_PGRP, &pid}, |
| {PRIO_USER, &uid} |
| }; |
| |
| static const char *str_which(int which) |
| { |
| switch (which) { |
| case PRIO_PROCESS: |
| return "PRIO_PROCESS"; |
| case PRIO_PGRP: |
| return "PRIO_PGRP"; |
| case PRIO_USER: |
| return "PRIO_USER"; |
| default: |
| return "???"; |
| } |
| } |
| |
| static void setpriority_test(struct tcase *tc) |
| { |
| int new_prio, cur_prio; |
| int failflag = 0; |
| |
| for (new_prio = -20; new_prio < 20; new_prio++) { |
| TEST(setpriority(tc->which, *tc->who, new_prio)); |
| |
| if (TEST_RETURN != 0) { |
| tst_res(TFAIL | TTERRNO, |
| "setpriority(%d, %d, %d) failed", |
| tc->which, *tc->who, new_prio); |
| failflag = 1; |
| continue; |
| } |
| |
| cur_prio = SAFE_GETPRIORITY(tc->which, *tc->who); |
| |
| if (cur_prio != new_prio) { |
| tst_res(TFAIL, "current priority(%d) and " |
| "new priority(%d) do not match", |
| cur_prio, new_prio); |
| failflag = 1; |
| } |
| } |
| |
| if (!failflag) { |
| tst_res(TPASS, "setpriority(%s(%d), %d, -20..19) succeeded", |
| str_which(tc->which), tc->which, *tc->who); |
| } |
| } |
| |
| static void verify_setpriority(unsigned int n) |
| { |
| struct tcase *tc = &tcases[n]; |
| |
| pid = SAFE_FORK(); |
| if (pid == 0) { |
| SAFE_SETUID(uid); |
| SAFE_SETPGID(0, 0); |
| |
| TST_CHECKPOINT_WAKE_AND_WAIT(0); |
| |
| exit(0); |
| } |
| |
| TST_CHECKPOINT_WAIT(0); |
| |
| setpriority_test(tc); |
| |
| TST_CHECKPOINT_WAKE(0); |
| |
| tst_reap_children(); |
| } |
| |
| static void setup(void) |
| { |
| const char *const cmd_useradd[] = {"useradd", username, NULL}; |
| struct passwd *ltpuser; |
| |
| if (eaccess("/etc/passwd", W_OK)) |
| tst_brk(TCONF, "/etc/passwd is not accessible"); |
| |
| tst_run_cmd(cmd_useradd, NULL, NULL, 0); |
| user_added = 1; |
| |
| ltpuser = SAFE_GETPWNAM(username); |
| uid = ltpuser->pw_uid; |
| } |
| |
| static void cleanup(void) |
| { |
| if (!user_added) |
| return; |
| |
| const char *const cmd_userdel[] = {"userdel", "-r", username, NULL}; |
| |
| if (tst_run_cmd(cmd_userdel, NULL, NULL, 1)) |
| tst_res(TWARN | TERRNO, "'userdel -r %s' failed", username); |
| } |
| |
| static struct tst_test test = { |
| .tcnt = ARRAY_SIZE(tcases), |
| .needs_root = 1, |
| .forks_child = 1, |
| .needs_checkpoints = 1, |
| .setup = setup, |
| .cleanup = cleanup, |
| .test = verify_setpriority, |
| }; |