b55c0a738ab0802d353d8a4120faaa1cdf84f709
[platform/upstream/coreutils.git] / src / nice.c
1 /* nice -- run a program with modified scheduling priority
2    Copyright (C) 1990-2003 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 /* David MacKenzie <djm@gnu.ai.mit.edu> */
19
20 #include <config.h>
21 #include <stdio.h>
22
23 #include <assert.h>
24
25 #include <getopt.h>
26 #include <sys/types.h>
27
28 #include "system.h"
29
30 #ifndef NICE_PRIORITY
31 /* Include this after "system.h" so we're sure to have definitions
32    (from time.h or sys/time.h) required for e.g. the ru_utime member.  */
33 # include <sys/resource.h>
34 #endif
35
36 #include "error.h"
37 #include "long-options.h"
38 #include "posixver.h"
39 #include "xstrtol.h"
40
41 /* The official name of this program (e.g., no `g' prefix).  */
42 #define PROGRAM_NAME "nice"
43
44 #define WRITTEN_BY _("Written by David MacKenzie.")
45
46 #ifdef NICE_PRIORITY
47 # define GET_PRIORITY() nice (0)
48 #else
49 # define GET_PRIORITY() getpriority (PRIO_PROCESS, 0)
50 #endif
51
52 /* The name this program was run with. */
53 char *program_name;
54
55 static struct option const longopts[] =
56 {
57   {"adjustment", required_argument, NULL, 'n'},
58   {NULL, 0, NULL, 0}
59 };
60
61 void
62 usage (int status)
63 {
64   if (status != 0)
65     fprintf (stderr, _("Try `%s --help' for more information.\n"),
66              program_name);
67   else
68     {
69       printf (_("Usage: %s [OPTION] [COMMAND [ARG]...]\n"), program_name);
70       fputs (_("\
71 Run COMMAND with an adjusted scheduling priority.\n\
72 With no COMMAND, print the current scheduling priority.  ADJUST is 10\n\
73 by default.  Range goes from -20 (highest priority) to 19 (lowest).\n\
74 \n\
75   -n, --adjustment=ADJUST   increment priority by ADJUST first\n\
76 "), stdout);
77       fputs (HELP_OPTION_DESCRIPTION, stdout);
78       fputs (VERSION_OPTION_DESCRIPTION, stdout);
79       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
80     }
81   exit (status);
82 }
83
84 int
85 main (int argc, char **argv)
86 {
87   int current_priority;
88   long int adjustment = 0;
89   int minusflag = 0;
90   int adjustment_given = 0;
91   int i;
92
93   initialize_main (&argc, &argv);
94   program_name = argv[0];
95   setlocale (LC_ALL, "");
96   bindtextdomain (PACKAGE, LOCALEDIR);
97   textdomain (PACKAGE);
98
99   atexit (close_stdout);
100
101   parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
102                       WRITTEN_BY, usage);
103
104   for (i = 1; i < argc; /* empty */)
105     {
106       char *s = argv[i];
107
108       if (s[0] == '-' && s[1] == '-' && ISDIGIT (s[2])
109           && posix2_version () < 200112)
110         {
111           if (xstrtol (&s[2], NULL, 10, &adjustment, "") != LONGINT_OK)
112             error (EXIT_FAILURE, 0, _("invalid option `%s'"), s);
113
114           minusflag = 1;
115           adjustment_given = 1;
116           ++i;
117         }
118       else if (s[0] == '-'
119                && (ISDIGIT (s[1]) || (s[1] == '+' && ISDIGIT (s[2])))
120                && posix2_version () < 200112)
121         {
122           if (s[1] == '+')
123             ++s;
124           if (xstrtol (&s[1], NULL, 10, &adjustment, "") != LONGINT_OK)
125             error (EXIT_FAILURE, 0, _("invalid option `%s'"), s);
126
127           minusflag = 0;
128           adjustment_given = 1;
129           ++i;
130         }
131       else
132         {
133           int optc;
134           char **fake_argv = argv + i - 1;
135
136           /* Initialize getopt_long's internal state.  */
137           optind = 0;
138
139           if ((optc = getopt_long (argc - (i - 1), fake_argv, "+n:",
140                                    longopts, NULL)) != -1)
141             {
142               switch (optc)
143                 {
144                 case '?':
145                   usage (EXIT_FAILURE);
146
147                 case 'n':
148                   if (xstrtol (optarg, NULL, 10, &adjustment, "")
149                       != LONGINT_OK)
150                     error (EXIT_FAILURE, 0, _("invalid priority `%s'"), optarg);
151
152                   minusflag = 0;
153                   adjustment_given = 1;
154                   break;
155                 }
156             }
157
158           i += optind - 1;
159
160           if (optc == EOF)
161             break;
162         }
163     }
164
165   if (minusflag)
166     adjustment = -adjustment;
167   if (!adjustment_given)
168     adjustment = 10;
169
170   if (i == argc)
171     {
172       if (adjustment_given)
173         {
174           error (0, 0, _("a command must be given with an adjustment"));
175           usage (EXIT_FAILURE);
176         }
177       /* No command given; print the priority. */
178       errno = 0;
179       current_priority = GET_PRIORITY ();
180       if (current_priority == -1 && errno != 0)
181         error (EXIT_FAILURE, errno, _("cannot get priority"));
182       printf ("%d\n", current_priority);
183       exit (EXIT_SUCCESS);
184     }
185
186 #ifndef NICE_PRIORITY
187   errno = 0;
188   current_priority = GET_PRIORITY ();
189   if (current_priority == -1 && errno != 0)
190     error (EXIT_FAILURE, errno, _("cannot get priority"));
191   if (setpriority (PRIO_PROCESS, 0, current_priority + adjustment))
192 #else
193   if (nice (adjustment) == -1)
194 #endif
195     error (EXIT_FAILURE, errno, _("cannot set priority"));
196
197   execvp (argv[i], &argv[i]);
198
199   {
200     int exit_status = (errno == ENOENT ? 127 : 126);
201     error (0, errno, "%s", argv[i]);
202     exit (exit_status);
203   }
204 }