(add_tabstop): Give correct size when reallocating tab_list buffer.
[platform/upstream/coreutils.git] / src / nice.c
1 /* nice -- run a program with modified scheduling priority
2    Copyright (C) 90, 91, 92, 93, 94, 1995 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
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17
18 /* David MacKenzie <djm@gnu.ai.mit.edu> */
19
20 #include <config.h>
21 #include <stdio.h>
22
23 #define NDEBUG
24 #include <assert.h>
25
26 #include <getopt.h>
27 #include <sys/types.h>
28 #ifndef NICE_PRIORITY
29 #include <sys/time.h>
30 #include <sys/resource.h>
31 #endif
32
33 #include "version.h"
34 #include "system.h"
35 #include "long-options.h"
36 #include "error.h"
37
38 #ifdef NICE_PRIORITY
39 #define GET_PRIORITY() nice (0)
40 #else
41 #define GET_PRIORITY() getpriority (PRIO_PROCESS, 0)
42 #endif
43
44 static int isinteger ();
45 static void usage ();
46
47 /* The name this program was run with. */
48 char *program_name;
49
50 static struct option const longopts[] =
51 {
52   {"adjustment", required_argument, NULL, 'n'},
53   {NULL, 0, NULL, 0}
54 };
55
56 void
57 main (argc, argv)
58      int argc;
59      char **argv;
60 {
61   int current_priority;
62   int adjustment = 0;
63   int minusflag = 0;
64   int adjustment_given = 0;
65   int long_option_priority = 0;
66   int last_optind = 0;
67
68   program_name = argv[0];
69   parse_long_options (argc, argv, "nice", version_string, usage);
70
71   for (optind = 1; optind < argc; /* empty */)
72     {
73       char *s;
74
75       s = argv[optind];
76
77       if (s[0] == '-' && s[1] == '-' && ISDIGIT (s[2]))
78         {
79           if (!isinteger (&s[2]))
80             error (1, 0, "invalid option `%s'", s);
81
82           minusflag = 1;
83           adjustment = atoi (&s[2]);
84           adjustment_given = 1;
85           long_option_priority = 1;
86           ++optind;
87         }
88       else
89         {
90           int optc;
91           while ((optc = getopt_long (argc, argv, "+0123456789n:", longopts,
92                                       (int *) 0)) != EOF)
93             {
94               switch (optc)
95                 {
96                 case '?':
97                   usage (1);
98
99                 case 'n':
100                   if (!isinteger (optarg))
101                     error (1, 0, "invalid priority `%s'", optarg);
102                   adjustment = atoi (optarg);
103                   adjustment_given = 1;
104                   break;
105
106                 default:
107                   assert (ISDIGIT (optc));
108                   /* Reset ADJUSTMENT if the last priority-specifying option
109                      was not of the same type or if it was, but a separate
110                      option.  */
111                   if (long_option_priority ||
112                       (adjustment_given && optind != last_optind))
113                     {
114                       long_option_priority = 0;
115                       adjustment = 0;
116                     }
117                   adjustment = adjustment * 10 + optc - '0';
118                   adjustment_given = 1;
119                   last_optind = optind;
120                 }
121             }
122           if (optc == EOF)
123             break;
124         }
125     }
126
127   if (minusflag)
128     adjustment = -adjustment;
129   if (!adjustment_given)
130     adjustment = 10;
131
132   if (optind == argc)
133     {
134       if (adjustment_given)
135         {
136           error (0, 0, "a command must be given with an adjustment");
137           usage (1);
138         }
139       /* No command given; print the priority. */
140       errno = 0;
141       current_priority = GET_PRIORITY ();
142       if (current_priority == -1 && errno != 0)
143         error (1, errno, "cannot get priority");
144       printf ("%d\n", current_priority);
145       exit (0);
146     }
147
148 #ifndef NICE_PRIORITY
149   errno = 0;
150   current_priority = GET_PRIORITY ();
151   if (current_priority == -1 && errno != 0)
152     error (1, errno, "cannot get priority");
153   if (setpriority (PRIO_PROCESS, 0, current_priority + adjustment))
154 #else
155   if (nice (adjustment) == -1)
156 #endif
157     error (1, errno, "cannot set priority");
158
159   execvp (argv[optind], &argv[optind]);
160   error (errno == ENOENT ? 127 : 126, errno, "%s", argv[optind]);
161 }
162
163 /* Return nonzero if S represents a (possibly signed) decimal integer,
164    zero if not. */
165
166 static int
167 isinteger (s)
168      char *s;
169 {
170   if (*s == '-' || *s == '+')
171     ++s;
172   if (*s == 0)
173     return 0;
174   while (*s)
175     {
176       if (!ISDIGIT (*s))
177         return 0;
178       ++s;
179     }
180   return 1;
181 }
182
183 static void
184 usage (status)
185      int status;
186 {
187   if (status != 0)
188     fprintf (stderr, "Try `%s --help' for more information.\n",
189              program_name);
190   else
191     {
192       printf ("Usage: %s [OPTION]... [COMMAND [ARG]...]\n", program_name);
193       printf ("\
194 \n\
195   -ADJUST                   increment priority by ADJUST first\n\
196   -n, --adjustment=ADJUST   same as -ADJUST\n\
197       --help                display this help and exit\n\
198       --version             output version information and exit\n\
199 \n\
200 With no COMMAND, print the current scheduling priority.  ADJUST is 10\n\
201 by default.  Range goes from -20 (highest priority) to 19 (lowest).\n\
202 ");
203     }
204   exit (status);
205 }