/*
 * 3supp.c
 * Public Domain
 *
 * miscellaneous support routines for type 3 ASCII packet manipulation
 * only fgets3 and strdup3 are required; snip and choose as you need
 * from the rest (see below #ifdef NEVER)
 *
 */

#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <io.h>
#include <ctype.h>

/* A specialized fgets() for type3 ASCII -- stops at <cr>s */

char * fgets3 (char *str, int num, int handle) {

  char           *p;
  long            pos;
  int             x;

  if (eof (handle)) {
    *str = 0;
    return NULL;
  }
  pos = tell (handle);
  x = read(handle,str,num);
  if (x < 1) {
    *str = 0;
    return NULL;
  }
  str[x] = 0;
  p = str;
  while (*p && *p != '\r')
    p++;
  if (!*p)
    return str;
  *p = 0;
  p++;
  lseek (handle, pos + ((int)p - (int)str), SEEK_SET);
  return str;
}


char * strdup3 (char *dupme) {  /* a strdup */

  char *a = NULL;

  if(dupme && *dupme) {
    a = (char *)malloc(strlen(dupme) + 1);
    if(a) strcpy(a,dupme);
  }
  return a;
}


#ifdef NEVER

/* not used by 3mailin or 3mailout, but you might find them useful */


#include <time.h>

static char illegal[] = {'\x8d'};  /* anything you want stripped in illegal */

int stripjnk3 (char *a,int len) {  /* remove some common 'illegal' chars */

  char *p = a;

  while (*p) {
    if(*p == '\t') *p = ' ';
    else if ((*p < 31 && *p != '\r') || strchr(illegal,*p)) {
      memmove (p, &p[1], len - ((int) p - (int)a));
      len--;
      if (!len)
        break;
      continue;
    }
    p++;
  }

  return len;
}


char * stripcr3 (char *a) {  /* remove trailing crs */

  register int x;

  x = strlen (a);
  while (x && a[x - 1] == '\r')
    a[--x] = 0;
  return a;
}


time_t fido_2_unix (char *str) {

  /* translate a fido/sea datestring to a unix timestamp
   * sscanf statements from Folkert Wijnstra via NET_DEV
   */

  int             month = 0,
                  day,
                  year,
                  hours,
                  minutes,
                  seconds = 0;
  char            monthStr[20] = "";

  if ((sscanf (str, "%d %s %d %d:%d:%d", &day, monthStr, &year,
               &hours, &minutes, &seconds) < 5) &&
      (sscanf (str, "%d-%d-%d %d:%d:%d", &day, &month, &year,
               &hours, &minutes, &seconds) < 5) &&
      (sscanf (&str[4], "%d %s %d %d:%d", &day, monthStr, &year,
               &hours, &minutes) < 5)) {  /* Date not recognized */
    return -1L;
  }
  else {                    /* Date was recognized (convert monthStr to
                             * month if necessary) */
    struct tm       tm;

    memset (&tm, 0, sizeof (struct tm));
    if (!month && *monthStr) {

      int             x;
      static char    *months[] = {"Jan", "Feb", "Mar", "Apr", "May",
                                  "Jun", "Jul", "Aug", "Sep", "Oct",
                                  "Nov", "Dec"};

      for (x = 0; x < 12; x++) {
        if (!strnicmp (monthStr, months[x], 3)) {
          month = x + 1;
          break;
        }
      }
    }

    tm.tm_mon = month - 1;
    tm.tm_mday = day;
    if (year > 1900)
      year -= 1900;
    tm.tm_year = year;
    if (hours > 23)
      hours = 0;
    tm.tm_hour = hours;
    tm.tm_min = minutes;
    tm.tm_sec = 0;          /* in case stripped */

    return mktime (&tm);
  }
}


char * unix_2_fido (time_t t,int sea) {

  /* translate a unix timestamp to a fido or sea datestring */

  static char fdate[22];

  if(sea) {
    strftime (fdate, 21, "%a %d %b %y %H:%M", localtime(&t));
    if(fdate[4] == '0') fdate[4] = ' ';
  }
  else {
    strftime (fdate, 21, "%d %b %y  %H:%M:%S", localtime(&t));
  }
  return fdate;
}


char * unix_2_type3a (time_t t) {

  /* translate a unix timestamp to a type3a datestring
   * YYYYMMDDhhmmss -- sortable, compact, unambiguous, ASCII
   */

  static char fdate[22];

  strftime (fdate, 21, "%Y%m%d%H%M%S", localtime(&t));
  return fdate;
}


time_t type3a_2_unix (char *a) {

  /* translate a type3a datestring to a unix timestamp */

    struct tm   tm;
    char        *p,w,*s;

    memset (&tm, 0, sizeof (struct tm));
    s = a;
    p = &a[4];
    w = *p;
    *p = 0;

    /* note:  if your compiler doesn't have atoi(), emulate w/ sscanf */

    tm.tm_year = atoi(s) - 1900;
    *p = w;
    s = p;
    p += 2;
    w = *p;
    *p = 0;
    tm.tm_mon = atoi(s);
    *p = w;
    s = p;
    p += 2;
    w = *p;
    *p = 0;
    tm.tm_mday = atoi(s);
    *p = w;
    s = p;
    p += 2;
    w = *p;
    *p = 0;
    tm.tm_hour = atoi(s);
    *p = w;
    s = p;
    p += 2;
    w = *p;
    *p = 0;
    tm.tm_min = atoi(s);
    *p = w;
    s = p;
    tm.tm_sec = atoi(s);

    return mktime (&tm);
}


char * type3a_2_fido (char *a,int sea) {

  /* translate a type3a datestring to a fido or sea datestring */

  time_t t;

  t = type3a_2_unix(a);
  return unix_2_fido(t,sea);
}


char * fido_2_type3a (char *a) {

  /* translate a fido or sea datestring to a type3a datestring */

  time_t t;

  t = fido_2_unix(a);
  if(t == -1L) return NULL;
  return unix_2_type3a(t);
}


struct address {
  unsigned int
        zone,net,node,point;
  char domain[9];
};

int parse_addr3 (char *addr3,struct address *addr) {

  /* parse a 5-D address from a type 3A From or To address */

  char *p,*pp;

  memset(addr,0,sizeof(struct address));
  if(!addr3 || !*addr3) return -1;

  p = strchr(addr3,'@');
  if(p) p++;
  else p = addr3;

  pp = addr->domain;
  while(*p != '#' && pp < addr->domain + 9) {
    *pp = *p;
    pp++;
    p++;
  }
  pp = strchr(addr->domain,'.');
  if(pp) *pp = 0;
  if(!*addr->domain) return -1;

  if(*p == '#') p++;
  else {
    p = strchr(p,'#');
    if(!p) return -1;
  }
  addr->zone = atoi(p);

  p = strchr(p,':');
  if(!p) return -1;
  p++;
  addr->net = atoi(p);

  p = strchr(p,'/');
  if(!p) return -1;
  p++;
  addr->node = atoi(p);

  p = strchr(p,'.');
  if(p) {
    p++;
    addr->point = atoi(p);
  }

  if(!addr->zone || !addr->net || !*addr->domain) return -1;

  return 0;
}


char * break_id (char *id,char *from,long *serial) {

  /*
   * return address portion of id, put serial # in *serial
   * return NULL on error.  not perfect, but works.
   */

  static char ret[256];
  char       *p;

  if(!id || !*id) return NULL;

  if(*id == ' ') {  /* address is same as From */
    if(!from || !*from) return NULL;
    while(*id == ' ') id++;
    *serial = atol(id);
    p = strchr(from,'@');
    if(!p) p = from;
    else p++;
    strcpy(ret,p);
  }
  else {
    if(*id == '\"') {
      p = id + 1;
      while(*p) {
        if(*p == '\"' && *(p + 1) != '\"') break;
        p++;
      }
    }
    else {
      p = strchr(p,' ');
    }
    if(!p || !*p) return NULL;
    else {
      memset(ret,0,256);
      strncpy(ret,id,(int)p - (int)serial);
      while(*p == ' ' || *p == '\"') p++;
      *serial = atol(p);
    }
  }
  return ret;
}

#endif
