Safe coding practices (was Re: Bug in users command)

Jef Poskanzer jef at well.sf.ca.us
Fri Jan 25 14:51:49 AEST 1991


In the referenced message, diamond at jit345.enet@tkou02.enet.dec.com (Norman Diamond) wrote:
}>Gosh, in ten years, if every trend in computer usage magically reverses
}>itself, I'll get a message telling me to change the number from 1000 to
}>10000.
}
}Suppose someone starts logging NFS clients?  Or the clients of some other
}service?  1000 would already be a bit small for that.

Huh?  In the users command?  What are you talking about?  Stick to the
given problem domain.

}>Yes, it does check for overflow.
}
}Uh, you mean that it doesn't abort on overflow, but only gives inaccurate
}answers.  OK, so your example does about 1/4 of what a good example would do.

No, of course that's not what I mean.  It checks for overflow, tells
you that it needs to be recompiled on overflow, and aborts on
overflow.  Why is that so hard to understand?  Complete source is
appended, so that we will have no more creative misunderstandings.
Note that it does a few more things than the usual users command.

Anyway, if you don't like the fixed-size array answer or the
doubling-realloc answer or the read it twice answer, then let's see
what you *do* like.  Time to sling some code, dude.
---
Jef

  Jef Poskanzer  jef at well.sf.ca.us  {apple, ucbvax, hplabs}!well!jef
                            INSPECTED BY #6

/*
** users - show users, with those on a list highlighted
**
** version of 10oct90
**
** Copyright (C) 1990 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <utmp.h>
#ifndef UT_NAMESIZE
#define UT_NAMESIZE 8
#endif
#ifndef _PATH_UTMP
#define _PATH_UTMP "/etc/utmp"
#endif

#define TBUFSIZE 1024
#define MAXNAMES 1000
#define LINEWIDTH 79

extern char* getenv();
extern char* tgetstr();
int cmp();
int inlist();
void putch();

main( argc, argv )
    int argc;
    char* argv[];
    {
    char* term;
    char* strptr;
    char* soptr;
    char* septr;
    int smart;
    char buf[TBUFSIZE];
    static char strbuf[TBUFSIZE];
    struct utmp u;
    FILE* fp;
    static char friends[MAXNAMES][UT_NAMESIZE+1];
    static char users[MAXNAMES][UT_NAMESIZE+1];
    int i, nfriends, nusers;
    int wid;

    /* Check args. */
    if ( argc == 1 )
	;
    else if ( argc == 3 && strcmp( argv[1], "-h" ) == 0 )
	{
	/* Read the friends list. */
	fp = fopen( argv[2], "r" );
	if ( fp == NULL )
	    {
	    perror( argv[2] );
	    exit( 1 );
	    }
	nfriends = 0;
	while ( fgets( buf, sizeof(buf), fp ) != NULL )
	    {
	    if ( buf[strlen(buf)-1] == '\n' )
		buf[strlen(buf)-1] = '\0';
	    if ( nfriends >= MAXNAMES )
		{
		(void) fprintf( stderr, "Oops, too many names in the friends file.  Gotta increase MAXNAMES.\n" );
		exit( 1 );
		}
	    (void) strncpy( friends[nfriends], buf, UT_NAMESIZE );
	    friends[nfriends][UT_NAMESIZE] = '\0';
	    ++nfriends;
	    }
	(void) fclose( fp );
	/* qsort( friends, nfriends, sizeof(friends[0]), cmp ); */
	}
    else
	{
	(void) fprintf( stderr, "usage:  %s [-h highlightlist]\n", argv[0] );
	exit( 1 );
	}

    /* Initialize termcap stuff. */
    if ( isatty( fileno( stdout ) ) == 0 )
	smart = 0;
    else
	{
	term = getenv( "TERM" );
	if ( term == 0 )
	    smart = 0;
	else if ( tgetent( buf, term ) <= 0 )
	    smart = 0;
	else
	    {
	    strptr = strbuf;
	    soptr = tgetstr( "so", &strptr );
	    septr = tgetstr( "se", &strptr );
	    if ( soptr == NULL || septr == NULL )
		smart = 0;
	    else
		smart = 1;
	    }
	}

    /* Open utmp and read the users. */
    fp = fopen( _PATH_UTMP, "r" );
    if ( fp == NULL )
	{
	perror( "utmp" );
	exit( 1 );
	}
    nusers = 0;
    while ( fread( (char*) &u, sizeof(u), 1, fp ) == 1 )
	{
	if ( u.ut_name[0] != '\0' )
	    {
	    if ( nusers >= MAXNAMES )
		{
		(void) fprintf( stderr, "Oops, too many users logged in.  Gotta increase MAXNAMES.\n" );
		exit( 1 );
		}
	    (void) strncpy( users[nusers], u.ut_name, UT_NAMESIZE );
	    users[nusers][UT_NAMESIZE] = '\0';
	    ++nusers;
	    }
	}
    (void) fclose( fp );
    qsort( users, nusers, sizeof(users[0]), cmp );
    
    /* Show the users. */
    wid = 0;
    for ( i = 0; i < nusers; ++i )
	{
	if ( wid + strlen( users[i] ) + 3 > LINEWIDTH )
	    {
	    putchar( '\n' );
	    wid = 0;
	    }
	if ( wid > 0 )
	    {
	    putchar( ' ' );
	    ++wid;
	    }
	if ( inlist( users[i], friends, nfriends ) )
	    {
	    if ( smart )
		tputs( soptr, 1, putch );
	    else
		putchar( '<' );
	    fputs( users[i], stdout );
	    if ( smart )
		tputs( septr, 1, putch );
	    else
		putchar( '>' );
	    if ( ! smart )
		wid += 2;
	    }
	else
	    fputs( users[i], stdout );
	wid += strlen( users[i] );
	}
    putchar( '\n' );

    exit( 0 );
    }

int
cmp( a, b )
    char* a;
    char* b;
    {
    return strcmp( a, b );
    }

int
inlist( str, list, nlist )
    char* str;
    char list[MAXNAMES][UT_NAMESIZE+1];
    int nlist;
    {
    int i;

    /* (This could be made into a binary search.) */
    for ( i = 0; i < nlist; ++i )
	if ( strcmp( str, list[i] ) == 0 )
	    return 1;
    return 0;
    }

void
putch( ch )
char ch;
    {
    putchar( ch );
    }



More information about the Comp.bugs.4bsd.ucb-fixes mailing list