Update of /cvsroot/mahogany/M/lib/imap/src/osdep/nt
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9509/src/osdep/nt

Modified Files:
        os_nt.c os_nt.h 
Added Files:
        auths.c ip_nt.c linkage.c linkage.h mhnt.c mhnt.h newsnt.c 
        newsnt.h 
Log Message:
applied (still relevant) Mahogany patches from the previous versions; added VC7 
project file; added some files normally built during the build process

--- NEW FILE ---
/*
   Kerberos authentificator only works on W2K and so isn't built in usually.

#include "auth_gss.c" 

*/
#include "auth_md5.c" 
#include "auth_log.c" 
#include "auth_pla.c"

--- NEW FILE ---
/*
 * Program:     UNIX IPv4 routines
 *
 * Author:      Mark Crispin
 *              Networks and Distributed Computing
 *              Computing & Communications
 *              University of Washington
 *              Administration Building, AG-44
 *              Seattle, WA  98195
 *              Internet: [EMAIL PROTECTED]
 *
 * Date:        18 December 2003
 * Last Edited: 23 February 2004
 * 
 * The IMAP toolkit provided in this Distribution is
 * Copyright 2004 University of Washington.
 * The full text of our legal notices is contained in the file called
 * CPYRIGHT, included with this Distribution.
 */

#define SADRLEN sizeof (struct sockaddr)

#define SADR4(sadr) ((struct sockaddr_in *) sadr)
#define SADR4LEN sizeof (struct sockaddr_in)
#define SADR4ADR(sadr) SADR4 (sadr)->sin_addr
#define ADR4LEN sizeof (struct in_addr)
#define SADR4PORT(sadr) SADR4 (sadr)->sin_port


/* IP abstraction layer */

char *ip_sockaddrtostring (struct sockaddr *sadr);
long ip_sockaddrtoport (struct sockaddr *sadr);
void *ip_stringtoaddr (char *text,size_t *len,int *family);
struct sockaddr *ip_newsockaddr (size_t *len);
struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,
                              unsigned short port,size_t *len);
char *ip_sockaddrtoname (struct sockaddr *sadr);
void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,
                     void **next);

/* Return IP address string from socket address
 * Accepts: socket address
 * Returns: IP address as name string
 */

char *ip_sockaddrtostring (struct sockaddr *sadr)
{
  return (sadr->sa_family == PF_INET) ?
    inet_ntoa (SADR4ADR (sadr)) : "NON-IPv4";
}


/* Return port from socket address
 * Accepts: socket address
 * Returns: port number or -1 if can't determine it
 */

long ip_sockaddrtoport (struct sockaddr *sadr)
{
  return (sadr->sa_family == PF_INET) ? ntohs (SADR4PORT (sadr)) : -1;
}


/* Return IP address from string
 * Accepts: name string
 *          pointer to returned length
 *          pointer to returned address family
 * Returns: address if valid, length and family updated, or NIL
 */

void *ip_stringtoaddr (char *text,size_t *len,int *family)
{
  unsigned long adr;
  struct in_addr *ret;
                                /* get address */
  if ((adr = inet_addr (text)) == -1) ret = NIL;
  else {                        /* make in_addr */
    ret = (struct in_addr *) fs_get (*len = ADR4LEN);
    *family = AF_INET;          /* IPv4 */
    ret->s_addr = adr;          /* set address */
  }
  return (void *) ret;
}

/* Create a maximum-size socket address
 * Accepts: pointer to return maximum socket address length
 * Returns: new, empty socket address of maximum size
 */

struct sockaddr *ip_newsockaddr (size_t *len)
{
  return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN);
}


/* Stuff a socket address
 * Accepts: address family
 *          IPv4 address
 *          length of address (always 4 in IPv4)
 *          port number
 *          pointer to return socket address length
 * Returns: socket address or NIL if error
 */

struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,
                              unsigned short port,size_t *len)
{
  struct sockaddr *sadr = ip_newsockaddr (len);
  switch (family) {             /* build socket address based upon family */
  case AF_INET:                 /* IPv4 */
    sadr->sa_family = PF_INET;
                                /* copy host address */
    memcpy (&SADR4ADR (sadr),adr,adrlen);
                                /* copy port number in network format */
    SADR4PORT (sadr) = htons (port);
    *len = SADR4LEN;
    break;
  default:                      /* non-IP?? */
    sadr->sa_family = PF_UNSPEC;
    break;
  }
  return sadr;
}

/* Return name from socket address
 * Accepts: socket address
 * Returns: canonical name for that address or NIL if none
 */

char *ip_sockaddrtoname (struct sockaddr *sadr)
{
  struct hostent *he;
  return ((sadr->sa_family == PF_INET) &&
          (he = gethostbyaddr ((char *) &SADR4ADR (sadr),ADR4LEN,AF_INET))) ?
    (char *) he->h_name : NIL;
}


/* Return address from name
 * Accepts: name or NIL to return next address
 *          pointer to previous/returned length
 *          pointer to previous/returned address family
 *          pointer to previous/returned canonical name
 *          pointer to previous/return state for next-address calls
 * Returns: address with length/family/canonical updated if needed, or NIL
 */

void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,
                     void **next)
{
  char **adl,tmp[MAILTMPLEN];
  struct hostent *he;
                                /* case-independent lookup */
  if (name && (strlen (name) < MAILTMPLEN) &&
      (he = gethostbyname (lcase (strcpy (tmp,name))))) {
    adl = he->h_addr_list;
    if (len) *len = he->h_length;
    if (family) *family = he->h_addrtype;
    if (canonical) *canonical = (char *) he->h_name;
    if (next) *next = (void *) adl;
  }
                                /* return next in series */
  else if (next && (adl = (char **) *next)) *next = ++adl;
  else adl = NIL;               /* failure */
  return adl ? (void *) *adl : NIL;
}

--- NEW FILE ---
  mail_link (&imapdriver);      /* link in the imap driver */
  mail_link (&nntpdriver);      /* link in the nntp driver */
  mail_link (&pop3driver);      /* link in the pop3 driver */
  mail_link (&newsdriver);      /* link in the news driver */
  mail_link (&mhdriver);        /* link in the mh driver */
  mail_link (&mbxdriver);       /* link in the mbx driver */
  mail_link (&mtxdriver);       /* link in the mtx driver */
  mail_link (&tenexdriver);     /* link in the tenex driver */
  mail_link (&unixdriver);      /* link in the unix driver */
  mail_link (&dummydriver);     /* link in the dummy driver */
  /* auth_link (&auth_gss); don't link in the gss authenticator */ 
  auth_link (&auth_md5);        /* link in the md5 authenticator */ 
  auth_link (&auth_pla);        /* link in the pla authenticator */ 
  auth_link (&auth_log);        /* link in the log authenticator */ 

--- NEW FILE ---
extern DRIVER imapdriver;
extern DRIVER nntpdriver;
extern DRIVER pop3driver;
extern DRIVER mhdriver;
extern DRIVER mbxdriver;
extern DRIVER mtxdriver;
extern DRIVER tenexdriver;
extern DRIVER unixdriver;
extern DRIVER newsdriver;
extern DRIVER dummydriver;
extern AUTHENTICATOR auth_gss; 
extern AUTHENTICATOR auth_md5; 
extern AUTHENTICATOR auth_pla; 
extern AUTHENTICATOR auth_log; 
#define DEFAULTPROTO mbxproto

--- NEW FILE ---
/*
 * Program:     MH mail routines
 *
 * Author(s):   Mark Crispin
 *              Networks and Distributed Computing
 *              Computing & Communications
 *              University of Washington
 *              Administration Building, AG-44
 *              Seattle, WA  98195
 *              Internet: [EMAIL PROTECTED]
 *
 * Modified by: Vadim Zeitlin
 *              adopted mh.c for Win32
 *
 * Date:        23 February 1992
 * Last Edited: 27 July 1999
 *
 * Copyright 1998 by the University of Washington
 *
[...1008 lines suppressed...]
 * Accepts: file name
 *          elt containing date
 */

void mh_setdate (char *file,MESSAGECACHE *elt)
{
  struct _utimbuf times;
  times.actime = time (0);              /* atime is now */
  times.modtime = mail_longdate (elt);  /* modification time */
  _utime (file,&times);         /* set the times */
}

/* Retrieve the MH path
 */
extern char *mh_getpath(void)
{
  return mh_path;
}

/* vi: set ts=8 sta noet list sw=2: */

--- NEW FILE ---
/*
 * Program:     MH mail routines
 *
 * Author(s):   Mark Crispin
 *              Networks and Distributed Computing
 *              Computing & Communications
 *              University of Washington
 *              Administration Building, AG-44
 *              Seattle, WA  98195
 *              Internet: [EMAIL PROTECTED]
 *
 * Date:        23 February 1992
 * Last Edited: 24 October 2000
 * 
 * The IMAP toolkit provided in this Distribution is
 * Copyright 2000 University of Washington.
 * The full text of our legal notices is contained in the file called
 * CPYRIGHT, included with this Distribution.
 */

/* Build parameters */

#define MHPROFILE ".mh_profile"
#define MHSEQUENCE ".mh_sequence"
#define MHPATH "Mail"


/* MH I/O stream local data */
        
typedef struct mh_local {
  char *dir;                    /* spool directory name */
  char *buf;                    /* temporary buffer */
  unsigned long buflen;         /* current size of temporary buffer */
  unsigned long cachedtexts;    /* total size of all cached texts */
  time_t scantime;              /* last time directory scanned */
} MHLOCAL;


/* Convenient access to local data */

#define LOCAL ((MHLOCAL *) stream->local)

/* Function prototypes */

DRIVER *mh_valid (char *name);
int mh_isvalid (char *name,char *tmp,long synonly);
void *mh_parameters (long function,void *value);
void mh_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
void mh_list (MAILSTREAM *stream,char *ref,char *pat);
void mh_lsub (MAILSTREAM *stream,char *ref,char *pat);
void mh_list_work (MAILSTREAM *stream,char *dir,char *pat,long level);
long mh_subscribe (MAILSTREAM *stream,char *mailbox);
long mh_unsubscribe (MAILSTREAM *stream,char *mailbox);
long mh_create (MAILSTREAM *stream,char *mailbox);
long mh_delete (MAILSTREAM *stream,char *mailbox);
long mh_rename (MAILSTREAM *stream,char *old,char *newname);
MAILSTREAM *mh_open (MAILSTREAM *stream);
void mh_close (MAILSTREAM *stream,long options);
void mh_fast (MAILSTREAM *stream,char *sequence,long flags);
char *mh_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *length,
                 long flags);
long mh_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
long mh_ping (MAILSTREAM *stream);
void mh_check (MAILSTREAM *stream);
void mh_expunge (MAILSTREAM *stream);
long mh_copy (MAILSTREAM *stream,char *sequence,char *mailbox,
              long options);
long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);

int mh_select (struct _finddata_t *fileinfo);
int mh_numsort (const void *d1,const void *d2);
char *mh_file (char *dst,char *name);
long mh_canonicalize (char *pattern,char *ref,char *pat);
void mh_setdate (char *file,MESSAGECACHE *elt);

/* vi: set ts=8 sta noet list: */

--- NEW FILE ---
/*
 * Program:     News routines
 *
 * Author:      Mark Crispin
 *              Networks and Distributed Computing
 *              Computing & Communications
 *              University of Washington
 *              Administration Building, AG-44
 *              Seattle, WA  98195
 *              Internet: [EMAIL PROTECTED]
 *
 * Modified by: Vadim Zeitlin
 *              adopted news.c for Win32
 *
 * Date:        4 September 1991
 * Last Edited: 24 October 2000
 * 
 * The IMAP toolkit provided in this Distribution is
 * Copyright 2000 University of Washington.
 * The full text of our legal notices is contained in the file called
 * CPYRIGHT, included with this Distribution.
 */

#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "mail.h"
#include "osdep.h"
#include <sys/stat.h>
#include "newsnt.h"
#include "misc.h"
#include "newsrc.h"

/* News routines */


/* Driver dispatch used by MAIL */

DRIVER newsdriver = {
  "news",                       /* driver name */
                                /* driver flags */
  DR_NEWS|DR_READONLY|DR_NOFAST|DR_NAMESPACE,
  (DRIVER *) NIL,               /* next driver */
  news_valid,                   /* mailbox is valid for us */
  news_parameters,              /* manipulate parameters */
  news_scan,                    /* scan mailboxes */
  news_list,                    /* find mailboxes */
  news_lsub,                    /* find subscribed mailboxes */
#include <fcntl.h>              /* _O_RDONLY and friends */

#define O_RDONLY  _O_RDONLY


  news_subscribe,               /* subscribe to mailbox */
  news_unsubscribe,             /* unsubscribe from mailbox */
  news_create,                  /* create mailbox */
  news_delete,                  /* delete mailbox */
  news_rename,                  /* rename mailbox */
  NIL,                          /* status of mailbox */
  news_open,                    /* open mailbox */
  news_close,                   /* close mailbox */
  news_fast,                    /* fetch message "fast" attributes */
  news_flags,                   /* fetch message flags */
  NIL,                          /* fetch overview */
  NIL,                          /* fetch message envelopes */
  news_header,                  /* fetch message header */
  news_text,                    /* fetch message body */
  NIL,                          /* fetch partial message text */
  NIL,                          /* unique identifier */
  NIL,                          /* message number */
  NIL,                          /* modify flags */
  news_flagmsg,                 /* per-message modify flags */
  NIL,                          /* search for message based on criteria */
  NIL,                          /* sort messages */
  NIL,                          /* thread messages */
  news_ping,                    /* ping mailbox to see if still alive */
  news_check,                   /* check for new messages */
  news_expunge,                 /* expunge deleted messages */
  news_copy,                    /* copy messages to another mailbox */
  news_append,                  /* append string message to mailbox */
  NIL                           /* garbage collect stream */
};

                                /* prototype stream */
MAILSTREAM newsproto = {&newsdriver};

/* News validate mailbox
 * Accepts: mailbox name
 * Returns: our driver if name is valid, NIL otherwise
 */

DRIVER *news_valid (char *name)
{
  int fd;
  char *s,*t,*u;
  struct stat sbuf;

  /* MAHOGANY: changed the code to return newsdriver if the active file doesn't
     exist (we do it because leafnode doesn't have one yet we still want to use
     Mahogany with it */
  if ((name[0] == '#') && (name[1] == 'n') && (name[2] == 'e') &&
      (name[3] == 'w') && (name[4] == 's') && (name[5] == '.') &&
      !strchr (name,'/') ) {
    if ( !stat ((char *) mail_parameters (NIL,GET_NEWSSPOOL,NIL),&sbuf) &&
      ((fd = open ((char *) mail_parameters (NIL,GET_NEWSACTIVE,NIL),O_RDONLY,
                   NIL)) >= 0)) {
        fstat (fd,&sbuf);               /* get size of active file */
                                    /* slurp in active file */
        read (fd,t = s = (char *) fs_get (sbuf.st_size+1),sbuf.st_size);
        s[sbuf.st_size] = '\0'; /* tie off file */
        close (fd);                     /* flush file */
        while (*t && (u = strchr (t,' '))) {
          *u++ = '\0';          /* tie off at end of name */
          if (!strcmp (name+6,t)) {
            fs_give ((void **) &s);     /* flush data */
            return &newsdriver;
          }
          t = 1 + strchr (u,'\n');      /* next line */
        }
        fs_give ((void **) &s); /* flush data */
    }
    else {
        return &newsdriver;     /* assume it's a newsgroup, no way to check */
    }
  }
  return NIL;                   /* return status */
}

/* News manipulate driver parameters
 * Accepts: function code
 *          function-dependent value
 * Returns: function-dependent return value
 */

void *news_parameters (long function,void *value)
{
  return NIL;
}


/* News scan mailboxes
 * Accepts: mail stream
 *          reference
 *          pattern to search
 *          string to scan
 */

void news_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents)
{
  char tmp[MAILTMPLEN];
  if (news_canonicalize (ref,pat,tmp))
    mm_log ("Scan not valid for news mailboxes",ERROR);
}

/* News find list of newsgroups
 * Accepts: mail stream
 *          reference
 *          pattern to search
 */

void news_list (MAILSTREAM *stream,char *ref,char *pat)
{
  int fd;
  int i;
  char *s,*t,*u,*lcl,pattern[MAILTMPLEN],name[MAILTMPLEN];
  struct stat sbuf;
  if (!pat || !*pat) {          /* empty pattern? */
    if (news_canonicalize (ref,"*",pattern)) {
                                /* tie off name at root */
      if (s = strchr (pattern,'.')) *++s = '\0';
      else pattern[0] = '\0';
      mm_list (stream,'.',pattern,LATT_NOSELECT);
    }
  }
  if (news_canonicalize (ref,pat,pattern) &&
      !stat ((char *) mail_parameters (NIL,GET_NEWSSPOOL,NIL),&sbuf) &&
      ((fd = open ((char *) mail_parameters (NIL,GET_NEWSACTIVE,NIL),O_RDONLY,
                   NIL)) >= 0)) {
    fstat (fd,&sbuf);           /* get file size and read data */
    read (fd,s = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);
    close (fd);                 /* close file */
    s[sbuf.st_size] = '\0';     /* tie off string */
                                /* point after prefix */
    lcl = strcpy (name,"#news.") + 6;
    i = strlen (pattern);       /* length of pattern */
    if (pattern[--i] != '%') i = 0;
    if (t = strtok (s,"\n")) do if (u = strchr (t,' ')) {
      *u = '\0';                /* tie off at end of name */
      strcpy (lcl,t);           /* make full form of name */
      if (pmatch_full (name,pattern,'.')) mm_list (stream,'.',name,NIL);
      else if (i && (u = strchr (name + i,'.'))) {
        *u = '\0';              /* tie off at delimiter, see if matches */
        if (pmatch_full (name,pattern,'.'))
          mm_list (stream,'.',name,LATT_NOSELECT);
      }
    } while (t = strtok (NIL,"\n"));
    fs_give ((void **) &s);
  }
}

/* News find list of subscribed newsgroups
 * Accepts: mail stream
 *          reference
 *          pattern to search
 */

void news_lsub (MAILSTREAM *stream,char *ref,char *pat)
{
  char pattern[MAILTMPLEN];
                                /* return data from newsrc */
  if (news_canonicalize (ref,pat,pattern)) newsrc_lsub (stream,pattern);
}


/* News canonicalize newsgroup name
 * Accepts: reference
 *          pattern
 *          returned single pattern
 * Returns: T on success, NIL on failure
 */

long news_canonicalize (char *ref,char *pat,char *pattern)
{
  if (ref && *ref) {            /* have a reference */
    strcpy (pattern,ref);       /* copy reference to pattern */
                                /* # overrides mailbox field in reference */
    if (*pat == '#') strcpy (pattern,pat);
                                /* pattern starts, reference ends, with . */
    else if ((*pat == '.') && (pattern[strlen (pattern) - 1] == '.'))
      strcat (pattern,pat + 1); /* append, omitting one of the period */
    else strcat (pattern,pat);  /* anything else is just appended */
  }
  else strcpy (pattern,pat);    /* just have basic name */
  return ((pattern[0] == '#') && (pattern[1] == 'n') && (pattern[2] == 'e') &&
          (pattern[3] == 'w') && (pattern[4] == 's') && (pattern[5] == '.') &&
          !strchr (pattern,'/')) ? T : NIL;
}

/* News subscribe to mailbox
 * Accepts: mail stream
 *          mailbox to add to subscription list
 * Returns: T on success, NIL on failure
 */

long news_subscribe (MAILSTREAM *stream,char *mailbox)
{
  return news_valid (mailbox) ? newsrc_update (stream,mailbox+6,':') : NIL;
}


/* NEWS unsubscribe to mailbox
 * Accepts: mail stream
 *          mailbox to delete from subscription list
 * Returns: T on success, NIL on failure
 */

long news_unsubscribe (MAILSTREAM *stream,char *mailbox)
{
  return news_valid (mailbox) ? newsrc_update (stream,mailbox+6,'!') : NIL;
}

/* News create mailbox
 * Accepts: mail stream
 *          mailbox name to create
 * Returns: T on success, NIL on failure
 */

long news_create (MAILSTREAM *stream,char *mailbox)
{
  return NIL;                   /* never valid for News */
}


/* News delete mailbox
 *          mailbox name to delete
 * Returns: T on success, NIL on failure
 */

long news_delete (MAILSTREAM *stream,char *mailbox)
{
  return NIL;                   /* never valid for News */
}


/* News rename mailbox
 * Accepts: mail stream
 *          old mailbox name
 *          new mailbox name
 * Returns: T on success, NIL on failure
 */

long news_rename (MAILSTREAM *stream,char *old,char *newname)
{
  return NIL;                   /* never valid for News */
}

/* News status of mailbox default handler
 * Accepts: mail stream
 *          mailbox name
 *          status flags
 * Returns: T on success, NIL on failure
 */

long news_status (MAILSTREAM *stream,char *mbx,long flags)
{
  MAILSTATUS status;
  unsigned long i;
  MAILSTREAM *tstream = NIL;
                                /* make temporary stream (unless this mbx) */
  if ((!stream || strcmp (stream->mailbox,mbx)) &&
      !(stream = tstream = mail_open (NIL,mbx,OP_READONLY|OP_SILENT)))
    return NIL;
  status.flags = flags;         /* return status values */
  status.messages = stream->nmsgs;
  status.recent = stream->recent;
  if (flags & SA_UNSEEN)        /* must search to get unseen messages */
    for (i = 1,status.unseen = 0; i <= stream->nmsgs; i++)
      if (!mail_elt (stream,i)->deleted) status.unseen++;
  status.uidnext = stream->uid_last + 1;
  status.uidvalidity = stream->uid_validity;
                                /* pass status to main program */
  mm_status (stream,mbx,&status);
  if (tstream) mail_close (tstream);
  return T;                     /* success */
}

/* News open
 * Accepts: stream to open
 * Returns: stream on success, NIL on failure
 */

MAILSTREAM *news_open (MAILSTREAM *stream)
{
  long i,nmsgs;
  char c = NIL,*s,tmp[MAILTMPLEN];
  struct _finddata_t **names = NIL;
                                /* return prototype for OP_PROTOTYPE call */
  if (!stream) return &newsproto;
  if (stream->local) fatal ("news recycle stream");
                                /* build directory name */
  sprintf (s = tmp,"%s/%s",(char *) mail_parameters (NIL,GET_NEWSSPOOL,NIL),
           stream->mailbox + 6);
  while (s = strchr (s,'.')) *s = '/';
                                /* scan directory */
  if ((nmsgs = scandir (tmp,&names,news_select,news_numsort)) >= 0) {
    mail_exists (stream,nmsgs); /* notify upper level that messages exist */
    stream->local = fs_get (sizeof (NEWSLOCAL));
    LOCAL->dirty = NIL;         /* no update to .newsrc needed yet */
    LOCAL->dir = cpystr (tmp);  /* copy directory name for later */
                                /* make temporary buffer */
    LOCAL->buf = (char *) fs_get ((LOCAL->buflen = MAXMESSAGESIZE) + 1);
    LOCAL->name = cpystr (stream->mailbox + 6);
    for (i = 0; i < nmsgs; ++i) {
      stream->uid_last = mail_elt (stream,i+1)->private.uid =
        atoi (names[i]->name);
      fs_give ((void **) &names[i]);
    }
    s = (void *) names;         /* stupid language */
    fs_give ((void **) &s);     /* free directory */
    LOCAL->cachedtexts = 0;     /* no cached texts */
    stream->sequence++;         /* bump sequence number */
    stream->rdonly = stream->perm_deleted = T;
                                /* UIDs are always valid */
    stream->uid_validity = 0xbeefface;
                                /* read .newsrc entries */
    mail_recent (stream,newsrc_read (LOCAL->name,stream));
                                /* notify if empty newsgroup */
    if (!(stream->nmsgs || stream->silent)) {
      sprintf (tmp,"Newsgroup %s is empty",LOCAL->name);
      mm_log (tmp,WARN);
    }
  }
  else mm_log ("Unable to scan newsgroup spool directory",ERROR);
  return LOCAL ? stream : NIL;  /* if stream is alive, return to caller */
}

/* News file name selection test
 * Accepts: candidate directory entry
 * Returns: T to use file name, NIL to skip it
 */

int news_select (struct _finddata_t *fileinfo)
{
  char c;
  char *s = fileinfo->name;
  while (c = *s++) if (!isdigit (c)) return NIL;
  return T;
}


/* News file name comparision
 * Accepts: first candidate directory entry
 *          second candidate directory entry
 * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2
 */

int news_numsort (const void *d1,const void *d2)
{
  return atoi ((*(struct _finddata_t **) d1)->name) -
    atoi ((*(struct _finddata_t **) d2)->name);
}


/* News close
 * Accepts: MAIL stream
 *          option flags
 */

void news_close (MAILSTREAM *stream,long options)
{
  if (LOCAL) {                  /* only if a file is open */
    news_check (stream);        /* dump final checkpoint */
    if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
                                /* free local scratch buffer */
    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
    if (LOCAL->name) fs_give ((void **) &LOCAL->name);
                                /* nuke the local data */
    fs_give ((void **) &stream->local);
    stream->dtb = NIL;          /* log out the DTB */
  }
}

/* News fetch fast information
 * Accepts: MAIL stream
 *          sequence
 *          option flags
 */

void news_fast (MAILSTREAM *stream,char *sequence,long flags)
{
  unsigned long i,j;
                                /* ugly and slow */
  if (stream && LOCAL && ((flags & FT_UID) ?
                          mail_uid_sequence (stream,sequence) :
                          mail_sequence (stream,sequence)))
    for (i = 1; i <= stream->nmsgs; i++)
      if (mail_elt (stream,i)->sequence) news_header (stream,i,&j,NIL);
}


/* News fetch flags
 * Accepts: MAIL stream
 *          sequence
 *          option flags
 */

void news_flags (MAILSTREAM *stream,char *sequence,long flags)
{
  unsigned long i;
  if ((flags & FT_UID) ?        /* validate all elts */
      mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))
    for (i = 1; i <= stream->nmsgs; i++) mail_elt (stream,i)->valid = T;
}

/* News fetch message header
 * Accepts: MAIL stream
 *          message # to fetch
 *          pointer to returned header text length
 *          option flags
 * Returns: message header in RFC822 format
 */

char *news_header (MAILSTREAM *stream,unsigned long msgno,
                   unsigned long *length,long flags)
{
  unsigned long i,hdrsize;
  int fd;
  char *t;
  struct stat sbuf;
  struct tm *tm;
  MESSAGECACHE *elt;
  *length = 0;                  /* default to empty */
  if (flags & FT_UID) return "";/* UID call "impossible" */
                                /* get elt */
  (elt = mail_elt (stream,msgno))->valid = T;
  if (!elt->private.msg.header.text.data) {
                                /* build message file name */
    sprintf (LOCAL->buf,"%s/%lu",LOCAL->dir,elt->private.uid);
    if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return "";
    fstat (fd,&sbuf);           /* get size of message */
                                /* make plausible IMAPish date string */
    tm = gmtime (&sbuf.st_mtime);
    elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
    elt->year = tm->tm_year + 1900 - BASEYEAR;
    elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
    elt->seconds = tm->tm_sec;
    elt->zhours = 0; elt->zminutes = 0;
                                /* is buffer big enough? */
    if ((unsigned)sbuf.st_size > LOCAL->buflen) {
      fs_give ((void **) &LOCAL->buf);
      LOCAL->buf = (char *) fs_get ((LOCAL->buflen = sbuf.st_size) + 1);
    }
                                /* slurp message */
    read (fd,LOCAL->buf,sbuf.st_size);
                                /* tie off file */
    LOCAL->buf[sbuf.st_size] = '\0';
    close (fd);                 /* flush message file */
                                /* find end of header */
    for (i = 0,t = LOCAL->buf; *t && !(i && (*t == '\n')); i = (*t++ == '\n'));
                                /* number of header bytes */
    hdrsize = (*t ? ++t : t) - LOCAL->buf;
    elt->rfc822_size =          /* size of entire message in CRLF form */
      (elt->private.msg.header.text.size =
       strcrlfcpy ((char **) &elt->private.msg.header.text.data,&i,LOCAL->buf,
                   hdrsize)) +
         (elt->private.msg.text.text.size =
          strcrlfcpy ((char **) &elt->private.msg.text.text.data,&i,t,
                      sbuf.st_size - hdrsize));
  }
  *length = elt->private.msg.header.text.size;
  return (char *) elt->private.msg.header.text.data;
}

/* News fetch message text (body only)
 * Accepts: MAIL stream
 *          message # to fetch
 *          pointer to returned stringstruct
 *          option flags
 * Returns: T on success, NIL on failure
 */

long news_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags)
{
  unsigned long i;
  MESSAGECACHE *elt;
                                /* UID call "impossible" */
  if (flags & FT_UID) return NIL;
  elt = mail_elt (stream,msgno);/* get elt */
                                /* snarf message if don't have it yet */
  if (!elt->private.msg.text.text.data) {
    news_header (stream,msgno,&i,flags);
    if (!elt->private.msg.text.text.data) return NIL;
  }
  if (!(flags & FT_PEEK)) {     /* mark as seen */
    mail_elt (stream,msgno)->seen = T;
    mm_flags (stream,msgno);
  }
  if (!elt->private.msg.text.text.data) return NIL;
  INIT (bs,mail_string,elt->private.msg.text.text.data,
        elt->private.msg.text.text.size);
  return T;
}

/* News per-message modify flag
 * Accepts: MAIL stream
 *          message cache element
 */

void news_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
{
  if (!LOCAL->dirty) {          /* only bother checking if not dirty yet */
    if (elt->valid) {           /* if done, see if deleted changed */
      if (elt->sequence != elt->deleted) LOCAL->dirty = T;
      elt->sequence = T;        /* leave the sequence set */
    }
                                /* note current setting of deleted flag */
    else elt->sequence = elt->deleted;
  }
}


/* News ping mailbox
 * Accepts: MAIL stream
 * Returns: T if stream alive, else NIL
 */

long news_ping (MAILSTREAM *stream)
{
  return T;                     /* always alive */
}


/* News check mailbox
 * Accepts: MAIL stream
 */

void news_check (MAILSTREAM *stream)
{
                                /* never do if no updates */
  if (LOCAL->dirty) newsrc_write (LOCAL->name,stream);
  LOCAL->dirty = NIL;
}


/* News expunge mailbox
 * Accepts: MAIL stream
 */

void news_expunge (MAILSTREAM *stream)
{
  if (!stream->silent) mm_log ("Expunge ignored on news",NIL);
}

/* News copy message(s)
 * Accepts: MAIL stream
 *          sequence
 *          destination mailbox
 *          option flags
 * Returns: T if copy successful, else NIL
 */

long news_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
{
  mailproxycopy_t pc =
    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);
  if (pc) return (*pc) (stream,sequence,mailbox,options);
  mm_log ("Copy not valid for News",ERROR);
  return NIL;
}


/* News append message from stringstruct
 * Accepts: MAIL stream
 *          destination mailbox
 *          append callback function
 *          data for callback
 * Returns: T if append successful, else NIL
 */

long news_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
{
  mm_log ("Append not valid for news",ERROR);
  return NIL;
}

/* vi: set ts=8 sta noet list sw=2: */

--- NEW FILE ---
/*
 * Program:     Netnews mail routines
 *
 * Author:      Mark Crispin
 *              Networks and Distributed Computing
 *              Computing & Communications
 *              University of Washington
 *              Administration Building, AG-44
 *              Seattle, WA  98195
 *              Internet: [EMAIL PROTECTED]
 *
 * Modified by: Vadim Zeitlin
 *              adopted news.h for Win32
 *
 * Date:        4 September 1991
 * Last Edited: 24 October 2000
 * 
 * The IMAP toolkit provided in this Distribution is
 * Copyright 2000 University of Washington.
 * The full text of our legal notices is contained in the file called
 * CPYRIGHT, included with this Distribution.
 */

/* NEWS I/O stream local data */
        
typedef struct news_local {
  unsigned int dirty : 1;       /* disk copy of .newsrc needs updating */
  char *dir;                    /* spool directory name */
  char *name;                   /* local mailbox name */
  char *buf;                    /* scratch buffer */
  unsigned long buflen;         /* current size of scratch buffer */
  unsigned long cachedtexts;    /* total size of all cached texts */
} NEWSLOCAL;


/* Convenient access to local data */

#define LOCAL ((NEWSLOCAL *) stream->local)

/* Function prototypes */

DRIVER *news_valid (char *name);
DRIVER *news_isvalid (char *name,char *mbx);
void *news_parameters (long function,void *value);
void news_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
void news_list (MAILSTREAM *stream,char *ref,char *pat);
void news_lsub (MAILSTREAM *stream,char *ref,char *pat);
long news_canonicalize (char *ref,char *pat,char *pattern);
long news_subscribe (MAILSTREAM *stream,char *mailbox);
long news_unsubscribe (MAILSTREAM *stream,char *mailbox);
long news_create (MAILSTREAM *stream,char *mailbox);
long news_delete (MAILSTREAM *stream,char *mailbox);
long news_rename (MAILSTREAM *stream,char *old,char *newname);
long news_status (MAILSTREAM *stream,char *mbx,long flags);
MAILSTREAM *news_open (MAILSTREAM *stream);
int news_select (struct _finddata_t *fileinfo);
int news_numsort (const void *d1,const void *d2);
void news_close (MAILSTREAM *stream,long options);
void news_fast (MAILSTREAM *stream,char *sequence,long flags);
void news_flags (MAILSTREAM *stream,char *sequence,long flags);
char *news_header (MAILSTREAM *stream,unsigned long msgno,
                   unsigned long *length,long flags);
long news_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
void news_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);
long news_ping (MAILSTREAM *stream);
void news_check (MAILSTREAM *stream);
void news_expunge (MAILSTREAM *stream);
long news_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
long news_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);

Index: os_nt.c
===================================================================
RCS file: /cvsroot/mahogany/M/lib/imap/src/osdep/nt/os_nt.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -b -u -2 -r1.1.1.1 -r1.2
--- os_nt.c     24 Apr 2004 21:46:54 -0000      1.1.1.1
+++ os_nt.c     24 Apr 2004 23:12:57 -0000      1.2
@@ -39,2 +39,46 @@
 #include "ssl_nt.c"
 #include "tcp_nt.c"
+
+/* Emulator for BSD scandir() call
+ * Accepts: directory name
+ *         destination pointer of names array
+ *         selection function
+ *         comparison function
+ * Returns: number of elements in the array or -1 if error
+ */
+
+int scandir (char *dirname,struct _finddata_t ***namelist,select_t select,
+            compar_t compar)
+{
+  struct _finddata_t *p, d, **names;
+  int nitems;
+  long nlmax;
+  long hDir;
+  char *filemask = (char *)fs_get((strlen(dirname) + 5) * sizeof(char));
+  strcpy(filemask, dirname);
+  strcat(filemask, "/*.*");
+  hDir = _findfirst(filemask, &d);/* open directory */
+  fs_give((void **)&filemask);
+  if (hDir == -1) return -1;
+  nlmax = 100;                 /* FIXME how to get number of files in dir? */
+  names = (struct _finddata_t **) fs_get (nlmax * sizeof (struct _finddata_t *));
+  nitems = 0;                  /* initially none found */
+  do {                         /* loop over all files */
+                               /* matches select criterion? */
+    if (select && !(*select) (&d)) continue;
+    p = (struct _finddata_t *)fs_get(sizeof(d));
+    strcpy (p->name,d.name);
+    if (++nitems >= nlmax) {   /* if out of space, try bigger guesstimate */
+      nlmax *= 2;              /* double it */
+      fs_resize ((void **) &names,nlmax * sizeof (struct _finddata_t *));
+    }
+    names[nitems - 1] = p;     /* store this file there */
+  }
+  while (_findnext(hDir, &d) == 0);
+  _findclose(hDir);            /* done with directory */
+                               /* sort if necessary */
+  if (nitems && compar) qsort (names,nitems,sizeof (struct _finddata_t *),compar);
+  *namelist = names;           /* return directory */
+  return nitems;               /* and size */
+}
+ 

Index: os_nt.h
===================================================================
RCS file: /cvsroot/mahogany/M/lib/imap/src/osdep/nt/os_nt.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -b -u -2 -r1.1.1.1 -r1.2
--- os_nt.h     24 Apr 2004 21:46:53 -0000      1.1.1.1
+++ os_nt.h     24 Apr 2004 23:12:57 -0000      1.2
@@ -43,2 +43,6 @@
 #undef noErr
 #undef MAC
+
+typedef int (*select_t) (struct _finddata_t *name);
+typedef int (*compar_t) (const void *d1,const void *d2); 
+int scandir (char *dirname,struct _finddata_t ***namelist,select_t select, compar_t 
compar);



-------------------------------------------------------
This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
For a limited time only, get FREE Ground shipping on all orders of $35
or more. Hurry up and shop folks, this offer expires April 30th!
http://www.thinkgeek.com/freeshipping/?cpg=12297
_______________________________________________
Mahogany-cvsupdates mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to