+++ /dev/null
-/* vi: set sw=4 ts=4: */
-/*
- * Calendar implementation for busybox
- *
- * See original copyright at the end of this file
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
- *
- * Major size reduction... over 50% (>1.5k) on i386.
- */
-//config:config CAL
-//config: bool "cal"
-//config: default y
-//config: help
-//config: cal is used to display a monthly calendar.
-
-//applet:IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP))
-
-//kbuild:lib-$(CONFIG_CAL) += cal.o
-
-/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */
-/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect. The upstream
- * BB_AUDIT BUG: version in util-linux seems to be broken as well. */
-/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */
-
-//usage:#define cal_trivial_usage
-//usage: "[-jy] [[MONTH] YEAR]"
-//usage:#define cal_full_usage "\n\n"
-//usage: "Display a calendar\n"
-//usage: "\n -j Use julian dates"
-//usage: "\n -y Display the entire year"
-
-#include "libbb.h"
-#include "unicode.h"
-
-/* We often use "unsigned" intead of "int", it's easier to div on most CPUs */
-
-#define THURSDAY 4 /* for reformation */
-#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
-
-#define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */
-#define NUMBER_MISSING_DAYS 11 /* 11 day correction */
-
-#define MAXDAYS 42 /* max slots in a month array */
-#define SPACE -1 /* used in day array */
-
-static const unsigned char days_in_month[] ALIGN1 = {
- 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-static const unsigned char sep1752[] ALIGN1 = {
- 1, 2, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30
-};
-
-/* Set to 0 or 1 in main */
-#define julian ((unsigned)option_mask32)
-
-/* leap year -- account for Gregorian reformation in 1752 */
-static int leap_year(unsigned yr)
-{
- if (yr <= 1752)
- return !(yr % 4);
- return (!(yr % 4) && (yr % 100)) || !(yr % 400);
-}
-
-/* number of centuries since 1700, not inclusive */
-#define centuries_since_1700(yr) \
- ((yr) > 1700 ? (yr) / 100 - 17 : 0)
-
-/* number of centuries since 1700 whose modulo of 400 is 0 */
-#define quad_centuries_since_1700(yr) \
- ((yr) > 1600 ? ((yr) - 1600) / 400 : 0)
-
-/* number of leap years between year 1 and this year, not inclusive */
-#define leap_years_since_year_1(yr) \
- ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
-
-static void center(char *, unsigned, unsigned);
-static void day_array(unsigned, unsigned, unsigned *);
-static void trim_trailing_spaces_and_print(char *);
-
-static void blank_string(char *buf, size_t buflen);
-static char *build_row(char *p, unsigned *dp);
-
-#define DAY_LEN 3 /* 3 spaces per day */
-#define J_DAY_LEN (DAY_LEN + 1)
-#define WEEK_LEN 20 /* 7 * 3 - one space at the end */
-#define J_WEEK_LEN (WEEK_LEN + 7)
-#define HEAD_SEP 2 /* spaces between day headings */
-
-int cal_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int cal_main(int argc UNUSED_PARAM, char **argv)
-{
- struct tm zero_tm;
- time_t now;
- unsigned month, year, flags, i;
- char *month_names[12];
- /* normal heading: */
- /* "Su Mo Tu We Th Fr Sa" */
- /* -j heading: */
- /* " Su Mo Tu We Th Fr Sa" */
- char day_headings[ENABLE_UNICODE_SUPPORT ? 28 * 6 : 28];
- IF_UNICODE_SUPPORT(char *hp = day_headings;)
- char buf[40];
-
- init_unicode();
-
- flags = getopt32(argv, "jy");
- /* This sets julian = flags & 1: */
- option_mask32 &= 1;
- month = 0;
- argv += optind;
-
- if (!argv[0]) {
- struct tm *ptm;
-
- time(&now);
- ptm = localtime(&now);
- year = ptm->tm_year + 1900;
- if (!(flags & 2)) { /* no -y */
- month = ptm->tm_mon + 1;
- }
- } else {
- if (argv[1]) {
- if (argv[2]) {
- bb_show_usage();
- }
- if (!(flags & 2)) { /* no -y */
- month = xatou_range(*argv, 1, 12);
- }
- argv++;
- }
- year = xatou_range(*argv, 1, 9999);
- }
-
- blank_string(day_headings, sizeof(day_headings) - 7 + 7*julian);
-
- i = 0;
- do {
- zero_tm.tm_mon = i;
- /* full month name according to locale */
- strftime(buf, sizeof(buf), "%B", &zero_tm);
- month_names[i] = xstrdup(buf);
-
- if (i < 7) {
- zero_tm.tm_wday = i;
- /* abbreviated weekday name according to locale */
- strftime(buf, sizeof(buf), "%a", &zero_tm);
-#if ENABLE_UNICODE_SUPPORT
- if (julian)
- *hp++ = ' ';
- {
- char *two_wchars = unicode_conv_to_printable_fixedwidth(/*NULL,*/ buf, 2);
- strcpy(hp, two_wchars);
- free(two_wchars);
- }
- hp += strlen(hp);
- *hp++ = ' ';
-#else
- strncpy(day_headings + i * (3+julian) + julian, buf, 2);
-#endif
- }
- } while (++i < 12);
- IF_UNICODE_SUPPORT(hp[-1] = '\0';)
-
- if (month) {
- unsigned row, len, days[MAXDAYS];
- unsigned *dp = days;
- char lineout[30];
-
- day_array(month, year, dp);
- len = sprintf(lineout, "%s %u", month_names[month - 1], year);
- printf("%*s%s\n%s\n",
- ((7*julian + WEEK_LEN) - len) / 2, "",
- lineout, day_headings);
- for (row = 0; row < 6; row++) {
- build_row(lineout, dp)[0] = '\0';
- dp += 7;
- trim_trailing_spaces_and_print(lineout);
- }
- } else {
- unsigned row, which_cal, week_len, days[12][MAXDAYS];
- unsigned *dp;
- char lineout[80];
-
- sprintf(lineout, "%u", year);
- center(lineout,
- (WEEK_LEN * 3 + HEAD_SEP * 2)
- + julian * (J_WEEK_LEN * 2 + HEAD_SEP
- - (WEEK_LEN * 3 + HEAD_SEP * 2)),
- 0
- );
- puts("\n"); /* two \n's */
- for (i = 0; i < 12; i++) {
- day_array(i + 1, year, days[i]);
- }
- blank_string(lineout, sizeof(lineout));
- week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN);
- for (month = 0; month < 12; month += 3-julian) {
- center(month_names[month], week_len, HEAD_SEP);
- if (!julian) {
- center(month_names[month + 1], week_len, HEAD_SEP);
- }
- center(month_names[month + 2 - julian], week_len, 0);
- printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings);
- if (!julian) {
- printf("%*s%s", HEAD_SEP, "", day_headings);
- }
- bb_putchar('\n');
- for (row = 0; row < (6*7); row += 7) {
- for (which_cal = 0; which_cal < 3-julian; which_cal++) {
- dp = days[month + which_cal] + row;
- build_row(lineout + which_cal * (week_len + 2), dp);
- }
- /* blank_string took care of nul termination. */
- trim_trailing_spaces_and_print(lineout);
- }
- }
- }
-
- fflush_stdout_and_exit(EXIT_SUCCESS);
-}
-
-/*
- * day_array --
- * Fill in an array of 42 integers with a calendar. Assume for a moment
- * that you took the (maximum) 6 rows in a calendar and stretched them
- * out end to end. You would have 42 numbers or spaces. This routine
- * builds that array for any month from Jan. 1 through Dec. 9999.
- */
-static void day_array(unsigned month, unsigned year, unsigned *days)
-{
- unsigned long temp;
- unsigned i;
- unsigned day, dw, dm;
-
- memset(days, SPACE, MAXDAYS * sizeof(int));
-
- if ((month == 9) && (year == 1752)) {
- /* Assumes the Gregorian reformation eliminates
- * 3 Sep. 1752 through 13 Sep. 1752.
- */
- unsigned j_offset = julian * 244;
- size_t oday = 0;
-
- do {
- days[oday+2] = sep1752[oday] + j_offset;
- } while (++oday < sizeof(sep1752));
-
- return;
- }
-
- /* day_in_year
- * return the 1 based day number within the year
- */
- day = 1;
- if ((month > 2) && leap_year(year)) {
- ++day;
- }
-
- i = month;
- while (i) {
- day += days_in_month[--i];
- }
-
- /* day_in_week
- * return the 0 based day number for any date from 1 Jan. 1 to
- * 31 Dec. 9999. Assumes the Gregorian reformation eliminates
- * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
- * missing days.
- */
- temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) + day;
- if (temp < FIRST_MISSING_DAY) {
- dw = ((temp - 1 + SATURDAY) % 7);
- } else {
- dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
- }
-
- if (!julian) {
- day = 1;
- }
-
- dm = days_in_month[month];
- if ((month == 2) && leap_year(year)) {
- ++dm;
- }
-
- do {
- days[dw++] = day++;
- } while (--dm);
-}
-
-static void trim_trailing_spaces_and_print(char *s)
-{
- char *p = s;
-
- while (*p) {
- ++p;
- }
- while (p != s) {
- --p;
- if (!isspace(*p)) {
- p[1] = '\0';
- break;
- }
- }
-
- puts(s);
-}
-
-static void center(char *str, unsigned len, unsigned separate)
-{
- unsigned n = strlen(str);
- len -= n;
- printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, "");
-}
-
-static void blank_string(char *buf, size_t buflen)
-{
- memset(buf, ' ', buflen);
- buf[buflen-1] = '\0';
-}
-
-static char *build_row(char *p, unsigned *dp)
-{
- unsigned col, val, day;
-
- memset(p, ' ', (julian + DAY_LEN) * 7);
-
- col = 0;
- do {
- day = *dp++;
- if (day != SPACE) {
- if (julian) {
- ++p;
- if (day >= 100) {
- *p = '0';
- p[-1] = (day / 100) + '0';
- day %= 100;
- }
- }
- val = day / 10;
- if (val > 0) {
- *p = val + '0';
- }
- *++p = day % 10 + '0';
- p += 2;
- } else {
- p += DAY_LEN + julian;
- }
- } while (++col < 7);
-
- return p;
-}
-
-/*
- * Copyright (c) 1989, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kim Letkeman.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
--- /dev/null
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mktemp implementation for busybox
+ *
+ *
+ * Copyright (C) 2000 by Daniel Jacobowitz
+ * Written by Daniel Jacobowitz <dan@debian.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+/* Coreutils 6.12 man page says:
+ * mktemp [OPTION]... [TEMPLATE]
+ * Create a temporary file or directory, safely, and print its name. If
+ * TEMPLATE is not specified, use tmp.XXXXXXXXXX.
+ * -d, --directory
+ * create a directory, not a file
+ * -q, --quiet
+ * suppress diagnostics about file/dir-creation failure
+ * -u, --dry-run
+ * do not create anything; merely print a name (unsafe)
+ * --tmpdir[=DIR]
+ * interpret TEMPLATE relative to DIR. If DIR is not specified,
+ * use $TMPDIR if set, else /tmp. With this option, TEMPLATE must
+ * not be an absolute name. Unlike with -t, TEMPLATE may contain
+ * slashes, but even here, mktemp still creates only the final com-
+ * ponent.
+ * -p DIR use DIR as a prefix; implies -t [deprecated]
+ * -t interpret TEMPLATE as a single file name component, relative to
+ * a directory: $TMPDIR, if set; else the directory specified via
+ * -p; else /tmp [deprecated]
+ */
+//config:config MKTEMP
+//config: bool "mktemp"
+//config: default y
+//config: help
+//config: mktemp is used to create unique temporary files
+
+//applet:IF_MKTEMP(APPLET(mktemp, BB_DIR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
+
+//usage:#define mktemp_trivial_usage
+//usage: "[-dt] [-p DIR] [TEMPLATE]"
+//usage:#define mktemp_full_usage "\n\n"
+//usage: "Create a temporary file with name based on TEMPLATE and print its name.\n"
+//usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n"
+//usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n"
+//usage: "\n -d Make directory, not file"
+//usage: "\n -q Fail silently on errors"
+//usage: "\n -t Prepend base directory name to TEMPLATE"
+//usage: "\n -p DIR Use DIR as a base directory (implies -t)"
+//usage: "\n -u Do not create anything; print a name"
+//usage: "\n"
+//usage: "\nBase directory is: -p DIR, else $TMPDIR, else /tmp"
+//usage:
+//usage:#define mktemp_example_usage
+//usage: "$ mktemp /tmp/temp.XXXXXX\n"
+//usage: "/tmp/temp.mWiLjM\n"
+//usage: "$ ls -la /tmp/temp.mWiLjM\n"
+//usage: "-rw------- 1 andersen andersen 0 Apr 25 17:10 /tmp/temp.mWiLjM\n"
+
+#include "libbb.h"
+
+int mktemp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int mktemp_main(int argc UNUSED_PARAM, char **argv)
+{
+ const char *path;
+ char *chp;
+ unsigned opts;
+ enum {
+ OPT_d = 1 << 0,
+ OPT_q = 1 << 1,
+ OPT_t = 1 << 2,
+ OPT_p = 1 << 3,
+ OPT_u = 1 << 4,
+ };
+
+ path = getenv("TMPDIR");
+ if (!path || path[0] == '\0')
+ path = "/tmp";
+
+ opt_complementary = "?1"; /* 1 argument max */
+ opts = getopt32(argv, "dqtp:u", &path);
+
+ chp = argv[optind];
+ if (!chp) {
+ /* GNU coreutils 8.4:
+ * bare "mktemp" -> "mktemp -t tmp.XXXXXX"
+ */
+ chp = xstrdup("tmp.XXXXXX");
+ opts |= OPT_t;
+ }
+#if 0
+ /* Don't allow directory separator in template */
+ if ((opts & OPT_t) && bb_basename(chp) != chp) {
+ errno = EINVAL;
+ goto error;
+ }
+#endif
+ if (opts & (OPT_t|OPT_p))
+ chp = concat_path_file(path, chp);
+
+ if (opts & OPT_u) {
+ chp = mktemp(chp);
+ if (chp[0] == '\0')
+ goto error;
+ } else if (opts & OPT_d) {
+ if (mkdtemp(chp) == NULL)
+ goto error;
+ } else {
+ if (mkstemp(chp) < 0)
+ goto error;
+ }
+ puts(chp);
+ return EXIT_SUCCESS;
+ error:
+ if (opts & OPT_q)
+ return EXIT_FAILURE;
+ /* don't use chp as it gets mangled in case of error */
+ bb_perror_nomsg_and_die();
+}
+++ /dev/null
-/* vi: set sw=4 ts=4: */
-/*
- * Mini mktemp implementation for busybox
- *
- *
- * Copyright (C) 2000 by Daniel Jacobowitz
- * Written by Daniel Jacobowitz <dan@debian.org>
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-/* Coreutils 6.12 man page says:
- * mktemp [OPTION]... [TEMPLATE]
- * Create a temporary file or directory, safely, and print its name. If
- * TEMPLATE is not specified, use tmp.XXXXXXXXXX.
- * -d, --directory
- * create a directory, not a file
- * -q, --quiet
- * suppress diagnostics about file/dir-creation failure
- * -u, --dry-run
- * do not create anything; merely print a name (unsafe)
- * --tmpdir[=DIR]
- * interpret TEMPLATE relative to DIR. If DIR is not specified,
- * use $TMPDIR if set, else /tmp. With this option, TEMPLATE must
- * not be an absolute name. Unlike with -t, TEMPLATE may contain
- * slashes, but even here, mktemp still creates only the final com-
- * ponent.
- * -p DIR use DIR as a prefix; implies -t [deprecated]
- * -t interpret TEMPLATE as a single file name component, relative to
- * a directory: $TMPDIR, if set; else the directory specified via
- * -p; else /tmp [deprecated]
- */
-//config:config MKTEMP
-//config: bool "mktemp"
-//config: default y
-//config: help
-//config: mktemp is used to create unique temporary files
-
-//applet:IF_MKTEMP(APPLET(mktemp, BB_DIR_BIN, BB_SUID_DROP))
-
-//kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
-
-//usage:#define mktemp_trivial_usage
-//usage: "[-dt] [-p DIR] [TEMPLATE]"
-//usage:#define mktemp_full_usage "\n\n"
-//usage: "Create a temporary file with name based on TEMPLATE and print its name.\n"
-//usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n"
-//usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n"
-//usage: "\n -d Make directory, not file"
-//usage: "\n -q Fail silently on errors"
-//usage: "\n -t Prepend base directory name to TEMPLATE"
-//usage: "\n -p DIR Use DIR as a base directory (implies -t)"
-//usage: "\n -u Do not create anything; print a name"
-//usage: "\n"
-//usage: "\nBase directory is: -p DIR, else $TMPDIR, else /tmp"
-//usage:
-//usage:#define mktemp_example_usage
-//usage: "$ mktemp /tmp/temp.XXXXXX\n"
-//usage: "/tmp/temp.mWiLjM\n"
-//usage: "$ ls -la /tmp/temp.mWiLjM\n"
-//usage: "-rw------- 1 andersen andersen 0 Apr 25 17:10 /tmp/temp.mWiLjM\n"
-
-#include "libbb.h"
-
-int mktemp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int mktemp_main(int argc UNUSED_PARAM, char **argv)
-{
- const char *path;
- char *chp;
- unsigned opts;
- enum {
- OPT_d = 1 << 0,
- OPT_q = 1 << 1,
- OPT_t = 1 << 2,
- OPT_p = 1 << 3,
- OPT_u = 1 << 4,
- };
-
- path = getenv("TMPDIR");
- if (!path || path[0] == '\0')
- path = "/tmp";
-
- opt_complementary = "?1"; /* 1 argument max */
- opts = getopt32(argv, "dqtp:u", &path);
-
- chp = argv[optind];
- if (!chp) {
- /* GNU coreutils 8.4:
- * bare "mktemp" -> "mktemp -t tmp.XXXXXX"
- */
- chp = xstrdup("tmp.XXXXXX");
- opts |= OPT_t;
- }
-#if 0
- /* Don't allow directory separator in template */
- if ((opts & OPT_t) && bb_basename(chp) != chp) {
- errno = EINVAL;
- goto error;
- }
-#endif
- if (opts & (OPT_t|OPT_p))
- chp = concat_path_file(path, chp);
-
- if (opts & OPT_u) {
- chp = mktemp(chp);
- if (chp[0] == '\0')
- goto error;
- } else if (opts & OPT_d) {
- if (mkdtemp(chp) == NULL)
- goto error;
- } else {
- if (mkstemp(chp) < 0)
- goto error;
- }
- puts(chp);
- return EXIT_SUCCESS;
- error:
- if (opts & OPT_q)
- return EXIT_FAILURE;
- /* don't use chp as it gets mangled in case of error */
- bb_perror_nomsg_and_die();
-}
+++ /dev/null
-/* vi: set sw=4 ts=4: */
-/*
- * mesg implementation for busybox
- *
- * Copyright (c) 2002 Manuel Novoa III <mjn3@codepoet.org>
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-//config:config MESG
-//config: bool "mesg"
-//config: default y
-//config: help
-//config: Mesg controls access to your terminal by others. It is typically
-//config: used to allow or disallow other users to write to your terminal
-//config:
-//config:config FEATURE_MESG_ENABLE_ONLY_GROUP
-//config: bool "Enable writing to tty only by group, not by everybody"
-//config: default y
-//config: depends on MESG
-//config: help
-//config: Usually, ttys are owned by group "tty", and "write" tool is
-//config: setgid to this group. This way, "mesg y" only needs to enable
-//config: "write by owning group" bit in tty mode.
-//config:
-//config: If you set this option to N, "mesg y" will enable writing
-//config: by anybody at all. This is not recommended.
-
-//applet:IF_MESG(APPLET(mesg, BB_DIR_USR_BIN, BB_SUID_DROP))
-
-//kbuild:lib-$(CONFIG_MESG) += mesg.o
-
-//usage:#define mesg_trivial_usage
-//usage: "[y|n]"
-//usage:#define mesg_full_usage "\n\n"
-//usage: "Control write access to your terminal\n"
-//usage: " y Allow write access to your terminal\n"
-//usage: " n Disallow write access to your terminal"
-
-#include "libbb.h"
-
-#if ENABLE_FEATURE_MESG_ENABLE_ONLY_GROUP
-#define S_IWGRP_OR_S_IWOTH S_IWGRP
-#else
-#define S_IWGRP_OR_S_IWOTH (S_IWGRP | S_IWOTH)
-#endif
-
-int mesg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int mesg_main(int argc UNUSED_PARAM, char **argv)
-{
- struct stat sb;
- mode_t m;
- char c = 0;
-
- argv++;
-
- if (argv[0]
- && (argv[1] || ((c = argv[0][0]) != 'y' && c != 'n'))
- ) {
- bb_show_usage();
- }
-
- if (!isatty(STDIN_FILENO))
- bb_error_msg_and_die("not a tty");
-
- xfstat(STDIN_FILENO, &sb, "stderr");
- if (c == 0) {
- puts((sb.st_mode & (S_IWGRP|S_IWOTH)) ? "is y" : "is n");
- return EXIT_SUCCESS;
- }
- m = (c == 'y') ? sb.st_mode | S_IWGRP_OR_S_IWOTH
- : sb.st_mode & ~(S_IWGRP|S_IWOTH);
- if (fchmod(STDIN_FILENO, m) != 0)
- bb_perror_nomsg_and_die();
- return EXIT_SUCCESS;
-}
+++ /dev/null
-/* vi: set sw=4 ts=4: */
-/*
- * renice implementation for busybox
- *
- * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org>
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
-
-/* Notes:
- * Setting an absolute priority was obsoleted in SUSv2 and removed
- * in SUSv3. However, the common linux version of renice does
- * absolute and not relative. So we'll continue supporting absolute,
- * although the stdout logging has been removed since both SUSv2 and
- * SUSv3 specify that stdout isn't used.
- *
- * This version is lenient in that it doesn't require any IDs. The
- * options -p, -g, and -u are treated as mode switches for the
- * following IDs (if any). Multiple switches are allowed.
- */
-//config:config RENICE
-//config: bool "renice"
-//config: default y
-//config: help
-//config: Renice alters the scheduling priority of one or more running
-//config: processes.
-
-//applet:IF_RENICE(APPLET(renice, BB_DIR_USR_BIN, BB_SUID_DROP))
-
-//kbuild:lib-$(CONFIG_RENICE) += renice.o
-
-//usage:#define renice_trivial_usage
-//usage: "[-n] PRIORITY [[-p | -g | -u] ID...]..."
-//usage:#define renice_full_usage "\n\n"
-//usage: "Change scheduling priority of a running process\n"
-//usage: "\n -n Add PRIORITY to current nice value"
-//usage: "\n Without -n, nice value is set to PRIORITY"
-//usage: "\n -p Process ids (default)"
-//usage: "\n -g Process group ids"
-//usage: "\n -u Process user names"
-
-#include "libbb.h"
-#include <sys/resource.h>
-
-void BUG_bad_PRIO_PROCESS(void);
-void BUG_bad_PRIO_PGRP(void);
-void BUG_bad_PRIO_USER(void);
-
-int renice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int renice_main(int argc UNUSED_PARAM, char **argv)
-{
- static const char Xetpriority_msg[] ALIGN1 = "%cetpriority";
-
- int retval = EXIT_SUCCESS;
- int which = PRIO_PROCESS; /* Default 'which' value. */
- int use_relative = 0;
- int adjustment, new_priority;
- unsigned who;
- char *arg;
-
- /* Yes, they are not #defines in glibc 2.4! #if won't work */
- if (PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX)
- BUG_bad_PRIO_PROCESS();
- if (PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX)
- BUG_bad_PRIO_PGRP();
- if (PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX)
- BUG_bad_PRIO_USER();
-
- arg = *++argv;
-
- /* Check if we are using a relative adjustment. */
- if (arg && arg[0] == '-' && arg[1] == 'n') {
- use_relative = 1;
- if (!arg[2])
- arg = *++argv;
- else
- arg += 2;
- }
-
- if (!arg) { /* No args? Then show usage. */
- bb_show_usage();
- }
-
- /* Get the priority adjustment (absolute or relative). */
- adjustment = xatoi_range(arg, INT_MIN/2, INT_MAX/2);
-
- while ((arg = *++argv) != NULL) {
- /* Check for a mode switch. */
- if (arg[0] == '-' && arg[1]) {
- static const char opts[] ALIGN1 = {
- 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER
- };
- const char *p = strchr(opts, arg[1]);
- if (p) {
- which = p[4];
- if (!arg[2])
- continue;
- arg += 2;
- }
- }
-
- /* Process an ID arg. */
- if (which == PRIO_USER) {
- struct passwd *p;
- p = getpwnam(arg);
- if (!p) {
- bb_error_msg("unknown user %s", arg);
- goto HAD_ERROR;
- }
- who = p->pw_uid;
- } else {
- who = bb_strtou(arg, NULL, 10);
- if (errno) {
- bb_error_msg("invalid number '%s'", arg);
- goto HAD_ERROR;
- }
- }
-
- /* Get priority to use, and set it. */
- if (use_relative) {
- int old_priority;
-
- errno = 0; /* Needed for getpriority error detection. */
- old_priority = getpriority(which, who);
- if (errno) {
- bb_perror_msg(Xetpriority_msg, 'g');
- goto HAD_ERROR;
- }
-
- new_priority = old_priority + adjustment;
- } else {
- new_priority = adjustment;
- }
-
- if (setpriority(which, who, new_priority) == 0) {
- continue;
- }
-
- bb_perror_msg(Xetpriority_msg, 's');
- HAD_ERROR:
- retval = EXIT_FAILURE;
- }
-
- /* No need to check for errors outputing to stderr since, if it
- * was used, the HAD_ERROR label was reached and retval was set. */
-
- return retval;
-}
--- /dev/null
+/* vi: set sw=4 ts=4: */
+/*
+ * Calendar implementation for busybox
+ *
+ * See original copyright at the end of this file
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Major size reduction... over 50% (>1.5k) on i386.
+ */
+//config:config CAL
+//config: bool "cal"
+//config: default y
+//config: help
+//config: cal is used to display a monthly calendar.
+
+//applet:IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_CAL) += cal.o
+
+/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */
+/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect. The upstream
+ * BB_AUDIT BUG: version in util-linux seems to be broken as well. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */
+
+//usage:#define cal_trivial_usage
+//usage: "[-jy] [[MONTH] YEAR]"
+//usage:#define cal_full_usage "\n\n"
+//usage: "Display a calendar\n"
+//usage: "\n -j Use julian dates"
+//usage: "\n -y Display the entire year"
+
+#include "libbb.h"
+#include "unicode.h"
+
+/* We often use "unsigned" intead of "int", it's easier to div on most CPUs */
+
+#define THURSDAY 4 /* for reformation */
+#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
+
+#define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */
+#define NUMBER_MISSING_DAYS 11 /* 11 day correction */
+
+#define MAXDAYS 42 /* max slots in a month array */
+#define SPACE -1 /* used in day array */
+
+static const unsigned char days_in_month[] ALIGN1 = {
+ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static const unsigned char sep1752[] ALIGN1 = {
+ 1, 2, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30
+};
+
+/* Set to 0 or 1 in main */
+#define julian ((unsigned)option_mask32)
+
+/* leap year -- account for Gregorian reformation in 1752 */
+static int leap_year(unsigned yr)
+{
+ if (yr <= 1752)
+ return !(yr % 4);
+ return (!(yr % 4) && (yr % 100)) || !(yr % 400);
+}
+
+/* number of centuries since 1700, not inclusive */
+#define centuries_since_1700(yr) \
+ ((yr) > 1700 ? (yr) / 100 - 17 : 0)
+
+/* number of centuries since 1700 whose modulo of 400 is 0 */
+#define quad_centuries_since_1700(yr) \
+ ((yr) > 1600 ? ((yr) - 1600) / 400 : 0)
+
+/* number of leap years between year 1 and this year, not inclusive */
+#define leap_years_since_year_1(yr) \
+ ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
+
+static void center(char *, unsigned, unsigned);
+static void day_array(unsigned, unsigned, unsigned *);
+static void trim_trailing_spaces_and_print(char *);
+
+static void blank_string(char *buf, size_t buflen);
+static char *build_row(char *p, unsigned *dp);
+
+#define DAY_LEN 3 /* 3 spaces per day */
+#define J_DAY_LEN (DAY_LEN + 1)
+#define WEEK_LEN 20 /* 7 * 3 - one space at the end */
+#define J_WEEK_LEN (WEEK_LEN + 7)
+#define HEAD_SEP 2 /* spaces between day headings */
+
+int cal_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int cal_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct tm zero_tm;
+ time_t now;
+ unsigned month, year, flags, i;
+ char *month_names[12];
+ /* normal heading: */
+ /* "Su Mo Tu We Th Fr Sa" */
+ /* -j heading: */
+ /* " Su Mo Tu We Th Fr Sa" */
+ char day_headings[ENABLE_UNICODE_SUPPORT ? 28 * 6 : 28];
+ IF_UNICODE_SUPPORT(char *hp = day_headings;)
+ char buf[40];
+
+ init_unicode();
+
+ flags = getopt32(argv, "jy");
+ /* This sets julian = flags & 1: */
+ option_mask32 &= 1;
+ month = 0;
+ argv += optind;
+
+ if (!argv[0]) {
+ struct tm *ptm;
+
+ time(&now);
+ ptm = localtime(&now);
+ year = ptm->tm_year + 1900;
+ if (!(flags & 2)) { /* no -y */
+ month = ptm->tm_mon + 1;
+ }
+ } else {
+ if (argv[1]) {
+ if (argv[2]) {
+ bb_show_usage();
+ }
+ if (!(flags & 2)) { /* no -y */
+ month = xatou_range(*argv, 1, 12);
+ }
+ argv++;
+ }
+ year = xatou_range(*argv, 1, 9999);
+ }
+
+ blank_string(day_headings, sizeof(day_headings) - 7 + 7*julian);
+
+ i = 0;
+ do {
+ zero_tm.tm_mon = i;
+ /* full month name according to locale */
+ strftime(buf, sizeof(buf), "%B", &zero_tm);
+ month_names[i] = xstrdup(buf);
+
+ if (i < 7) {
+ zero_tm.tm_wday = i;
+ /* abbreviated weekday name according to locale */
+ strftime(buf, sizeof(buf), "%a", &zero_tm);
+#if ENABLE_UNICODE_SUPPORT
+ if (julian)
+ *hp++ = ' ';
+ {
+ char *two_wchars = unicode_conv_to_printable_fixedwidth(/*NULL,*/ buf, 2);
+ strcpy(hp, two_wchars);
+ free(two_wchars);
+ }
+ hp += strlen(hp);
+ *hp++ = ' ';
+#else
+ strncpy(day_headings + i * (3+julian) + julian, buf, 2);
+#endif
+ }
+ } while (++i < 12);
+ IF_UNICODE_SUPPORT(hp[-1] = '\0';)
+
+ if (month) {
+ unsigned row, len, days[MAXDAYS];
+ unsigned *dp = days;
+ char lineout[30];
+
+ day_array(month, year, dp);
+ len = sprintf(lineout, "%s %u", month_names[month - 1], year);
+ printf("%*s%s\n%s\n",
+ ((7*julian + WEEK_LEN) - len) / 2, "",
+ lineout, day_headings);
+ for (row = 0; row < 6; row++) {
+ build_row(lineout, dp)[0] = '\0';
+ dp += 7;
+ trim_trailing_spaces_and_print(lineout);
+ }
+ } else {
+ unsigned row, which_cal, week_len, days[12][MAXDAYS];
+ unsigned *dp;
+ char lineout[80];
+
+ sprintf(lineout, "%u", year);
+ center(lineout,
+ (WEEK_LEN * 3 + HEAD_SEP * 2)
+ + julian * (J_WEEK_LEN * 2 + HEAD_SEP
+ - (WEEK_LEN * 3 + HEAD_SEP * 2)),
+ 0
+ );
+ puts("\n"); /* two \n's */
+ for (i = 0; i < 12; i++) {
+ day_array(i + 1, year, days[i]);
+ }
+ blank_string(lineout, sizeof(lineout));
+ week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN);
+ for (month = 0; month < 12; month += 3-julian) {
+ center(month_names[month], week_len, HEAD_SEP);
+ if (!julian) {
+ center(month_names[month + 1], week_len, HEAD_SEP);
+ }
+ center(month_names[month + 2 - julian], week_len, 0);
+ printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings);
+ if (!julian) {
+ printf("%*s%s", HEAD_SEP, "", day_headings);
+ }
+ bb_putchar('\n');
+ for (row = 0; row < (6*7); row += 7) {
+ for (which_cal = 0; which_cal < 3-julian; which_cal++) {
+ dp = days[month + which_cal] + row;
+ build_row(lineout + which_cal * (week_len + 2), dp);
+ }
+ /* blank_string took care of nul termination. */
+ trim_trailing_spaces_and_print(lineout);
+ }
+ }
+ }
+
+ fflush_stdout_and_exit(EXIT_SUCCESS);
+}
+
+/*
+ * day_array --
+ * Fill in an array of 42 integers with a calendar. Assume for a moment
+ * that you took the (maximum) 6 rows in a calendar and stretched them
+ * out end to end. You would have 42 numbers or spaces. This routine
+ * builds that array for any month from Jan. 1 through Dec. 9999.
+ */
+static void day_array(unsigned month, unsigned year, unsigned *days)
+{
+ unsigned long temp;
+ unsigned i;
+ unsigned day, dw, dm;
+
+ memset(days, SPACE, MAXDAYS * sizeof(int));
+
+ if ((month == 9) && (year == 1752)) {
+ /* Assumes the Gregorian reformation eliminates
+ * 3 Sep. 1752 through 13 Sep. 1752.
+ */
+ unsigned j_offset = julian * 244;
+ size_t oday = 0;
+
+ do {
+ days[oday+2] = sep1752[oday] + j_offset;
+ } while (++oday < sizeof(sep1752));
+
+ return;
+ }
+
+ /* day_in_year
+ * return the 1 based day number within the year
+ */
+ day = 1;
+ if ((month > 2) && leap_year(year)) {
+ ++day;
+ }
+
+ i = month;
+ while (i) {
+ day += days_in_month[--i];
+ }
+
+ /* day_in_week
+ * return the 0 based day number for any date from 1 Jan. 1 to
+ * 31 Dec. 9999. Assumes the Gregorian reformation eliminates
+ * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
+ * missing days.
+ */
+ temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) + day;
+ if (temp < FIRST_MISSING_DAY) {
+ dw = ((temp - 1 + SATURDAY) % 7);
+ } else {
+ dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
+ }
+
+ if (!julian) {
+ day = 1;
+ }
+
+ dm = days_in_month[month];
+ if ((month == 2) && leap_year(year)) {
+ ++dm;
+ }
+
+ do {
+ days[dw++] = day++;
+ } while (--dm);
+}
+
+static void trim_trailing_spaces_and_print(char *s)
+{
+ char *p = s;
+
+ while (*p) {
+ ++p;
+ }
+ while (p != s) {
+ --p;
+ if (!isspace(*p)) {
+ p[1] = '\0';
+ break;
+ }
+ }
+
+ puts(s);
+}
+
+static void center(char *str, unsigned len, unsigned separate)
+{
+ unsigned n = strlen(str);
+ len -= n;
+ printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, "");
+}
+
+static void blank_string(char *buf, size_t buflen)
+{
+ memset(buf, ' ', buflen);
+ buf[buflen-1] = '\0';
+}
+
+static char *build_row(char *p, unsigned *dp)
+{
+ unsigned col, val, day;
+
+ memset(p, ' ', (julian + DAY_LEN) * 7);
+
+ col = 0;
+ do {
+ day = *dp++;
+ if (day != SPACE) {
+ if (julian) {
+ ++p;
+ if (day >= 100) {
+ *p = '0';
+ p[-1] = (day / 100) + '0';
+ day %= 100;
+ }
+ }
+ val = day / 10;
+ if (val > 0) {
+ *p = val + '0';
+ }
+ *++p = day % 10 + '0';
+ p += 2;
+ } else {
+ p += DAY_LEN + julian;
+ }
+ } while (++col < 7);
+
+ return p;
+}
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kim Letkeman.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
--- /dev/null
+/* vi: set sw=4 ts=4: */
+/*
+ * mesg implementation for busybox
+ *
+ * Copyright (c) 2002 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config MESG
+//config: bool "mesg"
+//config: default y
+//config: help
+//config: Mesg controls access to your terminal by others. It is typically
+//config: used to allow or disallow other users to write to your terminal
+//config:
+//config:config FEATURE_MESG_ENABLE_ONLY_GROUP
+//config: bool "Enable writing to tty only by group, not by everybody"
+//config: default y
+//config: depends on MESG
+//config: help
+//config: Usually, ttys are owned by group "tty", and "write" tool is
+//config: setgid to this group. This way, "mesg y" only needs to enable
+//config: "write by owning group" bit in tty mode.
+//config:
+//config: If you set this option to N, "mesg y" will enable writing
+//config: by anybody at all. This is not recommended.
+
+//applet:IF_MESG(APPLET(mesg, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_MESG) += mesg.o
+
+//usage:#define mesg_trivial_usage
+//usage: "[y|n]"
+//usage:#define mesg_full_usage "\n\n"
+//usage: "Control write access to your terminal\n"
+//usage: " y Allow write access to your terminal\n"
+//usage: " n Disallow write access to your terminal"
+
+#include "libbb.h"
+
+#if ENABLE_FEATURE_MESG_ENABLE_ONLY_GROUP
+#define S_IWGRP_OR_S_IWOTH S_IWGRP
+#else
+#define S_IWGRP_OR_S_IWOTH (S_IWGRP | S_IWOTH)
+#endif
+
+int mesg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int mesg_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct stat sb;
+ mode_t m;
+ char c = 0;
+
+ argv++;
+
+ if (argv[0]
+ && (argv[1] || ((c = argv[0][0]) != 'y' && c != 'n'))
+ ) {
+ bb_show_usage();
+ }
+
+ if (!isatty(STDIN_FILENO))
+ bb_error_msg_and_die("not a tty");
+
+ xfstat(STDIN_FILENO, &sb, "stderr");
+ if (c == 0) {
+ puts((sb.st_mode & (S_IWGRP|S_IWOTH)) ? "is y" : "is n");
+ return EXIT_SUCCESS;
+ }
+ m = (c == 'y') ? sb.st_mode | S_IWGRP_OR_S_IWOTH
+ : sb.st_mode & ~(S_IWGRP|S_IWOTH);
+ if (fchmod(STDIN_FILENO, m) != 0)
+ bb_perror_nomsg_and_die();
+ return EXIT_SUCCESS;
+}
--- /dev/null
+/* vi: set sw=4 ts=4: */
+/*
+ * renice implementation for busybox
+ *
+ * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+/* Notes:
+ * Setting an absolute priority was obsoleted in SUSv2 and removed
+ * in SUSv3. However, the common linux version of renice does
+ * absolute and not relative. So we'll continue supporting absolute,
+ * although the stdout logging has been removed since both SUSv2 and
+ * SUSv3 specify that stdout isn't used.
+ *
+ * This version is lenient in that it doesn't require any IDs. The
+ * options -p, -g, and -u are treated as mode switches for the
+ * following IDs (if any). Multiple switches are allowed.
+ */
+//config:config RENICE
+//config: bool "renice"
+//config: default y
+//config: help
+//config: Renice alters the scheduling priority of one or more running
+//config: processes.
+
+//applet:IF_RENICE(APPLET(renice, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_RENICE) += renice.o
+
+//usage:#define renice_trivial_usage
+//usage: "[-n] PRIORITY [[-p | -g | -u] ID...]..."
+//usage:#define renice_full_usage "\n\n"
+//usage: "Change scheduling priority of a running process\n"
+//usage: "\n -n Add PRIORITY to current nice value"
+//usage: "\n Without -n, nice value is set to PRIORITY"
+//usage: "\n -p Process ids (default)"
+//usage: "\n -g Process group ids"
+//usage: "\n -u Process user names"
+
+#include "libbb.h"
+#include <sys/resource.h>
+
+void BUG_bad_PRIO_PROCESS(void);
+void BUG_bad_PRIO_PGRP(void);
+void BUG_bad_PRIO_USER(void);
+
+int renice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int renice_main(int argc UNUSED_PARAM, char **argv)
+{
+ static const char Xetpriority_msg[] ALIGN1 = "%cetpriority";
+
+ int retval = EXIT_SUCCESS;
+ int which = PRIO_PROCESS; /* Default 'which' value. */
+ int use_relative = 0;
+ int adjustment, new_priority;
+ unsigned who;
+ char *arg;
+
+ /* Yes, they are not #defines in glibc 2.4! #if won't work */
+ if (PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX)
+ BUG_bad_PRIO_PROCESS();
+ if (PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX)
+ BUG_bad_PRIO_PGRP();
+ if (PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX)
+ BUG_bad_PRIO_USER();
+
+ arg = *++argv;
+
+ /* Check if we are using a relative adjustment. */
+ if (arg && arg[0] == '-' && arg[1] == 'n') {
+ use_relative = 1;
+ if (!arg[2])
+ arg = *++argv;
+ else
+ arg += 2;
+ }
+
+ if (!arg) { /* No args? Then show usage. */
+ bb_show_usage();
+ }
+
+ /* Get the priority adjustment (absolute or relative). */
+ adjustment = xatoi_range(arg, INT_MIN/2, INT_MAX/2);
+
+ while ((arg = *++argv) != NULL) {
+ /* Check for a mode switch. */
+ if (arg[0] == '-' && arg[1]) {
+ static const char opts[] ALIGN1 = {
+ 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER
+ };
+ const char *p = strchr(opts, arg[1]);
+ if (p) {
+ which = p[4];
+ if (!arg[2])
+ continue;
+ arg += 2;
+ }
+ }
+
+ /* Process an ID arg. */
+ if (which == PRIO_USER) {
+ struct passwd *p;
+ p = getpwnam(arg);
+ if (!p) {
+ bb_error_msg("unknown user %s", arg);
+ goto HAD_ERROR;
+ }
+ who = p->pw_uid;
+ } else {
+ who = bb_strtou(arg, NULL, 10);
+ if (errno) {
+ bb_error_msg("invalid number '%s'", arg);
+ goto HAD_ERROR;
+ }
+ }
+
+ /* Get priority to use, and set it. */
+ if (use_relative) {
+ int old_priority;
+
+ errno = 0; /* Needed for getpriority error detection. */
+ old_priority = getpriority(which, who);
+ if (errno) {
+ bb_perror_msg(Xetpriority_msg, 'g');
+ goto HAD_ERROR;
+ }
+
+ new_priority = old_priority + adjustment;
+ } else {
+ new_priority = adjustment;
+ }
+
+ if (setpriority(which, who, new_priority) == 0) {
+ continue;
+ }
+
+ bb_perror_msg(Xetpriority_msg, 's');
+ HAD_ERROR:
+ retval = EXIT_FAILURE;
+ }
+
+ /* No need to check for errors outputing to stderr since, if it
+ * was used, the HAD_ERROR label was reached and retval was set. */
+
+ return retval;
+}