]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/unshare.c
build-sys: provide alternatives for err, errx, warn and warnx
[thirdparty/util-linux.git] / sys-utils / unshare.c
CommitLineData
4205f1fd
MG
1/*
2 * unshare(1) - command-line interface for unshare(2)
3 *
4 * Copyright (C) 2009 Mikhail Gusarov <dottedmag@dottedmag.net>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
4205f1fd
MG
21#include <errno.h>
22#include <getopt.h>
23#include <sched.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27
28#include "nls.h"
eb76ca98 29#include "c.h"
4205f1fd
MG
30
31#ifndef CLONE_NEWSNS
32# define CLONE_NEWNS 0x00020000
33#endif
34#ifndef CLONE_NEWUTS
35# define CLONE_NEWUTS 0x04000000
36#endif
37#ifndef CLONE_NEWIPC
38# define CLONE_NEWIPC 0x08000000
39#endif
40#ifndef CLONE_NEWNET
41# define CLONE_NEWNET 0x40000000
42#endif
43
44#ifndef HAVE_UNSHARE
45# include <sys/syscall.h>
46
47static int unshare(int flags)
48{
49 return syscall(SYS_unshare, flags);
50}
51#endif
52
53static void usage(int status)
54{
55 FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
56
57 fprintf(out, _("Usage: %s [options] <program> [args...]\n"),
58 program_invocation_short_name);
59
60 fputs(_("Run program with some namespaces unshared from parent\n\n"
61 " -h, --help usage information (this)\n"
62 " -m, --mount unshare mounts namespace\n"
63 " -u, --uts unshare UTS namespace (hostname etc)\n"
64 " -i, --ipc unshare System V IPC namespace\n"
65 " -n, --net unshare network namespace\n"), out);
66
67 fprintf(out, _("\nFor more information see unshare(1).\n"));
68 exit(status);
69}
70
71int main(int argc, char *argv[])
72{
73 struct option longopts[] = {
74 { "help", no_argument, 0, 'h' },
75 { "mount", no_argument, 0, 'm' },
76 { "uts", no_argument, 0, 'u' },
77 { "ipc", no_argument, 0, 'i' },
78 { "net", no_argument, 0, 'n' },
4ffde0b6 79 { NULL, 0, 0, 0 }
4205f1fd
MG
80 };
81
82 int unshare_flags = 0;
83
84 int c;
85
86 setlocale(LC_MESSAGES, "");
87 bindtextdomain(PACKAGE, LOCALEDIR);
88 textdomain(PACKAGE);
89
90 while((c = getopt_long(argc, argv, "hmuin", longopts, NULL)) != -1) {
91 switch(c) {
92 case 'h':
93 usage(EXIT_SUCCESS);
94 case 'm':
95 unshare_flags |= CLONE_NEWNS;
96 break;
97 case 'u':
98 unshare_flags |= CLONE_NEWUTS;
99 break;
100 case 'i':
101 unshare_flags |= CLONE_NEWIPC;
102 break;
103 case 'n':
104 unshare_flags |= CLONE_NEWNET;
105 break;
106 default:
107 usage(EXIT_FAILURE);
108 }
109 }
110
111 if(optind >= argc)
112 usage(EXIT_FAILURE);
113
114 if(-1 == unshare(unshare_flags))
115 err(EXIT_FAILURE, _("unshare failed"));
116
3f1be691
KZ
117 /* drop potential root euid/egid if we had been setuid'd */
118 if (setgid(getgid()) < 0)
119 err(EXIT_FAILURE, _("cannot set group id"));
120
121 if (setuid(getuid()) < 0)
122 err(EXIT_FAILURE, _("cannot set user id"));
123
4205f1fd
MG
124 execvp(argv[optind], argv + optind);
125
126 err(EXIT_FAILURE, _("exec %s failed"), argv[optind]);
127}