--- /dev/null
+/*
+ * (c) Copyright 1994 HEWLETT-PACKARD COMPANY
+ *
+ * To anyone who acknowledges that this file is provided
+ * "AS IS" without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this
+ * file for any purpose is hereby granted without fee,
+ * provided that the above copyright notice and this
+ * notice appears in all copies, and that the name of
+ * Hewlett-Packard Company not be used in advertising or
+ * publicity pertaining to distribution of the software
+ * without specific, written prior permission. Hewlett-
+ * Packard Company makes no representations about the
+ * suitability of this software for any purpose.
+ */
+/*
+ * Mailquery - contact the POP mail host an see if a user has
+ * mail. By default the result if reflected in the
+ * exit status.
+ *
+ * Usage: mailquery [-dv] [-e <cmd>]
+ * -d - debug
+ * -v - print result
+ * -e - exec this command if there is mail.
+ */
+#include <pwd.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <stdio.h>
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#include "pop.h"
+
+
+extern int pop_debug;
+int verbose = 0;
+char *exec_cmd;
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *getenv();
+ int nbytes;
+ char *mhost = NULL, *mhp;
+ char *user = 0;
+ struct passwd * pwd;
+ char response[128];
+ char c;
+ extern int optind;
+ extern char *optarg;
+#ifdef HESIOD
+ struct hes_postoffice *p;
+#endif /* HESIOD */
+ char *index();
+
+ while ((c = getopt(argc, argv, "dve:")) != EOF) {
+ switch (c) {
+ case 'd':
+ pop_debug = 1;
+ break;
+
+ case 'e':
+ exec_cmd = optarg;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case '?':
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ user = argv[0];
+ if ((mhost = index(argv[0], '@')) != NULL) {
+ *mhost = '\0';
+ mhost++;
+ }
+#ifndef HESIOD
+ else {
+ mhost = DEFMAILHOST;
+ }
+#endif
+ }
+
+ if (user == (char *) 0 || *user == '\0') {
+ if ((pwd = getpwuid(getuid())) == NULL) {
+ perror("getpwuid");
+ exit(1);
+ }
+ user = pwd->pw_name;
+ }
+
+ if ((mhost == NULL) &&
+ (mhp = getenv("MAILHOST")))
+ mhost = mhp;
+
+#ifdef HESIOD
+ if (mhost == NULL) {
+ p = hes_getmailhost(user);
+ if (p != NULL && strcmp(p->po_type, "POP") == 0)
+ mhost = p->po_host;
+ else {
+ fprintf(stderr,"no POP server listed in Hesiod for %s\n", user);
+ exit(1);
+ }
+ }
+#endif /* HESIOD */
+
+ if (mhost == NULL) {
+ mhost = DEFMAILHOST;
+ }
+
+ nbytes = mailquery(mhost, user);
+
+ if ((nbytes > 0) && (exec_cmd != 0)) {
+ if (pop_debug)
+ fprintf(stderr, "about to execute %s\n", exec_cmd);
+ system(exec_cmd);
+ }
+
+ exit(nbytes == 0);
+
+}
+
+mailquery(mhost, user)
+ char *mhost;
+ char *user;
+{
+ int nbytes, nmsgs;
+
+ if (pop_init(mhost, 0) == NOTOK) {
+ error(Errmsg);
+ exit(1);
+ }
+
+#ifdef KPOP
+ if (pop_command("USER %s", user) == NOTOK ||
+ pop_command("PASS %s", user) == NOTOK) {
+#else /* !KPOP */
+ if (pop_command("USER %s", user) == NOTOK ||
+ pop_command("RPOP %s", user) == NOTOK) {
+#endif /* KPOP */
+ error(Errmsg);
+ (void) pop_command("QUIT");
+ exit (1);
+ }
+
+ if (pop_stat(&nmsgs, &nbytes) == NOTOK) {
+ error(Errmsg);
+ (void) pop_command("QUIT");
+ exit (1);
+ }
+
+ if (verbose)
+ printf("%d messages (%d bytes) on host %s\n", nmsgs, nbytes, mhost);
+
+ return nbytes;
+}
+
+usage()
+{
+ fprintf(stderr, "usage: mailquery [-d] [-v] [-e cmd] [user[@host]]\n");
+}
+
+
--- /dev/null
+/*
+ * (c) Copyright 1994 HEWLETT-PACKARD COMPANY
+ *
+ * To anyone who acknowledges that this file is provided
+ * "AS IS" without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this
+ * file for any purpose is hereby granted without fee,
+ * provided that the above copyright notice and this
+ * notice appears in all copies, and that the name of
+ * Hewlett-Packard Company not be used in advertising or
+ * publicity pertaining to distribution of the software
+ * without specific, written prior permission. Hewlett-
+ * Packard Company makes no representations about the
+ * suitability of this software for any purpose.
+ */
+#if !defined(lint) && !defined(_NOIDENT)
+static char rcsid[] = "@(#)$Header$";
+#endif
+/*
+ * Poplib - library routines for speaking POP
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#if defined(KRB4) && defined(KRB5)
+# error You cannot define both KRB4 and KRB5
+#endif
+#ifndef KPOP_SERVICE
+#define KPOP_SERVICE "kpop"
+#endif
+#ifdef KPOP
+#ifdef KRB4
+#include <krb.h>
+#endif
+#ifdef KRB5
+#include <krb5/krb5.h>
+#include <krb5/ext-proto.h>
+#include <krb5/los-proto.h>
+#include <com_err.h>
+#include <ctype.h>
+#endif
+#endif
+
+#include "pop.h"
+
+void *xmalloc();
+
+char Errmsg[80]; /* to return error messages */
+int pop_debug;
+
+static FILE *sfi = 0;
+static FILE *sfo = 0;
+
+pop_init(host, reserved)
+char *host;
+int reserved;
+{
+ register struct hostent *hp;
+ register struct servent *sp;
+ int lport = IPPORT_RESERVED - 1;
+ struct sockaddr_in sin;
+ int s;
+ char *get_errmsg();
+ char response[1024];
+ char *routine;
+#ifdef KPOP
+#ifdef KRB4
+ CREDENTIALS cred;
+ KTEXT ticket = (KTEXT)NULL;
+ int rem;
+#endif
+#ifdef KRB5
+ krb5_error_code retval;
+ krb5_ccache ccdef;
+ krb5_principal client = NULL, server = NULL;
+ krb5_error *err_ret = NULL;
+ register char *cp;
+#endif
+#endif
+
+ if (sfi && sfo) {
+ return;
+ }
+
+ hp = gethostbyname(host);
+ if (hp == NULL) {
+ sprintf(Errmsg, "MAILHOST unknown: %s", host);
+ return(NOTOK);
+ }
+
+#ifdef KPOP
+ sp = getservbyname(KPOP_SERVICE, "tcp");
+ if (sp == 0) {
+ (void) strcpy(Errmsg, "tcp/kpop: unknown service");
+ return(NOTOK);
+ }
+#else /* !KPOP */
+ sp = getservbyname("pop", "tcp");
+ if (sp == 0) {
+ (void) strcpy(Errmsg, "tcp/pop: unknown service");
+ return(NOTOK);
+ }
+#endif /* KPOP */
+ if (sp == 0) {
+ strcpy(Errmsg, "tcp/pop: unknown service");
+ return(NOTOK);
+ }
+
+ sin.sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
+ sin.sin_port = sp->s_port;
+#ifdef KPOP
+ s = socket(AF_INET, SOCK_STREAM, 0);
+#else /* !KPOP */
+ if (reserved)
+ s = rresvport(&lport);
+ else
+ s = socket(AF_INET, SOCK_STREAM, 0);
+#endif /* KPOP */
+
+ if (s < 0) {
+ sprintf(Errmsg, "error creating socket: %s", get_errmsg());
+ return(NOTOK);
+ }
+
+ if (connect(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
+ sprintf(Errmsg, "error during connect: %s", get_errmsg());
+ close(s);
+ return(NOTOK);
+ }
+
+#ifdef KPOP
+#ifdef KRB4
+ /* Get tgt creds from ticket file. This is used to calculate the
+ * lifetime for the pop ticket so that it expires with the
+ * tgt */
+ rem = krb_get_cred("krbtgt", krb_realmofhost(hp->h_name), krb_realmofhost(hp->h_name), &cred);
+ if (rem == KSUCCESS) {
+ long lifetime;
+ lifetime = ((cred.issue_date + ((unsigned char)cred.lifetime * 5 * 60)) - time(0)) / (5 * 60);
+ if (lifetime > 0)
+ krb_set_lifetime(lifetime);
+ }
+ ticket = (KTEXT)malloc( sizeof(KTEXT_ST) );
+ rem = krb_sendauth(0L, s, ticket, "pop", hp->h_name, (char *)0,
+ 0, (MSG_DAT *) 0, (CREDENTIALS *) 0,
+ (bit_64 *) 0, (struct sockaddr_in *)0,
+ (struct sockaddr_in *)0,"ZMAIL0.0");
+ if (rem != KSUCCESS) {
+ (void) sprintf(Errmsg, "kerberos error: %s",krb_err_txt[rem]);
+ (void) close(s);
+ return(NOTOK);
+ }
+#endif /* KRB4 */
+#ifdef KRB5
+ krb5_init_ets();
+
+ routine = "krb5_cc_default";
+ if (retval = krb5_cc_default(&ccdef)) {
+ krb5error:
+ sprintf(Errmsg, "%s: krb5 error: %s", routine, error_message(retval));
+ close(s);
+ return(NOTOK);
+ }
+ routine = "krb5_cc_get_principal";
+ if (retval = krb5_cc_get_principal(ccdef, &client)) {
+ goto krb5error;
+ }
+
+#if 0
+ /* lower-case to get name for "instance" part of service name */
+ for (cp = hp->h_name; *cp; cp++)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+#endif
+
+ routine = "krb5_sname_to_principal";
+ if (retval = krb5_sname_to_principal(hp->h_name, "pop",
+ KRB5_NT_UNKNOWN,
+ &server)) {
+ goto krb5error;
+ }
+
+ retval = krb5_sendauth((krb5_pointer) &s, "KPOPV1.0", client, server,
+ AP_OPTS_MUTUAL_REQUIRED,
+ 0, /* no checksum */
+ 0, /* no creds, use ccache instead */
+ ccdef,
+ 0, /* don't need seq # */
+ 0, /* don't need a subsession key */
+ &err_ret,
+ 0); /* don't need reply */
+ krb5_free_principal(server);
+ if (retval) {
+ if (err_ret && err_ret->text.length) {
+ sprintf(Errmsg, "krb5 error: %s [server says '%*s'] ",
+ error_message(retval),
+ err_ret->text.length,
+ err_ret->text.data);
+ krb5_free_error(err_ret);
+ } else
+ sprintf(Errmsg, "krb5_sendauth: krb5 error: %s", error_message(retval));
+ close(s);
+ return(NOTOK);
+ }
+#endif /* KRB5 */
+#endif /* KPOP */
+
+ sfi = fdopen(s, "r");
+ sfo = fdopen(s, "w");
+ if (sfi == NULL || sfo == NULL) {
+ sprintf(Errmsg, "error in fdopen: %s", get_errmsg());
+ close(s);
+ return(NOTOK);
+ }
+
+ if (getline(response, sizeof response, sfi) != OK) {
+ error(response);
+ return(NOTOK);
+ }
+ if (pop_debug)
+ fprintf(stderr, "<--- %s\n", response);
+
+ return(OK);
+}
+
+pop_command(fmt, a, b, c, d)
+char *fmt;
+{
+ char buf[1024];
+ char errmsg[64];
+
+ sprintf(buf, fmt, a, b, c, d);
+
+ if (pop_debug) fprintf(stderr, "---> %s\n", buf);
+ if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK);
+
+ if (getline(buf, sizeof buf, sfi) != OK) {
+ strcpy(Errmsg, buf);
+ return(NOTOK);
+ }
+
+ if (pop_debug) fprintf(stderr, "<--- %s\n", buf);
+ if (*buf != '+') {
+ strcpy(Errmsg, buf);
+ return(NOTOK);
+ } else {
+ return(OK);
+ }
+}
+
+pop_query(nbytes, user)
+ int *nbytes;
+ char *user;
+{
+ char buf[1024];
+
+ if (strlen(user) > 120) {
+ if (pop_debug) fprintf(stderr, "username %s too long\n", user);
+ return NOTOK;
+ }
+
+ sprintf(buf, "QUERY %s", user);
+ if (pop_debug) fprintf(stderr, "---> %s\n", buf);
+ if (putline(buf, Errmsg, sfo) == NOTOK) return (NOTOK);
+
+ if (getline(buf, sizeof buf, sfi) != OK) {
+ strcpy(Errmsg, buf);
+ return NOTOK;
+ }
+
+ if (pop_debug) fprintf(stderr, "<--- %s\n", buf);
+ if (*buf != '+') {
+ strcpy(Errmsg, buf);
+ return NOTOK;
+ } else {
+ sscanf(buf, "+OK %d", nbytes);
+ return OK;
+ }
+}
+
+pop_stat(nmsgs, nbytes)
+int *nmsgs, *nbytes;
+{
+ char buf[1024];
+
+ if (pop_debug) fprintf(stderr, "---> STAT\n");
+ if (putline("STAT", Errmsg, sfo) == NOTOK) return(NOTOK);
+
+ if (getline(buf, sizeof buf, sfi) != OK) {
+ strcpy(Errmsg, buf);
+ return(NOTOK);
+ }
+
+ if (pop_debug) fprintf(stderr, "<--- %s\n", buf);
+ if (*buf != '+') {
+ strcpy(Errmsg, buf);
+ return(NOTOK);
+ } else {
+ sscanf(buf, "+OK %d %d", nmsgs, nbytes);
+ return(OK);
+ }
+}
+
+pop_retr(msgno, action, arg)
+int (*action)();
+{
+ char buf[1024];
+ int nbytes = 0;
+
+ sprintf(buf, "RETR %d", msgno);
+
+ if (pop_debug)
+ fprintf(stderr, "---> %s\n", buf);
+
+ if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK);
+
+ if (getline(buf, sizeof buf, sfi) != OK) {
+ strcpy(Errmsg, buf);
+ return(NOTOK);
+ }
+ if (pop_debug)
+ fprintf(stderr, "<--- %s\n", buf);
+
+ sscanf(buf, "+OK %d", &nbytes);
+
+ while (1) {
+ switch (multiline(buf, sizeof buf, sfi)) {
+ case OK:
+ if ((*action)(buf, arg, nbytes) < 0) {
+ strcat(Errmsg, get_errmsg());
+ return (DONE); /* Some error occured in action */
+ }
+ break;
+ case DONE:
+ return (OK);
+ case NOTOK:
+ strcpy(Errmsg, buf);
+ return (NOTOK);
+ }
+ }
+}
+
+pop_getline(buf, n)
+ char *buf;
+ int n;
+{
+ return getline(buf, n, sfi);
+}
+
+getline(buf, n, f)
+char *buf;
+register int n;
+FILE *f;
+{
+ register char *p;
+ int c;
+
+ p = buf;
+ while (--n > 0 && (c = fgetc(f)) != EOF)
+ if ((*p++ = c) == '\n') break;
+
+ if (ferror(f)) {
+ strcpy(buf, "error on connection");
+ return (NOTOK);
+ }
+
+ if (c == EOF && p == buf) {
+ strcpy(buf, "connection closed by foreign host");
+ return (DONE);
+ }
+
+ *p = NULL;
+ if (*--p == '\n') *p = NULL;
+ if (*--p == '\r') *p = NULL;
+ return(OK);
+}
+
+multiline(buf, n, f)
+char *buf;
+register int n;
+FILE *f;
+{
+ if (getline(buf, n, f) != OK) return (NOTOK);
+ if (*buf == '.') {
+ if (*(buf+1) == NULL) {
+ return (DONE);
+ } else {
+ strcpy(buf, buf+1);
+ }
+ }
+ return(OK);
+}
+
+#ifndef HAS_STRERROR
+char *
+strerror(e)
+ int e;
+{
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+
+ if (errno < sys_nerr)
+ s = sys_errlist[errno];
+ else
+ s = "unknown error";
+}
+#endif
+
+char *
+get_errmsg()
+{
+ char *s = strerror(errno);
+
+ return(s);
+}
+
+putline(buf, err, f)
+char *buf;
+char *err;
+FILE *f;
+{
+ fprintf(f, "%s\r\n", buf);
+ fflush(f);
+ if (ferror(f)) {
+ strcpy(err, "lost connection");
+ return(NOTOK);
+ }
+ return(OK);
+}
+
+
+/* Print error message and exit. */
+
+fatal (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+ exit (1);
+}
+
+/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+
+error (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ printf ("poplib: ");
+ printf (s1, s2, s3);
+ printf ("\n");
+}
+
+pfatal_with_name (name)
+ char *name;
+{
+ char *s = concat ("", strerror(errno), " for %s");
+
+ fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+void *
+xmalloc (size)
+ int size;
+{
+ void *result = malloc (size);
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}