Closes #238 Update all files to list SPDX license shortname. Most files are BSD 3 clause license. The exceptions are: serge@sl ~/src/shadow$ git grep SPDX-License | grep -v BSD-3-Clause contrib/atudel:# SPDX-License-Identifier: BSD-4-Clause lib/tcbfuncs.c: * SPDX-License-Identifier: 0BSD libmisc/salt.c: * SPDX-License-Identifier: Unlicense src/login_nopam.c: * SPDX-License-Identifier: Unlicense src/nologin.c: * SPDX-License-Identifier: BSD-2-Clause src/vipw.c: * SPDX-License-Identifier: GPL-2.0-or-later Signed-off-by: Serge Hallyn <serge@hallyn.com>
		
			
				
	
	
		
			466 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			466 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
| #!/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 <gk4@gnu.austin.ibm.com>.
 | |
| # 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 <stdio.h>
 | |
| #include <pwd.h>
 | |
| #include <grp.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #include <fcntl.h>
 | |
| #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
 |