home *** CD-ROM | disk | FTP | other *** search
- /*
- * switch.c -- process switches (flags) July 1987
- *
- * Copyright (C) 1987, 1990 Philip L. Budne
- *
- * This file is part of "Phil's Finger Program".
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or (at your option)
- * any later version.
- *
- */
-
- # ifndef lint
- static char *rcsid = "$Id: switch.c,v 3.0 90/07/06 13:11:48 budd Rel $";
- # endif /* lint not defined */
-
- # include <stdio.h>
- # include <strings.h>
- # include <ctype.h>
- # include <signal.h>
-
- # ifndef sigmask
- # define sigmask(s) (1<<(s))
- # endif /* sigmask not defined */
-
- # include "args.h"
- # include "finger.h"
-
- # ifndef PAGER
- # define PAGER "more"
- # endif /* PAGER not defined */
-
- # ifndef BUGS_TO
- # define BUGS_TO "bug-finger@bu-it.bu.edu"
- # endif /* BUGS_TO not defined */
-
- extern char *getenv(); /* libc */
- extern char longversion[]; /* from version.c */
-
- # define SWITCH(s,u,a,h) LOCAL int a();
- # include "switch.h" /* define forwards */
- # undef SWITCH
-
- LOCAL struct switchtab {
- char *s_name;
- int s_unique;
- int (*s_ptr)();
- char *s_help;
- } switches[] = {
- # define SWITCH(s,u,a,h) { s, u, a, h },
- # include "switch.h" /* define table entries */
- # undef SWITCH
- { NULL, NULL }
- };
-
- /*
- * switch actions
- */
-
- # define SET2(what,name) \
- LOCAL int CONC(set_,name) ( val ) char *val; \
- { if( val != NULL )fprintf(stderr, "%%Switch %s takes no args\n", STR(name)); \
- what = TRUE; return( TRUE ); }
-
- # define SETF(name) SET2(CONC(sw_,name),name)
- # define SETP(name) SET2(CONC(Sw.sw_,name),name)
-
- SETF(age);
- SETF(berkeley);
- # ifdef DEBUGSW
- SETF(debug);
- # endif /* DEBUGSW defined */
- SETF(follow);
- SETF(its);
- SETF(jobs);
- SETF(nosave);
- SETF(output);
- SETF(pid);
- SETF(read);
- SETF(state);
- SETF(whois);
-
- /* per person */
- SETP(location);
- SETP(mail);
- SETP(match);
- SETP(plan);
- SETP(noplan);
-
- # if 0
- LOCAL int set_fields( val )
- char *val;
- {
- if( val == NULL ) {
- sw_fields = ":";
- return( TRUE );
- }
- sw_fields = val;
- return( TRUE );
- } /* set fields */
- # endif /* 0 */
-
- # ifdef INQUIRE
- LOCAL int set_noinquire( val )
- char *val;
- {
- extern BOOL useinquire;
- useinquire = FALSE;
- return( TRUE );
- } /* set noinquire */
- # endif /* INQUIRE defined */
-
- LOCAL int display_version( val )
- char *val;
- {
- puts( longversion );
- # ifndef lint
- puts( Copyright );
- # endif /* lint not defined */
- exit( 0 );
- return( TRUE ); /* supress complaints */
- }
-
- LOCAL FILE *openpager(pager, mode, pid)
- char *pager, *mode;
- int *pid;
- {
- int pipefd[2], myend;
- register c;
-
- if( pipe(pipefd) < 0 ) {
- perror( "pipe" );
- return( NULL );
- }
-
- /* NOTE!! we depend on myend^1 being the other end */
- /* and that the child will connect myend to fd myend */
-
- if( *mode == 'r' ) /* parent reading? */
- myend = 1; /* child gets write/stdout */
- else /* parent writing. */
- myend = 0; /* child gets read/stdin */
-
- switch( (*pid = fork()) ) {
- case -1:
- perror( "fork" );
- close( pipefd[0] ); /* close reader */
- close( pipefd[1] ); /* close writer */
- return( NULL );
-
- case 0: /* child */
- close( pipefd[myend^1] ); /* close other end */
- if( pipefd[myend] != myend ) { /* in place?? (unlikely) */
- dup2( pipefd[myend], myend ); /* Nope, move it */
- close( pipefd[ myend ] );
- } /* not yet in place */
- setuid( getuid() ); /* remove any setuidness!!! */
- setgid( getgid() );
- execlp( pager, pager, 0 ); /* forgo doing "sh -c cmd" */
- perror( pager );
- while( (c = getchar()) != EOF ) /* whoops!! Just copy bytes! */
- putchar( c );
- exit( 0 );
- /* NOTREACHED */
-
- default: /* parent */
- myend ^= 1; /* parent gets other end */
- close( pipefd[myend^1] ); /* close childs end */
- return( fdopen( pipefd[myend], mode ) ); /* use "rw"[myend] ?? */
- /* check for failure!! */
- } /* switch */
- /* NOTREACHED */
- } /* openpager */
-
- LOCAL int closepager( f, pid )
- FILE *f;
- int pid;
- {
- int pid2, w, smask;
-
- fclose( f );
- # ifndef USG
- smask = sigblock( sigmask(SIGHUP) | sigmask(SIGQUIT) | sigmask(SIGINT) );
- # else /* USG defined */
- # ifdef SIGPOLL /* SVR3 signaling */
- sighold( SIGHUP );
- sighold( SIGQUIT );
- sighold( SIGINT );
- # endif /* SIGPOLL defined */
- # endif /* USG defined */
-
- while( (pid2 = wait(&w)) != -1 && pid2 != pid )
- printf("%d %d\n", pid, pid2);
-
- # ifndef USG
- sigsetmask( smask );
- # else /* USG defined */
- # ifdef SIGPOLL /* SVR3 signaling features */
- sigrelse( SIGHUP );
- sigrelse( SIGQUIT );
- sigrelse( SIGINT );
- # endif /* SIGPOLL defined */
- # endif /* USG defined */
-
- if( pid2 == -1 )
- return( -1 ); /* process not found? */
- return( w ); /* return (whole) status */
- } /* closepager */
-
- LOCAL int display_help( val )
- char *val;
- {
- static char help_format[] = "%-15s %s\n"; /* just one copy */
- register struct switchtab *sp;
- char *pager;
- int pid;
- FILE *p;
-
- if( (pager = getenv("PAGER")) == NULL )
- pager = PAGER;
-
- if( !isatty(STD_INPUT) || (p = openpager( pager, "w", &pid )) == NULL ) {
- pager = NULL; /* oh well */
- p = stdout;
- } /* openpager failed */
-
- fprintf( p, "finger/whois help:\n");
- fprintf( p, "%s\n", longversion );
- # ifndef lint
- fprintf( p, "%s\n", Copyright );
- # endif /* lint not defined */
- fprintf( p, "\n\
- finger accepts the following as arguments:\n\
- local usernames, local personal names, switches (/sw or -sw),\n\
- terminal names (+tty0d +0d), self (.), or remote (@host, user@host)\n\
- \n");
- fprintf( p, help_format, "switch", "action");
- fprintf( p, help_format, "======", "======");
- for( sp = switches; sp->s_help != NULL; sp++ )
- fprintf( p, help_format, sp->s_name, sp->s_help );
- fprintf( p, "\n");
- fprintf( p, "for more information type 'man finger', bugs to %s\n",
- BUGS_TO );
- fflush( p );
- if( pager != NULL ) /* have pager process? */
- closepager( p, pid ); /* be tidy */
- exit( 0 );
- return( TRUE ); /* keep gcc quiet */
- } /* display_help */
-
- GLOBAL void doswitch( cp ) /* see also args.h */
- register char *cp;
- {
- register char *tp, *vp, *ttp;
- register struct switchtab *sp;
- register len;
- int match;
-
- for( ; cp != NULL ; cp = tp ) {
- tp = index( cp, '/' );
- if( tp != NULL )
- *tp++ = EOS;
-
- if( (vp = index(cp,':')) != NULL )
- *vp++ = EOS;
-
- len = strlen( cp );
- if( len == 0 )
- continue;
-
- for( ttp = cp; *ttp != EOS; ttp++ )
- if( isupper( *ttp ) )
- *ttp = tolower( *ttp );
-
- match = 0;
- sp = switches;
- while( sp->s_name != NULL ) {
- if( strncmp(cp, sp->s_name, len) == 0 ) {
- match++;
- if( len >= sp->s_unique ) {
- (void) (*(sp->s_ptr))( vp );
- match = 1; /* force uniqueness */
- break;
- }
- } /* if strncmp [i] */
- sp++;
- } /* while */
- if( match > 1 ) {
- fprintf(stderr, "?Ambiguous switch '%s'. Use /help for help\n",
- cp );
- exit( 1 );
- }
- else if( sp->s_name == NULL ) {
- fprintf(stderr, "?Unknown switch '%s'. Use /help for help\n", cp );
- exit( 1 );
- }
- } /* for ever */
- } /* doswitch */
-
- /*
- * Local variables:
- * comment-column: 40
- * End:
- */
-