~ubuntu-branches/ubuntu/precise/util-linux/precise-proposed

« back to all changes in this revision

Viewing changes to schedutils/taskset.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-06-20 22:31:50 UTC
  • mfrom: (1.6.3 upstream) (4.5.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110620223150-lz8wrv0946ihcz3z
Tags: 2.19.1-2ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
* Dropped changes:
  - mount.preinst: lsb_release has been fixed in lucid and above to be
    usable without configuration, so we don't have to diverge from Debian
    here anymore.
* Changes merged upstream:
  - sfdisk support for '+' with '-N'
  - mount/umount.c: fix a segfault on umount with empty mtab entry
  - Fix arbitrary unmount with fuse security issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * taskset.c - taskset
3
 
 * Command-line utility for setting and retrieving a task's CPU affinity
4
 
 *
5
 
 * Robert Love <rml@tech9.net>          25 April 2002
6
 
 *
7
 
 * Linux kernels as of 2.5.8 provide the needed syscalls for
8
 
 * working with a task's cpu affinity.  Currently 2.4 does not
9
 
 * support these syscalls, but patches are available at:
10
 
 *
11
 
 *      http://www.kernel.org/pub/linux/kernel/people/rml/cpu-affinity/
 
2
 * taskset.c - command-line utility for setting and retrieving
 
3
 *             a task's CPU affinity
12
4
 *
13
5
 * This program is free software; you can redistribute it and/or modify
14
6
 * it under the terms of the GNU General Public License, v2, as
24
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
17
 *
26
18
 * Copyright (C) 2004 Robert Love
 
19
 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
27
20
 */
28
21
 
29
22
#include <stdio.h>
30
23
#include <stdlib.h>
31
24
#include <unistd.h>
32
25
#include <getopt.h>
33
 
#include <sched.h>
34
26
#include <errno.h>
35
 
#include <string.h>
36
 
#include <ctype.h>
37
 
#include <sys/syscall.h>
38
 
 
39
 
struct bitmask {
40
 
        unsigned int size;
41
 
        unsigned long *maskp;
42
 
};
43
 
 
44
 
static void show_usage(const char *cmd)
45
 
{
46
 
        fprintf(stderr, "taskset (%s)\n", PACKAGE_STRING);
47
 
        fprintf(stderr, "usage: %s [options] [mask | cpu-list] [pid |"\
48
 
                " cmd [args...]]\n", cmd);
49
 
        fprintf(stderr, "set or get the affinity of a process\n\n");
50
 
        fprintf(stderr, "  -p, --pid                  "
51
 
                "operate on existing given pid\n");
52
 
        fprintf(stderr, "  -c, --cpu-list             "\
53
 
                "display and specify cpus in list format\n");
54
 
        fprintf(stderr, "  -h, --help                 display this help\n");
55
 
        fprintf(stderr, "  -V, --version              "\
56
 
                "output version information\n\n");
57
 
        fprintf(stderr, "The default behavior is to run a new command:\n");
58
 
        fprintf(stderr, "  %s 03 sshd -b 1024\n", cmd);
59
 
        fprintf(stderr, "You can retrieve the mask of an existing task:\n");
60
 
        fprintf(stderr, "  %s -p 700\n", cmd);
61
 
        fprintf(stderr, "Or set it:\n");
62
 
        fprintf(stderr, "  %s -p 03 700\n", cmd);
63
 
        fprintf(stderr, "List format uses a comma-separated list instead"\
64
 
                        " of a mask:\n");
65
 
        fprintf(stderr, "  %s -pc 0,3,7-11 700\n", cmd);
66
 
        fprintf(stderr, "Ranges in list format can take a stride argument:\n");
67
 
        fprintf(stderr, "  e.g. 0-31:2 is equivalent to mask 0x55555555\n\n");
68
 
}
69
 
 
70
 
static inline int val_to_char(int v)
71
 
{
72
 
        if (v >= 0 && v < 10)
73
 
                return '0' + v;
74
 
        else if (v >= 10 && v < 16)
75
 
                return ('a' - 10) + v;
76
 
        else 
77
 
                return -1;
78
 
}
79
 
 
80
 
/*
81
 
 * The following bitmask declarations, bitmask_*() routines, and associated
82
 
 * _setbit() and _getbit() routines are:
83
 
 * Copyright (c) 2004 Silicon Graphics, Inc. (SGI) All rights reserved.
84
 
 * SGI publishes it under the terms of the GNU General Public License, v2,
85
 
 * as published by the Free Software Foundation.
86
 
 */
87
 
#define howmany(x,y) (((x)+((y)-1))/(y))
88
 
#define bitsperlong (8 * sizeof(unsigned long))
89
 
#define longsperbits(n) howmany(n, bitsperlong)
90
 
#define bytesperbits(x) ((x+7)/8)
91
 
 
92
 
static unsigned int _getbit(const struct bitmask *bmp, unsigned int n)
93
 
{
94
 
        if (n < bmp->size)
95
 
                return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1;
96
 
        else
97
 
                return 0;
98
 
}
99
 
 
100
 
static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v)
101
 
{
102
 
        if (n < bmp->size) {
103
 
                if (v)
104
 
                        bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong);
105
 
                else
106
 
                        bmp->maskp[n/bitsperlong] &= ~(1UL << (n % bitsperlong));
107
 
        }
108
 
}
109
 
 
110
 
int bitmask_isbitset(const struct bitmask *bmp, unsigned int i)
111
 
{
112
 
        return _getbit(bmp, i);
113
 
}
114
 
 
115
 
struct bitmask *bitmask_clearall(struct bitmask *bmp)
116
 
{
117
 
        unsigned int i;
118
 
        for (i = 0; i < bmp->size; i++)
119
 
                _setbit(bmp, i, 0);
120
 
        return bmp;
121
 
}
122
 
 
123
 
struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i)
124
 
{
125
 
        _setbit(bmp, i, 1);
126
 
        return bmp;
127
 
}
128
 
 
129
 
unsigned int bitmask_nbytes(struct bitmask *bmp)
130
 
{
131
 
        return longsperbits(bmp->size) * sizeof(unsigned long);
132
 
}
133
 
 
134
 
static char * cpuset_to_str(struct bitmask *mask, char *str)
135
 
{
136
 
        int base;
137
 
        char *ptr = str;
138
 
        char *ret = 0;
139
 
 
140
 
        for (base = mask->size - 4; base >= 0; base -= 4) {
141
 
                char val = 0;
142
 
                if (bitmask_isbitset(mask, base))
143
 
                        val |= 1;
144
 
                if (bitmask_isbitset(mask, base + 1))
145
 
                        val |= 2;
146
 
                if (bitmask_isbitset(mask, base + 2))
147
 
                        val |= 4;
148
 
                if (bitmask_isbitset(mask, base + 3))
149
 
                        val |= 8;
150
 
                if (!ret && val)
151
 
                        ret = ptr;
152
 
                *ptr++ = val_to_char(val);
153
 
        }
154
 
        *ptr = 0;
155
 
        return ret ? ret : ptr - 1;
156
 
}
157
 
 
158
 
struct bitmask *bitmask_alloc(unsigned int n)
159
 
{
160
 
        struct bitmask *bmp;
161
 
 
162
 
        bmp = malloc(sizeof(*bmp));
163
 
        if (!bmp)
164
 
                return 0;
165
 
        bmp->size = n;
166
 
        bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long));
167
 
        if (!bmp->maskp) {
168
 
                free(bmp);
169
 
                return 0;
170
 
        }
171
 
        return bmp;
172
 
}
173
 
 
174
 
static char * cpuset_to_cstr(struct bitmask *mask, char *str)
175
 
{
176
 
        int i;
177
 
        char *ptr = str;
178
 
        int entry_made = 0;
179
 
 
180
 
        for (i = 0; i < mask->size; i++) {
181
 
                if (bitmask_isbitset(mask, i)) {
182
 
                        int j;
183
 
                        int run = 0;
184
 
                        entry_made = 1;
185
 
                        for (j = i + 1; j < mask->size; j++) {
186
 
                                if (bitmask_isbitset(mask, j))
187
 
                                        run++;
188
 
                                else
189
 
                                        break;
190
 
                        }
191
 
                        if (!run)
192
 
                                sprintf(ptr, "%d,", i);
193
 
                        else if (run == 1) {
194
 
                                sprintf(ptr, "%d,%d,", i, i + 1);
195
 
                                i++;
196
 
                        } else {
197
 
                                sprintf(ptr, "%d-%d,", i, i + run);
198
 
                                i += run;
199
 
                        }
200
 
                        while (*ptr != 0)
201
 
                                ptr++;
202
 
                }
203
 
        }
204
 
        ptr -= entry_made;
205
 
        *ptr = 0;
206
 
 
207
 
        return str;
208
 
}
209
 
 
210
 
static inline int char_to_val(int c)
211
 
{
212
 
        int cl;
213
 
 
214
 
        cl = tolower(c);
215
 
        if (c >= '0' && c <= '9')
216
 
                return c - '0';
217
 
        else if (cl >= 'a' && cl <= 'f')
218
 
                return cl + (10 - 'a');
219
 
        else
220
 
                return -1;
221
 
}
222
 
 
223
 
static int str_to_cpuset(struct bitmask *mask, const char* str)
224
 
{
225
 
        int len = strlen(str);
226
 
        const char *ptr = str + len - 1;
227
 
        int base = 0;
228
 
 
229
 
        /* skip 0x, it's all hex anyway */
230
 
        if (len > 1 && !memcmp(str, "0x", 2L))
231
 
                str += 2;
232
 
 
233
 
        bitmask_clearall(mask);
234
 
        while (ptr >= str) {
235
 
                char val = char_to_val(*ptr);
236
 
                if (val == (char) -1)
237
 
                        return -1;
238
 
                if (val & 1)
239
 
                        bitmask_setbit(mask, base);
240
 
                if (val & 2)
241
 
                        bitmask_setbit(mask, base + 1);
242
 
                if (val & 4)
243
 
                        bitmask_setbit(mask, base + 2);
244
 
                if (val & 8)
245
 
                        bitmask_setbit(mask, base + 3);
246
 
                len--;
247
 
                ptr--;
248
 
                base += 4;
249
 
        }
250
 
 
251
 
        return 0;
252
 
}
253
 
 
254
 
static const char *nexttoken(const char *q,  int sep)
255
 
{
256
 
        if (q)
257
 
                q = strchr(q, sep);
258
 
        if (q)
259
 
                q++;
260
 
        return q;
261
 
}
262
 
 
263
 
static int cstr_to_cpuset(struct bitmask *mask, const char* str)
264
 
{
265
 
        const char *p, *q;
266
 
        q = str;
267
 
        bitmask_clearall(mask);
268
 
 
269
 
        while (p = q, q = nexttoken(q, ','), p) {
270
 
                unsigned int a; /* beginning of range */
271
 
                unsigned int b; /* end of range */
272
 
                unsigned int s; /* stride */
273
 
                const char *c1, *c2;
274
 
 
275
 
                if (sscanf(p, "%u", &a) < 1)
276
 
                        return 1;
277
 
                b = a;
278
 
                s = 1;
279
 
 
280
 
                c1 = nexttoken(p, '-');
281
 
                c2 = nexttoken(p, ',');
282
 
                if (c1 != NULL && (c2 == NULL || c1 < c2)) {
283
 
                        if (sscanf(c1, "%u", &b) < 1)
284
 
                                return 1;
285
 
                        c1 = nexttoken(c1, ':');
286
 
                        if (c1 != NULL && (c2 == NULL || c1 < c2))
287
 
                                if (sscanf(c1, "%u", &s) < 1) {
288
 
                                        return 1;
289
 
                        }
290
 
                }
291
 
 
292
 
                if (!(a <= b))
293
 
                        return 1;
294
 
                while (a <= b) {
295
 
                        bitmask_setbit(mask, a);
296
 
                        a += s;
297
 
                }
298
 
        }
299
 
 
300
 
        return 0;
301
 
}
302
 
 
303
 
/*
304
 
 * Number of bits in a CPU bitmask on current system
305
 
 */
306
 
static int
307
 
max_number_of_cpus(void)
308
 
{
309
 
        int n;
310
 
        int cpus = 2048;
311
 
 
312
 
        for (;;) {
313
 
                unsigned long buffer[longsperbits(cpus)];
314
 
                memset(buffer, 0, sizeof(buffer));
315
 
                /* the library version does not return size of cpumask_t */
316
 
                n = syscall(SYS_sched_getaffinity, 0, bytesperbits(cpus),
317
 
                                                                &buffer);
318
 
                if (n < 0 && errno == EINVAL && cpus < 1024*1024) {
319
 
                        cpus *= 2;
320
 
                        continue;
321
 
                }
322
 
                return n*8;
323
 
        }
324
 
        fprintf (stderr, "cannot determine NR_CPUS; aborting");
325
 
        exit(1);
326
 
        return 0;
 
27
#include <err.h>
 
28
 
 
29
#include "cpuset.h"
 
30
#include "nls.h"
 
31
 
 
32
#include "strutils.h"
 
33
 
 
34
static void __attribute__((__noreturn__)) usage(FILE *out)
 
35
{
 
36
        fprintf(out,
 
37
                _("Usage: %s [options] [mask | cpu-list] [pid|cmd [args...]]\n\n"),
 
38
                program_invocation_short_name);
 
39
 
 
40
        fprintf(out, _(
 
41
                "Options:\n"
 
42
                " -p, --pid               operate on existing given pid\n"
 
43
                " -c, --cpu-list          display and specify cpus in list format\n"
 
44
                " -h, --help              display this help\n"
 
45
                " -V, --version           output version information\n\n"));
 
46
 
 
47
        fprintf(out, _(
 
48
                "The default behavior is to run a new command:\n"
 
49
                "    %1$s 03 sshd -b 1024\n"
 
50
                "You can retrieve the mask of an existing task:\n"
 
51
                "    %1$s -p 700\n"
 
52
                "Or set it:\n"
 
53
                "    %1$s -p 03 700\n"
 
54
                "List format uses a comma-separated list instead of a mask:\n"
 
55
                "    %1$s -pc 0,3,7-11 700\n"
 
56
                "Ranges in list format can take a stride argument:\n"
 
57
                "    e.g. 0-31:2 is equivalent to mask 0x55555555\n"),
 
58
                program_invocation_short_name);
 
59
 
 
60
        fprintf(out, _("\nFor more information see taskset(1).\n"));
 
61
 
 
62
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
327
63
}
328
64
 
329
65
int main(int argc, char *argv[])
330
66
{
331
 
        struct bitmask *new_mask, *cur_mask;
 
67
        cpu_set_t *new_set, *cur_set;
332
68
        pid_t pid = 0;
333
 
        int opt, err;
334
 
        char *mstr;
335
 
        char *cstr;
336
 
        int c_opt = 0;
337
 
        unsigned int cpus_configured;
338
 
        int new_mask_byte_size, cur_mask_byte_size;
 
69
        int opt, c_opt = 0, rc;
 
70
        char *buf;
 
71
        unsigned int ncpus;
 
72
        size_t new_setsize, cur_setsize, cur_nbits, buflen;
339
73
 
340
74
        struct option longopts[] = {
341
75
                { "pid",        0, NULL, 'p' },
345
79
                { NULL,         0, NULL, 0 }
346
80
        };
347
81
 
 
82
        setlocale(LC_ALL, "");
 
83
        bindtextdomain(PACKAGE, LOCALEDIR);
 
84
        textdomain(PACKAGE);
 
85
 
348
86
        while ((opt = getopt_long(argc, argv, "+pchV", longopts, NULL)) != -1) {
349
 
                int ret = 1;
350
 
 
351
87
                switch (opt) {
352
88
                case 'p':
353
 
                        pid = atoi(argv[argc - 1]);
 
89
                        pid = strtol_or_err(argv[argc - 1], _("failed to parse pid"));
354
90
                        break;
355
91
                case 'c':
356
92
                        c_opt = 1;
357
93
                        break;
358
94
                case 'V':
359
95
                        printf("taskset (%s)\n", PACKAGE_STRING);
360
 
                        return 0;
 
96
                        return EXIT_SUCCESS;
361
97
                case 'h':
362
 
                        ret = 0;
 
98
                        usage(stdout);
 
99
                        break;
363
100
                default:
364
 
                        show_usage(argv[0]);
365
 
                        return ret;
 
101
                        usage(stderr);
 
102
                        break;
366
103
                }
367
104
        }
368
105
 
369
106
        if ((!pid && argc - optind < 2)
370
 
                        || (pid && (argc - optind < 1 || argc - optind > 2))) {
371
 
                show_usage(argv[0]);
372
 
                return 1;
373
 
        }
 
107
                        || (pid && (argc - optind < 1 || argc - optind > 2)))
 
108
                usage(stderr);
374
109
 
375
 
        cpus_configured = max_number_of_cpus();
 
110
        ncpus = get_max_number_of_cpus();
 
111
        if (ncpus <= 0)
 
112
                errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
376
113
 
377
114
        /*
378
 
         * cur_mask is always used for the sched_getaffinity call
 
115
         * cur_set is always used for the sched_getaffinity call
379
116
         * On the sched_getaffinity the kernel demands a user mask of
380
117
         * at least the size of its own cpumask_t.
381
118
         */
382
 
        cur_mask = bitmask_alloc(cpus_configured);
383
 
        if (!cur_mask) {
384
 
                fprintf (stderr, "bitmask_alloc failed\n");
385
 
                exit(1);
386
 
        }
387
 
        cur_mask_byte_size = bitmask_nbytes(cur_mask);
388
 
        mstr = malloc(1 + cur_mask->size / 4);
389
 
        cstr = malloc(7 * cur_mask->size);
 
119
        cur_set = cpuset_alloc(ncpus, &cur_setsize, &cur_nbits);
 
120
        if (!cur_set)
 
121
                err(EXIT_FAILURE, _("cpuset_alloc failed"));
 
122
 
 
123
        buflen = 7 * cur_nbits;
 
124
        buf = malloc(buflen);
 
125
        if (!buf)
 
126
                err(EXIT_FAILURE, _("malloc failed"));
390
127
 
391
128
        /*
392
 
         * new_mask is always used for the sched_setaffinity call
 
129
         * new_set is always used for the sched_setaffinity call
393
130
         * On the sched_setaffinity the kernel will zero-fill its
394
131
         * cpumask_t if the user's mask is shorter.
395
132
         */
396
 
        new_mask = bitmask_alloc(cpus_configured);
397
 
        if (!new_mask) {
398
 
                fprintf (stderr, "bitmask_alloc failed\n");
399
 
                exit(1);
400
 
        }
401
 
        new_mask_byte_size = bitmask_nbytes(new_mask);
 
133
        new_set = cpuset_alloc(ncpus, &new_setsize, NULL);
 
134
        if (!new_set)
 
135
                err(EXIT_FAILURE, _("cpuset_alloc failed"));
402
136
 
403
137
        if (pid) {
404
 
                if (sched_getaffinity(pid, cur_mask_byte_size,
405
 
                                        (cpu_set_t *)cur_mask->maskp) < 0) {
406
 
                        perror("sched_getaffinity");
407
 
                        fprintf(stderr, "failed to get pid %d's affinity\n",
408
 
                                pid);
409
 
                        return 1;
410
 
                }
 
138
                if (sched_getaffinity(pid, cur_setsize, cur_set) < 0)
 
139
                        err(EXIT_FAILURE, _("failed to get pid %d's affinity"), pid);
 
140
 
411
141
                if (c_opt)
412
 
                        printf("pid %d's current affinity list: %s\n", pid,
413
 
                                cpuset_to_cstr(cur_mask, cstr));
 
142
                        printf(_("pid %d's current affinity list: %s\n"), pid,
 
143
                                cpulist_create(buf, buflen, cur_set, cur_setsize));
414
144
                else
415
 
                        printf("pid %d's current affinity mask: %s\n", pid,
416
 
                                cpuset_to_str(cur_mask, mstr));
 
145
                        printf(_("pid %d's current affinity mask: %s\n"), pid,
 
146
                                cpumask_create(buf, buflen, cur_set, cur_setsize));
417
147
 
418
148
                if (argc - optind == 1)
419
 
                        return 0;
420
 
        }
421
 
 
422
 
        if (c_opt)
423
 
                err = cstr_to_cpuset(new_mask, argv[optind]);
424
 
        else
425
 
                err = str_to_cpuset(new_mask, argv[optind]);
426
 
 
427
 
        if (err) {
428
 
                if (c_opt)
429
 
                        fprintf(stderr, "failed to parse CPU list %s\n",
430
 
                                argv[optind]);
431
 
                else
432
 
                        fprintf(stderr, "failed to parse CPU mask %s\n",
433
 
                                argv[optind]);
434
 
                return 1;
435
 
        }
436
 
 
437
 
        if (sched_setaffinity(pid, new_mask_byte_size,
438
 
                                        (cpu_set_t *) new_mask->maskp) < 0) {
439
 
                perror("sched_setaffinity");
440
 
                fprintf(stderr, "failed to set pid %d's affinity.\n", pid);
441
 
                return 1;
442
 
        }
443
 
 
444
 
        if (sched_getaffinity(pid, cur_mask_byte_size,
445
 
                                        (cpu_set_t *)cur_mask->maskp) < 0) {
446
 
                perror("sched_getaffinity");
447
 
                fprintf(stderr, "failed to get pid %d's affinity.\n", pid);
448
 
                return 1;
449
 
        }
 
149
                        return EXIT_SUCCESS;
 
150
        }
 
151
 
 
152
        rc = c_opt ? cpulist_parse(argv[optind], new_set, new_setsize) :
 
153
                     cpumask_parse(argv[optind], new_set, new_setsize);
 
154
 
 
155
        if (rc)
 
156
                errx(EXIT_FAILURE, _("failed to parse %s %s"),
 
157
                                c_opt ? _("CPU list") : _("CPU mask"),
 
158
                                argv[optind]);
 
159
 
 
160
        if (sched_setaffinity(pid, new_setsize, new_set) < 0)
 
161
                err(EXIT_FAILURE, _("failed to set pid %d's affinity"), pid);
 
162
 
 
163
        if (sched_getaffinity(pid, cur_setsize, cur_set) < 0)
 
164
                err(EXIT_FAILURE, _("failed to get pid %d's affinity"), pid);
450
165
 
451
166
        if (pid) {
452
167
                if (c_opt)
453
 
                        printf("pid %d's new affinity list: %s\n", pid, 
454
 
                               cpuset_to_cstr(cur_mask, cstr));
 
168
                        printf(_("pid %d's new affinity list: %s\n"), pid,
 
169
                                cpulist_create(buf, buflen, cur_set, cur_setsize));
455
170
                else
456
 
                        printf("pid %d's new affinity mask: %s\n", pid, 
457
 
                               cpuset_to_str(cur_mask, mstr));
458
 
        } else {
 
171
                        printf(_("pid %d's new affinity mask: %s\n"), pid,
 
172
                                cpumask_create(buf, buflen, cur_set, cur_setsize));
 
173
        }
 
174
 
 
175
        free(buf);
 
176
        cpuset_free(cur_set);
 
177
        cpuset_free(new_set);
 
178
 
 
179
        if (!pid) {
459
180
                argv += optind + 1;
460
181
                execvp(argv[0], argv);
461
 
                perror("execvp");
462
 
                fprintf(stderr, "failed to execute %s\n", argv[0]);
463
 
                return 1;
 
182
                err(EXIT_FAILURE, _("executing %s failed"), argv[0]);
464
183
        }
465
184
 
466
 
        return 0;
 
185
        return EXIT_SUCCESS;
467
186
}