home *** CD-ROM | disk | FTP | other *** search
- /*
- * getcommand.c - return current command given a LUSER
- *
- * Copyright (C) 1986, 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: getcommand.c,v 3.0 90/07/06 13:10:45 budd Rel $";
- # endif /* lint not defined */
-
- # include "finger.h"
-
- # ifndef Umax
- # include "ustruct.h"
- # else /* Umax defined */
- # if Umax == 42
- # include <sys/signal.h> /* for SIGxxx */
- # include <sys/pmdefs.h> /* for SSTOP, procstates */
- # include <sys/time.h> /* for statistics */
- # include <sys/types.h> /* for dev_t */
- # include <sys/statistics.h> /* for inq_stats */
- # include <sys/procstats.h> /* for inq_stats */
- # endif /* Umax == 42 */
- # if Umax == 43
- # include <sys/signal.h> /* for SIGxxx */
- # define KERNEL
- # include <sys/types.h>
- # undef KERNEL
- # include <sys/time.h>
- # include <sys/resource.h>
- # include <sys/proc.h> /* Sxxx */
- # include <inq_stats/statistics.h>
- # include <inq_stats/procstats.h>
- # ifndef SSLEEP
- # define SSLEEP 1
- # endif /* SSLEEP not defined */
- # endif /* Umax == 43 */
- # endif /* Umax defined */
-
- # include <stdio.h>
- # include "args.h" /* before luser.h */
- # include "luser.h"
- # include "pr.h"
- # include "daemon.h"
- # define WAITSTATENAME waitstatename /* for waitstate.h */
- # include "waitstate.h"
-
- # ifdef Umax
- # include <sys/ioctl.h> /* to get pgrp!!! */
- # define MAXP 100
- LOCAL struct pr prvec[ MAXP ]; /* per terminal process table */
- # else /* Umax not defined */
- # include "kmem.h"
- extern FTYPE kmem; /* from kmem.c */
- extern struct pr *readpr(); /* from readpr.c */
- extern waitstate_t waitstate(); /* from readpr.c */
-
- LOCAL struct pr *prvec; /* vector of processes */
- LOCAL int initialized; /* true if have done readpr() */
- # endif /* Umax not defined */
-
- # if Umax != 42
- LOCAL char *procstates[] = {
- "?0", "SL",
- # ifdef SVR3_STATES
-
- "RU", "ZO", "ST", "ID", "ON", "SX",
- # ifdef UmaxV
- "BS",
- # endif /* UmaxV defined */
-
- # else /* SVR3_STATES not defined */
-
- /* SVR2 and BSD */
- "WA", "RU", "ID",
- # if Umax == 43
- "ST", "EX", "EV",
- # else /* not Umax == 43 */
- "ZO", "ST",
- # ifdef AIX_RT
- "?7", "?8", "?9", "SK",
- # endif /* AIX_RT defined */
- # endif /* not Umax == 43 */
-
- # endif /* SVR3_STATES not defined */
- "**" };
- # endif /* Umax != 42 */
-
- # ifdef sun
- extern dev_t consdev;
- extern dev_t rconsdev;
- extern dev_t dev_console;
- # endif /* sun defined */
-
- # ifndef PID_T
- # define PID_T short
- # endif /* PID_T not defined */
-
- # ifndef PID_BITS
- # define PID_BITS 15 /* most Unices only go up to 30000 */
- # endif /* PID_BITS not defined */
-
- LOCAL char *hidden[] = {
- # ifdef IN_DOT_SERVER
- "in.comsat",
- "in.syslog",
- "in.talkd",
- "in.rlogind",
- "in.telnetd",
- # else /* IN_DOT_SERVER not defined */
- "comsat",
- "syslogd",
- "talkd",
- "ntalkd", /* 4.3 */
- "rlogind",
- "telnetd",
- # endif /* IN_DOT_SERVER not defined */
- # ifdef sun
- "selection_svc", /* SunView barfage */
- # endif /* sun defined */
- # ifdef HIDDEN_PROGRAMS
- HIDDEN_PROGRAMS,
- # endif /* HIDDEN_PROGRAMS defined */
- NULL
- };
-
- LOCAL struct pr *getcommand2();
-
- /*
- * given a luser, return pr struct for executing command.
- *
- * getcommand is a jacket for getcommand2 which finds the
- * process. we then trace back for process parent, and mark in
- * luser struct for potential use in printing ttyloc.
- */
-
- GLOBAL struct pr *getcommand( u )
- LUSER *u;
- {
- struct pr *p2, *lastpr;
- register struct pr *pr;
- PID_T pp;
-
- u->u_command = u->u_daemonp = NULL;
- u->u_daemon = NULL;
-
- if( (p2 = getcommand2( u )) == NULL )
- return( NULL );
- u->u_command = p2;
-
- /* only do this for lusers on ptys? *TODO* */
- pp = p2->pr_ppid;
- lastpr = NULL;
- while( pp != INIT_PID && pp > 0 ) {
- register struct daemon *dp;
-
- for( pr = prvec; pr->pr_stat != 0; pr++ ) /* search process table */
- if( pr->pr_pid == pp ) /* for parent process pid */
- break;
-
- if( pr->pr_pid != pp ) /* did not find parent? */
- break; /* (parent did not have a tty..) */
-
- lastpr = pr; /* save most 'recent' ancestor */
- /* here with parent, check for daemon-ness */
- for( dp = daemons; dp->d_cmd != NULL; dp++ )
- /* printf("%d %s %s\n", pp, pr->pr_cmd, dp->d_cmd );/**/
- if( pr->pr_cmd[0] == dp->d_cmd[0] && /* quick test */
- strcmp( pr->pr_cmd, dp->d_cmd ) == 0 ) {
- u->u_daemon = dp; /* save daemon type */
- u->u_daemonp = pr; /* save process for kicks */
- return( p2 ); /* need goto to leave 2 loops */
- } /* daemon match */
- pp = pr->pr_ppid; /* keep moving up process tree */
- } /* while dp */
-
- /* catch things not in daemons[] */
- /* (*) perhaps flush INIT_PID test? */
- if( lastpr != NULL &&
- pp == INIT_PID ) /* child of init (*) */
- u->u_daemonp = lastpr; /* save for possible display */
- return( p2 );
- } /* getcommand */
-
- /*
- * locate "current" process on a tty.
- * requires many silly heuristics.
- */
-
- LOCAL struct pr *getcommand2( u )
- LUSER *u;
- {
- SIGNED long weight, topweight;
- struct pr *topweightpr;
- register struct pr *pp; /* process pointer */
- register PID_T curpid;
- char **progs;
- PID_T tpg; /* this tty's process group */
- dev_t ttyd; /* tty device */
-
- # ifndef Umax
- if( u->u_flags & U_BADTTY )
- return( NULL );
-
- if( !initialized ) {
- initialized = TRUE;
- prvec = readpr(); /* read process table once. */
- } /* not initialized */
-
- if( prvec == NULL ) /* have processes? */
- return( NULL );
-
- if( ISBADFILE( kmem ) ) /* have kernel memory? */
- return( NULL );
- # endif /* Umax not defined */
-
- tpg = -1; /* terminal process group */
- ttyd = u->u_ttydev; /* get terminal device number */
-
- topweight = MINUS_INF;
- topweightpr = NULL;
-
- # ifdef sun
- /*
- * Sun console redirection (under SunOS 3.x and 4.0.3);
- *
- * values are major,minor
- * consdev rconsdev
- * When the console device is the screen/kbd: 0,0(*) 0,0(*)
- * When the console is serial port n: 12,n 12,n
- * When the console is redirected to ptyN: 20,N as above
- *
- * (*) under SunOS 4.0, 4.0.1 and 4.1 this is always 1,0
- * but not under 4.0.3?!!
- */
-
- # if SunOS >= 400 && SunOS != 403
- if( ttyd == dev_console ) /* utter crockery */
- ttyd = makedev(1,0); /* seems to work! */
- # endif /* SunOS >= 400 && SunOS != 403 */
-
- if( ttyd == dev_console && /* this is /dev/console */
- consdev == rconsdev ) /* check if boot physical console */
- ttyd = consdev; /* is not screen, and not redirectd*/
- # endif /* sun defined */
-
-
- # ifdef Umax
- ttyprocs( ttyd ); /* create array of processes on */
- /* this terminal */
- # endif /* Umax defined */
-
- # ifdef DEBUGSW
- if( sw_debug )
- printf("ttyd=%#x\n", ttyd );
- # endif /* DEBUGSW defined */
-
- for( pp = prvec; pp->pr_stat != 0; pp++ ) { /* for all processes */
- if(
- # ifndef Umax
- pp->pr_ttyp == NULL || /* no tty? */
- # endif /* Umax not defined */
- ttyd != pp->pr_ttyd ) /* tty mismatch? */
- continue; /* yes, continue */
-
- # define ONE 8 /* do fixed point fractions */
- weight = 0;
- curpid = pp->pr_pid;
-
- if( tpg == -1 ) /* try to get terminal */
- tpg = gettpg( pp, u ); /* process group */
-
- # ifdef Umax
- switch( pp->pr_stat ) {
- case SRUN:
- if( pp->pr_wchan == 0 )
- weight += ONE;
- break;
- case SWAIT:
- weight += ONE; /* some semaphore */
- break;
- # ifndef SEVENT
- # define SEVENT (SEXEC+1) /* in proc.h but not pmdefs.h */
- # endif /* SEVENT not defined */
- case SEVENT: /* some event wait.. */
- weight += ONE / 2;
- break;
- } /* switch */
- # else /* Umax not defined */
- switch( waitstate( pp ) ) {
- case WS_TI:
- weight += ONE * 4;
- break;
- case WS_TO:
- weight += ONE * 2;
- break;
- case WS_TW: /* random terminal wait */
- case WS_SE: /* select */
- weight += ONE / 2;
- break;
- case WS_RU: /* no wait */
- if( pp->pr_stat == SRUN ) /* runnable? */
- weight += ONE;
- break;
- default:
- break;
- } /* case */
- # endif /* Umax not defined */
-
- /* sigh. give no special preference to leader (for things running under sh) */
- /* if( curpid == tpg ) /* pid matches tty group? */
- /* weight += ONE; /* leader */
-
- /* give bonus to children of leader? What about ..grandchildren? *WISH* */
- /* (pp->pr_ppid == tpg ) */
- /* other ways to benefit by looking up parents?? (done in getcommand()) */
-
- /* *WISH* perhaps consider p_pctcpu */
-
- if( pp->pr_pgrp == tpg ) /* process in process group? */
- weight += ONE;
-
- if( pp->pr_stat == SSTOP ) /* stopped? */
- weight -= ONE / 2;
-
- if( pp->pr_ppid == INIT_PID ) /* child of init? */
- weight -= ONE / 2;
-
- if( pp->pr_pgrp == 0 ) /* no process group? */
- weight -= ONE / 4;
-
- # ifdef SLOAD
- if( (pp->pr_flag & SLOAD) == 0 ) /* swapped? */
- weight -= ONE / 4;
- # endif /* SLOAD defined */
-
- /* this is to catch programs started by sh with '&' */
- if( pp->pr_intr == S_IGNORE && pp->pr_quit == S_IGNORE )
- weight -= ONE / 4;
-
- if( pp->pr_hup == S_IGNORE ) /* process is nohup? */
- weight -= ONE / 4; /* was once 1/8th */
-
- /*
- * penalize ugly stuff like "gamescontrol" which
- * tend to have high pids.
- */
- for( progs = hidden; *progs != NULL; progs++ )
- if( strcmp( pp->pr_cmd, *progs ) == 0 ) {
- weight -= ONE;
- break;
- }
-
- pp->pr_weight = weight = (weight<<PID_BITS)/ONE + curpid;
- if( weight > topweight ) { /* beat previous winner */
- topweight = weight;
- topweightpr = pp;
- } /* beat winner */
-
- # ifdef DEBUGSW
- if( sw_debug )
- dumppr( pp );
- # endif /* DEBUGSW defined */
-
- } /* for pp */
-
- return( topweightpr );
- } /* getcommand2 */
-
- # ifdef Umax
- LOCAL ttyprocs( dev ) /* get pr's for this terminal */
- dev_t dev;
- {
- struct stat_descr sd;
- register int i;
- register struct pr *pp;
- register struct proc_detail *pd;
- struct proc_detail dd[ MAXP ];
-
- sd.sd_next = NULL;
- sd.sd_objid = dev;
- sd.sd_subsys = SUBSYS_PROC;
- sd.sd_type = PROCTYPE_DETAIL;
- sd.sd_options = PROC_DETAIL_TERM | PROC_DETAIL_GLEADER;
- sd.sd_addr = (char *) dd; /* point to data region */
- sd.sd_size = sizeof( dd ); /* give size */
- sd.sd_sizeused = 0;
-
- if( inq_stats(1, &sd) != 0 ) {
- perror("inq_stats");
- exit(1);
- }
-
- # define SZ sizeof( struct proc_detail )
- pp = prvec;
- pd = dd;
- for( i = sd.sd_sizeused; i >= SZ; i -= SZ ) {
- pp->pr_pid = pd->pd_pid;
- pp->pr_ppid = pd->pd_ppid;
- pp->pr_pgrp = pd->pd_pgrp;
- pp->pr_uid = pd->pd_uid;
- pp->pr_flag = pd->pd_flag;
- pp->pr_stat = pd->pd_state;
- pp->pr_ttyd = dev;
- strncpy(pp->pr_cmd, pd->pd_command, sizeof( pp->pr_cmd ) );
- # define SIGFIG(pd,s) ( (pd->pd_sigignore & (1<<(s))) ? S_IGNORE : \
- (pd->pd_sigcatch & (1<<(s))) ? S_CATCH : S_DEFAULT )
- pp->pr_hup = SIGFIG(pd,SIGHUP);
- pp->pr_intr = SIGFIG(pd,SIGINT);
- pp->pr_quit = SIGFIG(pd,SIGQUIT);
- # undef SIGFIG
- pp->pr_wchan = (caddr_t) pd->pd_sem; /* why not? */
- /* no way to figure out what */
- /* EVENT is what tho... */
- pd++;
- pp++;
- } /* while i */
- pp->pr_stat = 0; /* mark end */
- } /* ttyprocs */
- # endif /* Umax defined */
-
- GLOBAL void
- dumppr( pp )
- register struct pr *pp;
- {
- int st;
- waitstate_t s;
-
- st = pp->pr_stat;
- if( st < 0 || st > sizeof( procstates ) - 1 )
- st = 0;
- # ifdef Umax
- s = WS_SL;
- # else /* Umax not defined */
- s = waitstate( pp );
- # endif /* Umax not defined */
- printf("%6dp %6dpp %6dpg %2s %2s %ci %cq %ch %5du %#8x %s %s %d\n",
- pp->pr_pid,
- pp->pr_ppid,
- pp->pr_pgrp,
- procstates[ st ],
- # if defined(SLOAD) && !defined(UmaxV)
- ( (pp->pr_flag & SLOAD) ? "" : "SW" ),
- # else /* not defined(SLOAD) && !defined(UmaxV) */
- "",
- # endif /* not defined(SLOAD) && !defined(UmaxV) */
- SIGNAME[ (int) pp->pr_intr ],
- SIGNAME[ (int) pp->pr_quit ],
- SIGNAME[ (int) pp->pr_hup ],
- pp->pr_uid,
- pp->pr_ttyd,
- # if Umax == 42
- "", /* always bogus */
- # else /* not Umax == 42 */
- WAITSTATENAME[ (int)s ],
- # endif /* not Umax == 42 */
- pp->pr_cmd,
- pp->pr_weight
- );
- } /* dumppr */
-
- GLOBAL int gettpg( pp, u )
- register struct pr *pp;
- LUSER *u;
- {
- short tpg; /* MUST BE SHORT! (for SHORT_TTYP) */
- # ifdef Umax
- static int checked = FALSE, notty = FALSE;
- int f, w;
- char devn[ 30 ];
-
- /* inq_stats does has no way to get terminal process group. Newer
- * releases have /dev/kmem, but rather than have to deal with kmem
- * at all we open the tty (for write!) and do the ioctl! if users
- * do "mesg n" finger has to run suid root to ensure access (it is
- * safe to do so)! (see BUGS in man page)
- */
- strcpy( devn, "/dev/" );
- strcat( devn, u->u_line );
-
- if( !checked ) { /* check if we have a tty */
- if( (f = open( "/dev/tty", 1)) >= 0 )
- close( f ); /* yes we do */
- else
- notty = TRUE; /* we don't */
- checked = TRUE;
- }
-
- tpg = -2;
- if( (f = open( devn, 1 )) >= 0 ) { /* open for write!! */
- if( ioctl( f, TIOCGPGRP, &w ) == 0 ) /* to get pgrp!!! */
- tpg = w;
- close( f );
-
- /* flush tty association -- so fingerd doesn't get attached!! */
- if( notty && (f = open( "/dev/tty", 1)) >= 0 ) { /* if no tty */
- ioctl( f, TIOCNOTTY, 0 ); /* flush assoc with one */
- close( f ); /* we just opened */
- }
- }
- # else /* Umax not defined */
- # ifndef AIX3
- # ifdef SHORT_TTYP
- /* ttyp is pointer to (short) process group in stream structure! */
- if( ! KMEMREAD( (long)pp->pr_ttyp, (char *)&tpg, sizeof(tpg)) )
- tpg = -2;
- # else /* SHORT_TTYP not defined */
- /* read just process group from tty struct */
- if( ! KMEMREAD( (long)&pp->pr_ttyp->t_pgrp, (char *)&tpg, sizeof(tpg)) )
- tpg = -2;
- # endif /* SHORT_TTYP not defined */
- # endif /* AIX3 not defined */
- # endif /* Umax not defined */
- # ifdef DEBUGSW
- if( sw_debug )
- printf("tpg=%d\n", tpg );
- # endif /* DEBUGSW defined */
- return( tpg );
- } /* gettpg */
-
- GLOBAL void
- getstate( bp, pp )
- char *bp;
- struct pr *pp;
- {
- waitstate_t s;
- int st;
-
- st = pp->pr_stat;
- if( st < 0 || st > sizeof( procstates ) - 1 )
- st = 0;
-
- # ifdef Umax
- # if Umax == 42
- bp[0] = procstates[st][0];
- bp[1] = procstates[st][1];
- bp[2] = procstates[st][2];
- bp[3] = procstates[st][3];
- # endif /* Umax == 42 */
- # else /* Umax not defined */
- if( st == SSLEEP ) {
- s = waitstate( pp );
- bp[0] = WAITSTATENAME[ (int)s ][0];
- bp[1] = WAITSTATENAME[ (int)s ][1];
- }
- else {
- bp[0] = procstates[st][0];
- bp[1] = procstates[st][1];
- }
-
- bp[2] = bp[3] = ' ';
- # if defined(SLOAD) && !defined(UmaxV)
- if( (pp->pr_flag & SLOAD) == 0 ) {
- bp[2] = 'S';
- bp[3] = 'W';
- }
- # endif /* defined(SLOAD) && !defined(UmaxV) */
- # endif /* Umax not defined */
- bp[4] = EOS;
-
- } /* getstate */
-
- /*
- * Local variables:
- * comment-column: 40
- * End:
- */
-