2 ** IRC - Internet Relay Chat, tools/wrapper.c
3 ** Copyright (C) 2000 by Kevin L. Mitchell <klmitch@mit.edu>
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sys/types.h>
28 #include <sys/resource.h>
32 * Try and find the correct name to use with getrlimit() for setting the max.
33 * number of files allowed to be open by this process.
35 * Shamelessly stolen from ircu...
38 #define RLIMIT_FD_MAX RLIMIT_FDMAX
41 #define RLIMIT_FD_MAX RLIMIT_NOFILE
43 #ifdef RLIMIT_OPEN_MAX
44 #define RLIMIT_FD_MAX RLIMIT_OPEN_MAX
46 #error Unable to find a valid RLIMIT_FD_MAX
52 * Set the hard and soft limits for maximum file descriptors.
55 set_fdlimit(unsigned int max_descriptors)
59 limit.rlim_max = limit.rlim_cur = max_descriptors;
61 return setrlimit(RLIMIT_FD_MAX, &limit);
65 * Change directories to the indicated root directory, then make it the
69 change_root(char *root)
80 * Change the user and group ids--including supplementary groups!--as
84 change_user(char *user, char *group)
91 /* Track down a struct passwd describing the desired user */
92 uid = strtol(user, &tmp, 10); /* was the user given as a number? */
93 if (*tmp) { /* strtol() failed to parse; look up as a user name */
94 if (!(pwd = getpwnam(user)))
96 } else if (!(pwd = getpwuid(uid))) /* look up uid */
99 uid = pwd->pw_uid; /* uid to change to */
100 gid = pwd->pw_gid; /* default gid for user */
102 if (group) { /* a group was specified; track down struct group */
103 gid = strtol(group, &tmp, 10); /* was the group given as a number? */
104 if (*tmp) { /* strtol() failed to parse; look up as a group name */
105 if (!(grp = getgrnam(group)))
107 } else if (!(grp = getgrgid(gid))) /* look up gid */
110 gid = grp->gr_gid; /* set the gid */
113 if (initgroups(pwd->pw_name, gid)) /* initialize supplementary groups */
115 if (setgid(gid)) /* change our current group */
117 if (setuid(uid)) /* change our current user */
120 return 0; /* success! */
124 * Explain how to use this program.
127 usage(char *prog, int retval)
129 fprintf(stderr, "Usage: %s [-u <user>] [-g <group>] [-l <limit>] [-c <root>]"
130 " -- \\\n\t\t<cmd> [<cmdargs>]\n", prog);
131 fprintf(stderr, " %s -h\n", prog);
137 main(int argc, char **argv)
140 char *prog, *user = 0, *group = 0, *root = 0;
142 /* determine program name for error reporting */
143 if ((prog = strrchr(argv[0], '/')))
148 /* process command line arguments */
149 while ((c = getopt(argc, argv, "hu:g:l:c:")) > 0)
151 case 'h': /* requested help */
155 case 'u': /* suggested a user */
159 case 'g': /* suggested a group */
163 case 'l': /* file descriptor limit */
164 limit = strtol(optarg, 0, 10);
167 case 'c': /* select a root directory */
171 default: /* unknown command line argument */
176 /* Not enough arguments; we must have a command to execute! */
180 if (limit > 0) /* set the requested fd limit */
181 if (set_fdlimit(limit) < 0) {
186 if (root) /* change root directories */
187 if (change_root(root)) {
192 if (user) /* change to selected user account */
193 if (change_user(user, group)) {
198 /* execute the requested command */
199 execvp(argv[optind], argv + optind);
201 /* If we got here, execvp() failed; report the error */