home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / finger / part04 / switch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-03  |  7.0 KB  |  307 lines

  1. /*
  2.  * switch.c -- process switches (flags)    July 1987
  3.  *
  4.  * Copyright (C) 1987, 1990  Philip L. Budne
  5.  *
  6.  * This file is part of "Phil's Finger Program".
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 1, or (at your option)
  11.  * any later version.
  12.  *
  13.  */
  14.  
  15. # ifndef lint
  16. static char *rcsid = "$Id: switch.c,v 3.0 90/07/06 13:11:48 budd Rel $";
  17. # endif /* lint not defined */
  18.  
  19. # include <stdio.h>
  20. # include <strings.h>
  21. # include <ctype.h>
  22. # include <signal.h>
  23.  
  24. # ifndef sigmask
  25. # define sigmask(s) (1<<(s))
  26. # endif /* sigmask not defined */
  27.  
  28. # include "args.h"
  29. # include "finger.h"
  30.  
  31. # ifndef PAGER
  32. # define PAGER "more"
  33. # endif /* PAGER not defined */
  34.  
  35. # ifndef BUGS_TO
  36. # define BUGS_TO "bug-finger@bu-it.bu.edu"
  37. # endif /* BUGS_TO not defined */
  38.  
  39. extern char *getenv();            /* libc */
  40. extern char longversion[];        /* from version.c */
  41.  
  42. # define SWITCH(s,u,a,h) LOCAL int a();
  43. # include "switch.h"            /* define forwards */
  44. # undef SWITCH
  45.  
  46. LOCAL struct switchtab {
  47.     char *s_name;
  48.     int s_unique;
  49.     int (*s_ptr)();
  50.     char *s_help;
  51. } switches[] = {
  52. # define SWITCH(s,u,a,h) { s, u, a, h },
  53. # include "switch.h"            /* define table entries */
  54. # undef SWITCH
  55.     { NULL, NULL }
  56. };
  57.  
  58. /*
  59.  *    switch actions
  60.  */
  61.  
  62. # define SET2(what,name)    \
  63. LOCAL int CONC(set_,name) ( val ) char *val; \
  64. { if( val != NULL )fprintf(stderr, "%%Switch %s takes no args\n", STR(name)); \
  65.   what = TRUE; return( TRUE ); }
  66.  
  67. # define SETF(name) SET2(CONC(sw_,name),name)
  68. # define SETP(name) SET2(CONC(Sw.sw_,name),name)
  69.  
  70. SETF(age);
  71. SETF(berkeley);
  72. # ifdef DEBUGSW
  73. SETF(debug);
  74. # endif /* DEBUGSW defined */
  75. SETF(follow);
  76. SETF(its);
  77. SETF(jobs);
  78. SETF(nosave);
  79. SETF(output);
  80. SETF(pid);
  81. SETF(read);
  82. SETF(state);
  83. SETF(whois);
  84.  
  85. /* per person */
  86. SETP(location);
  87. SETP(mail);
  88. SETP(match);
  89. SETP(plan);
  90. SETP(noplan);
  91.  
  92. # if 0
  93. LOCAL int set_fields( val )
  94. char *val;
  95. {
  96.     if( val == NULL ) {
  97.     sw_fields = ":";
  98.     return( TRUE );
  99.     }
  100.     sw_fields = val;
  101.     return( TRUE );
  102. } /* set fields */
  103. # endif /* 0 */
  104.  
  105. # ifdef INQUIRE
  106. LOCAL int set_noinquire( val )
  107. char *val;
  108. {
  109.     extern BOOL useinquire;
  110.     useinquire = FALSE;
  111.     return( TRUE );
  112. } /* set noinquire */
  113. # endif /* INQUIRE defined */
  114.  
  115. LOCAL int display_version( val )
  116. char *val;
  117. {
  118.     puts( longversion );
  119. # ifndef lint
  120.     puts( Copyright );
  121. # endif /* lint not defined */
  122.     exit( 0 );
  123.     return( TRUE );            /* supress complaints */
  124. }
  125.  
  126. LOCAL FILE *openpager(pager, mode, pid)
  127.     char *pager, *mode;
  128.     int *pid;
  129. {
  130.     int pipefd[2], myend;
  131.     register c;
  132.  
  133.     if( pipe(pipefd) < 0 ) {
  134.     perror( "pipe" );
  135.     return( NULL );
  136.     }
  137.  
  138.     /* NOTE!! we depend on myend^1 being the other end */
  139.     /* and that the child will connect myend to fd myend */
  140.  
  141.     if( *mode == 'r' )            /* parent reading? */
  142.     myend = 1;            /* child gets write/stdout */
  143.     else                /* parent writing. */
  144.     myend = 0;            /* child gets read/stdin */
  145.  
  146.     switch( (*pid = fork()) ) {
  147.     case -1:
  148.     perror( "fork" );
  149.     close( pipefd[0] );        /* close reader */
  150.     close( pipefd[1] );        /* close writer */
  151.     return( NULL );
  152.  
  153.     case 0:                /* child */
  154.     close( pipefd[myend^1] );    /* close other end */
  155.     if( pipefd[myend] != myend ) {    /* in place?? (unlikely) */
  156.         dup2( pipefd[myend], myend ); /* Nope, move it */
  157.         close( pipefd[ myend ] );
  158.     } /* not yet in place */
  159.     setuid( getuid() );        /* remove any setuidness!!! */
  160.     setgid( getgid() );
  161.     execlp( pager, pager, 0 );    /* forgo doing "sh -c cmd" */
  162.     perror( pager );
  163.     while( (c = getchar()) != EOF )    /* whoops!! Just copy bytes! */
  164.         putchar( c );
  165.     exit( 0 );
  166.     /* NOTREACHED */
  167.  
  168.     default:                /* parent */
  169.     myend ^= 1;            /* parent gets other end */
  170.     close( pipefd[myend^1] );    /* close childs end */
  171.     return( fdopen( pipefd[myend], mode ) ); /* use "rw"[myend] ?? */
  172.                     /* check for failure!! */
  173.     } /* switch */
  174.     /* NOTREACHED */
  175. } /* openpager */
  176.  
  177. LOCAL int closepager( f, pid )
  178.     FILE *f;
  179.     int pid;
  180. {
  181.     int pid2, w, smask;
  182.  
  183.     fclose( f );
  184. # ifndef USG
  185.     smask = sigblock( sigmask(SIGHUP) | sigmask(SIGQUIT) | sigmask(SIGINT) );
  186. # else  /* USG defined */
  187. # ifdef SIGPOLL                /* SVR3 signaling */
  188.     sighold( SIGHUP );
  189.     sighold( SIGQUIT );
  190.     sighold( SIGINT );
  191. # endif /* SIGPOLL defined */
  192. # endif /* USG defined */
  193.  
  194.     while( (pid2 = wait(&w)) != -1 && pid2 != pid )
  195.     printf("%d %d\n", pid, pid2);
  196.  
  197. # ifndef USG
  198.     sigsetmask( smask );
  199. # else  /* USG defined */
  200. # ifdef SIGPOLL                /* SVR3 signaling features */
  201.     sigrelse( SIGHUP );
  202.     sigrelse( SIGQUIT );
  203.     sigrelse( SIGINT );
  204. # endif /* SIGPOLL defined */
  205. # endif /* USG defined */
  206.  
  207.     if( pid2 == -1 )
  208.     return( -1 );            /* process not found? */
  209.     return( w );            /* return (whole) status */
  210. } /* closepager */
  211.  
  212. LOCAL int display_help( val )
  213. char *val;
  214. {
  215.     static char help_format[] = "%-15s %s\n"; /* just one copy */
  216.     register struct switchtab *sp;
  217.     char *pager;
  218.     int pid;
  219.     FILE *p;
  220.  
  221.     if( (pager = getenv("PAGER")) == NULL )
  222.     pager = PAGER;
  223.  
  224.     if( !isatty(STD_INPUT) || (p = openpager( pager, "w", &pid )) == NULL ) {
  225.     pager = NULL;            /* oh well */
  226.     p = stdout;
  227.     } /* openpager failed */
  228.  
  229.     fprintf( p, "finger/whois help:\n");
  230.     fprintf( p, "%s\n",  longversion );
  231. # ifndef lint
  232.     fprintf( p, "%s\n",  Copyright );
  233. # endif /* lint not defined */
  234.     fprintf( p, "\n\
  235. finger accepts the following as arguments:\n\
  236. local usernames, local personal names, switches (/sw or -sw),\n\
  237. terminal names (+tty0d +0d), self (.), or remote (@host, user@host)\n\
  238. \n");
  239.     fprintf( p, help_format, "switch", "action");
  240.     fprintf( p, help_format, "======", "======");
  241.     for( sp = switches; sp->s_help != NULL; sp++ )
  242.     fprintf( p, help_format, sp->s_name, sp->s_help );
  243.     fprintf( p, "\n");
  244.     fprintf( p, "for more information type 'man finger', bugs to %s\n",
  245.         BUGS_TO );
  246.     fflush( p );
  247.     if( pager != NULL )            /* have pager process? */
  248.     closepager( p, pid );        /* be tidy */
  249.     exit( 0 );
  250.     return( TRUE );            /* keep gcc quiet */
  251. } /* display_help */
  252.  
  253. GLOBAL void doswitch( cp )        /* see also args.h */
  254. register char *cp;
  255. {
  256.     register char *tp, *vp, *ttp;
  257.     register struct switchtab *sp;
  258.     register len;
  259.     int match;
  260.  
  261.     for( ; cp != NULL ; cp = tp ) {
  262.     tp = index( cp, '/' );
  263.     if( tp != NULL )
  264.         *tp++ = EOS;
  265.  
  266.     if( (vp = index(cp,':')) != NULL )
  267.         *vp++ = EOS;
  268.  
  269.     len = strlen( cp );
  270.     if( len == 0 )
  271.         continue;
  272.  
  273.     for( ttp = cp; *ttp != EOS; ttp++ )
  274.         if( isupper( *ttp ) )
  275.         *ttp = tolower( *ttp );
  276.  
  277.     match = 0;
  278.     sp = switches;
  279.     while( sp->s_name != NULL ) {
  280.         if( strncmp(cp, sp->s_name, len) == 0 ) {
  281.         match++;
  282.         if( len >= sp->s_unique ) {
  283.             (void) (*(sp->s_ptr))( vp );
  284.             match = 1;        /* force uniqueness */
  285.             break;
  286.         }
  287.         } /* if strncmp [i] */
  288.         sp++;
  289.     } /* while */
  290.     if( match > 1 ) {
  291.         fprintf(stderr, "?Ambiguous switch '%s'. Use /help for help\n",
  292.             cp );
  293.         exit( 1 );
  294.     }
  295.     else if( sp->s_name == NULL ) {
  296.         fprintf(stderr, "?Unknown switch '%s'. Use /help for help\n", cp );
  297.         exit( 1 );
  298.     }
  299.     } /* for ever */
  300. } /* doswitch */
  301.  
  302. /*
  303.  * Local variables:
  304.  * comment-column: 40
  305.  * End:
  306.  */
  307.