Article 2802 of comp.sources.unix:
Submitted-By: peter@ifm.liu.se (Peter Eriksson)
Posting-Number: Volume 29, Issue 128
Archive-Name: pidentd-2.7/part05

#!/bin/sh
# This is part 05 of a multipart archive.
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh08724; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= pidentd-2.7/src/kernel/4.3bsd.c ==============
if test ! -d 'pidentd-2.7'; then
  $echo 'x -' 'creating directory' 'pidentd-2.7'
  mkdir 'pidentd-2.7'
fi
if test ! -d 'pidentd-2.7/src'; then
  $echo 'x -' 'creating directory' 'pidentd-2.7/src'
  mkdir 'pidentd-2.7/src'
fi
if test ! -d 'pidentd-2.7/src/kernel'; then
  $echo 'x -' 'creating directory' 'pidentd-2.7/src/kernel'
  mkdir 'pidentd-2.7/src/kernel'
fi
if test -f 'pidentd-2.7/src/kernel/4.3bsd.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/kernel/4.3bsd.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/kernel/4.3bsd.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/kernel/4.3bsd.c' &&
/*
** kernel/bsd43.c		Low level kernel access functions for 4.3BSD
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 17 March 1993
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <nlist.h>
#include <pwd.h>
#include <signal.h>
#include <syslog.h>
X
#include "kvm.h"
X
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
X
#include <sys/socketvar.h>
X
#define KERNEL
X
#include <sys/file.h>
X
#if 0
X
#include <sys/time.h>
#include <sys/vmmac.h>
#include <sys/proc.h>
#include <sys/dir.h>
X
#include <fcntl.h>
X
#ifdef DIRBLKSIZ
#  undef DIRBLKSIZ
#endif
#include <sys/user.h>
X
#include <sys/wait.h>
X
#else
X
#include <sys/dir.h>	/* tmk */
#include <sys/user.h>	/* tmk */
/*#include <sys/time.h>
*/
#include <sys/vmmac.h>
#include <sys/proc.h>
/*#include <sys/dir.h>
*/
#include <fcntl.h>
X  
#ifdef DIRBLKSIZ
#  undef DIRBLKSIZ
#endif
/*#include <sys/user.h>
*/
#endif
X
#ifdef KERNEL
#undef KERNEL
#endif
X
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
X
#include <netinet/in_systm.h>
#include <netinet/ip.h>
X
#include <netinet/in_pcb.h>
X
#include <netinet/tcp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
X
#include <arpa/inet.h>
X
#include "identd.h"
#include "error.h"
X
X
extern void *calloc();
extern void *malloc();
X
X
struct nlist nl[] =
{
#define N_FILE 0  
#define N_NFILE 1
#define N_TCB 2
X
X  { "_file" },
X  { "_nfile" },
X  { "_tcb" },
X  { "" }
};
X
static kvm_t *kd;
X
static struct file *xfile;
static int nfile;
X
static struct inpcb tcb;
X
X
int k_open()
{
X  /*
X  ** Open the kernel memory device
X  */
X  if (!(kd = kvm_open(path_unix, path_kmem, NULL, O_RDONLY, NULL)))
X    ERROR("main: kvm_open");
X  
X  /*
X  ** Extract offsets to the needed variables in the kernel
X  */
X  if (kvm_nlist(kd, nl) != 0)
X    ERROR("main: kvm_nlist");
X
X  return 0;
}
X
X
/*
** Get a piece of kernel memory with error handling.
** Returns 1 if call succeeded, else 0 (zero).
*/
static int getbuf(addr, buf, len, what)
X  long addr;
X  char *buf;
X  int len;
X  char *what;
{
X  if (kvm_read(kd, addr, buf, len) < 0)
X  {
X    if (syslog_flag)
X      syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
X	     addr, len, what);
X
X    return 0;
X  }
X  
X  return 1;
}
X
X
X
/*
** Traverse the inpcb list until a match is found.
** Returns NULL if no match.
*/
static struct socket *
X    getlist(pcbp, faddr, fport, laddr, lport)
X  struct inpcb *pcbp;
X  struct in_addr *faddr;
X  int fport;
X  struct in_addr *laddr;
X  int lport;
{
X  struct inpcb *head;
X
X  if (!pcbp)
X    return NULL;
X
X  
X  head = pcbp->inp_prev;
X  do 
X  {
X    if ( pcbp->inp_faddr.s_addr == faddr->s_addr &&
X	 pcbp->inp_laddr.s_addr == laddr->s_addr &&
X	 pcbp->inp_fport        == fport &&
X	 pcbp->inp_lport        == lport )
X      return pcbp->inp_socket;
X  } while (pcbp->inp_next != head &&
X	   getbuf((long) pcbp->inp_next,
X		  pcbp,
X		  sizeof(struct inpcb),
X		  "tcblist"));
X
X  return NULL;
}
X
X
X
/*
** Return the user number for the connection owner
*/
int k_getuid(faddr, fport, laddr, lport, uid)
X  struct in_addr *faddr;
X  int fport;
X  struct in_addr *laddr;
X  int lport;
X  int *uid;
{
X  long addr;
X  struct proc *pp;
X  struct user *up;
X  int offset;
X  struct socket *sockp;
X  int i;
X  
X  /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
X  if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile"))
X    return -1;
X  
X  if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file"))
X    return -1;
X
X  xfile = (struct file *) calloc(nfile, sizeof(struct file));
X  if (!xfile)
X    ERROR2("k_getuid: calloc(%d,%d)", nfile, sizeof(struct file));
X  
X  if (!getbuf(addr, xfile, sizeof(struct file)*nfile, "file[]"))
X    return -1;
X  
X  /* -------------------- TCP PCB LIST -------------------- */
X  if (!getbuf(nl[N_TCB].n_value, &tcb, sizeof(tcb), "tcb"))
X    return -1;
X  
X  tcb.inp_prev = (struct inpcb *) nl[N_TCB].n_value;
X  sockp = getlist(&tcb, faddr, fport, laddr, lport);
X  
X  if (!sockp)
X    return -1;
X
X  /* -------------------- SCAN PROCESS TABLE ------------------- */
X  if (kvm_setproc(kd) < 0)
X    ERROR("k_getuid: kvm_setproc() failed");
X  
X  while (pp = kvm_nextproc(kd))
X  {
X    if (pp->p_stat == 0)
X      continue;
X
X    if (pp->p_stat == SZOMB)
X      continue;
X
X    /* ------------------- GET U_AREA FOR PROCESS ----------------- */
X    if ((up = kvm_getu(kd, pp)) == NULL)
X      ERROR1("k_getuid: kvm_getu() failed for process %d", pp->p_pid);
X
X    /* ------------------- SCAN FILE TABLE ------------------------ */
X    for (i = up->u_lastfile; i >= 0; i--)
X    {
X      if (up->u_ofile[i] == 0)
X	continue;
X
X      offset = up->u_ofile[i] - (struct file *) addr;
X      if (xfile[offset].f_type == DTYPE_SOCKET && 
X	  (struct socket *) xfile[offset].f_data == sockp)
X      {
#ifdef TAHOE
X	*uid = up->u_ruid;
#else
X	*uid = pp->p_ruid;
#endif
X	return 0;
X      } 		/* if */
X    } 			/* for -- ofiles */
X  }   			/* for -- proc */
X  
X  return -1;
}
X
SHAR_EOF
  $shar_touch -am 1110211693 'pidentd-2.7/src/kernel/4.3bsd.c' &&
  chmod 0644 'pidentd-2.7/src/kernel/4.3bsd.c' ||
  $echo 'restore of' 'pidentd-2.7/src/kernel/4.3bsd.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/kernel/4.3bsd.c:' 'MD5 check failed'
40b3ebdbd8a80f0db708af177cdb96ea  pidentd-2.7/src/kernel/4.3bsd.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/kernel/4.3bsd.c'`"
    test 5106 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/kernel/4.3bsd.c:' 'original size' '5106,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/kernel/aix.c ==============
if test -f 'pidentd-2.7/src/kernel/aix.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/kernel/aix.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/kernel/aix.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/kernel/aix.c' &&
/*
** 941026: Harlan Stenn <harlan@pfcs.com> Hacked mercilessly from:
**
**  aixident -- AIX identification daemon
**  version 1.0
**
**  Copyright 1992 by Charles M. Hannum.
**
**  Permission is granted to copy, modify, and use this program in any way,
**  so long as the above copyright notice, this permission notice, and the
**  warranty disclaimer below remain on all copies, and are unaltered.
**
**  aixident is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <sys/types.h>
X
#include <stdlib.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <syslog.h>
X
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/vfs.h>
#include <net/route.h>
#include <netinet/in.h>
X 
#if	defined(_AIX4)
#include <netinet/ip.h>
#endif	/* defined(_AIX4) */
X 
#include <netinet/in_pcb.h>
#include <arpa/inet.h>
X
#define _KERNEL 1
#include <sys/file.h>
#undef  _KERNEL
#include <procinfo.h>
X 
#if	defined(_AIX4)
#define	u_maxofile	U_maxofile
#define	u_ufd	U_ufd
#endif	/* defined(_AIX4) */
X
#include "identd.h"
#include "error.h"
#include "paths.h"
X
int kmem;
X
int kread ();
X
int k_open()
{
X    if ((kmem = open (_PATH_KMEM, O_RDONLY)) == -1)
X	ERROR("main: k_open");
X
X    return 0;
}
X
/*
** Return the user number for the connection owner
*/
int k_getuid(faddr, fport, laddr, lport, uid
#ifdef ALLOW_FORMAT
X	     , pid, cmd, cmd_and_args
#endif
X 	     )
X  struct in_addr *faddr;
X  int fport;
X  struct in_addr *laddr;
X  int lport;
X  int *uid;
#ifdef ALLOW_FORMAT
X  int *pid;
X  char **cmd,**cmd_and_args;
#endif
{
X  struct sockaddr_in foreign, local;
X  int max_procs = 64,
X      num_procs, fd;
X  struct procinfo *procinfo;
X  struct user user;
X  struct file *filep, file;
X  struct socket *socketp, socket;
X  struct protosw *protoswp, protosw;
X  struct domain *domainp, domain;
X  struct inpcb *inpcbp, inpcb;
X  struct passwd *passwd;
X  static char argline[4096],progname[256];
X  char *cp;
X 
X  while ((procinfo = (struct procinfo *)
X		     malloc ((size_t) (max_procs * sizeof (*procinfo)))) &&
X         (num_procs = getproc (procinfo, max_procs,
X			       sizeof (*procinfo))) == -1 &&
X	 errno == ENOSPC) {
X    max_procs <<= 1;
X    free (procinfo);
X  }
X
X  if (! procinfo) {
X    if (syslog_flag)
X      (void) syslog (LOG_ERR, "out of memory allocating %ld procinfo structs\n",
X		     max_procs);
X    return -1;
X  }
X
X  for (; num_procs; num_procs--, procinfo++) {
X
X    if (procinfo->pi_stat == 0 || procinfo->pi_stat == SZOMB)
X      continue;
X
X    if (getuser (procinfo, sizeof (*procinfo), &user, sizeof (user)))
X      continue;
X
X    for (fd = 0; fd < user.u_maxofile; fd++) {
X
X      if (! (filep = user.u_ufd[fd].fp))
X	continue;
X
X      if (kread ((off_t) filep, (char *) &file, sizeof (file))) {
X	if (syslog_flag)
X          (void) syslog (LOG_ERR, "can't read file struct from %#x",
X		         (unsigned) filep);
X	return -1;
X      }
X
X      if (file.f_type != DTYPE_SOCKET)
X	continue;
X
X      if (! (socketp = (struct socket *) file.f_data))
X	continue;
X
X      if (kread ((off_t) socketp, (char *) &socket, sizeof (socket))) {
X	if (syslog_flag)
X          (void) syslog (LOG_ERR, "can't read socket struct from %#x",
X			 (unsigned) socketp);
X	return -1;
X      }
X
X      if (! (protoswp = socket.so_proto))
X	continue;
X
X      if (kread ((off_t) protoswp, (char *) &protosw, sizeof (protosw))) {
X	if (syslog_flag)
X	  (void) syslog (LOG_ERR, "can't read protosw struct from %#x",
X			 (unsigned) protoswp);
X	return -1;
X      }
X
X      if (protosw.pr_protocol != IPPROTO_TCP)
X	continue;
X
X      if (! (domainp = protosw.pr_domain))
X	continue;
X
X      if (kread ((off_t) domainp, (char *) &domain, sizeof (domain))) {
X	if (syslog_flag)
X	  (void) syslog (LOG_ERR, "can't read domain struct from %#x",
X			 (unsigned) domainp);
X	return -1;
X      }
X
X      if (domain.dom_family != AF_INET)
X	continue;
X
X      if (! (inpcbp = (struct inpcb *) socket.so_pcb))
X	continue;
X
X      if (kread ((off_t) inpcbp, (char *) &inpcb, sizeof (inpcb))) {
X	if (syslog_flag)
X	  (void) syslog (LOG_ERR, "can't read inpcb struct from %#x",
X			 (unsigned) inpcbp);
X	return -1;
X      }
X
X      if (socketp != inpcb.inp_socket)
X	continue;
X
X      if (inpcb.inp_faddr.s_addr != faddr->s_addr ||
X	  inpcb.inp_fport != fport ||
X	  inpcb.inp_laddr.s_addr != laddr->s_addr ||
X	  inpcb.inp_lport != lport)
X	continue;
X
X      *uid = procinfo->pi_uid;
#ifdef ALLOW_FORMAT
X      *pid = procinfo->pi_pid;
X      bzero(argline,sizeof(argline));
X      getargs(procinfo,sizeof(*procinfo),argline,sizeof(argline));
X      strcpy(progname,argline);
X      *cmd = progname;
X      for (cp = argline; *cp != '\0';) {
X	cp += strlen(cp);
X	*cp++ = ' ';
X      }
X      *cmd_and_args = argline;
#endif
X
X      return 0;
X    }
X  }
X
X  return -1;
}
X
int
kread (addr, buf, len)
X  off_t addr;
X  char *buf;
X  int len;
{
X  int br;
X
X  if (lseek (kmem, addr, L_SET) == (off_t) -1)
X    return (-1);
X
X  br = read(kmem, buf, len);
X
X  return ((br == len) ? 0 : 1);
}
X
X
SHAR_EOF
  $shar_touch -am 0812002696 'pidentd-2.7/src/kernel/aix.c' &&
  chmod 0644 'pidentd-2.7/src/kernel/aix.c' ||
  $echo 'restore of' 'pidentd-2.7/src/kernel/aix.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/kernel/aix.c:' 'MD5 check failed'
a2e2bb20500fa94adfb9621b0a4b9300  pidentd-2.7/src/kernel/aix.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/kernel/aix.c'`"
    test 5074 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/kernel/aix.c:' 'original size' '5074,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/kernel/alpha3.c ==============
if test -f 'pidentd-2.7/src/kernel/alpha3.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/kernel/alpha3.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/kernel/alpha3.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/kernel/alpha3.c' &&
/*
X * 16 Apr 96 - Changes by Paul Szabo <psz@maths.usyd.edu.au>
X *
X * May 23, 1994 - Modified by Allan E. Johannesen (aej@wpi.edu) from code
X * kindly provided by Digital during the Beta test of Digital Alpha AXP OSF/1
X * 3.0 when WPI discovered that the file structures had changed.  Prior to 3.0,
X * OSF/1 ident support had only needed 64-bit modifications to the `other.c'
X * kernel routine (those mods done at WPI during the initial OSF/1 Beta tests).
X *
X * NOTE:
X *   This tool is NOT part of DEC OSF/1 and is NOT a supported product.
X *
X * BASED ON code provided by
X *   Aju John, UEG, Digital Equipment Corp. (ZK3) Nashua, NH.
X *
X * The following is an **unsupported** tool. Digital Equipment Corporation
X * makes no representations about the suitability of the software described
X * herein for any purpose. It is provided "as is" without express or implied
X * warranty.
X *
X * BASED ON:
X *  PADS program by Stephen Carpenter, UK UNIX Support, Digital Equipment Corp.
X * */
X
/*
X * Multiple, almost simultaneous identd requests were causing a
X * 'kernel panic' crash on our 2-CPU 2100 server running OSF 3.2C
X * (though no such problems were seen on Alphastations). We were
X * initially told to try patch 158. When that did not cure the
X * problem, Digital service came up with the following on 9 May 96:
X *
X * > The following came from an outage in the states about the same thing.
X * > 
X * > The active program was "identd" which is a freeware
X * > program that identifies the user who is opening a port on the system.
X * > 
X * > Careful analysis shows that the identd program is causing the crash by
X * > seeking to an invalid address in /dev/kmem. The program, identd reads
X * > through /dev/kmem looking for open files that are sockets, which then send
X * > pertainent information back to the other end. In this case, the socket has
X * > gone away before the read has been performed thereby causing a panic.
X * > 
X * > identd reading /dev/kmem, causing a fault on the  kernel stack guard pages
X * > which in turn cause the kernel to panic. To fix  this problem, set the
X * > following in /etc/sysconfigtab:
X * > 
X * > vm:
X * >         kernel-stack-guard-pages = 0
X * > 
X * > could you try this and see if that fixes your problem.
X *
X * This has fixed our problem, though I am worried what other
X * effects this may have.
X *
X * These crashes occured while we had k_open in the parent process (in
X * src/identd.c): the file pointers would have been all over the place.
X * Now that we have k_open in the child process (in src/parse.c) we may
X * not have a crash anyway...
X */
X
#include <stdlib.h>
#include <stdio.h>
#include <nlist.h>
#include <sys/types.h>
#define SHOW_UTT
#include <sys/user.h>
#define KERNEL_FILE
#include <sys/file.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
X
#include <alloca.h>
X
#include "identd.h"
#include "error.h"
#include "kvm.h"
X
/* The following is in <sys/proc.h>, but only if _KERNEL is defined */
struct pid_entry {
X        pid_t   pe_pid;                /* process id */
X        int     pe_generation;         /* checks for struct re-use */
X        struct proc *pe_proc;          /* pointer to this pid's proc */
X        union {
X                struct pid_entry *peu_nxt;     /* next entry in free list */
X                struct {
X                        int     peus_pgrp;     /* pid is pgrp leader? */
X                        int     peus_sess;     /* pid is session leader? */
X                } peu_s;
X        } pe_un;
};
X
/* The following is in <sys/proc.h>, but only if _KERNEL is defined */
#define	PID_INVALID(pid) ((pid_t)(pid) < 0 || (pid_t)(pid) > (pid_t)PID_MAX)
X
/* The following is in <sys/ucred.h>, but only if _KERNEL is defined */
#define	INVALID_UID(uid) ((uid_t)(uid) < 0 || (uid_t)(uid) > (uid_t)UID_MAX)
X
X
#ifdef NOFILE_IN_U		/* more than 64 open files per process ? */
#  define OFILE_EXTEND
#else
#  define NOFILE_IN_U NOFILE
#endif
X
X
#define BUFLEN 1024 /* buffer length */
X
#ifdef DEBUG
#define sysl(a,b)	printf(a, b); printf("\n");
#else /* DEBUG */
#ifdef STRONG_LOG
#define sysl(a,b)	if (syslog_flag) { syslog(LOG_INFO, a, b); }
#else
#define sysl(a,b)
#endif
#endif /* DEBUG */
X
X
#define ZAP(x,fmt,err) \
X  if (x) \
X   { \
X    sysl(fmt, err) \
X    return (-1); \
X   }
X
#ifdef DEBUG
#define SETZAP(x,lev,fmt,err1,err2,err3) \
X  if (x) \
X   { \
X    printf ("zap to level %d: ", lev); printf (fmt, err1, err2, err3); printf ("\n"); \
X    if (lev > zaplevel) \
X     { \
X      sprintf (zapmess, fmt, err1, err2, err3); \
X      zaplevel = lev; \
X      printf ("zap level set to %d\n", zaplevel); \
X     } \
X    continue; \
X   }
#else /* DEBUG */
#define SETZAP(x,lev,fmt,err1,err2,err3) \
X  if (x) \
X   { \
X    if (lev > zaplevel && syslog_flag) \
X     { \
X      sprintf (zapmess, fmt, err1, err2, err3); \
X      zaplevel = lev; \
X     } \
X    continue; \
X   }
#endif /* DEBUG */
X
X
struct nlist name_list[] = {
#define N_PIDTAB 0
X  { "_pidtab" },
#define N_NPID 1
X  { "_npid" },
X  { 0 }
};
X
static kvm_t *kd;
X
X
int k_open()
{
X  if (!(kd = kvm_open("/vmunix", "/dev/kmem" , NULL, O_RDONLY, NULL)))
X  {
X    if (syslog_flag) syslog(LOG_ERR, "kvm_open call failed");
X    return 1;
X  }
X
X  if (kvm_nlist(kd, name_list) != 0)
X  {
X    if (syslog_flag) syslog(LOG_ERR, "kvm_nlist call failed");
X    return 1;
X  }
X
X  return 0;
}
X
X
int k_getuid(struct in_addr *faddr, int fport,
X	     struct in_addr *laddr, int lport,
X	     int *uid
#ifdef ALLOW_FORMAT
X	     , int *pid
X	     , char **cmd
X	     , char **cmd_and_args
#endif
X	    )
{
X  off_t pidtab_base;	/* Start address of the process table */
X  int npid;		/* Number of processes in the process table */
X
X  struct proc_plus_utask {
X    struct proc The_Proc;
X    struct utask Proc_Utask;
X  } pu;
X
X  struct pid_entry *the_pid_entry;
X  struct file **ofile_table_extension, open_file;
X  int index, index1;
X
#define the_proc pu.The_Proc
#define proc_utask pu.Proc_Utask
#define p_i the_pid_entry[index]
#define f_s proc_utask.uu_file_state
X
X  static char	zapmess[BUFLEN];
X  long		zaplevel;
X
#ifdef ALLOW_FORMAT
X  static char	cmdbuf[BUFLEN];
X  static char	c_abuf[BUFLEN];
X  int		blen;
#endif
X
X
/* Just to save us some typing: we ALWAYS test return from kvm_read */
#define goodr(k,addr,buf,len) (kvm_read(k,addr,buf,len) == len)
#define badr(k,addr,buf,len)  (kvm_read(k,addr,buf,len) != len)
X
X
#ifdef OFILE_EXTEND
X  /* Reserve space for the extended open file table of a process */
X  ofile_table_extension = (struct file **) alloca((getdtablesize ())
X				 * sizeof(struct file *));
#endif
X
X
X  /* Do we need these extra checks? */
X  ZAP(fport<1 || fport>65535 || lport<1 || lport>65535, "port numbers out of range",0)
X  ZAP(faddr->s_addr==0 || faddr->s_addr==-1 || laddr->s_addr==0 || laddr->s_addr==-1, "net addresses out of range",0)
X
#ifdef DEBUG
X  printf ("Looking up   faddr %08x  fport %d\n", faddr->s_addr, fport);
X  printf ("             laddr %08x  lport %d\n", laddr->s_addr, lport);
#endif /* DEBUG */
X
X
X  zaplevel = 0;
X  sprintf (zapmess, "no such TCP connection");
X
X
X  /* Find the start of the process table */
X  ZAP(badr(kd, (off_t) name_list[N_PIDTAB].n_value, &pidtab_base, sizeof(pidtab_base)),
X	"Cannot read pidtab_base",0)
X
X  /* Find the size of the process table */
X  ZAP(badr(kd, (off_t) name_list[N_NPID].n_value, &npid, sizeof(npid)), "Cannot read npid",0)
X  /* Sanity check */
X  ZAP(npid < 1 || npid > 20000, "Bad npid of %d", npid)
X
/*
** To improve on the 20000 above:
**
** (method 1)
**
**   We observe that npid is 1024 or 4096.
**   (Are any other multiples of 1024 allowed?)
**   Accept these allowed values only.
**
** (method 2) THIS WOULD NOT WORK:
**
**   Change the declaration of name_list at the beginning to:
**
**   struct nlist name_list[] = {
**   #define N_PIDTAB 0
**     { "_pidtab" },
**   #define N_NPID 1
**     { "_npid" },
**   #define N_TASKMAX 2
**     { "task_max" },
**     { 0 }
**   };
**
**   then use
**
**   int taskmax;
**     kvm_read (kd, (off_t) name_list[N_TASKMAX].n_value, &taskmax, sizeof(taskmax));
**
**   and then replace 20000 by taskmax-1.
**
**   But then, we are still relying on values returned from kvm_read...
**   or put another way, we have no good way of checking taskmax.
**
**   This probably would not work anyway: our DEC 2100 should show around
**   1000 for taskmax (128 users), but npid returned is 4096.
*/
X
#ifdef DEBUG
X  printf ("Number of processes: %d\n", npid);
#endif /* DEBUG */
X
X
X  /* Read in the process structure */
X  the_pid_entry = (struct pid_entry*)alloca(sizeof(struct pid_entry) * npid);
X  ZAP(badr(kd, pidtab_base, the_pid_entry, sizeof(struct pid_entry) * npid),
X	"Cannot read process structure",0)
X
X  for (index = 0; index < npid; index++) {
X
X    /* Sanity checks */
X    /*
X    This is a 'normal' thing:
X    SETZAP(p_i.pe_proc == 0, 11, "Proc/utask pointer zero for proc slot %d",index,0,0)
X    */
X    if (p_i.pe_proc == 0) continue;
X    SETZAP(PID_INVALID(p_i.pe_pid), 12, "Invalid PID %d for proc slot %d",p_i.pe_pid,index,0)
X
X    /* Read in the proc and utask structs of the process */
X    SETZAP(badr(kd, (off_t) p_i.pe_proc, &pu, sizeof(pu)), 13,
X	"Cannot read proc/utask for proc slot %d (PID %d)",index,p_i.pe_pid,0)
X
X    /* Sanity checks */
X    SETZAP(p_i.pe_pid != the_proc.p_pid, 21,
X	"Proc slot %d was PID %d, but has %d in proc/utask",index,p_i.pe_pid,the_proc.p_pid)
X    SETZAP(INVALID_UID(the_proc.p_ruid), 22,
X	"Invalid UID %d for proc slot %d (PID %d)",the_proc.p_ruid,index,p_i.pe_pid)
X
#ifdef DEBUG
X    printf ("Looking at proc slot %d: PID %d, UID %d\n", index, the_proc.p_pid, the_proc.p_ruid);
#endif /* DEBUG */
X
X    /* Sanity checks */
X    if (f_s.uf_lastfile < 0) continue;
X    SETZAP((f_s.uf_lastfile + 1) > getdtablesize(), 31,
X	"Too many files used (%d) for proc slot %d (PID %d)",f_s.uf_lastfile,index,p_i.pe_pid)
X
#ifdef OFILE_EXTEND
X    if (f_s.uf_lastfile >= NOFILE_IN_U) {
X      /* Sanity checks */
X      SETZAP(f_s.uf_of_count > (getdtablesize()), 32,
X	"Too many (%d) OFILE_EXTEND files used for proc slot %d (PID %d)",f_s.uf_of_count,index,p_i.pe_pid)
X
#if 0 /* Disabled, 960811 Peter Eriksson <pen@lysator.liu.se< */
X      SETZAP((f_s.uf_lastfile + 1) != (f_s.uf_of_count + NOFILE_IN_U), 33,
X	"Files used %d, but %d OFILE_EXTEND ones for proc slot %d",f_s.uf_lastfile,f_s.uf_of_count,index)
#endif
X
X      SETZAP(badr(kd, (off_t) f_s.uf_ofile_of, ofile_table_extension, f_s.uf_of_count * sizeof(struct file *)), 34,
X	"Cannot read OFILE_EXTEND files for proc slot %d (PID %d)",index,p_i.pe_pid,0)
X    }
#endif
X
#ifdef DEBUG
X    printf ("proc slot %d uses %d files\n", index, f_s.uf_lastfile);
#endif /* DEBUG */
X
X    for (index1 = 0; index1 <= f_s.uf_lastfile; index1++) {
X
X      if (index1 < NOFILE_IN_U) {
X	if (f_s.uf_ofile[index1] == (struct file *) NULL) continue;
X	if (f_s.uf_ofile[index1] == (struct file *) -1)   continue;
X
X	SETZAP(badr(kd, (off_t) f_s.uf_ofile[index1], &open_file, sizeof(open_file)), 41,
X	  "Cannot read file %d for proc slot %d (PID %d)",index1,index,p_i.pe_pid)
X      }
#ifdef OFILE_EXTEND
X      else {
X	if (ofile_table_extension[index1-NOFILE_IN_U] == (struct file *) NULL) continue;
X
X	SETZAP(badr(kd,(off_t) ofile_table_extension[index1-NOFILE_IN_U], &open_file, sizeof(open_file)), 42,
X	  "Cannot read OFILE_EXTEND file %d for proc slot %d (PID %d)",index1,index,p_i.pe_pid)
X      }
#endif
X
#ifdef DEBUG
X      printf ("Looking at proc slot %d, file %d\n", index, index1);
#endif /* DEBUG */
X
X      if (open_file.f_type == DTYPE_SOCKET) {
X
X	struct socket try_socket;
X	struct inpcb try_pcb;
X
X	SETZAP(badr(kd,(off_t) open_file.f_data, &try_socket,sizeof(try_socket)), 51,
X	  "Cannot read socket of file %d for proc slot %d (PID %d)",index1,index,p_i.pe_pid)
X	if (try_socket.so_pcb) {
X	  SETZAP(badr(kd, (off_t) try_socket.so_pcb, &try_pcb,sizeof(try_pcb)), 52,
X	    "Cannot read pcb of file %d for proc slot %d (PID %d)",index1,index,p_i.pe_pid)
X	  if (try_pcb.inp_faddr.s_addr == faddr->s_addr &&
X	      try_pcb.inp_laddr.s_addr == laddr->s_addr &&
X	      try_pcb.inp_fport        == fport &&
X	      try_pcb.inp_lport        == lport ) {
X
X	    *uid = the_proc.p_ruid;
X
#ifdef ALLOW_FORMAT
X
X	    *pid = the_proc.p_pid;
X
X	    blen = strlen(proc_utask.uu_comm);
X	    if (blen > BUFLEN-1) blen = BUFLEN-1;
X	    sprintf(cmdbuf, "%.*s", blen, proc_utask.uu_comm);
X	    *cmd = cmdbuf;
X
/*
How to use proc_utask.uu_arg_size and proc_utask.uu_argp ??
The value proc_utask.uu_arg_size seems to be the length of the
cmd+args string (including trailing null), but where is the string?
X
Neither of the following two ways work:
Way 1:
X	    blen = strlen(proc_utask.uu_argp);
X	    if (blen > BUFLEN-1) blen = BUFLEN-1;
X	    sprintf(c_abuf, "%.*s", blen, proc_utask.uu_argp);
X
Way 2:
X	    blen = proc_utask.uu_arg_size;
X	    if (blen > BUFLEN-1) blen = BUFLEN-1;
X	    SETZAP(badr(kd, (off_t) proc_utask.uu_argp,c_abuf,blen), 53, "Cannot read cmd args for proc slot %d (PID %d)",index,p_i.pe_pid,0)
X	    c_abuf[blen] = 0;
X
Finally:
X	    *cmd_and_args = c_abuf;
*/
X
/*
** Other stuff we could return:
**	    login_namep = proc_utask.uu_logname;
**	    envp  = proc_utask.uu_envp;
**	    n_env = proc_utask.uu_env_size;
*/
X
#endif
X
X	    return (0);
X	  };
X	};
X	continue; /* Is not this superfluous? We are at the end of the file loop anyway. */
X      };
X    };
X  };
X  ZAP(1,zapmess,0)
X  return (-1);
}
SHAR_EOF
  $shar_touch -am 0811205196 'pidentd-2.7/src/kernel/alpha3.c' &&
  chmod 0644 'pidentd-2.7/src/kernel/alpha3.c' ||
  $echo 'restore of' 'pidentd-2.7/src/kernel/alpha3.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/kernel/alpha3.c:' 'MD5 check failed'
ff2a623afc172448cf7747f953a413c6  pidentd-2.7/src/kernel/alpha3.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/kernel/alpha3.c'`"
    test 13380 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/kernel/alpha3.c:' 'original size' '13380,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/kernel/netbsd.c ==============
if test -f 'pidentd-2.7/src/kernel/netbsd.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/kernel/netbsd.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/kernel/netbsd.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/kernel/netbsd.c' &&
/*
**	$Id: netbsd.c,v 1.8 1995/07/08 23:57:06 pk Exp $
**
** netbsd.c		Low level kernel access functions for NetBSD
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 17 March 1993
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <nlist.h>
#include <pwd.h>
#include <signal.h>
#include <syslog.h>
X
#include "kvm.h"
X
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
X
#include <sys/socketvar.h>
X
#define _KERNEL
X
#include <sys/file.h>
X
#undef _KERNEL
#include <sys/sysctl.h>
X
#include <fcntl.h>
X
#include <sys/user.h>
X
#include <sys/wait.h>
X
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
X
#include <netinet/in_systm.h>
#include <netinet/ip.h>
X
#include <netinet/in_pcb.h>
X
#include <netinet/tcp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
X
#include <arpa/inet.h>
X
#include "identd.h"
#include "error.h"
X
X
extern void *calloc();
extern void *malloc();
X
X
struct nlist nl[] =
{
#define N_FILE 0
#define N_NFILE 1
#define N_TCBTABLE 2
X      
X  { "_filehead" },
X  { "_nfiles" },
X  { "_tcbtable" },
X  { "" }
};
X
static kvm_t *kd;
X
static struct file *xfile;
static int nfile;
X
static struct inpcbtable tcbtable;
X  
X
int k_open()
{
X  char errbuf[_POSIX2_LINE_MAX];
X
X  /*
X  ** Open the kernel memory device
X  */
X  if ((kd = kvm_openfiles(path_unix, path_kmem, NULL, O_RDONLY, errbuf)) ==
X      NULL)
X    ERROR1("main: kvm_open: %s", errbuf);
X  
X  /*
X  ** Extract offsets to the needed variables in the kernel
X  */
X  if (kvm_nlist(kd, nl) < 0)
X    ERROR("main: kvm_nlist");
X
X  return 0;
}
X
X
/*
** Get a piece of kernel memory with error handling.
** Returns 1 if call succeeded, else 0 (zero).
*/
static int getbuf(addr, buf, len, what)
X  long addr;
X  char *buf;
X  int len;
X  char *what;
{
X  if (kvm_read(kd, addr, buf, len) < 0)
X  {
X    if (syslog_flag)
X      syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
X	     addr, len, what);
X
X    return 0;
X  }
X  
X  return 1;
}
X
X
X
/*
** Traverse the inpcb list until a match is found.
** Returns NULL if no match.
*/
static struct socket *
getlist(tcbtablep, ktcbtablep, faddr, fport, laddr, lport)
X	struct inpcbtable *tcbtablep, *ktcbtablep;
X	struct in_addr *faddr;
X	int fport;
X	struct in_addr *laddr;
X	int lport;
{
X	struct inpcb *kpcbp, pcb;
X
X	if (!tcbtablep)
X		return NULL;
X 
X	for (kpcbp = tcbtablep->inpt_queue.cqh_first;
X	     kpcbp != (struct inpcb *)ktcbtablep;
X	     kpcbp = pcb.inp_queue.cqe_next) {
X		if (!getbuf((long) kpcbp, &pcb, sizeof(struct inpcb), "tcb"))
X			break;
X		if (pcb.inp_faddr.s_addr == faddr->s_addr &&
X		    pcb.inp_laddr.s_addr == laddr->s_addr &&
X		    pcb.inp_fport        == fport &&
X		    pcb.inp_lport        == lport )
X			return pcb.inp_socket;
X	}
X  return NULL;
}
X
X
X
/*
** Return the user number for the connection owner
*/
int k_getuid(faddr, fport, laddr, lport, uid)
X  struct in_addr *faddr;
X  int fport;
X  struct in_addr *laddr;
X  int lport;
X  int *uid;
{
X  long addr;
X  struct socket *sockp;
X  int i, mib[2];
X  struct ucred ucb;
X  
X  /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
X  if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile"))
X    return -1;
X  
X  if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file"))
X    return -1;
X
X  {
X    size_t siz;
X    int rv;
X
X    mib[0] = CTL_KERN;
X    mib[1] = KERN_FILE;
X    if ((rv = sysctl(mib, 2, NULL, &siz, NULL, 0)) == -1)
X    {
X      ERROR1("k_getuid: sysctl 1 (%d)", rv);
X      return -1;
X    }
X    xfile = malloc(siz);
X    if (!xfile)
X      ERROR1("k_getuid: malloc(%d)", siz);
X    if ((rv = sysctl(mib, 2, xfile, &siz, NULL, 0)) == -1)
X    {
X      ERROR1("k_getuid: sysctl 2 (%d)", rv);
X      return -1;
X    }
X    xfile = (struct file *)((char *)xfile + sizeof(filehead));
X  }
X  
X  /* -------------------- TCP PCB LIST -------------------- */
X  if (!getbuf(nl[N_TCBTABLE].n_value, &tcbtable, sizeof(tcbtable), "tcbtable"))
X    return -1;
X  
X  sockp = getlist(&tcbtable, nl[N_TCBTABLE].n_value, faddr, fport, laddr,
X      lport);
X  
X  if (!sockp)
X    return -1;
X
X  /*
X  ** Locate the file descriptor that has the socket in question
X  ** open so that we can get the 'ucred' information
X  */
X  for (i = 0; i < nfile; i++)
X  {
X    if (xfile[i].f_count == 0)
X      continue;
X    
X    if (xfile[i].f_type == DTYPE_SOCKET &&
X	(struct socket *) xfile[i].f_data == sockp)
X    {
X      if (!getbuf(xfile[i].f_cred, &ucb, sizeof(ucb), "ucb"))
X	return -1;
X
X      *uid = ucb.cr_uid;
X      return 0;
X    }
X  }
X
X  return -1;
}
X
SHAR_EOF
  $shar_touch -am 0811224796 'pidentd-2.7/src/kernel/netbsd.c' &&
  chmod 0644 'pidentd-2.7/src/kernel/netbsd.c' ||
  $echo 'restore of' 'pidentd-2.7/src/kernel/netbsd.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/kernel/netbsd.c:' 'MD5 check failed'
1bd2597c14e706f1ce16ae7ebb8c286e  pidentd-2.7/src/kernel/netbsd.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/kernel/netbsd.c'`"
    test 4698 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/kernel/netbsd.c:' 'original size' '4698,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/kernel/apollo.c ==============
if test -f 'pidentd-2.7/src/kernel/apollo.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/kernel/apollo.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/kernel/apollo.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/kernel/apollo.c' &&
/*
X * 12 Apr 96 - Written by Paul Szabo <psz@maths.usyd.edu.au>
X */
X
#include <stdio.h>
#include <ctype.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <signal.h>
#include <setjmp.h>
#include <apollo/base.h>
#include <apollo/name.h>	/* Not really needed */
#include <apollo/pgm.h>
X
#include "identd.h"
#include "error.h"
X
X
#define USE_SAFE_ADDR
X
X
#define BUFLEN 256 /* buffer length, 80 would probably be enough */
X
X
/* These are from #include <limits.h>, but is only with #ifdef _INCLUDE_SYS5_SOURCE */
#define	PID_MAX		30000		/* max value for a process ID */
#define	UID_MAX		65535		/* max value for a user or group ID */
X
typedef unsigned int tcp_$netaddr_t;
/* An address of 129.78.69.2 is 0x814e4502 as int,
X   or [0] is 0x81, [1] is 0x4e, [2] is 0x45, [3] is 0x02 as char array */
X
typedef struct {	/* network status structure */
/* Note the mismatches between /sys/ins/tcp.ins.{pas,c}, both dated 3 May 89 */
X    unsigned short	nsnd;		/* # send bufs allocated */	/* Always 0x239c */
X    unsigned short	nrcv;		/* # receive bufs allocated */	/* Either 0x239c, or maybe 0x2000, 0x8000 or 0xc000 */
X    unsigned short	ssize;		/* # bufs on send buffer */	/* Stuff in queue, sndQ */
X    unsigned short	rsize;		/* # bufs on receive buffer */	/* Stuff in queue, rcvQ */
X    unsigned short	xstat;		/* network status word */
X    unsigned short	state;		/* state of this connection */
X    unsigned short	iostate;
X    unsigned short	flags;		/* misc. flags (see below) */	/* See where??? 0x0002 tcp, 0x0220 udp, 0x0804 ip */
X    unsigned short	lport;		/* local port */
X    unsigned short	rport;		/* foreign port */
X    tcp_$netaddr_t	raddr;		/* foreign address */
X    tcp_$netaddr_t	laddr;		/* local address */
X    unsigned short	options;	/* corresponds to ucb uc_options */
X    unsigned short	pad1;		/* Padding for alignment */
} tcp_$netstate_t;
X
typedef char enum {
X    tcp_$CLOSED,
X    tcp_$LISTEN,
X    tcp_$SYN_SENT,
X    tcp_$state_0x03,
X    tcp_$state_0x04,
X    tcp_$ESTABLISHED,
X    tcp_$state_0x06,
X    tcp_$state_0x07,
X    tcp_$TIME_WAIT,
X    tcp_$CLOSE_WAIT,
X    tcp_$state_0x0a,
X    tcp_$CLOSING
} tcp_$tcpstate_t;
X
typedef struct {	/* Complete state of a connection */
/*
X * Both /sys/ins/tcp.ins.{pas,c} have 8-character ifname (so mis-alignment at ifunit);
X * /sys/ins/tcp.ins.pas has process UID instead of pgrp.
X */
X    tcp_$netstate_t	cstate;
X    tcp_$netaddr_t	route;		/* Gateway address, if any */
X    char		*tcb;		/* The tcb, if any, for this connection */
X    tcp_$tcpstate_t	tstate;		/* State of tcp connection, if any */
X    char		ifname[9];	/* Name of network interface */
X    pinteger		ifunit;		/* Unit number of device */
X    pinteger		pr_num;		/* Raw protocol number, if any */
X    uid_$t		pgrp #attribute[aligned(1)]; /* Process group (??) */
} tcp_$constate_t;
X
typedef tcp_$constate_t *tcp_$constate_p;
X
typedef short enum {
X    tcp_$memstats,
X    tcp_$netstats,
X    tcp_$ifcbs,
X    tcp_$tcbs,
X    tcp_$hosts,
X    tcp_$gateway,
X    tcp_$all_conns
} tcp_$info_key_t;
X
#define MAXCON 0x0080	/* Why 128??? This is what netstat uses.
X			   What happens if there are more connections? */
X
void extern tcp_$get_server_info (
X    tcp_$info_key_t	&key,
X    tcp_$constate_p	&state_p,
X    short		&statesize,
X    short		&max_con,
X    short		*num_con,
X    status_$t		*status);
X
X
typedef struct {
X  uid_$t pers;
X  uid_$t proj;
X  uid_$t org ;
X  uid_$t subs;
X  long   node;
X  } acl_$sid;
X
X
#define proc2_$aname_len 32
typedef char proc2_$aname_t[proc2_$aname_len];	/* accounting name */
X
typedef short proc2_$state_t;
typedef struct {
X	uid_$t		stack_uid;	/* uid of user stack			*/
X	linteger	stack_base;	/* base address of user stack		*/
X	proc2_$state_t	state;		/* ready, waiting, etc.			*/
X	pinteger	usr;		/* user sr				*/
X	linteger	upc;		/* user pc				*/
X	linteger	usp;		/* user stack pointer			*/
X	linteger	usb;		/* user sb ptr (A6)			*/
X	time_$clock_t	cpu_total;	/* cumulative cpu used by process	*/
X	pinteger	priority;	/* process priority			*/
X	acl_$sid	sid;		/* sid of process			*/
X	uid_$t		pgroup;		/* process group uid			*/
X	boolean		is_server;	/* process is a server			*/
X	boolean		pad;
X	pinteger	min_pri;	/* min priority of process (1..16)	*/
X	pinteger	max_pri;	/* max priority of process (1..16)	*/
X	linteger	exec_faults;	/* execute faults			*/
X	linteger	data_faults;	/* data faults				*/
X	linteger	disk_pageIO;	/* disk paging				*/
X	linteger	net_pageIO;	/* net paging				*/
X	uid_$t		orig_pgroup;	/* original process group		*/
X	pinteger	orig_upgid;	/* original unix process group		*/
X	pinteger	unix_PID;	/* Unix process ID			*/
X	pinteger	unix_PPID;	/* Unix Process Parent ID		*/
X	pinteger	unix_PGID;	/* Unix Process Group ID		*/
X	pinteger	udpid;		/* unix debugger id			*/
X	pinteger	asid;		/* address space id			*/
X	uid_$t		acct_uid;	/* uid of command being run		*/
X	pinteger	acct_len;	/* length of command name		*/
X	proc2_$aname_t	acct_name;	/* name of the invoked command		*/
X	pinteger	proc_len;	/* length of process name		*/
X	proc2_$aname_t	proc_name;	/* process name				*/
X	uid_$t		tty_uid;	/* uid of controlling terminal		*/
X	pinteger	pad2;
X	time_$clock_t	cpu_time;	/* total CPU time used			*/
X	pinteger	pad3;
X	linteger	user_ticks;	/* ticks executing in user space	*/
X	linteger	system_ticks;	/* ticks executing in system space	*/
X	linteger	tick_size;	/* size of a tick in microseconds	*/
} proc2_$info_t;
X
extern void proc2_$upid_to_uid (
X	short		&upid,	/* convert unix pid to puid */
X	uid_$t		*p2_uid,
X	status_$t	*status
X	);
X
extern void proc2_$get_info(
X	uid_$t		&p2_uid,
X	proc2_$info_t	*info,
X	pinteger	&info_buf_len,	/* size of info buffer (bytes) */
X	status_$t	*status
X	);
X
X
/*
X * Converts SID to string: <person.group.org.nodeID> or maybe
X * <person.group.org.nodeID.subsys>. Writes the string
X * without adding a null byte: zero the buffer first.
X */
extern void rgyc_$sid2text (
X	acl_$sid	&sid,
X	char		*buffer,
X	status_$t	*status
X	);
X
/* Surely we could use rgyc_$pgo_uid_to_name instead */
X
typedef int acl_$unix_id;
X
/*
X * Converts UID to UNIX number, for pers, proj or org.
X */
extern void rgyc_$pgo_uid_to_num (
X	int	&domain,	/* convert: 0: pers, 1: proj, 2: org */
X	uid_$t	&uid,		/* UID to convert */
X        short	*unknown,	/* set to 0 for pers or proj, 0 for org (why??) */
X	acl_$unix_id *num,	/* UNIX number */
X	status_$t *status);
X
X
typedef short enum {	/* Returned by VALIDATE */
X    name_$junk_flag,
X    name_$wdir_flag,
X    name_$ndir_flag,
X    name_$node_flag,
X    name_$root_flag,
X    name_$node_data_flag,
X    name_$cs_flag
} name_$namtyp_t;
X
/*
X * Do a gpath on an object UID
X */
extern void name_$gpath_lc (
X	uid_$t		&inuid,
X	name_$namtyp_t	&namtyp,
X	pinteger	&maxpnamlen,
X	name_$long_pname_t	pname,
X	pinteger	*pnamlen,
X	status_$t	*status);
X
X
extern void context_$set (
X	uid_$t		&p2_uid,
X	status_$t	*status);
X
extern void pgm_$context_get_args (
X	short		*argument_count,
X	pgm_$argv_ptr	*arg_vector_ptr,
X	status_$t	*status);
X
/* Look up values in other process's address space */
extern void xpd_$locate_proc (
X	uid_$t		&p2_uid,
X	void		&address,
X	int		zero[2],	/* Is this some UID? Why need to set to zero? */
X	void		*value,
X	int		*stat,		/* Why does always get set to 0x070000 ? Is it really a short? */
X	status_$t	*status);
X
X
#ifdef USE_SAFE_ADDR
static jmp_buf jmpenv;
X
void my_fault_handler (int sig)
{
X  _longjmp (jmpenv, 1);
X  exit (1);	/* This should never be reached */
}
X
/*
X * Tests if object at addr, of length len, is readable.
X * Any way to do this easier??? Must I generate and trap an error???
X * Does not test each address, only endpoints of range.
X */
int testaddr (char addr[], long len)
{
X  char	c1, c2;
X
X  if (_setjmp (jmpenv)) {
X    signal (11, SIG_DFL);
X    return (0);
X  }
X
X  c1 = 0; c2 = 0;
X  signal (11, my_fault_handler);
X  c1 = addr[0];
X  if (len > 0 && len < 100000) c2 = addr[len];
X  signal (11, SIG_DFL);
X
X  /*
X   * While all we want is to look up c1,c2, we must actually use them,
X   * otherwise the optimiser may eliminate the assignments.
X   */
X  return (((int)(c1|c2)&0x00ff) + 1024);
}
#endif /* USE_SAFE_ADDR */
X
X
#ifdef DEBUG
#define sysl(a,b)	printf(a, b); printf("\n");
#else /* DEBUG */
#ifdef STRONG_LOG
X /* This isn't worth the time for the procedure call, but if you want... */
#define sysl(a,b)	if (syslog_flag) { syslog(LOG_INFO, a, b); }
#else
#define sysl(a,b)
#endif
#endif /* DEBUG */
X
X
#define ZAP(x,fmt,err) \
X  if (x) \
X   { \
X    sysl(fmt, err) \
X    return (-1); \
X   }
X
#ifdef DEBUG
#define SETZAP(x,lev,fmt,err1,err2,err3) \
X  if (x) \
X   { \
X    printf ("zap to level %d: ", lev); printf (fmt, err1, err2, err3); printf ("\n"); \
X    if (lev > zaplevel) \
X     { \
X      sprintf (zapmess, fmt, err1, err2, err3); \
X      zaplevel = lev; \
X      printf ("zap level set to %d\n", zaplevel); \
X     } \
X    continue; \
X   }
#else /* DEBUG */
#define SETZAP(x,lev,fmt,err1,err2,err3) \
X  if (x) \
X   { \
X    if (lev > zaplevel && syslog_flag) \
X     { \
X      sprintf (zapmess, fmt, err1, err2, err3); \
X      zaplevel = lev; \
X     } \
X    continue; \
X   }
#endif /* DEBUG */
X
X
struct UCB;
struct PCB;
X
struct	PCB
{
X	struct PCB *self1;
X	struct PCB *self2;
X	struct PCB *next;
X	struct PCB *prev;
X	struct UCB *ucb;
} *sock_PCB;
X
struct	UCB
{
X	struct UCB *next;
X	struct UCB *prev;
X	struct in_addr ucb_faddr;
X	struct in_addr ucb_laddr;
X	u_short ucb_fport;
X	u_short ucb_lport;
X	struct	PCB *pcb;
X	void	*Unknown;	/* What is this for??? */
X	char	Dummy[PIDOFF];	/* What goodies lurk within??? */
X	short	PID;
} *sock_UCB;
X
/*
Known good values of PIDOFF:
X OS Version    PIDOFF
X 10.2   m68k   0x46   (probably should be higher!)
X 10.3   m68k   0xc9
X 10.4   m68k   0xc9
X 10.4.1 m68k   0xc9
X 10.4.1 a88k   0x52   (probably should be higher!)
Some values should be higher to correctly allow for incoming
telnet connections (and find the running shell, not a PID of
zero or the PID of telnetd).
*/
X
X
X
int k_open()
{
X  /* Apollos do not use this rubbish */
X  return 0;
}
X
X
X
int k_getuid(struct in_addr *faddr, int fport,
X	     struct in_addr *laddr, int lport,
X	     int *uid
#ifdef ALLOW_FORMAT
X	     , int *retpid
X	     , char **retcmd
X	     , char **retcmd_and_args
#endif
X	    )
{
X int		pcb, ucb;
X short		pid;
X
X status_$t	status;
X
X tcp_$netaddr_t	tcp_ra, tcp_la;
X unsigned short	tcp_rp, tcp_lp;
X tcp_$constate_t tcp_state[MAXCON];
X short		tcp_ncon;
X long		tcp_i;
X
X uid_$t		p2_uid;
X proc2_$info_t	p2_info;
X
X int		domain;
X acl_$unix_id	unix_num;
X short		unknown;
X
#ifdef ALLOW_FORMAT
X static name_$long_pname_t	pname;
X pinteger	pnamlen;
X
X short		arg_count;
X pgm_$arg       *arg;
X pgm_$arg_ptr	*arg_ptr, *arg_ptr2;
X pgm_$argv_ptr	arg_vector_ptr;
X
X static name_$long_pname_t	cmdarg;
#endif
X
X static char	zapmess[BUFLEN];
X long		zaplevel;
X
X
X /* Do we need this extra check? */
X ZAP(fport<1 || fport>65535 || lport<1 || lport>65535, "port numbers out of range",0)
X tcp_rp = fport & 0xffff;
X tcp_lp = lport & 0xffff;
X
X /* Do we need this extra check? */
X ZAP(faddr->s_addr==0 || faddr->s_addr==-1 || laddr->s_addr==0 || laddr->s_addr==-1, "net addresses out of range",0)
X tcp_ra = faddr->s_addr;
X tcp_la = laddr->s_addr;
X
X zaplevel = 0;
X sprintf (zapmess, "no such TCP connection");
X
X
X tcp_$get_server_info (
X   tcp_$all_conns,
X   tcp_state,
X   (short) sizeof(tcp_$constate_t),
X   MAXCON,
X   &tcp_ncon,
X   &status);
X ZAP (status.all,"tcp_$get_server_info failed with status %08x",status.all)
X
X for (tcp_i=0; tcp_i<tcp_ncon; tcp_i++) {
#ifdef DEBUG
X   printf ("\n");
X   printf ("Connection %d (of %d):\n", tcp_i, tcp_ncon);
X   printf ("cstate.nsnd       %6d (%04x)\n", tcp_state[tcp_i].cstate.nsnd&0xffff, tcp_state[tcp_i].cstate.nsnd&0xffff);
X   printf ("cstate.nrcv       %6d (%04x)\n", tcp_state[tcp_i].cstate.nrcv&0xffff, tcp_state[tcp_i].cstate.nrcv&0xffff);
X   printf ("cstate.ssize      %6d (%04x)\n", tcp_state[tcp_i].cstate.ssize&0xffff, tcp_state[tcp_i].cstate.ssize&0xffff);
X   printf ("cstate.rsize      %6d (%04x)\n", tcp_state[tcp_i].cstate.rsize&0xffff, tcp_state[tcp_i].cstate.rsize&0xffff);
X   printf ("cstate.xstat      %6d (%04x)\n", tcp_state[tcp_i].cstate.xstat&0xffff, tcp_state[tcp_i].cstate.xstat&0xffff);
X   printf ("cstate.state      %6d (%04x)\n", tcp_state[tcp_i].cstate.state&0xffff, tcp_state[tcp_i].cstate.state&0xffff);
X   printf ("cstate.iostate    %6d (%04x)\n", tcp_state[tcp_i].cstate.iostate&0xffff, tcp_state[tcp_i].cstate.iostate&0xffff);
X   printf ("cstate.flags      %6d (%04x)\n", tcp_state[tcp_i].cstate.flags&0xffff, tcp_state[tcp_i].cstate.flags&0xffff);
X   printf ("cstate.lport      %6d (%04x)\n", tcp_state[tcp_i].cstate.lport&0xffff, tcp_state[tcp_i].cstate.lport&0xffff);
X   printf ("cstate.rport      %6d (%04x)\n", tcp_state[tcp_i].cstate.rport&0xffff, tcp_state[tcp_i].cstate.rport&0xffff);
X   printf ("cstate.raddr      %08x\n", tcp_state[tcp_i].cstate.raddr);
X   printf ("cstate.laddr      %08x\n", tcp_state[tcp_i].cstate.laddr);
X   printf ("cstate.options    %6d (%04x)\n", tcp_state[tcp_i].cstate.options&0xffff, tcp_state[tcp_i].cstate.options&0xffff);
X   printf ("cstate.pad1       %6d (%04x)\n", tcp_state[tcp_i].cstate.pad1&0xffff, tcp_state[tcp_i].cstate.pad1&0xffff);
X   printf ("route             %08x\n", tcp_state[tcp_i].route);
X   printf ("tcb               %08x\n", (int)tcp_state[tcp_i].tcb);
X   printf ("tstate            %02x\n", tcp_state[tcp_i].tstate&0xff);
X   printf ("ifname            %.9s\n", tcp_state[tcp_i].ifname);
X   printf ("ifunit            %6d (%04x)\n", tcp_state[tcp_i].ifunit&0xffff, tcp_state[tcp_i].ifunit&0xffff);
X   printf ("pr_num            %6d (%04x)\n", tcp_state[tcp_i].pr_num&0xffff, tcp_state[tcp_i].pr_num&0xffff);
X   printf ("pgrp              %08x.%08x\n", tcp_state[tcp_i].pgrp.high, tcp_state[tcp_i].pgrp.low);
X   printf ("\n");
#endif /* DEBUG */
X
X
X   if (
X      (tcp_state[tcp_i].cstate.raddr == tcp_ra &&
X       tcp_state[tcp_i].cstate.laddr == tcp_la &&
X       tcp_state[tcp_i].cstate.rport == tcp_rp &&
X       tcp_state[tcp_i].cstate.lport == tcp_lp)) {
X     /* What??? No sanity check of tcp_state[tcp_i].tstate ? */
X
X     pcb = (int)tcp_state[tcp_i].tcb;
X
X     /* We must not just ZAP on error, but keep message and loop through all lines/connections */
X
X     SETZAP(!pcb, 11, "pcb is zero (closed?)",0,0,0)
#ifdef USE_SAFE_ADDR
X     SETZAP(!testaddr((char*)pcb,sizeof(*sock_PCB)), 12, "pcb at %08x is unreadable",pcb,0,0)
#endif /* USE_SAFE_ADDR */
X     sock_PCB = (struct PCB *) pcb;
X
#ifdef DEBUG
X     printf ("PCB.self1         %08x\n", (int)sock_PCB->self1);
X     printf ("PCB.self2         %08x\n", (int)sock_PCB->self2);
X     printf ("PCB.next          %08x\n", (int)sock_PCB->next);
X     printf ("PCB.prev          %08x\n", (int)sock_PCB->prev);
X     printf ("PCB.ucb           %08x\n", (int)sock_PCB->ucb);
X     printf ("\n");
#endif /* DEBUG */
X
X     SETZAP(pcb!=(int)sock_PCB->self1, 13, "pcb at %d, but PCB.self1 at %d",pcb,(int)sock_PCB->self1,0)
X     SETZAP(pcb!=(int)sock_PCB->self2, 14, "pcb at %d, but PCB.self2 at %d",pcb,(int)sock_PCB->self2,0)
X
X     ucb = (int)sock_PCB->ucb;
X     /* Cannot just test ucb==0: usually we get bogus, but non-null, ucb addresses. */
#ifdef USE_SAFE_ADDR
X     SETZAP(!(ucb&0xffff0000), 21, "ucb is zero (closed?)",0,0,0)
X     SETZAP(!testaddr((char*)ucb,sizeof(*sock_UCB)), 22, "ucb at %08x is unreadable",ucb,0,0)
#else /* USE_SAFE_ADDR */
X     SETZAP(!(ucb&0xf0000000), 21, "ucb is zero (closed?)",0,0,0)
#endif /* USE_SAFE_ADDR */
X     sock_UCB = (struct UCB *) ucb;
X
#ifdef DEBUG
X     printf ("UCB.next          %08x\n", (int)sock_UCB->next);
X     printf ("UCB.prev          %08x\n", (int)sock_UCB->prev);
X     printf ("UCB.ucb_faddr     %08x\n", (int)sock_UCB->ucb_faddr.s_addr);
X     printf ("UCB.ucb_laddr     %08x\n", (int)sock_UCB->ucb_laddr.s_addr);
X     printf ("UCB.ucb_fport     %6d (%04x)\n", sock_UCB->ucb_fport&0xffff, sock_UCB->ucb_fport&0xffff);
X     printf ("UCB.ucb_lport     %6d (%04x)\n", sock_UCB->ucb_lport&0xffff, sock_UCB->ucb_lport&0xffff);
X     printf ("UCB.pcb           %08x\n", (int)sock_UCB->pcb);
X     printf ("UCB.Unknown       %08x\n", (int)sock_UCB->Unknown);
X     printf ("UCB.PID           %6d (%04x)\n", sock_UCB->PID&0xffff, sock_UCB->PID&0xffff);
X     printf ("\n");
X     {
X       long	i;
X       char	*cp;
X       short	*sp;
X       long	*lp, *qp;
X
X       printf ("The Dummy array:\n");
X       printf ("      index      byte         short                   long                quad\n");
X       for (cp=sock_UCB->Dummy, i=0; i<256; i++, cp++) {
X         sp = (short *) cp;
X         lp = (long *)  cp;
X         qp = (long *)  (cp + 4);
X         printf ("%6d %04x %6d %02x %8d %04x %13d %08x   %08x.%08x\n", i,i,*cp,*cp&0xff,*sp,*sp&0xffff,*lp,*lp,*lp,*qp);
X       }
X     }
X     printf ("\n");
#endif /* DEBUG */
X
X     SETZAP(tcp_ra!=(int)sock_UCB->ucb_faddr.s_addr, 23, "Wanted faddr %08x, but found %08x",tcp_ra,(int)sock_UCB->ucb_faddr.s_addr,0)
X     SETZAP(tcp_la!=(int)sock_UCB->ucb_laddr.s_addr, 24, "Wanted laddr %08x, but found %08x",tcp_la,(int)sock_UCB->ucb_laddr.s_addr,0)
X     SETZAP(tcp_rp!=sock_UCB->ucb_fport, 25, "Wanted fport %d, but found %d",tcp_rp,sock_UCB->ucb_fport,0)
X     SETZAP(tcp_lp!=sock_UCB->ucb_lport, 26, "Wanted lport %d, but found %d",tcp_lp,sock_UCB->ucb_lport,0)
X     SETZAP(pcb!=(int)sock_UCB->pcb, 27, "pcb at %d, but UCB.pcb at %d",pcb,(int)sock_UCB->pcb,0)
X
X     pid = sock_UCB->PID;
X     SETZAP(pid<=0 || pid>PID_MAX, 28, "Bad PID %d in UCB",pid,0,0)
X
X     proc2_$upid_to_uid (pid, &p2_uid, &status);
X     SETZAP(status.all, 31, "proc2_$upid_to_uid failed for PID %d with status %08x", pid&0xffff, status.all, 0)
X
#ifdef DEBUG
X     printf ("process uid       %08x.%08x\n", p2_uid.high, p2_uid.low);
X     printf ("\n");
#endif /* DEBUG */
X
X     proc2_$get_info (p2_uid, &p2_info, sizeof(p2_info), &status);
X     SETZAP(status.all, 41, "proc2_$get_info failed on PID %d with status %08x", pid&0xffff, status.all, 0)
X
#ifdef DEBUG
X     printf ("stack_uid         %08x.%08x\n", p2_info.stack_uid.high, p2_info.stack_uid.low);
X     printf ("stack_base        %d\n", p2_info.stack_base);
X     printf ("state             %08x\n", p2_info.state);
X     printf ("usr               %d\n", p2_info.usr);
X     printf ("upc               %d\n", p2_info.upc);
X     printf ("usp               %d\n", p2_info.usp);
X     printf ("usb               %d\n", p2_info.usb);
X     printf ("cpu_total         %08x %04x\n", p2_info.cpu_total.high, p2_info.cpu_total.low);
X     printf ("priority          %d\n", p2_info.priority);
X     printf ("sid.pers          %08x.%08x\n", p2_info.sid.pers.high, p2_info.sid.pers.low);
X     printf ("sid.proj          %08x.%08x\n", p2_info.sid.proj.high, p2_info.sid.proj.low);
X     printf ("sid.org           %08x.%08x\n", p2_info.sid.org.high, p2_info.sid.org.low);
X     printf ("sid.subs          %08x.%08x\n", p2_info.sid.subs.high, p2_info.sid.subs.low);
X     printf ("sid.node          %x\n", p2_info.sid.node);
X     printf ("pgroup            %08x.%08x\n", p2_info.pgroup.high, p2_info.pgroup.low);
X     printf ("is_server         %d\n", p2_info.is_server);
X     printf ("min_pri           %d\n", p2_info.min_pri);
X     printf ("max_pri           %d\n", p2_info.max_pri);
X     printf ("exec_faults       %d\n", p2_info.exec_faults);
X     printf ("data_faults       %d\n", p2_info.data_faults);
X     printf ("disk_pageIO       %d\n", p2_info.disk_pageIO);
X     printf ("net_pageIO        %d\n", p2_info.net_pageIO);
X     printf ("orig_pgroup       %08x.%08x\n", p2_info.orig_pgroup.high, p2_info.orig_pgroup.low);
X     printf ("orig_upgid        %d\n", p2_info.orig_upgid);
X     printf ("unix_PID          %d\n", p2_info.unix_PID);
X     printf ("unix_PPID         %d\n", p2_info.unix_PPID);
X     printf ("unix_PGID         %d\n", p2_info.unix_PGID);
X     printf ("udpid             %d\n", p2_info.udpid);
X     printf ("asid              %d\n", p2_info.asid);
X     printf ("acct_uid          %08x.%08x\n", p2_info.acct_uid.high, p2_info.acct_uid.low);
X     printf ("acct_len          %d\n", p2_info.acct_len);
X     printf ("acct_name         %.*s\n", p2_info.acct_len, p2_info.acct_name);
X     printf ("proc_len          %d\n", p2_info.proc_len);
X     printf ("proc_name         %.*s\n", p2_info.proc_len, p2_info.proc_name);
X     printf ("tty_uid           %08x.%08x\n", p2_info.tty_uid.high, p2_info.tty_uid.low);
X     printf ("cpu_time          %08x %04x\n", p2_info.cpu_time.high, p2_info.cpu_time.low);
X     printf ("user_ticks        %d\n", p2_info.user_ticks);
X     printf ("system_ticks      %d\n", p2_info.system_ticks);
X     printf ("tick_size         %d\n", p2_info.tick_size);
X     printf ("\n");
#endif /* DEBUG */
X
X     SETZAP(p2_info.unix_PID!=pid, 42, "Looked up PID %d, but proc2_$get_info found %d", pid&0xffff, p2_info.unix_PID&0xffff, 0)
X
X     /*
X     for (p2_i = 0; p2_i < BUFLEN; p2_i++) retbuf[p2_i] = 0x00;
X     rgyc_$sid2text (p2_info.sid, retbuf, &status);
X     SETZAP(status.all, 51, "rgyc_$sid2text failed on person UID %08x.%08x with status %08x", p2_info.sid.pers.high, p2_info.sid.pers.low, status.all)
X     */
X
X     domain = 0;
X     rgyc_$pgo_uid_to_num (domain, p2_info.sid.pers, &unknown, &unix_num, &status);
X     SETZAP(status.all, 51, "rgyc_$pgo_uid_to_num failed on person UID %08x.%08x with status %08x", p2_info.sid.pers.high, p2_info.sid.pers.low, status.all)
X     SETZAP(unix_num<0 || unix_num>UID_MAX, 52, "Bad unix UID %d from rgyc_$pgo_uid_to_num on person UID %08x.%08x",unix_num,p2_info.sid.pers.high,p2_info.sid.pers.low)
X
#ifdef DEBUG
X     printf ("Unix UID:         %d\n", unix_num);
X     printf ("Unknown:          %d\n", unknown);
X     printf ("\n");
#endif /* DEBUG */
X
X     *uid = unix_num;
X
#ifdef ALLOW_FORMAT
X     *retpid = pid;
X
X     name_$gpath_lc (p2_info.acct_uid, name_$junk_flag, name_$long_pnamlen_max, pname, &pnamlen, &status);
X     /*
X      * We can fail this with binaries removed,
X      * or hard-linked and removed from original location.
X      * So we fail gracefully...
X     SETZAP(status.all, 61, "name_$gpath_lc failed on object UID %08x.%08x with status %08x", p2_info.acct_uid.high, p2_info.acct_uid.low, status.all)
X     */
X     if (status.all) {
X       pnamlen = p2_info.acct_len;
X       if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X       sprintf (pname, "%.*s (UID=%08x.%08x --> status=%08x)", pnamlen, p2_info.acct_name, p2_info.acct_uid.high, p2_info.acct_uid.low, status.all);
X       pnamlen = strlen(pname);
X     }
X     else if (pnamlen < 1 || pnamlen > name_$long_pnamlen_max) {
X       pnamlen = p2_info.acct_len;
X       if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X       sprintf (pname, "%.*s (UID=%08x.%08x --> bad return length)", pnamlen, p2_info.acct_name, p2_info.acct_uid.high, p2_info.acct_uid.low);
X       pnamlen = strlen(pname);
X     }
X     pname[pnamlen] = 0;
X
#ifdef DEBUG
X     printf ("Command length:   %d\n", pnamlen);
X     printf ("Command name:     %s\n", pname);
X     printf ("\n");
#endif /* DEBUG */
X
X     *retcmd = pname;
X
X     context_$set (p2_uid, &status);
X     SETZAP(status.all, 71, "context_$set failed on process UID %08x.%08x with status %08x", p2_uid.high, p2_uid.low, status.all)
X
X     pgm_$context_get_args (&arg_count, &arg_vector_ptr, &status);
X     /*
X      * We can fail this for processes we do not 'own'.
X      * So we fail gracefully...
X     SETZAP(status.all, 81, "pgm_$context_get_args failed on process UID %08x.%08x with status %08x", p2_uid.high, p2_uid.low, status.all)
X     */
X     if (status.all) {
X       pnamlen = p2_info.acct_len;
X       if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X       sprintf (cmdarg, "%.*s (pgm_$context_get_args --> status=%08x)", pnamlen, p2_info.acct_name, status.all);
X       pnamlen = strlen(cmdarg);
X     }
X     else {
X       short i, j;
X
X       int k1[2];
X       void *k2;
X       int k3;
X
X       if (arg_count > 0) {
#ifdef DEBUG
X         printf ("Argument count:   %d\n", arg_count);
#endif /* DEBUG */
X         pnamlen = 0;
X         arg_ptr = arg_vector_ptr;
X         for (i = 0; i< arg_count; i++, arg_ptr++) {
X           /*
X           ** For 'own' argument would simply have
X           **   arg = *arg_ptr;
X           ** But need to de-reference arg_ptr in context of other process,
X           ** and then need to de-reference the arg pointer itself.
X           */
X           k1[0] = 0; k1[1] = 0; k3 = 0;
X           xpd_$locate_proc (p2_uid, (void)arg_ptr, k1, &k2, &k3, &status);
X           if (status.all) {
X             pnamlen = p2_info.acct_len;
X             if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X             sprintf (cmdarg, "%.*s (xpd_$locate_proc --> status=%08x)", pnamlen, p2_info.acct_name, status.all);
X             pnamlen = strlen(cmdarg);
X             break;
X           }
X           if (k3 != 0x070000) {
X             pnamlen = p2_info.acct_len;
X             if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X             sprintf (cmdarg, "%.*s (xpd_$locate_proc --> k3=%08x)", pnamlen, p2_info.acct_name, k3);
X             pnamlen = strlen(cmdarg);
X             break;
X           }
X           arg_ptr2 = k2;
X           arg = *arg_ptr2;
X           k1[0] = 0; k1[1] = 0; k3 = 0;
X           xpd_$locate_proc (p2_uid, (void)arg, k1, &k2, &k3, &status);
X           if (status.all) {
X             pnamlen = p2_info.acct_len;
X             if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X             sprintf (cmdarg, "%.*s (xpd_$locate_proc --> status=%08x)", pnamlen, p2_info.acct_name, status.all);
X             pnamlen = strlen(cmdarg);
X             break;
X           }
X           if (k3 != 0x070000) {
X             pnamlen = p2_info.acct_len;
X             if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X             sprintf (cmdarg, "%.*s (xpd_$locate_proc --> k3=%08x)", pnamlen, p2_info.acct_name, k3);
X             pnamlen = strlen(cmdarg);
X             break;
X           }
X           arg = k2;
X           if (pnamlen > 0) { sprintf (&cmdarg[pnamlen], " "); pnamlen++; }
X           j = arg->len;
X           if (j + pnamlen > name_$long_pnamlen_max) j = name_$long_pnamlen_max - pnamlen;
X           sprintf (&cmdarg[pnamlen], "%.*s", j, arg->chars);
X           pnamlen += strlen (&cmdarg[pnamlen]);
X           if (pnamlen+10 > name_$long_pnamlen_max) break;
X         }
X       }
X       else {
X         pnamlen = p2_info.acct_len;
X         if (pnamlen > proc2_$aname_len) pnamlen = proc2_$aname_len;
X         sprintf (cmdarg, "%.*s (pgm_$context_get_args --> no args)", pnamlen, p2_info.acct_name);
X         pnamlen = strlen(cmdarg);
X       }
X     }
X
#ifdef DEBUG
X     printf ("Cmd+args length:  %d\n", pnamlen);
X     printf ("Command+args:     %s\n", cmdarg);
X     printf ("\n");
#endif /* DEBUG */
X
X     *retcmd_and_args = cmdarg;
X
X
/*
X * Do we need to set context back to our own with
X *  context_$current (what arguments?)   or
X *  context_$set (our_own_Proc-UID)      ?
*/
X
/*
X * Could we figure out environment with ev_$context_read_var_entry ?
X * Current (working) and home (naming) directories with name_$read_dirs_p ?
*/
X
X
#endif
X
X     return (0);
X   }
X }
X
X ZAP(1,zapmess,0)
X /* return (-1); */
}
X
SHAR_EOF
  $shar_touch -am 0514055996 'pidentd-2.7/src/kernel/apollo.c' &&
  chmod 0644 'pidentd-2.7/src/kernel/apollo.c' ||
  $echo 'restore of' 'pidentd-2.7/src/kernel/apollo.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/kernel/apollo.c:' 'MD5 check failed'
4039e0a767fbe8dc81b175b14e67616c  pidentd-2.7/src/kernel/apollo.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/kernel/apollo.c'`"
    test 27026 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/kernel/apollo.c:' 'original size' '27026,' 'current size' "$shar_count!"
  fi
fi
: || $echo 'restore of' 'pidentd-2.7/src/kernel/irix5.c' 'failed'
$echo 'End of part' '5,' 'continue with part' '6'
exit 0


