/* =========================================================================== = = = (C) Copyright 1991 The Trustees of Indiana University = = = = Permission to use, copy, modify, and distribute this program for = = non-commercial use and without fee is hereby granted, provided that = = this copyright and permission notice appear on all copies and = = supporting documentation, the name of Indiana University not be used = = in advertising or publicity pertaining to distribution of the program = = without specific prior permission, and notice be given in supporting = = documentation that copying and distribution is by permission of = = Indiana University. = = = = Indiana University makes no representations about the suitability of = = this software for any purpose. It is provided "as is" without express = = or implied warranty. = = = =========================================================================== = = = File: = = IUPOP3_UTILITY.C = = = = Synopsis: = = This file contains miscellaneous functions that support the = = VMS IUPOP3 server. = = = = Authors: = = Jacob Levanon & Larry Hughes = = Indiana University = = University Computing Services, Network Applications = = = = Credits: = = This software is based on the Post Office Protocol version 3, = = as implemented by the University of California at Berkeley. = = = =========================================================================== */ /* ====================================================================== */ /* Includes */ /* ====================================================================== */ #include #include #ifdef MULTINET #include #include #else /* WINS || UCX */ #include #include #endif #include #include #include "iupop3_general.h" #include "iupop3_global.h" #include "iupop3_vms.h" /* ====================================================================== */ /* Prototypes */ /* ====================================================================== */ void bcopy(); void get_date(); void get_time(); int isnumeric(); void make_argv(); int pop_build_info(); void pop_log(); char *pop_msg(); int strncasecmp(); int str_index(); void system_log(); #ifdef PATCH_FROM_LINE int patch_from_line(); #endif /* ====================================================================== */ /* Bcopy */ /* ====================================================================== */ #ifndef WINS void bcopy(source, destination, length) char *source; char *destination; int length; { register char *pointer; pointer = malloc(length); memcpy(pointer, source, length); memcpy(destination, pointer, length); free(pointer); } #endif /* WINS */ /* ====================================================================== */ /* Get Date */ /* ====================================================================== */ void get_date(date_str) char *date_str; { time_t calendar_time; struct tm *local_time; calendar_time = time(0); local_time = localtime(&calendar_time); ++local_time->tm_mon; sprintf(date_str,"19%02d-%02d-%02d", local_time->tm_year,local_time->tm_mon,local_time->tm_mday); } /* ====================================================================== */ /* Get Time */ /* ====================================================================== */ void get_time(time_str) char *time_str; { time_t calendar_time; struct tm *local_time; calendar_time = time(0); local_time = localtime(&calendar_time); sprintf(time_str,"%02d:%02d:%02d", local_time->tm_hour,local_time->tm_min,local_time->tm_sec); } /* ====================================================================== */ /* Is Numeric */ /* ====================================================================== */ int is_numeric(instring) char *instring; { int numeric = TRUE; while (*instring && numeric) numeric = isdigit(*instring++); return(numeric); } /* ======================================================================= */ /* Make Argv */ /* ======================================================================= */ void make_argv(string,argc,argv,delimiters) char *string; int *argc; char *argv[]; char *delimiters; { #define isdelimiter(a,b) (strchr(b,a) != NULL) register char *cpointer; register char **argpointer = argv; *argc = 0; cpointer = string; while (*cpointer) { while (*cpointer && isdelimiter(*cpointer,delimiters)) cpointer++; if (*cpointer == '\0') break; if (*cpointer == '\"') { cpointer++; *argpointer++ = cpointer; (*argc)++; while (*cpointer && (*cpointer != '\"')) cpointer++; } else { *argpointer++ = cpointer; (*argc)++; while (*cpointer && !isdelimiter(*cpointer,delimiters)) cpointer++; } if (*cpointer == '\0') break; *(cpointer++) = '\0'; } *(argpointer++) = 0; } /* ====================================================================== */ /* POP Build_info */ /* ====================================================================== */ pop_build_info(p) POP *p; { char buffer[BUFSIZ]; Message *mp; register int msg_num; int bytes = 0; int status; /* ** Initialize mail folder status variables. */ p->msgs_deleted = 0; p->last_msg = 0; p->bytes_deleted = 0; /* ** Allocate memory for message information structures. */ p->mptr = (Message *)calloc((unsigned)p->msg_count,sizeof(Message)); if (p->mptr == NULL) { p->msg_count = 0; return (pop_msg (p,POP_FAILURE, "Can't build message list for '%s': Out of memory", p->user, 0)); } /* ** Scan the NEMAIL folder in the VMS MAIL file, loading the message ** information list with information about each message. */ mp = p->mptr; for (msg_num=1; msg_num <= p->msg_count; msg_num++,bytes=0, mp++) { mp->lines = mail_message_lines(p, &msg_num)+1; mp->number = msg_num; status = mail_message_bytes(p,&msg_num,&bytes); mp->length = bytes; mp->del_flag = FALSE; mp->retr_flag = FALSE; } return(POP_SUCCESS); } /* ====================================================================== */ /* POP Log */ /* ====================================================================== */ void pop_log(va_alist) va_dcl { POP *p; char *format; va_list ap; register char *mp; char message[MAXLINELEN]; char date_str[11]; char time_str[9]; get_time(time_str); get_date(date_str); sprintf(message, "%s %s ", date_str, time_str); va_start(ap); p = va_arg(ap, POP *); format = va_arg(ap, char *); mp = message + strlen(message); sprintf(mp, "thread %d: ", p->threadnum); mp = message + strlen(message); vsprintf(mp, format, ap); va_end(ap); printf("%s\n",message); } /* ====================================================================== */ /* POP Message */ /* ====================================================================== */ char *pop_msg(va_alist) va_dcl { POP *p; int stat; char *format; va_list ap; register char *mp; char message[MAXLINELEN]; int len, flag, status; va_start(ap); p = va_arg(ap, POP *); stat = va_arg(ap, int); format = va_arg(ap, char *); mp = message; if (stat == POP_SUCCESS) sprintf (mp,"%s ",POP_OK); else sprintf (mp,"%s ",POP_ERR); mp += strlen(mp); if (format) vsprintf(mp, format, ap); va_end(ap); pop_log(p,"told: %s",message,0); strcat(message, "\r\n"); len = strlen(message); status = send(p->sockfd, message, len, flag); if (status < 0) { pop_log(p,"pop_msg: error sending to client: %d",status,0); return(0); } return(stat); } /* ====================================================================== */ /* Patch From Line */ /* ====================================================================== */ #ifdef PATCH_FROM_LINE int patch_from_line(POP *p, char *from) { #define FROM "From:" #define FROMLEN 5 int parsing = TRUE; int in_quotes = FALSE; int length; int offset; char chr; char *bufptr; char *start; char *end; char *truestart; char transport[16] = ""; char decnode[16] = ""; char clusternodes[] = "/prism/gold/jade/aqua/rose/amber/"; lower(from+FROMLEN); bufptr = from + FROMLEN; while (isspace(*bufptr)) bufptr++; truestart = start = end = bufptr; for (; *bufptr && parsing; bufptr++) { chr = *bufptr; if (in_quotes) { switch (chr) { case '"' : /* Foreign mailer delimiter */ case '>' : /* SMTP delimiter */ end--; parsing = FALSE; continue; case '<' : /* SMTP delimiter */ start = end = bufptr+1; break; case ':' : /* DECnet delimiter */ start = end = bufptr+2; bufptr++; break; default : end++; break; } } else { switch (chr) { case '%' : /* Foreign mailer delimiter */ length = bufptr - truestart; memcpy(transport,truestart,length); *(transport+length) = '\0'; start = end = bufptr+1; break; case '"' : /* Foreign mailer delimiter */ in_quotes = TRUE; start = end = bufptr+1; break; case ':' : /* DECnet delimiter */ length = bufptr - truestart; memcpy(decnode,truestart,length); *(decnode+length) = '\0'; start = end = bufptr+2; bufptr++; break; case ' ' : case '\t' : end--; parsing = FALSE; continue; default : end++; break; } } } if (*transport) { if ((offset = str_index(transport,":")) >= 0) bcopy(transport+offset+2,transport,strlen(transport)-offset-1); } if (end <= start) { pop_log(p,"parse error: %s",from,0); from_parse_errors++; } else { *(from + FROMLEN) = ' '; length = end - start + 1; bcopy(start,from+FROMLEN+1,length); *(from+FROMLEN+length+1) = '\0'; if ((offset = str_index(from,"@")) >= 0) { if ((offset = str_index(from+offset+1,".")) < 0) strcat(from,".bitnet"); } else if (*decnode) { if (str_index(clusternodes,decnode) >= 0) strcat(from,"@ucs.indiana.edu"); else { strcat(from,"%"); strcat(from,decnode); strcat(from,".decnet@iugate.ucs.indiana.edu"); } } } return(POP_SUCCESS); } #endif /* PATCH_FROM_LINE */ /* ====================================================================== */ /* POP Send Line */ /* ====================================================================== */ pop_sendline(p,buffer) POP *p; char *buffer; { char *bp; char tmp[256]; int status, len, flag; /* ** Byte stuff lines that begin with the termination octet. */ if (*buffer == POP_TERMINATE) { sprintf(tmp, ".%s", buffer); strcpy(buffer, tmp); } if (bp = strchr(buffer,NEWLINE)) *bp = 0; strcat(buffer, "\r\n"); len = strlen(buffer); status = send(p->sockfd, buffer, len, flag); return(POP_SUCCESS); } /* ====================================================================== */ /* String Index - find string s in string t */ /* ====================================================================== */ str_index(register char s[], register char t[]) { register int i,k,j; for (i=0; s[i] != '\0'; i++) { for (j=i, k=0; t[k] != '\0' && s[j] == t[k]; j++, k++); if (t[k] == '\0') return(i); } return (-1); } /* ======================================================================== */ /* 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); } /* ======================================================================== */ /* System Log */ /* ======================================================================== */ void system_log(va_alist) va_dcl { char *format; va_list ap; register char *mp; char message[MAXLINELEN]; char date_str[11]; char time_str[9]; get_time(time_str); get_date(date_str); sprintf(message, "%s %s ", date_str, time_str); va_start(ap); format = va_arg(ap, char *); mp = message + strlen(message); vsprintf(mp, format, ap); va_end(ap); printf("%s\n",message); }