This is popper.c in view mode; [Download] [Up]
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Copyright (c) 1997 by Qualcomm Incorporated.
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>
#ifdef POPSCO
# include <sys/security.h>
# include <sys/audit.h>
# include <prot.h>
# define VOIDSTAR
# ifdef SCOR5
# define VOIDSTAR (void (*)(int))
# endif
#else
# ifdef AIX
# define VOIDSTAR (void (*)(int))
# else
# define VOIDSTAR (void *)
# endif
#endif
#if defined(AUTH)
# ifdef HAVE_SYS_SECURITY_H
# include <sys/security.h>
# endif
# ifdef HAVE_PROTO_H
# include <prot.h>
# endif
#endif
#include <popper.h>
#ifdef NEED_STRERROR
char * strerror();
#endif
extern state_table * pop_get_command();
int hangup = FALSE ;
int catchSIGHUP();
int poptimeout = 0;
int pop_timeout = POP_TIMEOUT;
FILE *debuglog;
/*
* popper: Handle a Post Office Protocol version 3 session
*/
main (argc, argv)
int argc;
char ** argv;
{
POP p;
state_table * s;
char message[MAXLINELEN];
char * tgets();
#if defined(POPSCO) || defined(AUTH)
# ifdef HAVE_SET_AUTH_PARAMETERS
(void) set_auth_parameters(argc, argv);
# endif
#endif
#ifdef AUX
(void)set42sig();
#endif
/* Set umask for better security */
#ifdef BINMAIL_IS_SETGID
umask(0007); /* Trust the mail delivery group */
#else
umask(0077); /* Trust no-one */
#endif
(void) signal(SIGHUP,VOIDSTAR catchSIGHUP);
(void) signal(SIGPIPE,VOIDSTAR catchSIGHUP);
/* Start things rolling */
if (pop_init(&p,argc,argv) != POP_SUCCESS)
exit(1);
/* Tell the user that we are listenting */
#ifdef APOP
sprintf(p.md5str, "<%d.%d@%s>", getpid(), time((TIME_T *)0), p.myhost);
#else
p.md5str[0] = '\0';
#endif
pop_msg(&p, POP_SUCCESS, "QPOP (version %s) at %s starting. %s",
VERSION, p.myhost, p.md5str);
/* State loop. The POP server is always in a particular state in
which a specific suite of commands can be executed. The following
loop reads a line from the client, gets the command, and processes
it in the current context (if allowed) or rejects it. This continues
until the client quits or an error occurs. */
for (p.CurrentState=auth1;p.CurrentState!=halt&&p.CurrentState!=error;) {
#ifdef SETPROCTITLE
setproctitle("%s@%s [%s]: cmd read", p.user, p.client, p.ipaddr);
#endif
if (hangup) {
pop_msg(&p,POP_FAILURE,"POP hangup",p.myhost);
#ifndef NOUPDATEONABORT
if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
!pop_updt(&p))
pop_msg(&p,POP_FAILURE,"POP mailbox update failed.",p.myhost);
#else
if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
!pop_restore(&p))
pop_msg(&p, POP_FAILURE,"POP mailbox restoration failed.",p.myhost);
#endif
p.CurrentState = error;
} else if (tgets(message,MAXLINELEN,p.input,pop_timeout) == NULL) {
if (poptimeout) {
if (p.xmitting) pop_xmit_clean(&p);
pop_msg(&p,POP_FAILURE,"POP timeout",p.myhost);
}
else
pop_msg(&p,POP_FAILURE,"POP EOF received",p.myhost);
#ifndef NOUPDATEONABORT
if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
!pop_updt(&p))
pop_msg(&p,POP_FAILURE,"POP mailbox update failed!",p.myhost);
#else
if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
!pop_restore(&p))
pop_msg(&p,POP_FAILURE,"POP mailbox restoration failed!",p.myhost);
#endif
p.CurrentState = error;
} else if (p.xmitting) { /* After the xtnd xmit initiates the mail txfer */
pop_xmit_recv(&p,message);
} else if ((s = pop_get_command(&p,message)) != NULL) {
if (s->function != NULL) {
#ifdef SETPROCTITLE
int i;
char command[10];
for (i = 0; s->command[i]; i++)
command[i] = toupper(s->command[i]);
command[i] = 0;
setproctitle("%s@%s [%s]: %s",
p.user, p.client, p.ipaddr, command);
#endif
p.CurrentState = s->result[(*s->function)(&p)];
} else {
p.CurrentState = s->success_state;
pop_msg(&p,POP_SUCCESS,NULL);
}
}
}
/* Say goodbye to the client */
pop_msg(&p,POP_SUCCESS,"Pop server at %s signing off.",p.myhost);
#ifdef DEBUG
/* Log the end of activity */
if (p.debug)
pop_log(&p,POP_PRIORITY,
"(v%s) Ending request from \"%s\" at (%s) %s",
VERSION,p.user,p.client,p.ipaddr);
#endif
/* Stop logging */
closelog();
return(0);
}
jmp_buf env;
/*
* There seems to be a problem with the AIX fgets. This is suppose to
* fix it.
*/
char *
myfgets(str, size, fp)
char *str;
int size;
FILE *fp;
{
char *cp;
char ch;
int nbytes;
int found_nl = 0;
cp = str;
while (--size > 0) {
if ((nbytes = read(fileno(fp), cp, 1)) <= 0)
break;
if (*cp == '\n') {
*++cp = '\0';
found_nl++;
break;
}
++cp;
}
if ((nbytes <= 0) || (cp == str)) {
return(NULL);
} else {
if (!found_nl)
while ((read(fileno(fp), &ch, 1) == 1) && ch != '\n');
return(str);
}
}
/*
* fgets, but with a timeout
*/
char *tgets(str,size,fp,timeout)
char *str;
int size;
FILE *fp;
int timeout;
{
int ring();
(void) signal(SIGALRM, VOIDSTAR ring);
alarm(timeout);
if (setjmp(env))
str = NULL;
else
str = myfgets(str,size,fp);
/* str = fgets(str,size,fp); */
alarm(0);
signal(SIGALRM,SIG_DFL);
return(str);
}
int ring()
{
poptimeout = 1;
longjmp(env,1);
}
#ifdef STRNCASECMP
/*
* Perform a case-insensitive string comparision
*/
strncasecmp(str1,str2,len)
register char * str1;
register char * str2;
register int len;
{
register int i;
char a,
b;
for (i=len-1;i>=0;i--){
a = str1[i];
b = str2[i];
if (isupper(a)) a = tolower(str1[i]);
if (isupper(b)) b = tolower(str2[i]);
if (a > b) return (1);
if (a < b) return(-1);
}
return(0);
}
#endif
int catchSIGHUP()
{
extern int hangup ;
hangup = TRUE ;
/* This should not be a problem on BSD systems */
signal(SIGHUP, VOIDSTAR catchSIGHUP);
signal(SIGPIPE, VOIDSTAR catchSIGHUP);
}
/*
* $Author: qpop $ $Date: 1997/03/14 05:01:07 $
* $Header: /users/sources/Qpopper/popper.c,v 1.1.1.1 1997/03/14 05:01:07 qpop Exp $
* $Revision: 1.1.1.1 $
*/
#ifdef NEED_STRERROR
char *
strerror(e)
int e;
{
extern char *sys_errlist[];
extern int sys_nerr;
if(e < sys_nerr)
return(sys_errlist[e]);
else
return("unknown error");
}
#endif
#ifdef POPSCO
/*
* Ftruncate() for non-BSD systems.
*
* This module gives the basic functionality for ftruncate() which
* truncates the given file descriptor to the given length.
* ftruncate() is a Berkeley system call, but does not exist in any
* form on many other versions of UNIX such as SysV. Note that Xenix
* has chsize() which changes the size of a given file descriptor,
* so that is used if M_XENIX is defined.
*
* Since there is not a known way to support this under generic SysV,
* there is no code generated for those systems.
*
* SPECIAL NOTE: On Xenix, using this call in the BSD library
* will REQUIRE the use of -lx for the extended library since chsize()
* is not in the standard C library.
*
* By Marc Frajola, 3/27/87
*/
#include <fcntl.h>
ftruncate(fd,length)
int fd; /* File descriptor to truncate */
off_t length; /* Length to truncate file to */
{
int status; /* Status returned from truncate proc */
status = chsize(fd,length);
/*
status = -1;
NON-XENIX SYSTEMS CURRENTLY NOT SUPPORTED
*/
return(status);
}
#endif
#ifdef NEED_FTRUNCATE
/* ftruncate emulations that work on some System V's.
This file is in the public domain. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#ifdef F_CHSIZE
int
ftruncate (fd, length)
int fd;
off_t length;
{
return fcntl (fd, F_CHSIZE, length);
}
#else /* not F_CHSIZE */
#ifdef F_FREESP
/* By William Kucharski <kucharsk@netcom.com>. */
#include <sys/stat.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
int
ftruncate (fd, length)
int fd;
off_t length;
{
struct flock fl;
struct stat filebuf;
if (fstat (fd, &filebuf) < 0)
return -1;
if (filebuf.st_size < length)
{
/* Extend file length. */
if (lseek (fd, (length - 1), SEEK_SET) < 0)
return -1;
/* Write a "0" byte. */
if (write (fd, "", 1) != 1)
return -1;
}
else
{
/* Truncate length. */
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = length;
fl.l_type = F_WRLCK; /* write lock on file space */
/* This relies on the *undocumented* F_FREESP argument to fcntl,
which truncates the file so that it ends at the position
indicated by fl.l_start. Will minor miracles never cease? */
if (fcntl (fd, F_FREESP, &fl) < 0)
return -1;
}
return 0;
}
#else /* not F_CHSIZE nor F_FREESP */
#ifdef HAVE_CHSIZE
int
ftruncate (fd, length)
int fd;
off_t length;
{
return chsize (fd, length);
}
#else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */
#include <errno.h>
#ifndef errno
extern int errno;
#endif
int
ftruncate (fd, length)
int fd;
off_t length;
{
errno = EIO;
return -1;
}
#endif /* not HAVE_CHSIZE */
#endif /* not F_FREESP */
#endif /* not F_CHSIZE */
#endif /* NEED_FTRUNCATE */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.