/*
 * dnode.c - PTX node functions for lsof
 */


/*
 * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana
 * 47907.  All rights reserved.
 *
 * Written by Victor A. Abell
 *
 * This software is not subject to any license of the American Telephone
 * and Telegraph Company or the Regents of the University of California.
 *
 * Permission is granted to anyone to use this software for any purpose on
 * any computer system, and to alter it and redistribute it freely, subject
 * to the following restrictions:
 *
 * 1. Neither the authors nor Purdue University are responsible for any
 *    consequences of the use of this software.
 *
 * 2. The origin of this software must not be misrepresented, either by
 *    explicit claim or by omission.  Credit to the authors and Purdue
 *    University must appear in documentation and sources.
 *
 * 3. Altered versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 *
 * 4. This notice may not be removed or altered.
 */

#ifndef lint
static char copyright[] =
"@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n";
static char *rcsid = "$Id: dnode.c,v 1.9 96/01/11 16:41:58 abe Exp $";
#endif


#include "lsof.h"


#if	_PTXV>=400
_PROTOTYPE(static void ent_fa,(caddr_t *a1, caddr_t *a2, char *d));
#endif	/* _PTXV>=400 */

_PROTOTYPE(static struct l_dev * finddev,(dev_t *dev, int stream));
_PROTOTYPE(static int isip,(char *mn));
_PROTOTYPE(static char isvlocked,(struct vnode *va));


struct iptab_proto {
	char *mn;			/* module name */
	char *nm;			/* protocol name */
	int fam;			/* protocol familiy */
	int ipid;			/* IP protocol ID */
} IPtab[] = {
	{ "tcp",	"TCP",	AF_INET,	IPPROTO_TCP	},
	{ "udp",	"UDP",	AF_INET,	IPPROTO_UDP	},
	{ NULL,		NULL,	0,		0		},
};


#if	_PTXV>=400
/*
 * ent_fa() - enter fattach addresses in NAME column addition
 */

static void
ent_fa(a1, a2, d)
	caddr_t *a1;			/* first fattach address (NULL OK) */
	caddr_t *a2;			/* second fattach address */
	char *d;			/* direction ("->" or "<-") */
{
	char buf[64], *cp;
	MALLOC_S len;

	if (Lf->nma)
		return;
	if (!a1)
		(void) sprintf(buf, "(FA:%s%#x)", d, *a2);
	else
		(void) sprintf(buf, " (FA:%#x%s%#x)", *a1, d, *a2);
	len = strlen(buf) + 1;
	if ((cp = (char *)malloc(len)) == NULL) {
		(void) fprintf(stderr,
			"%s: no space for fattach addresses at PID %d, FD %s\n",
			Pn, Lp->pid, Lf->fd);
		exit(1);
	}
	(void) strcpy(cp, buf);
	Lf->nma = cp;
}
#endif	/* _PTXV>=400 */



/*
 * finddev() - look up device by device number
 */

static struct l_dev *
finddev(dev, stream)
	dev_t *dev;			/* device */
	int stream;			/* stream if 1 */
{
	struct clone *c;
	struct l_dev *dp;
/*
 * Search device table for match.
 */
	if ((dp = lkupdev(dev, 0)) != (struct l_dev *)NULL)
		return(dp);
/*
 * Search for clone.
 */
	if (stream && Clone) {
		for (c = Clone; c; c = c->next) {
			if (major(*dev) == minor(Devtp[c->dx].rdev))
				return(&Devtp[c->dx]);
		}
	}
	return(NULL);
}


/*
 * isip() - is the module name an IP name?
 */

int
isip(mn)
	char *mn;			/* module_info name */
{
	int i;

	for (i = 0; IPtab[i].mn; i++) {
		if (strcasecmp(mn, IPtab[i].mn) == 0)
			return(i);
	}
	return(-1);
}


/*
 * isvlocked() - is a vnode locked
 */

static char
isvlocked(va)
	struct vnode *va;		/* local vnode address */
{

	struct filock f;
	off_t l;

#if	_PTXV>=410
	struct vreclck vl;
#endif	/* _PTXV<410 */

#if	_PTXV<410
	if (va->v_filocks == NULL
	||  kread((KA_T)va->v_filocks, (char *)&f, sizeof(f)))
		return(' ');
#else	/* _PTXV>=410 */
	if (va->v_recp == NULL
	||  kread((KA_T)va->v_recp, (char *)&vl, sizeof(vl))
	||  vl.vr_filocks == NULL
	||  kread((KA_T)vl.vr_filocks, (char *)&f, sizeof(f)))
		return(' ');
	
#endif	/* _PTXV<410 */

	if (f.set.l_whence == 0 && f.set.l_start == 0 && f.set.l_len == 0)
		l = 1;
	else
		l = 0;
	switch (f.set.l_type & (F_RDLCK | F_WRLCK)) {

	case F_RDLCK:
		return((l) ? 'R' : 'r');
	case F_WRLCK:
		return((l) ? 'W' : 'w');
	case (F_RDLCK + F_WRLCK):
		return('u');
	}
	return(' ');
}


/*
 * process_node() - process vnode
 */

void
process_node(va)
	caddr_t va;			/* vnode kernel space address */
{

#if	defined(HAS_CDFS)
	struct cd_inode c;
#endif	/* defined(HAS_CDFS) */

	char *cp, dev_ch[32];
	dev_t dev;
	int dl, j, k, l, pt, px;
	struct l_dev *dp;
	struct fifonode f;
	struct inode i;
	KA_T ka, qp;
	struct module_info mi;
	struct inpcb *p, pcb;
	struct queue q;
	struct qinit qi;
	struct so_so so, *sop;
	struct sockaddr_un ua;

#if	defined(HAS_NFS)
	struct rnode r;
#endif	/* defined(HAS_NFS) */

	struct snode s;
	KA_T sa;
	struct stdata sd, *sp;
	int sin = 0;
	int sns = 0;
	int srv = 0;
	char *ty;
	enum vtype type;
	struct vnode v, rv, uv;
	struct l_vfs *vfs;

#if	_PTXV>=400
	struct vfs favfs;
	struct namenode n;
	int nmst = 1;
#endif	/* _PTXV>=400 */

/*
 * Read the vnode.
 */

read_vnode:

	if ( ! va) {
		enter_nm("no vnode address");
		return;
	}
	if (readvnode((caddr_t)va, &v)) {
                enter_nm(Namech);
                return;
        }

# if	defined(HASNCACHE)
	Lf->na = (unsigned long)va;
# endif	/* defined(HASNCACHE) */

/*
 * Determine the vnode type.
 */
	if (Nl[X_FIFOOPS].n_value && (long)v.v_op == Nl[X_FIFOOPS].n_value)
		Ntype = N_FIFO;

#if	defined(HAS_NFS)
	else if (Nl[X_NFSOPS].n_value && (long)v.v_op == Nl[X_NFSOPS].n_value)
		Ntype = N_NFS;
#endif	/* defined(HAS_NFS) */

	else if (Nl[X_SPECOPS].n_value
	     &&  (long)v.v_op == Nl[X_SPECOPS].n_value)
		Ntype = N_SPEC;

#if	defined(HAS_CDFS)
	else if (Nl[X_CDFSOPS].n_value
	     &&  (long)v.v_op == Nl[X_CDFSOPS].n_value)
		Ntype = N_CDFS;
#endif	/* defined(HAS_CDFS) */

#if	_PTXV>=400
	else if (Nl[X_NMOPS].n_value && (long)v.v_op == Nl[X_NMOPS].n_value) {
		Ntype = N_NM;
	/*
	 * Read the namenode and enter the fattach addresses.
	 */
		if (!v.v_data || kread((KA_T)v.v_data, (char *)&n, sizeof(n))) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read namenode (%#x)",
				va, v.v_data);
			enter_nm(Namech);
			return;
		}
		if (n.nm_mountpt)
			ent_fa(&va, (caddr_t *)&n.nm_mountpt, "->");
	/*
	 * If this is the first time a namenode has been examined, and
	 * if it has an nm_filevp pointer, reset the vnode address to
	 * it and start over.
	 */
		if (nmst && n.nm_filevp) {
			va = (caddr_t)n.nm_filevp;
			nmst = 0;
			goto read_vnode;
		}
	}
#endif	/* _PTXV>=400 */

#if	_PTXV>=400
/*
 * If this node has a v_vfsmountedhere pointer, read it.  If it represents
 * a "namefs" file system, and has a private data pointer, record the
 * fattach addresses.
 */
	if (v.v_vfsmountedhere
	&&  kread((KA_T)v.v_vfsmountedhere, (char *)&favfs, sizeof(favfs)) == 0
	&&  favfs.vfs_data)
		ent_fa(&va, &favfs.vfs_data, "<-");
#endif	/* _PTXV>=400 */

/*
 * Determine the lock type.
 */
	Lf->lock = isvlocked(&v);
/*
 * Establish the local virtual file system structure.
 */
	if (v.v_vfsp == NULL)
		vfs = NULL;
	else {
	    if ((vfs = readvfs(v.v_vfsp)) == NULL) {
                (void) sprintf(Namech, "bad vfs for %#x at %#x", va, v.v_vfsp);
                enter_nm(Namech);
		return;
	    }
	}
/*
 * Read the cd_inode, fifonode, inode, rnode, or snode.
 */
	switch (Ntype) {

#if	defined(HAS_CDFS)
	case N_CDFS:
		if (!v.v_data || kread((KA_T)v.v_data, (char *)&c, sizeof(c))) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read cd_inode (%#x)",
				va, v.v_data);
			enter_nm(Namech);
			return;
		}
		break;
#endif	/* defined(HAS_CDFS) */

	case N_FIFO:
		if (!v.v_data || kread((KA_T)v.v_data, (char *)&f, sizeof(f))) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read fifonode (%#x)",
				va, v.v_data);
			enter_nm(Namech);
			return;
		}
		break;

#if	defined(HAS_NFS)
	case N_NFS:
		if (!v.v_data || readrnode((caddr_t)v.v_data, &r)) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read rnode (%#x)",
				va, v.v_data);
			enter_nm(Namech);
			return;
		}
		break;
#endif	/* defined(HAS_NFS) */

#if	_PTXV>=400
	case N_NM:
		if (!v.v_data || kread((KA_T)v.v_data, (char *)&n, sizeof(n))) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read namenode (%#x)",
				va, v.v_data);
			enter_nm(Namech);
			return;
		}
		break;
#endif	/* _PTXV>=400 */

	case N_SPEC:
		p = (struct inpcb *)NULL;
		pt = -1;
		sop = (struct so_so *)NULL;
		if ((sa = (KA_T)v.v_snode) == NULL
		&&  (sa = (KA_T)v.v_data) == NULL) {
			sns = 0;
			break;
		}
	/*
	 * Read the snode.
	 */
		if (kread(sa, (char *)&s, sizeof(s))) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read snode (%#x)", va, sa);
			enter_nm(Namech);
			return;
		}
		sns = 1;
		if (s.s_realvp) {

		/*
		 * Read the "real" vnode, if there is one, then read its inode.
		 */
		    if (readvnode((caddr_t)s.s_realvp, &rv)) {
			(void) sprintf(Namech,
			    "snode at %#x; can't read real vnode at %#x",
			    sa, s.s_realvp);
			return;
		    }
		    srv = 1;
		    if (rv.v_data) {
			if (readinode((struct inode *)v.v_data, &i) == 0) {
			    sin = 1;

#if	defined(HASLFILEADD)
			    Lf->ina = rv.v_data;
			    Lf->ina_def = 1;
#endif	/* defined(HASLFILEADD) */

			}
		    }
		}

#if	_PTXV<400
		if ((sp = s.s_sptr) == NULL)
#else	/* _PTXV>=400 */
		if ((sp = v.v_stream) == NULL)
#endif	/*_PTXV<400 */
			break;
	/*
	 * Namech may be:
	 *    /dev/* name if it exists for s.s_dev;
	 *    "STR:" otherwise.
	 */
		(void) strcpy(Namech, "STR:");
		Lf->is_stream = 1;
		k = strlen(Namech);
		cp = NULL;
		if ((dp = finddev(&s.s_dev, 1)) != NULL) {
			(void) strcpy(&Namech[k], dp->name);
			k += strlen(dp->name);
			if ((cp = strrchr(dp->name, '/')) != NULL)
			    cp++;
		}
	    /*
	     * Get the module names of all queue elements of the stream's
	     * sd_wrq queue.  Skip module names that end in "head" or
	     * match the last component of the /dev name.
	     *
	     * If the module name at the "end" ("head") of the stream
	     * is "tcp" or "udp" treat this as a socket file.
	     *
	     * If a stream entry contains the "sockmod" module name, save
	     * the private pointer of its queue structure as a possible
	     * struct so_so address.
	     */
		if (kread((KA_T)sp, (char *)&sd, sizeof(sd)) == 0) {
		    dl = sizeof(dev_ch) - 1;
		    dev_ch[dl] = '\0';
		    qp = (KA_T)sd.sd_wrq;
		    for (j = 0; qp && j < 20; j++, qp = (KA_T)q.q_next) {
			if (kread(qp, (char *)&q, sizeof(q)))
			    break;
			if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL
			||  kread(ka, (char *)&qi, sizeof(qi)))
			    continue;
			if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL
			||  kread(ka, (char *)&mi, sizeof(mi)))
			    continue;
			if ((ka = (KA_T)mi.mi_idname) == (KA_T)NULL
			||  kread(ka, dev_ch, dl))
			    continue;
			if ((l = strlen(dev_ch)) < 1)
			    continue;
			if (l >= 4 && strcasecmp(&dev_ch[l - 4], "head") == 0)
			    continue;
			if (q.q_next == NULL && q.q_ptr != NULL
			&&  (px = isip(dev_ch)) >= 0)
			{
			    process_socket(IPtab[px].nm, IPtab[px].fam,
				IPtab[px].ipid, (KA_T)q.q_ptr);
			    return;
			}
			if (cp && strcmp(cp, dev_ch) == 0) {
			    if (q.q_ptr && pt < 0 && (px = isip(cp)) >= 0) {

			    /*
			     * If this is a TCP or UDP module and the
			     * queue structure has a private pointer in
			     * q_ptr, save it as a PCB address.
			     */
				switch (IPtab[px].ipid) {
				case IPPROTO_TCP:
				    pt = 0;
				case IPPROTO_UDP:
				    pt = 1;
				}
				if (pt >= 0) {
				    p = (struct inpcb *)q.q_ptr;
				    (void) strcpy(Lf->iproto, IPtab[px].nm);
				}
			    }
			    continue;
			}
			if (q.q_ptr && strcasecmp(dev_ch, "sockmod") == 0
			&&  sop == (struct so_so *)NULL)
			    sop = (struct so_so *)q.q_ptr;
			if (k) {
			    if ((k + 2) > (MAXPATHLEN - 1))
				break;
			    (void) strcpy(&Namech[k], "->");
			    k += 2;
			}
			if ((k + l) > (MAXPATHLEN - 1))
			    break;
			(void) strcpy(&Namech[k], dev_ch);
			k += l;
		    }
		}
		if (p && pt >= 0) {
		    sop = NULL;

		/*
		 * If the stream has a TCP or UDP module with a PCB
		 * pointer, print any associated local and foreign
		 * Internet addresses.
		 */
		    if (kread((KA_T)p, (char *)&pcb, sizeof(pcb)))
			break;
		    if (Fnet)
			Lf->sf |= SELNET;
		    if ((k + 1) > (MAXPATHLEN - 1))
			break;
		    Namech[k++] = ' ';
		    Namech[k] = '\0';
	 	/*
		 * Print the local and foreign addresses from the PCB.
		 */
		    printinaddr((struct in_addr *)&pcb.inp_laddr,
			(int)ntohs(pcb.inp_lport));
		    if (pcb.inp_faddr != INADDR_ANY ||  pcb.inp_fport != 0) {
			cp = endnm();
			if ((MAXPATHLEN - 1 - (cp - Namech)) >= 2)
			    (void) strcat(cp, "->");
			printinaddr((struct in_addr *)&pcb.inp_faddr,
			    (int)ntohs(pcb.inp_fport));
		    }
		    Lf->inp_ty = 2;
		} else if (sop != (struct so_so *)NULL) {
		    
		/*
		 * The stream has a "sockmod" member and its queue structure
		 * has a private pointer; see if it points to Unix domain
		 * socket information; if it does, read its so_so structure.
		 */
		    if (kread((KA_T)sop, (char *)&so, sizeof(so))) {
			sop = (struct so_so *)NULL;
			break;
		    }
		}
		break;
	case N_REGLR:
	default:
		if (!v.v_data || readinode((struct inode *)v.v_data, &i)) {
			(void) sprintf(Namech,
				"vnode at %#x: can't read inode (%#x)",
				va, v.v_data);
			enter_nm(Namech);
			return;
		}
		sin = 1;

#if	defined(HASLFILEADD)
		Lf->ina = v.v_data;
		Lf->ina_def = 1;
#endif	/* defined(HASLFILEADD) */

	}
/*
 * Get device and type for printing.
 */
	dev = 0;
	switch(Ntype) {

#if	defined(HAS_CDFS)
	case N_CDFS:
#endif	/* defined(HAS_CDFS) */


#if	defined(HAS_NFS)
	case N_NFS:
		if (vfs) {
			dev = vfs->dev;
			Lf->dev_def = 1;
		}
		break;
#endif	/* defined(HAS_NFS) */

#if	_PTXV>=400
	case N_NM:
		dev = n.nm_vattr.va_fsid;
		Lf->dev_def = 1;
		break;
#endif	/* _PTXV>=400 */

	case N_FIFO:
		(void) sprintf(dev_ch, "0x%08x", va);
		enter_dev_ch(dev_ch);
		break;
	case N_SPEC:
		if (sop != (struct so_so *)NULL)
			dev = so.lux_dev.addr.tu_addr.dev;
		else
			dev = sns ? s.s_dev : v.v_rdev;
		Lf->dev_def = 1;
		break;
	default:
		if (v.v_type == VCHR) {
			dev = v.v_rdev;
			Lf->dev_def = 1;
		} else {
		    if (srv) {
			dev = rv.v_rdev;
			Lf->dev_def = 1;
		    } else if (v.v_devvp != NULL
		     	   &&  kread((KA_T)i.i_devvp, (char *)&uv, sizeof(uv))
			   == 0)
		    {
			dev = uv.v_rdev;
			Lf->dev_def = 1;
		    }
		}
	}
	type = v.v_type;
/*
 * Obtain the inode number.
 */
	switch (Ntype) {

#if	defined(HAS_CDFS)
	case N_CDFS:
		Lf->inode = (unsigned long)c.iso_extent;
		Lf->inp_ty = 1;
		break;
#endif	/* defined(HAS_CDFS) */

	case N_FIFO:
		break;

#if	defined(HAS_NFS)
	case N_NFS:
		Lf->inode = (unsigned long)r.r_nfsattr.na_nodeid;
		Lf->inp_ty = 1;
		break;
#endif	/* defined(HAS_NFS) */

#if	_PTXV>=400
	case N_NM:
		Lf->inode = (unsigned long)n.nm_vattr.va_nodeid;
		Lf->inp_ty = 1;
		break;
#endif	/* _PTXV>=400 */

	case N_REGLR:
		if (sin) {
			Lf->inode = (unsigned long)i.i_number;
			Lf->inp_ty = 1;
		}
		break;
	case N_SPEC:
		if (sop) {
			Lf->inode = (unsigned long)so.lux_dev.addr.tu_addr.ino;
			Lf->inp_ty = 1;
		}
		break;
	}
/*
 * Obtain the file size.
 */
	if (Foffset)
		Lf->off_def = 1;
	else {
		switch (Ntype) {

#if	defined(HAS_CDFS)
		case N_CDFS:
			Lf->sz = (unsigned long)c.i_size;
			Lf->sz_def = 1;
			break;
#endif	/* defined(HAS_CDFS) */

		case N_FIFO:

#if	_PTXV<400
			if (Fsize || (Lf->access != 'r' && Lf->access != 'w')) {
				(void) sprintf(Namech, "rd=%#x; wr=%#x",
					f.fn_rptr, f.fn_wptr);
				Lf->sz = (unsigned long)f.fn_size;
				Lf->sz_def = 1;
				break;
			}
			Lf->off = (unsigned long)
				  (Lf->access == 'r') ? f.fn_rptr : f.fn_wptr;
			(void) sprintf(Namech, "%s=%#x",
				(Lf->access == 'r') ? "wr" : "rd",
				(Lf->access == 'r') ? f.fn_wptr : f.fn_rptr);
#endif	/* _PTXV<400 */

			Lf->off_def = 1;
			break;

#if	defined(HAS_NFS)
		case N_NFS:
			Lf->sz = (unsigned long)r.r_size;
			Lf->sz_def = 1;
			break;
#endif	/* defined(HAS_NFS) */

#if	_PTXV>=400
		case N_NM:
			Lf->sz = (unsigned long)n.nm_vattr.va_size;
			Lf->sz_def = 1;
			break;
#endif	/* _PTXV>=400 */

		case N_REGLR:
			if (type == VREG || type == VDIR) {
				if (sin) {
					Lf->sz = (unsigned long)
						 i.i_ic.ic_size.val[0];
					Lf->sz_def = 1;
				}
			} else if (type == VCHR && !Fsize)
				Lf->off_def = 1;
			break;
		case N_SPEC:
			if (type == VCHR && !Fsize)
				Lf->off_def = 1;
			break;
		}
	}

#if	defined(HAS_NFS)
/*
 * Record an NFS file selection.
 */
	if (Ntype == N_NFS && Fnfs)
		Lf->sf |= SELNFS;
#endif	/* defined(HAS_NFS) */

/*
 * Save the file system names.
 */
	if (vfs) {
		Lf->fsdir = vfs->dir;
		Lf->fsdev = vfs->fsname;

#if	defined(HASFSINO)
		Lf->fs_ino = vfs->fs_ino;
#endif	/* defined(HASFSINO) */

	}
/*
 * Format the vnode type, and possibly the device name.
 */
	switch (type) {

	case VNON:
		ty ="VNON";
		break;
	case VREG:
	case VDIR:
		ty = (type == VREG) ? "VREG" : "VDIR";
		Lf->dev = dev;
		break;
	case VBLK:
		ty = "VBLK";
		break;
	case VCHR:
		Lf->dev = dev;
		Lf->is_chr_dev = 1;
		ty = "VCHR";
		break;
	case VLNK:
		ty = "VLNK";
		break;

#if	defined(VSOCK)
	case VSOCK:
		ty = "SOCK";
		break;
#endif

	case VBAD:
		ty = "VBAD";
		break;
	case VFIFO:
		Lf->dev = dev;
		ty = "FIFO";
		break;
	default:
		if (type > 9999)
			(void) sprintf(Lf->type, "*%03d", type % 1000);
		else
			(void) sprintf(Lf->type, "%4d", type);
		(void) strcpy(Namech, "unknown type");
		ty = NULL;
	}
	if (ty)
		(void) strcpy(Lf->type, ty);
/*
 * If this is a VCHR file and it's missing an inode number, try to
 * supply one.
 */
	if (Lf->inp_ty == 0 && type == VCHR && Lf->dev_def)
		find_ch_ino();
#if	_PTXV>=400
/*
 * If a PTX 4 or greater FIFO node has a mate, and if nothing has been
 * put in Namech already, put the mate's address there.
 */
	if (Ntype == N_FIFO && f.fn_mate && Namech[0] == '\0')
		(void) sprintf(Namech, "->0x%08x", f.fn_mate);
#endif	/* _PTXV>=400 */

/*
 * If this is a "sockmod" special file and it has a so_so structure,
 * try to retrieve the Unix domain socket path.
 */
	if (Ntype == N_SPEC && sop != (struct so_so *)NULL) {
	    if (Funix)
		Lf->sf |= SELUNX;
	    (void) strcpy(Lf->type, "unix");
	    if ((Namech[0] == '\0' || !strncmp(Namech, "STR:", strlen("STR:")))
	    &&  so.laddr.buf != (char *)NULL
	    &&  so.laddr.len == sizeof(ua))
	    {
		if (kread((KA_T)so.laddr.buf, (char *)&ua, sizeof(ua)) == 0) {
		    ua.sun_path[sizeof(ua.sun_path) - 1] = '\0';
		    (void) strcpy(Namech, ua.sun_path);
		}
	    }
	}
/*
 * Test for specified file.
 */
	if (Sfile && is_file_named(NULL, type))
		Lf->sf |= SELNM;
/*
 * Enter name characters.
 */
	if (Namech[0])
		enter_nm(Namech);
}
