diff uip/popi.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children a6481689f99c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uip/popi.c	Mon Apr 18 23:46:02 2005 +0900
@@ -0,0 +1,878 @@
+/* popi.c - POP initiator - for MPOP */
+#ifndef	lint
+static char ident[] = "@(#)$Id$";
+#endif	lint
+
+#include "../h/mh.h"
+#include "../h/formatsbr.h"
+#include "../h/scansbr.h"
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef	SMTP
+#include "../h/local.h"
+#else	/* SMTP */
+#include <sys/stat.h>
+#endif	/* SMTP */
+#include "../zotnet/mts.h"
+#ifdef SYS5DIR
+#include <stdlib.h>
+#endif
+
+/*  */
+
+#ifndef	RPOP
+#define	RPOPminc(a)	(a)
+#else
+#define	RPOPminc(a)	0
+#endif
+
+#ifndef	APOP
+#define	APOPminc(a)	(a)
+#else
+#define	APOPminc(a)	0
+#endif
+
+#if !defined(BPOP) || defined(NNTP)
+#define	BPOPminc(a)	(a)
+#else
+#define	BPOPminc(a)	0
+#endif
+
+#ifndef	SMTP
+#define	BULKminc(a)	(a)
+#else
+#define	BULKminc(a)	0
+#endif
+
+static struct swit  switches[] = {
+#define	APOPSW	0
+    "apop", APOPminc (-4),
+#define	NAPOPSW	1
+    "noapop", APOPminc (-6),
+
+#define	AUTOSW	2
+    "auto", BPOPminc(-4),
+#define	NAUTOSW	3
+    "noauto", BPOPminc(-6),
+
+#define	BULKSW	4
+    "bulk directory", BULKminc(-4),
+
+#define	FORMSW	5
+    "form formatfile", 0,
+
+#define	FMTSW	6
+    "format string", 5,
+
+#define	HOSTSW	7
+    "host host", 0,
+
+#define	PROGSW	8
+    "mshproc program", 0,
+
+#define	RPOPSW	9
+    "rpop", RPOPminc (-4),
+#define	NRPOPSW	10
+    "norpop", RPOPminc (-6),
+
+#define	USERSW	11
+    "user user", 0,
+
+#define	WIDSW	12
+    "width columns", 0,
+
+#define	HELPSW	13
+    "help", 4,
+
+    NULL, 0
+};
+
+/*  */
+
+static	char   *bulksw = NULLCP;
+static	int	snoop = 0;
+static	int	width = 0;
+
+static	char	mailname[BUFSIZ];
+
+static	char   *nfs = NULL;
+
+static	struct msgs *mp;
+
+extern	int	errno;
+
+extern	char	response[];
+
+static popi(), retr_action();
+#if defined(BPOP) && !defined(NNTP)
+static msh();
+#endif
+#ifdef SMTP
+static do_bulk();
+#endif
+
+/*  */
+
+/* ARGSUSED */
+
+main (argc, argv)
+int	argc;
+char   *argv[];
+{
+    int	    autosw = 1,
+	    noisy = 1,
+	    rpop;
+    char   *cp,
+	   *maildir,
+	   *folder = NULL,
+	   *form = NULL,
+	   *format = NULL,
+	   *host = NULL,
+	   *user = NULL,
+	   *pass = NULL,
+	    buf[100],
+	  **ap,
+	  **argp,
+	   *arguments[MAXARGS];
+    struct stat st;
+
+    invo_name = r1bindex (argv[0], '/');
+    mts_init (invo_name);
+    if (pophost && *pophost)
+	host = pophost;
+    if ((cp = getenv ("MHPOPDEBUG")) && *cp)
+	snoop++;
+    if ((cp = m_find (invo_name)) != NULL) {
+	ap = brkstring (cp = getcpy (cp), " ", "\n");
+	ap = copyip (ap, arguments);
+    }
+    else
+	ap = arguments;
+    (void) copyip (argv + 1, ap);
+    argp = arguments;
+
+    rpop = getuid () && !geteuid ();
+
+/*  */
+
+    while (cp = *argp++) {
+	if (*cp == '-')
+	    switch (smatch (++cp, switches)) {
+		case AMBIGSW: 
+		    ambigsw (cp, switches);
+		    done (1);
+		case UNKWNSW: 
+		    adios (NULLCP, "-%s unknown", cp);
+		case HELPSW: 
+		    (void) sprintf (buf, "%s [+folder] [switches]", invo_name);
+		    help (buf, switches);
+		    done (1);
+
+		case AUTOSW:
+		    autosw = 1;
+		    continue;
+		case NAUTOSW:
+		    autosw = 0;
+		    continue;
+
+		case BULKSW: 
+		    if (!(bulksw = *argp++) || *bulksw == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+
+		case FORMSW: 
+		    if (!(form = *argp++) || *form == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    format = NULL;
+		    continue;
+		case FMTSW: 
+		    if (!(format = *argp++) || *format == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    form = NULL;
+		    continue;
+
+		case WIDSW: 
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    width = atoi (cp);
+		    continue;
+
+		case HOSTSW:
+		    if (!(host = *argp++) || *host == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+		case USERSW:
+		    if (!(user = *argp++) || *user == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+
+		case APOPSW:
+		    rpop = -1;
+		    continue;
+		case RPOPSW:
+		    rpop = 1;
+		    continue;
+		case NAPOPSW:
+		case NRPOPSW:
+		    rpop = 0;
+		    continue;
+
+		case PROGSW:
+		    if (!(mshproc = *argp++) || *mshproc == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+	    }
+	if (*cp == '+' || *cp == '@') {
+	    if (folder)
+		adios (NULLCP, "only one folder at a time!");
+	    else
+		folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
+	}
+	else
+	    adios (NULLCP, "usage: %s [+folder] [switches]", invo_name);
+    }
+
+/*  */
+
+    if (!host)
+	adios (NULLCP, "usage: %s -host \"host\"", invo_name);
+
+#ifdef	SMTP
+    if (bulksw)
+	do_bulk (host);
+#endif
+
+    if (user == NULL)
+	user = getusr ();
+    if (rpop > 0)
+	pass = getusr ();
+    else {
+	(void) setuid (getuid ());
+	ruserpass (host, &user, &pass);
+    }
+    (void) sprintf (mailname, "PO box for %s@%s", user, host);
+
+    if (pop_init (host, user, pass, snoop, rpop) == NOTOK)
+	adios (NULLCP, "%s", response);
+    if (rpop > 0)
+	(void) setuid (getuid ());
+
+    nfs = new_fs (form, format, FORMAT);
+
+    if (!m_find ("path"))
+	free (path ("./", TFOLDER));
+    if (!folder && !(folder = m_find (inbox)))
+	folder = defalt;
+    maildir = m_maildir (folder);
+
+    if (stat (maildir, &st) == NOTOK) {
+	if (errno != ENOENT)
+	    adios (maildir, "error on folder");
+	cp = concat ("Create folder \"", maildir, "\"? ", NULLCP);
+	if (noisy && !getanswer (cp))
+	    done (1);
+	free (cp);
+	if (!makedir (maildir))
+	    adios (NULLCP, "unable to create folder %s", maildir);
+    }
+
+    if (chdir (maildir) == NOTOK)
+	adios (maildir, "unable to change directory to");
+    if (!(mp = m_gmsg (folder)))
+	adios (NULLCP, "unable to read folder %s", folder);
+
+#if defined(BPOP) && !defined(NNTP)
+    if (autosw)
+	msh ();
+    else
+#endif
+	popi ();
+
+    (void) pop_quit ();
+
+    m_replace (pfolder, folder);
+    m_setvis (mp, 0);
+    m_sync (mp);
+    m_update ();
+
+    done (0);
+
+    /* NOTREACHED */
+}
+
+/*  */
+
+static struct swit popicmds[] = {
+#define	DELECMD	 0
+    "dele", 0,
+#define	LASTCMD	 1
+    "last", 0,
+#define	LISTCMD	 2
+    "list", 0,
+#define	NOOPCMD	 3
+    "noop", 0,
+#define	QUITCMD	 4
+    "quit", 0,
+#define	RETRCMD	 5
+    "retr", 0,
+#define	RSETCMD	 6
+    "rset", 0,
+#define	SCANCMD	 7
+    "scan", 0,
+#define	STATCMD	 8
+    "stat", 0,
+#define	TOPCMD	 9
+    "top", 0,
+#if defined(BPOP) && !defined(NNTP)
+#define	MSHCMD	10
+    "msh", 0,
+#endif
+
+    NULL, 0
+};
+
+/*  */
+
+static	popi ()
+{
+    int	    eof;
+
+    eof = 0;
+    for (;;) {
+	int	i;
+	register char *cp;
+	char	buffer[BUFSIZ];
+
+	if (eof)
+	    return;
+
+	printf ("(%s) ", invo_name);
+	for (cp = buffer; (i = getchar ()) != '\n'; ) {
+	    if (i == EOF) {
+		(void) putchar ('\n');
+		if (cp == buffer)
+		    return;
+		eof = 1;
+		break;
+	    }
+
+	    if (cp < buffer + sizeof buffer - 2)
+		*cp++ = i;
+	}
+	*cp = '\0';
+	if (buffer[0] == '\0')
+	    continue;
+	if (buffer[0] == '?') {
+	    printf ("commands:\n");
+	    printsw (ALL, popicmds, "");
+	    printf ("type CTRL-D or use \"quit\" to leave %s\n", invo_name);
+	    continue;
+	}
+
+	if (cp = index (buffer, ' '))
+	    *cp = '\0';
+	switch (i = smatch (buffer, popicmds)) {
+	    case AMBIGSW:
+	        ambigsw (buffer, popicmds);
+		continue;
+	    case UNKWNSW:
+		printf ("%s unknown -- type \"?\" for help\n", buffer);
+		continue;
+		
+	    case QUITCMD:
+		return;
+
+	    case STATCMD:
+	    case DELECMD:
+	    case NOOPCMD:
+	    case LASTCMD:
+	    case RSETCMD:
+	    case TOPCMD:
+		if (cp)
+		    *cp = ' ';
+		(void) pop_command ("%s%s", popicmds[i].sw, cp ? cp : "");
+		printf ("%s\n", response);
+		break;		
+
+	    case LISTCMD:
+		if (cp)
+		    *cp = ' ';
+		if (pop_command ("%s%s", popicmds[i].sw, cp ? cp : "")
+		        == OK) {
+		    printf ("%s\n", response);
+		    if (!cp)
+			for (;;) {
+			    switch (pop_multiline ()) {
+				case DONE:
+				    (void) strcpy (response, ".");
+				    /* and fall... */
+			        case NOTOK:
+				    printf ("%s\n", response);
+			            break;
+
+				case OK:
+				    printf ("%s\n", response);
+				    continue;
+			     }
+			    break;
+			}
+		}
+		break;
+
+	    case RETRCMD:
+		if (!cp) {
+		    advise (NULLCP, "missing argument to %s", buffer);
+		    break;
+		}
+		retr_action (NULLCP, OK);
+		(void) pop_retr (atoi (++cp), retr_action);
+		retr_action (NULLCP, DONE);
+		printf ("%s\n", response);
+		break;
+
+	    case SCANCMD:
+		{
+		    char   *dp,
+			   *ep,
+			   *fp;
+
+		    if (width == 0)
+			width = sc_width ();
+
+		    for (dp = nfs, i = 0; *dp; dp++, i++)
+			if (*dp == '\\' || *dp == '"' || *dp == '\n')
+			    i++;
+		    i++;
+		    if ((ep = malloc ((unsigned) i)) == NULL)
+			adios (NULLCP, "out of memory");
+		    for (dp = nfs, fp = ep; *dp; dp++) {
+			if (*dp == '\n') {
+			    *fp++ = '\\', *fp++ = 'n';
+			    continue;
+			}
+			if (*dp == '"' || *dp == '\\')
+			    *fp++ = '\\';
+			*fp++ = *dp;
+		    }
+		    *fp = '\0';
+
+		    (void) pop_command ("xtnd scan %d \"%s\"", width, ep);
+		    printf ("%s\n", response);
+
+		    free (ep);
+		}
+		break;
+
+#if defined(BPOP) && !defined(NNTP)
+	    case MSHCMD:
+		msh ();
+		break;
+#endif
+	}
+    }
+}
+
+/*  */
+
+static int  retr_action (rsp, flag)
+char   *rsp;
+int	flag;
+{
+    static FILE    *fp;
+
+    if (rsp == NULL) {
+	static int    msgnum;
+	static char  *cp;
+
+	if (flag == OK) {
+	    if ((mp = m_remsg (mp, 0, msgnum = mp -> hghmsg + 1)) == NULL)
+		adios (NULLCP, "unable to allocate folder storage");
+
+	    cp = getcpy (m_name (mp -> hghmsg + 1));
+	    if ((fp = fopen (cp, "w+")) == NULL)
+		adios (cp, "unable to write");
+	    (void) chmod (cp, m_gmprot ());
+	}
+	else {
+	    struct stat st;
+
+	    (void) fflush (fp);
+	    if (fstat (fileno (fp), &st) != NOTOK && st.st_size > 0) {
+		mp -> msgstats[msgnum] = EXISTS | UNSEEN;
+		mp -> msgflags |= SEQMOD;
+
+		if (ferror (fp))
+		    advise (cp, "write error on");
+		mp -> hghmsg = msgnum;
+	    }
+	    else
+		(void) unlink (cp);
+
+	    (void) fclose (fp), fp = NULL;
+	    free (cp), cp = NULL;
+	}
+
+	return;
+    }
+
+    fprintf (fp, "%s\n", rsp);
+}
+
+/*  */
+
+#if defined(BPOP) && !defined(NNTP)
+static	msh ()
+{
+    int	    child_id,
+	    vecp;
+    char    buf1[BUFSIZ],
+	    buf2[BUFSIZ],
+	   *vec[9];
+
+    if (pop_fd (buf1, buf2) == NOTOK)
+	adios (NULLCP, "%s", response);
+
+    vecp = 0;
+    vec[vecp++] = r1bindex (mshproc, '/');
+		    
+    switch (child_id = fork ()) {
+	case NOTOK:
+	    adios ("fork", "unable to");
+
+	case OK:
+	    vec[vecp++] = "-popread";
+	    vec[vecp++] = buf1;
+	    vec[vecp++] = "-popwrite";
+	    vec[vecp++] = buf2;
+	    vec[vecp++] = "-idname";
+	    vec[vecp++] = mailname;
+	    vec[vecp++] = mailname;
+	    vec[vecp] = NULL;
+	    (void) execvp (mshproc, vec);
+	    fprintf (stderr, "unable to exec ");
+	    perror (mshproc);
+	    _exit (-1);
+
+       default:
+	    (void) pidXwait (child_id, mshproc);
+	    break;
+   }
+}
+#endif
+
+/*  */
+
+#ifdef	SMTP
+#include "../zotnet/mts.h"
+#include "../mts/sendmail/smail.h"
+
+
+static int  dselect (d)
+#ifdef SYS5DIR
+register struct dirent *d;
+#else
+register struct direct *d;
+#endif
+{
+    int	    i;
+
+    if ((i = strlen (d -> d_name)) < sizeof "smtp"
+	    || strncmp (d -> d_name, "smtp", sizeof "smtp" - 1))
+	return 0;
+    return ((i -= (sizeof ".bulk" - 1)) > 0
+	        && !strcmp (d -> d_name + i, ".bulk"));
+}
+
+
+static int  dcompar (d1, d2)
+#ifdef SYS5DIR
+struct dirent **d1,
+	      **d2;
+#else
+struct direct **d1,
+	      **d2;
+#endif
+{
+    struct stat s1,
+		s2;
+
+    if (stat ((*d1) -> d_name, &s1) == NOTOK)
+	return 1;
+    if (stat ((*d2) -> d_name, &s2) == NOTOK)
+	return -1;
+    return ((int) (s1.st_mtime - s2.st_mtime));
+}
+
+
+static	do_bulk (host)
+char   *host;
+{
+    register int    i;
+    int	    n,
+	    retval,
+	    sm;
+#ifdef SYS5DIR
+    struct dirent **namelist;
+#else
+    struct direct **namelist;
+#endif
+
+    if (chdir (bulksw) == NOTOK)
+	adios (bulksw, "unable to change directory to");
+
+    if ((n = scandir (".", &namelist, dselect, dcompar)) == NOTOK)
+	adios (bulksw, "unable to scan directory");
+
+    sm = NOTOK;
+    for (i = 0; i < n; i++) {
+#ifdef SYS5DIR
+	register struct dirent *d = namelist[i];
+#else
+	register struct direct *d = namelist[i];
+#endif
+
+	if (sm == NOTOK) {
+	    if (rp_isbad (retval = sm_init (NULLCP, host, 1, 1, snoop)))
+		adios (NULLCP, "problem initializing server: %s",
+		       rp_string (retval));
+	    else
+		sm = OK;
+	}
+
+	switch (retval = sm_bulk (d -> d_name)) {
+	    default:
+	        if (rp_isbad (retval))
+		    adios (NULLCP, "problem delivering msg %s: %s",
+			   d -> d_name, rp_string (retval));
+		/* else fall... */
+	    case RP_OK:
+	    case RP_NO:
+	    case RP_NDEL:
+		advise (NULLCP, "msg %s: %s", d -> d_name, rp_string (retval));
+		break;
+	}
+    }
+
+    if (sm == OK) {
+	register int j;
+	int	l,
+		m;
+#ifdef SYS5DIR
+	struct dirent **newlist;
+#else
+	struct direct **newlist;
+#endif
+
+	while ((l = scandir (".", &newlist, dselect, dcompar)) > OK) {
+	    m = 0;
+
+	    for (j = 0; j < l; j++) {
+#ifdef SYS5DIR
+		register struct dirent *d = newlist[j];
+#else
+		register struct direct *d = newlist[j];
+#endif
+
+		for (i = 0; i < n; i++)
+		    if (strcmp (d -> d_name, namelist[i] -> d_name) == 0)
+			break;
+		if (i >= n) {
+		    switch (retval = sm_bulk (d -> d_name)) {
+		        default:
+			    if (rp_isbad (retval))
+				adios (NULLCP, "problem delivering msg %s: %s",
+				       d -> d_name, rp_string (retval));
+			    /* else fall... */
+			case RP_OK:
+			case RP_NO:
+			case RP_NDEL:
+			    advise (NULLCP, "msg %s: %s", d -> d_name,
+				    rp_string (retval));
+			    break;
+		    }
+
+		    m = 1;
+		}
+	    }
+
+	    for (i = 0; i < n; i++)
+		free ((char *) namelist[i]);
+	    free ((char *) namelist);
+	    namelist = newlist, n = l;
+
+	    if (!m)
+		break;
+	    newlist = NULL;
+	}
+    }
+
+    if (sm == OK && rp_isbad (retval = sm_end (OK)))
+	adios (NULLCP, "problem finalizing server: %s", rp_string (retval));
+
+    for (i = 0; i < n; i++)
+	free ((char *) namelist[i]);
+    free ((char *) namelist);
+
+    free ((char *) namelist);
+
+    done (0);
+}
+#endif
+#if defined(SYS5DIR) && !defined(BSD42) && !defined(hpux) && !defined(sgi) && !defined(linux)
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c	5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
+ */
+/*
+ * This code modified by Ted Nolan to take Solaris dirent structures
+ * and mollify gcc -traditional.  In general, everything from BSD that
+ * didn't work is "ifdef notdef" ed out
+ *
+ * 3 Feb 94
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+/* #include <stdlib.h> */
+#include <string.h>
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry.  This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+#ifdef notdef
+#define DIRSIZ(dp) \
+    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+#else
+#define DIRSIZ(dp) \
+    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + ((strlen(dp->d_name)+1 + 3) &~ 3))
+#endif
+int
+scandir(dirname, namelist, select, dcomp)
+#ifdef notdef
+	const char *dirname;
+#else
+	char *dirname;
+#endif
+	struct dirent ***namelist;
+#ifdef notdef
+        int (*select) __P((struct dirent *));
+        int (*dcomp) __P((const void *, const void *));
+#else
+	int (*select)();
+	int (*dcomp)();
+#endif
+{
+	register struct dirent *d, *p, **names;
+	register size_t nitems;
+	struct stat stb;
+	long arraysz;
+	DIR *dirp;
+	if ((dirp = opendir(dirname)) == NULL)
+		return(-1);
+	if (stat(dirname, &stb) < 0)
+		return(-1);
+	/*
+	 * estimate the array size by taking the size of the directory file
+	 * and dividing it by a multiple of the minimum size entry.
+	 */
+	arraysz = (stb.st_size / 24);
+	names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+	if (names == NULL)
+		return(-1);
+	nitems = 0;
+	while ((d = readdir(dirp)) != NULL) {
+		if (select != NULL && !(*select)(d))
+			continue;	/* just selected names */
+		/*
+		 * Make a minimum size copy of the data
+		 */
+		p = (struct dirent *)malloc(DIRSIZ(d));
+		if (p == NULL)
+			return(-1);
+		p->d_ino = d->d_ino;
+		p->d_reclen = d->d_reclen;
+#ifdef notdef
+		p->d_namlen = d->d_namlen;
+		bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+#else
+		bcopy(d->d_name, p->d_name, strlen(p->d_name) + 1);
+#endif
+		/*
+		 * Check to make sure the array has space left and
+		 * realloc the maximum size.
+		 */
+		if (++nitems >= arraysz) {
+			if (stat(dirname, &stb) < 0)
+				return(-1);	/* just might have grown */
+			arraysz = stb.st_size / 12;
+			names = (struct dirent **)realloc((char *)names,
+				arraysz * sizeof(struct dirent *));
+			if (names == NULL)
+				return(-1);
+		}
+		names[nitems-1] = p;
+	}
+	closedir(dirp);
+	if (nitems && dcomp != NULL)
+		qsort(names, nitems, sizeof(struct dirent *), dcomp);
+	*namelist = names;
+	return(nitems);
+}
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+#ifdef notdef
+	const void *d1;
+	const void *d2;
+#else
+	char *d1;
+	char *d2;
+#endif /* notdef */
+{
+	return(strcmp((*(struct dirent **)d1)->d_name,
+	    (*(struct dirent **)d2)->d_name));
+}
+#endif