commit: 1413ee0cb60c5ce1bc4cc67c6a24afc3ece9f9e4
parent 9028fdf9b20566fe6836fc72b8b28e4405f5f7b1
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun,  8 Sep 2024 02:16:18 +0200
cmd/renice: new
Diffstat:
| M | cmd/nice.1 | 3 | +++ | 
| A | cmd/renice.1 | 56 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| A | cmd/renice.c | 168 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
3 files changed, 227 insertions(+), 0 deletions(-)
diff --git a/cmd/nice.1 b/cmd/nice.1
@@ -48,6 +48,9 @@ was found but couldn't be invoked.
 .Ar command
 wasn't found.
 .El
+.Sh SEE ALSO
+.Xr renice 1 ,
+.Xr nice 3
 .Sh STANDARDS
 .Nm
 should be compliant with the
diff --git a/cmd/renice.1 b/cmd/renice.1
@@ -0,0 +1,56 @@
+.\" utils-std: Collection of commonly available Unix tools
+.\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+.\" SPDX-License-Identifier: MPL-2.0
+.Dd 2024-09-08
+.Dt RENICE 1
+.Os
+.Sh NAME
+.Nm renice
+.Nd modify scheduling priority of running processes
+.Sh SYNOPSIS
+.Nm
+.Op Fl p
+.Fl n Ar adj
+.Ar PID...
+.Nm
+.Fl g
+.Fl n Ar adj
+.Ar PGID...
+.Nm
+.Fl u
+.Fl n Ar adj
+.Ar UID...
+.Sh DESCRIPTION
+.Nm
+modifies the scheduling priority of running processes.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl g
+Adjust all processes of each given process groups IDs
+.Pq Ar PGID .
+.It Fl n Ar adj
+Positive or negative integer used to adjust the scheduling priority
+of the process relative to it's current priority.
+Negative
+.Ar adj
+may require appropriate privileges.
+.It Fl p
+Adjust each given process IDs
+.Pq Ar PID .
+(default)
+.It Fl u
+Adjust all processes of each given user IDs
+.Pq Ar UID .
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr nice 1 ,
+.Xr setpriority 3
+.Sh STANDARDS
+.Nm
+should be compliant with the
+IEEE Std 1003.1-2024 (“POSIX.1”)
+specification.
+.Sh AUTHORS
+.An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me
diff --git a/cmd/renice.c b/cmd/renice.c
@@ -0,0 +1,168 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#define _POSIX_C_SOURCE 200809L
+#define _XOPEN_SOURCE 700 // getpriority, setpriority
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>        // fprintf
+#include <stdlib.h>       // abort
+#include <string.h>       // strerror
+#include <sys/resource.h> // getpriority, setpriority
+#include <unistd.h>       // getopt, nice
+
+static int
+renice(int which, int who, int adj)
+{
+	const char *which_s = NULL;
+	switch(which)
+	{
+	case PRIO_PROCESS:
+		which_s = "PRIO_PROCESS";
+		break;
+	case PRIO_PGRP:
+		which_s = "PRIO_PGRP";
+		break;
+	case PRIO_USER:
+		which_s = "PRIO_USER";
+		break;
+	default:
+		which_s = NULL;
+	}
+
+	errno = 0;
+	int prio = getpriority(which, who);
+	if(errno != 0)
+	{
+		fprintf(stderr, "renice: getpriority(%s, %d): %s\n", which_s, who, strerror(errno));
+		return -1;
+	}
+
+	prio += adj;
+
+	if(setpriority(which, who, prio) != 0)
+	{
+		fprintf(stderr, "renice: setpriority(%s, %d, %d): %s\n", which_s, who, prio, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "\
+Usage: renice [-p] -n adj PID...\n\
+       renice  -g  -n adj PGID...\n\
+       renice  -u  -n adj UID...\n\
+");
+}
+
+int
+main(int argc, char *argv[])
+{
+	long adj = 0;
+	int which = PRIO_PROCESS;
+
+	int c = -1;
+	while((c = getopt(argc, argv, ":gpun:")) != -1)
+	{
+		switch(c)
+		{
+		case 'g':
+			which = PRIO_PGRP;
+			break;
+		case 'p':
+			which = PRIO_PROCESS;
+			break;
+		case 'u':
+			which = PRIO_USER;
+			break;
+		case 'n':
+			assert(errno == 0);
+			char *endptr = NULL;
+
+			adj = strtol(optarg, &endptr, 10);
+
+			if(endptr && *endptr != 0) errno = EINVAL;
+			if(errno != 0)
+			{
+				fprintf(stderr,
+				        "renice: Error: Failed parsing '%s' as a number: %s\n",
+				        optarg,
+				        strerror(errno));
+				usage();
+				return 1;
+			}
+			if(adj < PRIO_MIN)
+			{
+				fprintf(stderr, "renice: Error: '-n %ld' is lower than PRIO_MIN(%d)\n", adj, PRIO_MIN);
+				return 1;
+			}
+			if(adj > PRIO_MAX)
+			{
+				fprintf(stderr, "renice: Error: '-n %ld' is greater than PRIO_MAX(%d)\n", adj, PRIO_MAX);
+				return 1;
+			}
+			if(adj == 0)
+			{
+				fprintf(stderr, "renice: Error: '-n 0' makes no sense\n");
+				return 1;
+			}
+			break;
+		case ':':
+			fprintf(stderr, "renice: Error: Missing operand for option: '-%c'\n", optopt);
+			usage();
+			return 1;
+		case '?':
+			fprintf(stderr, "renice: Error: Unrecognised option: '-%c'\n", optopt);
+			usage();
+			return 1;
+		default:
+			abort();
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if(argc == 0)
+	{
+		fprintf(stderr, "renice: Error: No IDs passed\n");
+		usage();
+		return 1;
+	}
+
+	if(adj == 0)
+	{
+		fprintf(stderr, "renice: Mandatory option '-n adj' not passed\n");
+		usage();
+		return 1;
+	}
+
+	for(int i = 0; i < argc; i++)
+	{
+		char *endptr = NULL;
+		char *arg = argv[i];
+
+		long who = strtol(arg, &endptr, 0);
+		if(endptr && *endptr != 0) errno = EINVAL;
+
+		if(errno != 0)
+		{
+			fprintf(stderr,
+			        "renice: Error: Failed parsing argument '%s' as a number: %s\n",
+			        arg,
+			        strerror(errno));
+			usage();
+			return 1;
+		}
+
+		renice(which, who, adj);
+	}
+
+	return 0;
+}