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

  1. /*
  2.  * finger.c -- output formatting for finger (main is in args.c)
  3.  *
  4.  * Copyright (C) 1986, 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: finger.c,v 3.0 90/07/06 13:10:35 budd Rel $";
  17. # endif /* lint not defined */
  18.  
  19. # include <sys/types.h>
  20. # include <stdio.h>
  21. # include "person.h"
  22. # include "output.h"
  23. # include "args.h"            /* before luser.h */
  24. # include "luser.h"
  25. # include "finger.h"
  26. # include "pr.h"
  27. # include "inquire.h"            /* for INQUIRE */
  28. # include "ttylocfile.h"
  29.  
  30. # define PID_COL        /* display /pid in seperate column */
  31.  
  32. /*# define RELATION            /* display REL if this is defined */
  33. /*# define REL_SUP ""        /* (define as quoted string of relations */
  34.                 /*  to supress display of) */
  35.  
  36. FORWARD LOCAL void
  37. # ifdef RELATION
  38.     prelation(),
  39. # endif /* RELATION defined */
  40.     pusername(), pgroup(), pspace(), ppname(),
  41.     pcmd(), pidle(), pbiff(), ptty(), pmesg(), plocation(), ppid(),
  42.     pstr(), pchar(), togoal();
  43.  
  44. LOCAL int outcol, goalcol;
  45.  
  46. # define USER_WID 8
  47. # define PROG_WID 7            /* 6 prog + 1 flag */
  48.  
  49. # ifndef TTY_WID
  50. # ifdef AIX3
  51. # define TTY_WID 6
  52. # else  /* AIX3 not defined */
  53. # if defined(UmaxV) || defined(PTS_PTY_NAMES)
  54. # define TTY_WID 5            /* rtAAPPS or ptsNN */
  55. # else  /* not defined(UmaxV) || defined(PTS_PTY_NAMES) */
  56. # define TTY_WID 3
  57. # endif /* not defined(UmaxV) || defined(PTS_PTY_NAMES) */
  58. # endif /* AIX3 not defined */
  59. # endif /* TTY_WID not defined */
  60.  
  61. # define BASE_PER_WID (22+3+3)        /* base person width */
  62.  
  63. typedef void (*FPTR)();
  64.  
  65. FPTR fields[] = {
  66.     pusername,
  67.     pspace,
  68.     pgroup,
  69. # ifdef RELATION
  70. # define GRPREL_WID 3            /* 2 + space */
  71.     prelation,
  72. # else  /* RELATION not defined */
  73. # define GRPREL_WID 2            /* 1 + space */
  74. # endif /* RELATION not defined */
  75.     pspace,
  76.     ppname,
  77.     NULL
  78. }; /* fields */
  79.  
  80. # define PER_WID (BASE_PER_WID-TTY_WID-GRPREL_WID)
  81.  
  82.  
  83. FPTR fields2[] = {
  84. # ifdef PID_COL
  85.     ppid,
  86. # endif /* PID_COL defined */
  87. # ifndef SUPPRESS_WHAT
  88.     pcmd,
  89. # endif /* SUPPRESS_WHAT not defined */
  90.     pidle,
  91.     pbiff,
  92.     ptty,
  93.     pmesg,
  94.     plocation,
  95.     NULL
  96. }; /* fields2 */
  97.  
  98. /* display when program running from another uid */
  99. # ifndef SUID_ROOT
  100. # define SUID_ROOT '+'
  101. # endif /* SUID_ROOT not defined */
  102.  
  103. # ifndef SUID_OTHER
  104. # define SUID_OTHER '!'
  105. # endif /* SUID_OTHER not defined */
  106.  
  107. /* when no command found */
  108. # ifndef EMPTY_CMD
  109. # define EMPTY_CMD "??"
  110. # endif /* EMPTY_CMD not defined */
  111.  
  112. # define NO_GROUP ' '
  113.  
  114. # ifdef RELATION
  115. # define REL_HEADER 'R'
  116. # define GRP_HEADER 'G'
  117. # else  /* RELATION not defined */
  118. # define GRP_HEADER ' '        /* or 'G' */
  119. # endif /* RELATION not defined */
  120.  
  121. /****** what to show when there is no person structure ******/
  122. # define NO_RELATION ' '
  123.  
  124. # ifdef INQUIRE
  125. # define NO_NAME "--No inquire entry--"
  126. # else  /* INQUIRE not defined */
  127. # define NO_NAME "--No password entry--" /* acucntrl locks?!*/
  128. # endif /* INQUIRE not defined */
  129.  
  130. extern LTREE *maketree();        /* from getent.c */
  131. extern struct pr *getcommand();        /* from getcommand.c */
  132. extern char *getttyloc();        /* from gettyloc.c */
  133. extern int pwtree();            /* from getperson.c */
  134. extern whois(), plan();            /* from whois.c */
  135. extern char *gtname(), *intstr();    /* from output.c */
  136.  
  137. LOCAL time_t now;            /* current time */
  138. LOCAL int personwidth;            /* calculated at runtime! */
  139.  
  140. LOCAL void                /* forwards.. */
  141.     finguser(),
  142.     fingheader(),
  143.     dogecos();
  144.  
  145. GLOBAL void dofinger( t )
  146. LTREE *t;
  147. {
  148.     int n;
  149.  
  150.     personwidth = PER_WID;
  151. # ifdef PID_COL
  152. # define PID_WID 6
  153.     if( sw_pid )
  154.     personwidth -= PID_WID/2;
  155. # endif /* PID_COL defined */
  156.  
  157. # ifdef LASTLOG
  158.     llopen();                /* open lastlog file */
  159. # endif /* LASTLOG defined */
  160.  
  161.     time( &now );            /* get current time */
  162.     if( t == NULL )            /* nothing? */
  163.     pwtree( (t = maketree()) );    /* get tree of all logged in users */
  164.  
  165.     n = treesize( t );            /* count users */
  166.     if( n == 0 )
  167.     puts("No one logged in.");
  168.     else {
  169. # ifndef ALWAYS_PRINT_HEADER
  170.     if( n > 1 )            /* be like oz finger */
  171. # endif /* ALWAYS_PRINT_HEADER not defined */
  172.         fingheader();        /* print header */
  173.  
  174.     ptree( t, finguser );        /* print tree */
  175.     } /* n != 0 */
  176.  
  177. # ifdef LASTLOG
  178.     llclose();                /* close lastlog file */
  179. # endif /* LASTLOG defined */
  180. } /* finger */
  181.  
  182. LOCAL BOOL same;
  183.  
  184. LOCAL void finguser(u)
  185. register LUSER *u;
  186. {
  187.     static PERSON *person;
  188.     static int incarnations;
  189.     register FPTR *fp;
  190.  
  191.     if( u->u_person != NULL ) {
  192.     if( (u->u_person->p_flags & P_RC) != 0 ) { /* pw_gecos == "RC" ?*/
  193.         dogecos( u );
  194.         return;
  195.     } /* RC hack */
  196.     } /* run command */
  197.  
  198.     if( u->u_flags & U_NLI ) {        /* not logged in */
  199.     char location[ 50 ];
  200.     time_t ltime;            /* last login time */
  201.     int host;
  202.     PERSON *p;
  203.  
  204.     p = u->u_person;
  205.     same = FALSE;            /* crock, pass as arg? *TODO* */
  206.     for( fp = fields; *fp != NULL; fp++ )
  207.         (*fp)( FALSE, u, p );
  208.     goalcol++;            /* space */
  209.  
  210.     /* get last login time from lastlog */
  211.     if( p == NULL || (p->p_flags & P_NOPWENT) )
  212.         pstr( "NO PASSWORD ENTRY (EXPIRED ACCOUNT?)" ); /* no pw ent? */
  213. # ifdef LASTLOG
  214.     else if( !lltime( p->p_uid, location, <ime, &host ) || ltime == 0 )
  215.         pstr( "Login Unknown" );    /* no login time */
  216.     else {                /* have login time. format it */
  217.         int printed;
  218.         TTYLOC *tp;
  219.  
  220.         pstr( "Login " );
  221.         pstr( nicetime( ltime ) );
  222.  
  223.         /* TODO: if sw_its no "from...." */
  224.         pstr( " from " );
  225.         printed = FALSE;
  226.         inittylocs();
  227.         if( !host && (tp = findttyloc( location )) != NULL ) {
  228.         char *s;
  229.         if( tp->t_short != NULL )
  230.             s = tp->t_short;
  231.         else if( tp->t_locn != NULL )
  232.             s = tp->t_locn;
  233.         else
  234.             s = NULL;
  235.         if( s != NULL ) {
  236.             printed = TRUE;
  237.             pstr( s );
  238.             pchar('{');
  239.             pstr( location );
  240.             pchar('}');
  241.         }
  242.         } /* foundttyloc */
  243.         if( !printed )
  244.         pstr( location );
  245.     } /* have login time */
  246. # endif /* LASTLOG defined */
  247.     /* if sw_its check plan */
  248.     pchar('\n');
  249.     incarnations = 1;
  250.     } /* not logged in */
  251.     else {                /* is logged in */
  252.     termstat( u );            /* get tty status (before getcommand) */
  253. # ifndef SUPPRESS_WHAT
  254.     getcommand( u );        /* get command/daemon procs */
  255. # endif /* SUPPRESS_WHAT not defined */
  256.  
  257. # ifndef NEVER_SAME
  258.     if( u->u_person != NULL && u->u_person == person ) /* same person */
  259.         same = TRUE;        /* as before? */
  260.     else
  261. # endif /* NEVER_SAME not defined */
  262.         same = FALSE;
  263.  
  264.     person = u->u_person;
  265.     if( !same )
  266.         if( person != NULL )
  267.         incarnations = person->p_count;
  268.         else
  269.         incarnations = 1;
  270.  
  271.     for( fp = fields; *fp != NULL; fp++ )
  272.         (*fp)( FALSE, u, person );
  273.     goalcol++;            /* blank space */
  274.     for( fp = fields2; *fp != NULL; fp++ )
  275.         (*fp)( FALSE, u, person );
  276.     pchar( '\n' );
  277.     } /* logged in */
  278.  
  279.     if( incarnations-- == 1 ) {        /* final incarnation? */
  280.     if( sw_whois ) {        /* do whois stuff */
  281.         whois( u );
  282.         blankline();
  283.     }
  284.  
  285.     if( u->u_sw.sw_mail || sw_whois || (u->u_flags & U_NLI) ) {
  286.         mcheck( u );
  287.         blankline();
  288.     }
  289.  
  290.     if( sw_whois ) {
  291.         remarks( u );
  292.         blankline();
  293.     }
  294.  
  295.     /*
  296.      * show plan if asked for.  if user not logged in
  297.      * show unless prohibited.
  298.      */
  299.     if( u->u_sw.sw_plan || (u->u_flags & U_NLI) && !u->u_sw.sw_noplan ) {
  300.         plan( u );
  301.         blankline();
  302.     }
  303.     } /* last incarnation */
  304. } /* finguser */
  305.  
  306. LOCAL void fingheader() {
  307.     FPTR *fp;
  308.  
  309.     for( fp = fields; *fp != NULL; fp++ )
  310.     (*fp)( TRUE, NULL, NULL );
  311.     goalcol++;                /* blank space */
  312.     for( fp = fields2; *fp != NULL; fp++ )
  313.     (*fp)( TRUE, NULL, NULL );
  314.     pchar( '\n' );
  315.     fflush(OUTPUT);
  316. } /* fingheader */
  317.  
  318. LOCAL void dogecos( u )            /* here if PNAME == "RC" */
  319. LUSER *u;
  320. {
  321.     int pid, wpid;
  322.  
  323.     pid = fork();            /* no vfork uses stdio */
  324.     if( pid == 0 ) {            /* be childish */
  325.     PERSON *p;
  326.     p = u->u_person;
  327.  
  328.     chdir(p->p_home);
  329.     setuid(p->p_uid);
  330.     setgid(p->p_gid);
  331.     printf("%s/%s:\n", p->p_home, u->u_user);
  332.     fflush( stdout );
  333.     execl(u->u_user, u->u_user, 0);
  334.     perror("Sorry");
  335.     exit(1);
  336.     }
  337.     else if( pid < 0 )
  338.     perror("fork");
  339.  
  340.     while( (wpid = wait(0)) > 0 && wpid != pid ) /* lassie come home!! */
  341.     ;
  342. } /* dogecos */
  343.  
  344. LOCAL void
  345. _pchar( c )
  346.     char c;
  347. {
  348.     static char linebuf[ 512 ], *lp = linebuf;
  349.     if( c == '\n' ) {
  350.     *lp = EOS;
  351.     outline( linebuf );
  352.     outcol = goalcol = 0;
  353.     lp = linebuf;
  354.     } /* newline */
  355.     else {                /* not newline */
  356.     if( c == '\t' )
  357.         outcol = (outcol + 8) & ~7;
  358.     else
  359.         outcol++;
  360.     *lp++ = c;
  361.     } /* not newline */
  362. } /* _pchar */
  363.  
  364. LOCAL void
  365. togoal() {
  366.     while( outcol < goalcol ) {
  367.     int temp;
  368.     temp = (outcol + 8) & ~7;
  369.     if( temp <= goalcol )
  370.         _pchar( '\t' );
  371.     else
  372.         _pchar( ' ' );
  373.     }
  374.     goalcol = outcol;
  375. } /* togoal */
  376.  
  377. LOCAL void
  378. pchar( c )
  379.     char c;
  380. {
  381.     if( outcol < goalcol )        /* save extra calls */
  382.     togoal();
  383.     _pchar( c );
  384. } /* pchar */
  385.  
  386. LOCAL void
  387. pstr( s )
  388.     register char *s;
  389. {
  390.     if( s == NULL )
  391.     return;
  392.     togoal();
  393.     while( *s )
  394.     _pchar( *s++ );
  395. } /* pstr */
  396.  
  397. LOCAL void
  398. pcount( c, s )
  399.     register c;
  400.     register char *s;
  401. {
  402.     if( s == NULL )
  403.     return;
  404.     togoal();
  405.     while( c-- && *s )
  406.     _pchar( *s++ );
  407. } /* pcount */
  408.  
  409. LOCAL void
  410. pusername( title, u, p )
  411.     BOOL title;
  412.     LUSER *u;
  413.     PERSON *p;
  414. {
  415.     if( title )
  416.     pstr( "-User-" );
  417.     else if( !same )
  418.     pcount( USER_WID, u->u_user );
  419.     goalcol += USER_WID;
  420. } /* pusername */
  421.  
  422. # ifdef INQUIRE
  423. # ifdef RELATION
  424. LOCAL void
  425. prelation( title, u, p )
  426.     BOOL title;
  427.     LUSER *u;
  428.     PERSON *p;
  429. {
  430.     char rel;
  431.     if( title )
  432.     pchar( REL_HEADER );        /* title */
  433.     else if( !same )            /* not same as last */
  434.     if( p != NULL ) {        /* have person info */
  435.         rel = p->p_relation;
  436. # ifdef REL_SUP
  437.         if( sw_whois || index(REL_SUP, rel) == NULL ) /* whois or */
  438. # endif /* REL_SUP defined */
  439.         pchar( rel );        /* not suppressed */
  440.     } /* have person */
  441.     else
  442.         pchar( NO_REL );
  443.     goalcol++;
  444. } /* prelation */
  445. # endif /* RELATION defined */
  446. # endif /* INQUIRE defined */
  447.  
  448. LOCAL void
  449. pgroup( title, u, p )
  450.     BOOL title;
  451.     LUSER *u;
  452.     PERSON *p;
  453. {
  454.  
  455.     if( title )
  456.     pchar( GRP_HEADER  );        /* title */
  457.     else if( !same && p != NULL )    /* not same and have person */
  458.     pchar( p->p_group );
  459.  
  460.     goalcol++;
  461. } /* pgroup */
  462.  
  463. LOCAL void
  464. pspace( title, u, p )
  465.     BOOL title;
  466.     LUSER *u;
  467.     PERSON *p;
  468. {
  469.     goalcol++;
  470. } /* pspace */
  471.  
  472. LOCAL void
  473. ppname( title, u, p )
  474.     BOOL title;
  475.     LUSER *u;
  476.     PERSON *p;
  477. {
  478.     if( title )
  479.     pstr( "--Full name--" );
  480.     else if( !same )
  481.     if( p != NULL )
  482.         pcount( personwidth, p->p_personal );
  483.     else
  484.         pstr( NO_NAME );
  485.     goalcol += personwidth;
  486. } /* ppname */
  487.  
  488. LOCAL void
  489. pcmd( title, u, p )
  490.     BOOL title;
  491.     LUSER *u;
  492.     PERSON *p;
  493. {
  494.     struct pr *pr;
  495.  
  496.     if( title ) {
  497.     pstr( (sw_its ? "Jobnam" : "-What-") );
  498.     goalcol += PROG_WID;
  499.     return;
  500.     }
  501.  
  502.     pr = u->u_command;
  503.     if( pr != NULL ) {
  504.     char suid;
  505.  
  506.     if( p == NULL || pr->pr_uid == p->p_uid ) /* same uid? */
  507.         suid = ' ';            /* no flag */
  508.     else if( pr->pr_uid == 0 )    /* super user? */
  509.         suid = SUID_ROOT;        /* flag it */
  510.     else                /* someone else */
  511.         suid = SUID_OTHER;
  512.  
  513.     pcount( PROG_WID-1, pr->pr_cmd ); /* leave one for suid */
  514.     pchar( suid );
  515.     } /* pr not null */
  516.     else
  517.     pstr( EMPTY_CMD );
  518.  
  519.     goalcol += PROG_WID;
  520. } /* pcmd */
  521.  
  522. # ifdef PID_COL
  523. LOCAL void
  524. ppid( title, u, p )
  525.     BOOL title;
  526.     LUSER *u;
  527.     PERSON *p;
  528. {
  529.     if( !sw_pid )
  530.     return;                /* takes no space!! */
  531.  
  532.     if( title )
  533.     pstr("  Pid");            /* two leading spaces */
  534.     else if( u->u_command != NULL ) {
  535.     char tbuf[10];
  536.     sprintf(tbuf, "%5d", u->u_command->pr_pid );
  537.     pstr( tbuf );
  538.     }
  539.     goalcol += PID_WID;            /* leave space after */
  540. } /* ppid */
  541. # endif /* PID_COL defined */
  542.  
  543. LOCAL void
  544. pidle( title, u, p )
  545.     BOOL title;
  546.     LUSER *u;
  547.     PERSON *p;
  548. {
  549.     if( title ) {
  550.     if( sw_age )
  551.         pstr( "-On-" );
  552.     else if( sw_state )
  553.         pstr( "Stat" );
  554. # ifndef PID_COL
  555.     else if( sw_pid )
  556.         pstr( "  Pid" );        /* two spaces!! */
  557. # endif /* PID_COL not defined */
  558.     else
  559.         pstr( "Idle" );
  560.     } /* title */
  561.     else {                /* real thing */
  562.     char idbuf[ 100 ];
  563.     strcpy( idbuf, "??" );
  564.  
  565.     if( sw_age )
  566.         intstr(idbuf, now - u->u_time ); /* get time on */
  567.     else if( sw_state ) {
  568.         if( u->u_command != NULL )
  569.         getstate( idbuf, u->u_command ); /* get state */
  570.     }
  571. # ifndef PID_COL
  572.     else if( sw_pid ) {
  573.         if( u->u_command != NULL )
  574.         sprintf(idbuf, "%5d", u->u_command->pr_pid );
  575.     }
  576. # endif /* PID_COL not defined */
  577.     else if( u->u_flags & U_BADTTY )
  578.         strcpy( idbuf, "*:**" );
  579.     else
  580.         intstr(idbuf, u->u_idle );    /* get idle time */
  581.     pstr( idbuf );
  582.     }
  583.  
  584. # ifndef PID_COL
  585.     if( sw_pid )            /* variable width!! */
  586.     goalcol += 5;
  587.     else
  588. # endif /* PID_COL not defined */
  589.     goalcol += 4;
  590. } /* pidle */
  591.  
  592. LOCAL void
  593. pbiff( title, u, p )
  594.     BOOL title;
  595.     LUSER *u;
  596.     PERSON *p;
  597. {
  598.     /* alright, I lost control. C at its ugliest
  599.      * nothing - space
  600.      * biff    - dot
  601.      * hungry  - comma
  602.      * both    - semi
  603.      */
  604.     if( !title )
  605.     pchar( " .,;"[ ((u->u_flags & U_BIFF)   ? 01 : 0) |
  606.                ((u->u_flags & U_HUNGRY) ? 02 : 0) ] );
  607.     goalcol++;
  608. } /* pbiff */
  609.  
  610. LOCAL void
  611. ptty( title, u, p )
  612.     BOOL title;
  613.     LUSER *u;
  614.     PERSON *p;
  615. {
  616.     if( title )
  617.     pstr("TTY");
  618.     else
  619.     pcount( TTY_WID, gtname( u->u_line ) ); /* get trimmed tty name */
  620.     goalcol += TTY_WID;
  621. } /* ptty */
  622.  
  623. LOCAL void
  624. pmesg( title, u, p )
  625.     BOOL title;
  626.     LUSER *u;
  627.     PERSON *p;
  628. {
  629.     if( !title && (u->u_flags & U_NOWRITE) )
  630.     pchar( '*' );
  631.     goalcol++;
  632. } /* pmesg */
  633.  
  634. LOCAL void
  635. plocation( title, u, p )
  636.     BOOL title;
  637.     LUSER *u;
  638.     PERSON *p;
  639. {
  640.     if( title )
  641.     pstr( "-Console Location-" );
  642.     else
  643.     pstr( getttyloc( u ) );        /* tty location */
  644.     /* no new goal!! */
  645. } /* plocation */
  646.  
  647. /*
  648.  * Local variables:
  649.  * comment-column: 40
  650.  * End:
  651.  */
  652.