Path: | icdoc!mvax.cc.ic.ac.uk!dds |
From: | dds@cc.ic.ac.uk (Diomidis Spinellis) |
Newsgroups: | comp.os.minix |
Subject: | Group commands for Minix |
Keywords: | Minix, groups |
Message-ID: | <1988Mar3.220039.5819@mvax.cc.ic.ac.uk> |
Date: | 3 Mar 88 20:00:38 GMT |
Reply-To: | dds@cc.ic.ac.uk (Diomidis Spinellis) |
Organization: | Computer Center, Imperial College, London, England |
Lines: | 450 |
Content-Length: | 9876 |
Support for the shell newgrp builtin. See the README file and the newgrp
source.
------8<-----CUT-HERE-----------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README
# chgrp.c
# getgrent.c
# grp.h
# id.c
# newgrp.c
# This archive created: Thu Mar 3 19:08:39 WET 1988
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
Here is group support for Minix. It consists of the
newgrp and chgrp commands, a modified getgrent.c and grp.h
that support group members and the id command used for
debugging.
Newgrp is a shell built in. No change is needed to the
shell as the shell already knows about it. When a user
enters the newgrp command the shell does an exec on
/bin/newgrp or /usr/bin/newgrp which should be installed as
setuid root. This checks if the user is allowed to change
group and changes the real and effective group id. It then
execs another shell.
Chgrp works like the chown command. The format of
/etc/group file needed is :
groupname:passwd:gid:user,user ...
The password can be an encrypted password, empty or
``*''. The optional list of users are users who belong to
that group without it being their default one.
In order to change group you enter newgrp optionally
followed by a group name. Newgrp without groupname returns
yyou to your default group.
If the group has a password and the user has not or if
the group has a password and the user is not in the member
list of the group the user is prompted for the group pass-
word.
The user always gets a new shell no matter if he gets
into a new group or not.
BUGS
The - option in newgrp is not supported.
AUTHOR
Diomidis D. Spinellis (dds@cc.ic.ac.uk)
SHAR_EOF
fi # end of overwriting check
if test -f 'chgrp.c'
then
echo shar: will not over-write existing file "'chgrp.c'"
else
cat << \SHAR_EOF > 'chgrp.c'
/*
* chgrp username file ...
*
* By Diomidis D. Spinellis
* Heavilly based on chown by Patrick van Kleef
*
*/
#include "grp.h"
#include "../h/type.h"
#include "stat.h"
#include "stdio.h"
main (argc, argv)
int argc;
char *argv[];
{
int i,
status = 0;
struct group *grp, *getgrnam ();
struct stat stbuf;
if (argc < 3) {
fprintf (stderr,"Usage: chgrp gid file ...\n");
exit (1);
}
if ((grp = getgrnam (argv[1])) == 0) {
fprintf (stderr,"Unknown group id: %s\n", argv[1]);
exit (4);
}
for (i = 2; i < argc; i++) {
if (stat (argv[i], &stbuf) < 0) {
perror (argv[i]);
status++;
}
else
if (chown (argv[i], stbuf.st_uid, grp -> gr_gid) < 0) {
fprintf (stderr,"%s: not changed\n", argv[i]);
status++;
}
}
exit (status);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'getgrent.c'
then
echo shar: will not over-write existing file "'getgrent.c'"
else
cat << \SHAR_EOF > 'getgrent.c'
/*
* get entry from group file
*
* By: Patrick van Kleef
* Modified by Diomidis Spinellis.
*/
#include "../include/grp.h"
#define PRIVATE static
PRIVATE char _gr_file[] = "/etc/group";
PRIVATE char _grbuf[256];
PRIVATE char _buffer[1024];
PRIVATE char *_membuf[32];
PRIVATE char *_pnt;
PRIVATE char *_buf;
PRIVATE int _gfd = -1;
PRIVATE int _bufcnt;
PRIVATE struct group grp;
setgrent ()
{
if (_gfd >= 0)
lseek (_gfd, 0L, 0);
else
_gfd = open (_gr_file, 0);
_bufcnt = 0;
return (_gfd);
}
endgrent ()
{
if (_gfd >= 0)
close (_gfd);
_gfd = -1;
_bufcnt = 0;
}
static getline ()
{
if (_gfd < 0 && setgrent () < 0)
return (0);
_buf = _grbuf;
do {
if (--_bufcnt <= 0){
if ((_bufcnt = read (_gfd, _buffer, 1024)) <= 0)
return (0);
else
_pnt = _buffer;
}
*_buf++ = *_pnt++;
} while (*_pnt != '\n');
_pnt++;
_bufcnt--;
*_buf = 0;
_buf = _grbuf;
return (1);
}
static skip_period ()
{
while (*_buf != ':')
_buf++;
*_buf++ = '\0';
}
struct group *getgrent ()
{
register i ;
if (getline () == 0)
return (0);
grp.gr_name = _buf;
skip_period ();
grp.gr_passwd = _buf;
skip_period ();
grp.gr_gid = atoi (_buf);
skip_period ();
for( i = 0 ; *_buf ; i++ ){
_membuf[i] = _buf ;
while( *_buf && *_buf != ',' )
_buf++ ;
if( *_buf )
*_buf++ = '\0' ;
}
_membuf[i] = (char *) 0 ;
grp.gr_mem = &_membuf[0] ;
return (&grp);
}
struct group *getgrnam (name)
char *name;
{
struct group *grp;
setgrent ();
while ((grp = getgrent ()) != 0)
if (!strcmp (grp -> gr_name, name))
break;
endgrent ();
if (grp != 0)
return (grp);
else
return (0);
}
struct group *getgrgid (gid)
int gid;
{
struct group *grp;
setgrent ();
while ((grp = getgrent ()) != 0)
if (grp -> gr_gid == gid)
break;
endgrent ();
if (grp != 0)
return (grp);
else
return (0);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'grp.h'
then
echo shar: will not over-write existing file "'grp.h'"
else
cat << \SHAR_EOF > 'grp.h'
struct group {
char *gr_name;
char *gr_passwd;
int gr_gid;
char **gr_mem;
};
SHAR_EOF
fi # end of overwriting check
if test -f 'id.c'
then
echo shar: will not over-write existing file "'id.c'"
else
cat << \SHAR_EOF > 'id.c'
/*
* id - Print the real and effective user and group id
*
* By Diomidis D. Spinellis
*/
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
main()
{
printf("Real : ") ;
idprint( getuid(), getgid() ) ;
printf("Effective : ") ;
idprint( geteuid(), getegid() ) ;
_cleanup() ;
exit( 0 ) ;
}
idprint( uid, gid)
int uid, gid ;
{
struct passwd *pw, *getpwuid() ;
struct group *gr, *getgrgid() ;
pw = getpwuid( uid ) ;
gr = getgrgid( gid ) ;
printf("user=%d (%s) group=%d (%s)\n",
uid,
pw ? pw->pw_name : "unknown",
gid,
gr ? gr->gr_name : "unknown"
) ;
return ;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'newgrp.c'
then
echo shar: will not over-write existing file "'newgrp.c'"
else
cat << \SHAR_EOF > 'newgrp.c'
/*
* newgrp - Change current group
*
* By Diomidis D. Spinellis
*
*/
#include <grp.h>
#include <pwd.h>
#include <sgtty.h>
/* Error messages */
#define E_USAGE "Usage : newgrp [ group ]\n"
#define E_UNKNOWN "Unknown group\n"
#define E_SORRY "Sorry !\n"
#define E_NOSHELL "You have no shell\n"
/* This is needed globaly */
struct passwd *pw ;
main(argc, argv)
int argc ;
char *argv[] ;
{
char password[14];
struct group *gr ;
struct sgttyb args;
struct passwd *getpwuid ();
struct group *getgrnam ();
char *crypt ();
int nr ;
switch( argc ){
default :
std_err( E_USAGE ) ;
newshell( -2 ) ;
case 1 :
/* Change to the users default group */
pw = getpwuid( getuid() ) ;
newshell( pw->pw_gid ) ;
case 2 :
/* Change to the group specified */
if( ! (gr = getgrnam( argv[1] ) ) ){
std_err( E_UNKNOWN ) ;
newshell( -2 ) ;
}
pw = getpwuid( getuid() ) ;
/* A user may change group if :
* He is root OR
* the group has an empty password OR
* the user is a member of the group AND
* the user has a non empty password OR
* the group has a password and the user enters it correctly
*/
if( getuid() == 0 || *gr->gr_passwd == '\0' )
newshell( gr->gr_gid ) ;
if( ismember( pw->pw_name, gr->gr_mem ) && *pw->pw_passwd != '\0' )
newshell( gr->gr_gid ) ;
if( isequal( gr->gr_passwd, "*" ) )
newshell( -1 ) ;
/*
* Ask for password
* (Code copied from su.c)
*/
std_err("Password: ");
ioctl (0, TIOCGETP, &args); /* get parameters */
args.sg_flags = args.sg_flags & (~ECHO);
ioctl (0, TIOCSETP, &args);
nr = read (0, password, 14);
password[nr - 1] = '\0';
std_err("\n") ;
args.sg_flags = args.sg_flags | ECHO;
ioctl (0, TIOCSETP, &args);
if( isequal(gr->gr_passwd, crypt (password, gr->gr_passwd) ) )
newshell( gr->gr_gid ) ;
else
newshell( -1 ) ;
}
}
/*
* Give the user a new shell with a specified gid.
* If the gid is -1 say you are sorry.
*/
newshell( gid )
int gid ;
{
char *shell = "/bin/sh" ;
if( gid >= 0 )
setgid( gid ) ;
else if( gid == -1 )
std_err( E_SORRY ) ;
setuid( pw->pw_uid ) ;
if( pw->pw_shell[0] )
shell = pw->pw_shell ;
execn( shell ) ;
execn( "/bin/sh" ) ;
execn( "/usr/bin/sh" ) ;
std_err( E_NOSHELL ) ;
exit(3);
}
/*
* Return true if the two strings are equal
*/
int
isequal( s1, s2 )
char *s1, *s2 ;
{
while( *s1 && *s2 )
if( *s1++ != *s2++ )
return 0 ;
return *s1 == *s2 ;
}
/*
* Return true if name n is in the null terminated array of groups g
*/
int
ismember(n, g)
char *n, **g ;
{
register i ;
for( i = 0 ; g[i] ; i++ )
if( isequal(n, g[i] ) )
return 1 ;
return 0 ;
}
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
--
Diomidis D. Spinellis, Imperial College | echo `/usr/games/fortune -o`
dds@cc.ic.ac.uk |
Newsgroup comp.os.minix contents
Newsgroup list
Diomidis Spinellis home page
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.