1
0
Files
irix-657m-src/eoe/cmd/grpck/grpck.c
2022-09-29 17:59:04 +03:00

338 lines
6.5 KiB
C

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)grpck:grpck.c 1.3"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <pwd.h>
#include <limits.h>
#define BADLINE "Too many/few fields"
#define TOOLONG "Line too long"
#define NONAME "No group name"
#define BADNAME "Bad character(s) in group name"
#define BADGID "Invalid GID"
#define NULLNAME "Null login name"
#define NOTFOUND "Logname not found in password file"
#define DUPNAME "Duplicate logname entry"
#define NOMEM "Out of memory"
#define NGROUPS "Maximum groups exceeded for logname "
int eflag, badchar, baddigit,badlognam,colons,len,i;
#define MYBUFSIZE 512 /* max line length including newline and null */
char buf[MYBUFSIZE];
char tmpbuf[MYBUFSIZE];
char *nptr;
char *cptr;
FILE *fptr;
int delim[MYBUFSIZE];
gid_t gid;
int error();
struct group {
struct group *nxt;
int cnt;
gid_t grp;
};
struct node {
struct node *next;
int ngroups;
struct group *groups;
char user[1];
};
void *
emalloc(size)
{
void *vp;
vp = malloc(size);
if (vp == NULL) {
fprintf(stderr, "%s\n", NOMEM);
exit(1);
}
return vp;
}
main (argc,argv)
int argc;
char *argv[];
{
struct passwd *pwp;
struct node *root = NULL;
struct node *t;
struct group *gp;
int ngroups_max;
#ifdef NOT_WORKING
int listlen; /* See comments below */
#endif /* NOT_WORKING */
int i;
char c; /* SGI */
int ypflag; /* SGI */
ngroups_max = sysconf(_SC_NGROUPS_MAX);
if ( argc == 1)
argv[1] = "/etc/group";
else if ( argc != 2 ) {
printf ("\nusage: %s filename\n\n",*argv);
exit(1);
}
if ( ( fptr = fopen (argv[1],"r" ) ) == NULL ) {
printf ("\ncannot open file %s\n\n",argv[1]);
exit(1);
}
while ((pwp = getpwent()) != NULL) {
t = (struct node *)emalloc(sizeof(*t) + strlen(pwp->pw_name));
t->next = root;
root = t;
strcpy(t->user, pwp->pw_name);
t->ngroups = 1;
if (!ngroups_max)
t->groups = NULL;
else {
t->groups = (struct group*)
emalloc(sizeof(struct group));
t->groups->grp = pwp->pw_gid;
t->groups->cnt = 1;
t->groups->nxt = NULL;
}
}
while(fgets(buf,MYBUFSIZE,fptr) != NULL ) {
eflag=0; /* Bug fix to allow printing of TOOLONG error */
ypflag=0; /* SGI */
if ( buf[0] == '\n' ) /* blank lines are ignored */
continue;
i = strlen(buf);
if ( (i == (MYBUFSIZE-1)) && (buf[i-1] != '\n') ) {
/* line too long */
buf[i-1] = '\n'; /* add newline for printing */
error(TOOLONG);
#ifdef NOT_WORKING
/*
* If two lines fail the "TOOLONG" test and the lines are
* back to back in the group file - The following code will
* not report an error message on the second line that is
* "TOOLONG". Thus, reason for ifdefing code out.
*/
while(fgets(tmpbuf,MYBUFSIZE,fptr) != NULL ) {
i = strlen(tmpbuf);
if ( (i == (MYBUFSIZE-1))
&& (tmpbuf[i-1] != '\n') )
/* another long line */
continue;
else
break;
}
#endif /* NOT_WORKING */
/* done reading continuation line(s) */
while((c = getc(fptr)) != '\n'); /* SGI */
strcpy(tmpbuf, buf);
} else {
/* change newline to comma for strchr */
strcpy(tmpbuf, buf);
tmpbuf[i-1] = ',';
}
colons=0;
badchar=0;
baddigit=0;
badlognam=0;
gid=(gid_t)0;
/* Check yellow page entry - SGI */
if (buf[0] == '+' || buf[0] == '-')
ypflag++;
/* Check number of fields */
for (i=0 ; buf[i]!=NULL ; i++) {
if (buf[i]==':') {
delim[colons]=i;
++colons;
}
}
/* Addition of ypflag check - SGI */
if (!ypflag && colons != 3 ) {
error(BADLINE);
continue;
}
/* check to see that group name is at least 1 character */
/* and that all characters are printable. */
if ( buf[0] == ':' )
error(NONAME);
else {
for ( i=0; buf[i] != ':' && buf[i] != '\n' && buf[i] != '\0'; i++ ) {
if (!isprint(buf[i]) && (!ypflag))
badchar++;
}
if ( badchar > 0 )
error(BADNAME);
}
/*
* If a yp entry in group file - ignore the following checks :
* valid gid, null login name, valid login name in passwd
* and duplicate login names. - SGI
*/
if (ypflag)
continue;
len = ( delim[2] - delim[1] ) - 1;
if ( len <= 5 && len > 0 ) {
for ( i=(delim[1]+1); i < delim[2] && !baddigit; i++ ) {
if (!isdigit(buf[i]))
baddigit++;
else /* converts ascii GID to decimal */
gid=gid * 10 + (gid_t)(buf[i] - '0');
}
if ( !baddigit && (gid > UID_MAX || gid < (gid_t)0) )
baddigit++;
}
else
baddigit++;
if (baddigit > 0) {
error(BADGID);
continue;
}
nptr = &tmpbuf[delim[2]];
nptr++;
#ifdef NOT_WORKING
listlen = strlen(nptr) - 1; /* See comments below */
#endif /* NOT_WORKING */
while ( ( cptr = strchr(nptr,',') ) != NULL ) {
*cptr=NULL;
/* Checking for groups with null login name */
if (*nptr == NULL) {
#ifdef NOT_WORKING
/*
* If this "if" statement is kept then group names
* that are null would not have been caught as errors.
*/
if (listlen)
error(NULLNAME);
#endif /* NOT_WORKING */
error(NULLNAME);
nptr++;
continue;
}
/* check that logname appears in the passwd file */
for (t = root; ; t = t->next) {
if (t == NULL){
badlognam++;
error(NOTFOUND);
goto getnext;
}
if (strcmp(t->user, nptr) == 0)
break;
}
if (!ngroups_max)
goto getnext;
t->ngroups++;
/* check for duplicate logname in group */
for (gp = t->groups; gp != NULL; gp = gp->nxt) {
if (gid == gp->grp) {
if (gp->cnt++ == 1) {
badlognam++;
error(DUPNAME);
}
goto getnext;
}
}
gp = (struct group*)emalloc(sizeof(struct group));
gp->grp = gid;
gp->cnt = 1;
gp->nxt = t->groups;
t->groups = gp;
getnext:
nptr = ++cptr;
}
}
if (ngroups_max) {
for (t = root; t != NULL; t = t->next) {
if (t->ngroups > ngroups_max)
fprintf(stderr,"\n\n%s%s (%d)\n",
NGROUPS, t->user, t->ngroups);
}
}
}
/* Error printing routine */
error(msg)
char *msg;
{
if ( eflag==0 ) {
fprintf(stderr,"\n\n%s",buf);
eflag=1;
}
if ( badchar != 0 ) {
fprintf (stderr,"\t%d %s\n",badchar,msg);
badchar=0;
return;
}
else if ( baddigit != 0 ) {
fprintf (stderr,"\t%s\n",msg);
baddigit=0;
return;
}
else if ( badlognam != 0 ) {
fprintf (stderr,"\t%s - %s\n",nptr,msg);
badlognam=0;
return;
}
else {
fprintf (stderr,"\t%s\n",msg);
return;
}
}