#!/bin/sh # This is a shell archive (produced by GNU sharutils 4.2.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 2000-05-25 14:41 CDT by . # Source directory was `/home/gk4/src/groupmem'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1960 -rw-r--r-- Makefile # 6348 -rw-r--r-- groupmems.c # 3372 -rw------- groupmems.8 # save_IFS="${IFS}" IFS="${IFS}:" gettext_dir=FAILED locale_dir=FAILED first_param="$1" for dir in $PATH do if test "$gettext_dir" = FAILED && test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then set `$dir/gettext --version 2>&1` if test "$3" = GNU then gettext_dir=$dir fi fi if test "$locale_dir" = FAILED && test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` fi done IFS="$save_IFS" if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED then echo=echo else TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"' elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"' elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then shar_touch='touch -am $3$4$5$6$2 "$8"' else shar_touch=: echo $echo 'WARNING: not restoring timestamps. Consider getting and' $echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch # if mkdir _sh10937; then $echo 'x -' 'creating lock directory' else $echo 'failed to create lock directory' exit 1 fi # ============= Makefile ============== if test -f 'Makefile' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'Makefile' '(file already exists)' else $echo 'x -' extracting 'Makefile' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && /* # SPDX-FileCopyrightText: 2000, International Business Machines, Inc. # SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com # SPDX-License-Identifier: BSD-3-Clause # X all: groupmems X groupmems: groupmems.c X cc -g -o groupmems groupmems.c -L. -lshadow X install: groupmems X -/usr/sbin/groupadd groups X install -o root -g groups -m 4770 groupmems /usr/bin X install.man: groupmems.8 X install -o root -g root -m 644 groupmems.8 /usr/man/man8 X SHAR_EOF (set 20 00 05 25 14 40 28 'Makefile'; eval "$shar_touch") && chmod 0644 'Makefile' || $echo 'restore of' 'Makefile' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'Makefile:' 'MD5 check failed' b46cf7ef8d59149093c011ced3f3103c Makefile SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`" test 1960 -eq "$shar_count" || $echo 'Makefile:' 'original size' '1960,' 'current size' "$shar_count!" fi fi # ============= groupmems.c ============== if test -f 'groupmems.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'groupmems.c' '(file already exists)' else $echo 'x -' extracting 'groupmems.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'groupmems.c' && /* X * SPDX-FileCopyrightText: 2000, International Business Machines, Inc. X * SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com X * SPDX-License-Identifier: BSD-3-Clause X */ /* ** ** Utility "groupmem" adds and deletes members from a user's group. ** ** Setup (as "root"): ** ** groupadd -r groups ** chmod 2770 groupmems ** chown root.groups groupmems ** groupmems -g groups -a gk4 ** ** Usage (as "gk4"): ** ** groupmems -a olive ** groupmems -a jordan ** groupmems -a meghan ** groupmems -a morgan ** groupmems -a jake ** groupmems -l ** groupmems -d jake ** groupmems -l */ X #include #include #include #include #include #include #include "defines.h" #include "groupio.h" X /* Exit Status Values */ X #define EXIT_SUCCESS 0 /* success */ #define EXIT_USAGE 1 /* invalid command syntax */ #define EXIT_GROUP_FILE 2 /* group file access problems */ #define EXIT_NOT_ROOT 3 /* not superuser */ #define EXIT_NOT_EROOT 4 /* not effective superuser */ #define EXIT_NOT_PRIMARY 5 /* not primary owner of group */ #define EXIT_NOT_MEMBER 6 /* member of group does not exist */ #define EXIT_MEMBER_EXISTS 7 /* member of group already exists */ X #define TRUE 1 #define FALSE 0 X /* Globals */ X extern int optind; extern char *optarg; static char *adduser = NULL; static char *deluser = NULL; static char *thisgroup = NULL; static int purge = FALSE; static int list = FALSE; static int exclusive = 0; X static int isroot(void) { X return getuid() ? FALSE : TRUE; } X static int isgroup(void) { X gid_t g = getgid(); X struct group *grp = getgrgid(g); X X return TRUE; } X static char *whoami(void) { X struct group *grp = getgrgid(getgid()); X struct passwd *usr = getpwuid(getuid()); X X if (0 == strcmp(usr->pw_name, grp->gr_name)) { X return (char *)strdup(usr->pw_name); X } else { X return NULL; X } } X static void addtogroup(char *user, char **members) { X int i; X char **pmembers; X X for (i = 0; NULL != members[i]; i++ ) { X if (0 == strcmp(user, members[i])) { X fprintf(stderr, "Member already exists\n"); X exit(EXIT_MEMBER_EXISTS); X } X } X X if (0 == i) { X pmembers = (char **)calloc(2, sizeof(char *)); X } else { X pmembers = (char **)realloc(members, sizeof(char *)*(i+1)); X } X X *members = *pmembers; X members[i] = user; X members[i+1] = NULL; } X static void rmfromgroup(char *user, char **members) { X int i; X int found = FALSE; X X i = 0; X while (!found && NULL != members[i]) { X if (0 == strcmp(user, members[i])) { X found = TRUE; X } else { X i++; X } X } X X while (found && NULL != members[i]) { X members[i] = members[++i]; X } X X if (!found) { X fprintf(stderr, "Member to remove could not be found\n"); X exit(EXIT_NOT_MEMBER); X } } X static void nomembers(char **members) { X int i; X X for (i = 0; NULL != members[i]; i++ ) { X members[i] = NULL; X } } X static void members(char **members) { X int i; X X for (i = 0; NULL != members[i]; i++ ) { X printf("%s ", members[i]); X X if (NULL == members[i+1]) { X printf("\n"); X } else { X printf(" "); X } X } } X static void usage(void) { X fprintf(stderr, "usage: groupmems -a username | -d username | -D | -l [-g groupname]\n"); X exit(EXIT_USAGE); } X main(int argc, char **argv) { X int arg, i; X char *name; X struct group *grp; X X while ((arg = getopt(argc, argv, "a:d:g:Dl")) != EOF) { X switch (arg) { X case 'a': X adduser = strdup(optarg); X ++exclusive; X break; X case 'd': X deluser = strdup(optarg); X ++exclusive; X break; X case 'g': X thisgroup = strdup(optarg); X break; X case 'D': X purge = TRUE; X ++exclusive; X break; X case 'l': X list = TRUE; X ++exclusive; X break; X default: X usage(); X } X } X X if (exclusive > 1 || optind < argc) { X usage(); X } X X if (!isroot() && NULL != thisgroup) { X fprintf(stderr, "Only root can add members to different groups\n"); X exit(EXIT_NOT_ROOT); X } else if (isroot() && NULL != thisgroup) { X name = thisgroup; X } else if (!isgroup()) { X fprintf(stderr, "Group access is required\n"); X exit(EXIT_NOT_EROOT); X } else if (NULL == (name = whoami())) { X fprintf(stderr, "Not primary owner of current group\n"); X exit(EXIT_NOT_PRIMARY); X } X X if (!gr_lock()) { X fprintf(stderr, "Unable to lock group file\n"); X exit(EXIT_GROUP_FILE); X } X X if (!gr_open(O_RDWR)) { X fprintf(stderr, "Unable to open group file\n"); X exit(EXIT_GROUP_FILE); X } X X grp = (struct group *)gr_locate(name); X X if (NULL != adduser) { X addtogroup(adduser, grp->gr_mem); X gr_update(grp); X } else if (NULL != deluser) { X rmfromgroup(deluser, grp->gr_mem); X gr_update(grp); X } else if (purge) { X nomembers(grp->gr_mem); X gr_update(grp); X } else if (list) { X members(grp->gr_mem); X } X X if (!gr_close()) { X fprintf(stderr, "Cannot close group file\n"); X exit(EXIT_GROUP_FILE); X } X X gr_unlock(); X X exit(EXIT_SUCCESS); } X /* EOF */ SHAR_EOF (set 20 00 05 25 14 36 38 'groupmems.c'; eval "$shar_touch") && chmod 0644 'groupmems.c' || $echo 'restore of' 'groupmems.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'groupmems.c:' 'MD5 check failed' f0dd68f8d762d89d24d3ce1f4141f981 groupmems.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'groupmems.c'`" test 6348 -eq "$shar_count" || $echo 'groupmems.c:' 'original size' '6348,' 'current size' "$shar_count!" fi fi # ============= groupmems.8 ============== if test -f 'groupmems.8' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'groupmems.8' '(file already exists)' else $echo 'x -' extracting 'groupmems.8' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'groupmems.8' && X.\" X.\" SPDX-FileCopyrightText: 2000, International Business Machines, Inc. X.\" SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com X.\" SPDX-License-Identifier: BSD-3-Clause X.\" X.\" $Id$ X.\" X.TH GROUPMEMS 8 X.SH NAME groupmems \- Administer members of a user's primary group X.SH SYNOPSIS X.B groupmems \fB-a\fI user_name \fR | \fB-d\fI user_name \fR | \fB-l\fR | \fB-D\fR | [\fB-g\fI group_name \fR] X.SH DESCRIPTION The \fBgroupmems\fR utility allows a user to administer their own group membership list without the requirement of superuser privileges. The \fBgroupmems\fR utility is for systems that configure its users to be in their own name sake primary group (i.e., guest / guest). X.P Only the superuser, as administrator, can use \fBgroupmems\fR to alter the memberships of other groups. X.IP "\fB-a \fIuser_name\fR" Add a new user to the group membership list. X.IP "\fB-d \fIuser_name\fR" Delete a user from the group membership list. X.IP "\fB-l\fR" List the group membership list. X.IP "\fB-D\fR" Delete all users from the group membership list. X.IP "\fB-g \fIgroup_name\fR" The superuser can specify which group membership list to modify. X.SH SETUP The \fBgroupmems\fR executable should be in mode \fB2770\fR as user \fBroot\fR and in group \fBgroups\fR. The system administrator can add users to group groups to allow or disallow them using the \fBgroupmems\fR utility to manager their own group membership list. X.P X $ groupadd -r groups X.br X $ chmod 2770 groupmems X.br X $ chown root.groups groupmems X.br X $ groupmems -g groups -a gk4 X.SH FILES /etc/group X.br /etc/gshadow X.SH SEE ALSO X.BR chfn (1), X.BR chsh (1), X.BR useradd (8), X.BR userdel (8), X.BR usermod (8), X.BR passwd (1), X.BR groupadd (8), X.BR groupdel (8) X.SH AUTHOR George Kraft IV (gk4@us.ibm.com) X.\" EOF SHAR_EOF (set 20 00 05 25 14 38 23 'groupmems.8'; eval "$shar_touch") && chmod 0600 'groupmems.8' || $echo 'restore of' 'groupmems.8' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'groupmems.8:' 'MD5 check failed' 181e6cd3a3c9d3df320197fa2cde2b4a groupmems.8 SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'groupmems.8'`" test 3372 -eq "$shar_count" || $echo 'groupmems.8:' 'original size' '3372,' 'current size' "$shar_count!" fi fi rm -fr _sh10937 exit 0