[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re:NNTP and POP3



|Does anyone know if there is a way to send and recieve usenet news with
|NNTP (other than tin) with MiNT, specificaly KGMD. Also is it possible to
|get mail with POP3. My ISP is having problems with UUCP right now.

I get my mail on MiNT from a POP3 server
Here's my POP3 client:

You will have to remplace mail.sct.fr with your mail host in the line
#define POP_SERVER "mail.sct.fr"

Feel free to ask me questions, if something is wrong!

Ciao, Stéphane


/*
** pop.c for Pop
** Tiny POP3 implementation
**
** Copyright (C) 1994, Stephane Boisson. All Rights reserved.
** Login <boisson@worldnet.net>
**
** Started on  Sat Apr 15 22:41:52 1995 Stephane Boisson
** Last update Fri Dec 15 19:36:02 1995 Stephane Boisson
**
** This file can be redistributed under the terms of the GNU General
** Public Licence.
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <varargs.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ctype.h>

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

/*--- Definitions ---*/
#define POP_SERVER "mail.sct.fr"

/*--- POP prototypes ---*/
int popBegin(char *hostname, FILE **fdinp, FILE **fdoutp);
void popEnd(FILE *fdin, FILE *fdout);
void popSend( /* FILE *fd, char *string, ... */ );
int popReceive(FILE *fd, char *string, int size);
int popGetStatus(FILE *fd, char *string, int size);

int popMsgInfo(FILE *fdin, FILE *fdout, int id,
	       char **from, char **to, char **subject);
char *get_realname(char *from);


/* ----------------------------------------------------------------- **
** main - Parse command line                                         **
** ----------------------------------------------------------------- */
int main(argc, argv)
int argc;
char **argv;
{
  char *progname, passwd[128], buffer[1024];
  int verbose_flag, delete_flag, all_flag;
  FILE *fdin, *fdout;

  verbose_flag = delete_flag = all_flag = FALSE;
  progname = *argv;
  passwd[0] = 0;

  /*--- Parse command line ---*/
  for(argc--, argv++; argc; argc--, argv++)
    if(**argv == '-')
      switch((*argv)[1])
	{
	  /*--- Password ---*/
	case 'p':
	  if(argc == 1) break;
	  argv++, argc--;
	  strncpy(passwd, *argv, 127);
	  passwd[127] = 0;
	  break;

	  /*--- Verbose ---*/
	case 'v':
	  verbose_flag = TRUE;
	  break;

	  /*--- Delete when read ---*/
	case 'd':
	  delete_flag = TRUE;
	  break;

	  /*--- All messages ---*/
	case 'a':
	  all_flag = TRUE;
	  break;

	  /*--- Usage ---*/
	default:
	  fprintf(stderr, "Usage: %s [-vda] [-p <password>] [<message #>]\n",
		  progname);
	  exit(1);
	}
    else
      break;

  /*--- get password ---*/
  if(passwd[0] == 0)
    {
      fprintf(stderr, "Password: ");
      fflush(stderr);
      if(popReceive(stdin, passwd, 127) == FALSE) exit(1);
    }

  /*--- Start transaction ---*/
  if(popBegin(POP_SERVER, &fdin, &fdout) == FALSE) exit(2);

  while(42)
    {
      int msg_count;

      /*--- Authentification ---*/
      popSend(fdout, "USER %s", getenv("USER"));
      if(popGetStatus(fdin, buffer, 1023) == FALSE) break;

      popSend(fdout, "PASS %s", passwd);
      if(popGetStatus(fdin, buffer, 1023) == FALSE) break;

      /*--- Transaction ---*/
      popSend(fdout, "STAT");
      if(popGetStatus(fdin, buffer, 1023) == FALSE) break;
      if((msg_count = atoi(buffer)) == 0)
	{
	  popSend(fdout, "QUIT");
	  popEnd(fdin, fdout);
	  if(verbose_flag != FALSE)
	    fprintf(stderr, "No mail for %s\n", getenv("USER"));
	  exit(0);
	}

      if((argc == 0) && (all_flag == FALSE))
	{
	  char *from, *subject;
	  int i;

	  /*--- Message list ---*/

	  if(verbose_flag != FALSE)
	    {
	      for(i = 1 ; i <= msg_count; i++)
		if(popMsgInfo(fdin, fdout, i, &from, NULL, &subject) != FALSE)
		  {
		    fprintf(stderr, "[%d] from %s: %s\n", i,
			    get_realname(from),
			    (subject && *subject)? subject : "<no subject>");
		
		    if(subject != NULL) free(subject);
		    if(from != NULL) free(from);
		  }
	    }
	  else
	    fprintf(stderr, "%s have %d mail%c\n", getenv("USER"),
		    msg_count, msg_count? 's' : ' ');
	}
      else
	{
	  int i;

	  /*--- retrive message ---*/

	  if(verbose_flag != FALSE)
	    fprintf(stderr, "%s have %d mail%c\n",
		    getenv("USER"), msg_count, msg_count? 's' : ' ');

	  i = 1;
	  while((all_flag && (i <= msg_count)) || argc)
	    {
	      char *from, *subject;
	      int nb;

	      if(all_flag == FALSE)
		{
		  argc--;
		  if((nb = atoi(*argv++)) == 0) continue;
		}
	      else
		nb = i++;

	      /*--- Get message info ---*/
	      if(verbose_flag &&
		 popMsgInfo(fdin, fdout, nb, &from, NULL, &subject))
		{
		  fprintf(stderr, "[%d] from %s: %s\n", nb,
			  get_realname(from),
			  (subject && *subject)? subject : "<no subject>");
		
		  if(subject != NULL) free(subject);
		  if(from != NULL) free(from);
		}

	      /*--- Get message data ---*/
	      popSend(fdout, "RETR %d", nb);
	      if(popGetStatus(fdin, buffer, 1023) == FALSE) continue;

	      while(popReceive(fdin, buffer, 1023) != FALSE)
		{
		  if(!strcmp(buffer, ".")) break;
		  printf("%s\n", (*buffer == '.')? buffer + 1: buffer);
		}

	      /*--- Delete message ---*/
	      if(delete_flag != FALSE)
		{
		  popSend(fdout, "DELE %d", nb);
		  if(popGetStatus(fdin, buffer, 1023) == FALSE) continue;
		}
	    }
	}

      /*--- End transaction ---*/
      popSend(fdout, "QUIT");
      popEnd(fdin, fdout);
      exit(0);
    }

  /*--- Error ---*/
  popSend(fdout, "QUIT");
  popEnd(fdin, fdout);
  fprintf(stderr, "POP error: %s\n", buffer);
  exit(1);
}


/* ----------------------------------------------------------------- **
** popBegin - Start POP connection                                   **
** ----------------------------------------------------------------- */
int popBegin(hostname, fdinp, fdoutp)
char *hostname;
FILE **fdinp;
FILE **fdoutp;
{
  struct sockaddr_in sin;
  struct hostent *host;
  char buffer[1024];
  char **addr_ptr;
  int sockfd, rc;

  /*--- Set server address ---*/
  if((host = gethostbyname(hostname)) == NULL)
    {
      fprintf(stderr, "%s: Unknow host\n", hostname);
      return FALSE;
    }

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = host->h_addrtype;
  sin.sin_port = htons(110);

  /*--- Try all the IP address ---*/
  for(addr_ptr = host->h_addr_list, rc = -1; addr_ptr && *addr_ptr; addr_ptr++)
    {
      if((sockfd = socket(host->h_addrtype, SOCK_STREAM, 0)) < 0)
	{
	  perror("socket");
	  return FALSE;
	}

      memcpy(&sin.sin_addr, *addr_ptr, host->h_length);
      /*fprintf(stderr, "Trying %s\n", inet_ntoa(sin.sin_addr));*/
      if((rc = connect(sockfd, (struct sockaddr *)&sin, sizeof(sin))) == 0)
	break;
      perror("connect");
      close(sockfd);
    }
  if(rc < 0) return FALSE;

  /*--- Setup files handles ---*/
  if((*fdinp = fdopen(sockfd, "rb")) == NULL)
    {
      perror("fdopen in");
      *fdoutp = NULL;
      close(sockfd);
      return FALSE;
    }
  sockfd = dup(sockfd);
  if((*fdoutp = fdopen(sockfd, "wb")) == NULL)
    {
      perror("fdopen out");
      fclose(*fdinp);
      close(sockfd),
      *fdinp = NULL;
      return FALSE;
    }

  if(popGetStatus(*fdinp, buffer, 1023) == FALSE)
    {
      popEnd(*fdinp, *fdoutp);
      *fdinp = *fdoutp = NULL;
      return FALSE;
    }
  return TRUE;
}


/* ----------------------------------------------------------------- **
** popEnd - End of POP connection                                   **
** ----------------------------------------------------------------- */
void popEnd(fdin, fdout)
FILE *fdin;
FILE *fdout;
{
  if((fdin == NULL) || (fdout == NULL)) return;

  popSend(fdout, "QUIT");
  fclose(fdin);
  fclose(fdout);
}


/* ----------------------------------------------------------------- **
** popSend - Send a string as a <crlf> ended line                    **
** ----------------------------------------------------------------- */
void popSend(fd, string, va_alist)
FILE *fd;
char *string;
va_dcl
{
  va_list ap;

  va_start(ap);
  vfprintf(fd, string, ap);
  va_end(ap);
  fputc('\r', fd);
  fputc('\n', fd);
  fflush(fd);
#ifdef DEBUG
  vfprintf(stderr, string, ap);
  fputc('\r', stderr);
  fputc('\n', stderr);
#endif
}


/* ----------------------------------------------------------------- **
** popReceive - Receive a <crlf> line from server                    **
** ----------------------------------------------------------------- */
int popReceive(fd, string, size)
FILE *fd;
char *string;
int size;
{
  char *ptr;

  if(fgets(string, size, fd) == NULL)
    {
      if(errno != ENOERR) perror("popReceive");
      return FALSE;
    }
  if((ptr = (char *) strchr (string, '\r')) != NULL) *ptr = 0;
  if((ptr = (char *) strchr (string, '\n')) != NULL) *ptr = 0;

#ifdef DEBUG
  fprintf(stderr, "%s\n", string);
#endif
  return TRUE;
}


/* ----------------------------------------------------------------- **
** popGetStatus - Get status from server                             **
** ----------------------------------------------------------------- */
int popGetStatus(fd, buffer, len)
FILE *fd;
char *buffer;
int len;
{
  char *ptr;
  int rc;

  if(popReceive(fd, buffer, len) == FALSE) return -1;
  rc = strncmp("+OK", buffer, 3)? FALSE: TRUE;

  if(rc == TRUE)
    ptr = buffer + 3;
  else if(!strncmp("-ERR", buffer, 4))
    ptr = buffer + 4;
  else
    return FALSE;

  while(*ptr && (*ptr == 32)) ptr++;
  memmove(buffer, ptr, strlen(ptr) + 1);

#ifdef DEBUG
  fprintf(stderr, "%s: %s\n", (rc? "TRUE":"FALSE"), buffer);
#endif

  return rc;
}


/* ----------------------------------------------------------------- **
** popMsgInfo - Get infos about message                              **
** ----------------------------------------------------------------- */
int popMsgInfo(fdin, fdout, id, from, to, subject)
FILE *fdin;
FILE *fdout;
int id;
char **from;
char **to;
char **subject;
{
  char buffer[1024], *ptr;

  if(subject) *subject = NULL;
  if(from) *from = NULL;
  if(to) *to = NULL;
  buffer[1023] = 0;

  popSend(fdout, "TOP %d 0", id);
  if(popGetStatus(fdin, buffer, 1023) == FALSE) return FALSE;

  while(popReceive(fdin, buffer, 1023) != FALSE)
    {
      for(ptr = buffer; (*ptr > 32) && (*ptr != ':'); ptr++)
	if(islower(*ptr)) *ptr = toupper(*ptr);

      while(*ptr && ((*ptr <= 32) || (*ptr == ':')))
	*ptr++ = 0;

      if(from && !strcmp(buffer, "FROM"))
	*from = strdup(ptr);
      else if(to && !strcmp(buffer, "TO"))
	*to = strdup(ptr);
      else if(subject && !strcmp(buffer, "SUBJECT"))
	*subject = strdup(ptr);

      if(!strcmp(buffer, ".")) return TRUE;
    }

  if(subject && *subject != NULL)
    {
      free(*subject);
      *subject = NULL;
    }
  if(from && *from != NULL)
    {
      free(*from);
      *from = NULL;
    }
  if(to && *to != NULL)
    {
      free(*to);
      *to = NULL;
    }

  return FALSE;
}


/* ----------------------------------------------------------------- **
** get_realname - return fullname from a 'From' keyword              **
** ----------------------------------------------------------------- */
char *get_realname(from)
char *from;
{
  static char realname[128];
  char *source, *target;
  int flag;

  flag = FALSE;
  realname[127] = 0;
  target = realname;
  for(source = from; (*source != 0) && (target < (realname + 127)); source++)
    {
      if(*source == '<')
	{
	  while((target > realname) && (target[-1] <= 32)) target--;
	  *target = 0;
	  if(!*realname) strncmp(realname, from, 127);
	  return realname;
	}
      else if(flag == FALSE)
	{
	  if(*source == '(')
	    {
	      target = realname;
	      flag = TRUE;
	    }
	  else
	    *target++ = *source;
	}
      else
	{
	  if(*source == ')')
	    {
	      *target = 0;
	      if(!*realname) strncmp(realname, from, 127);
	      return realname;
	    }
	  else
	    *target++ = *source;
	}
    }
  *target = 0;
  return realname;
}





--
  Stephane Boisson   | 11, rue de la Garenne | Falcon030/MiNT, MacIIci, Un*x
boisson@worldnet.net |  92310 Sevres FRANCE  |   TCP/IP, XWindow, C, 680x0
http://www.worldnet.net/~boisson/
http://www.x4u.com/