Subject: DSN (sendmail) support

From: [email-masked] (Chris Taylor)
Date: 6 Jan 1997 09:31:58 GMT

Please find enclosed the patches to convert 3.9x (it was actually done
on 3.95, but it should work on all of the 9 versions) to support DSN 
for sendmail 8.8.

It provides a switch in the configuration screen to support DSN.

When this has been turned on, you will be asked if you want delivery
notification when you send the mail (^X in compose).  Sendmail will
then mail you back a DSN in a normal mail message.

If people have problems with these patches (legitimate problems please, not 
diff/patch problems), please mail me and I will try and have a look, 
but nothing is guaranteed.

---- Cut Here -------- Cut Here -------- Cut Here -------- Cut Here ----
*** ./imap/ANSI/c-client/mail.h	Tue Jun  4 00:04:29 1996
--- ./imap/ANSI/c-client/mail.h	Tue Nov 26 12:02:24 1996
***************
*** 202,207 ****
    char *newsgroups;		/* USENET newsgroups */
    char *followup_to;		/* USENET reply newsgroups */
    char *references;		/* USENET references */
  } ENVELOPE;
  
  /* Primary body types */
--- 202,210 ----
    char *newsgroups;		/* USENET newsgroups */
    char *followup_to;		/* USENET reply newsgroups */
    char *references;		/* USENET references */
+ 
+   /* Chris T */
+   int dsn;
  } ENVELOPE;
  
  /* Primary body types */
*** ./imap/ANSI/c-client/smtp.c	Fri Jun 28 20:57:09 1996
--- ./imap/ANSI/c-client/smtp.c	Tue Nov 26 12:06:09 1996
***************
*** 144,161 ****
      smtp_fake (stream,SMTPHARDERROR,"No recipients specified");
      return NIL;
    }
    				/* make sure stream is in good shape */
    smtp_send (stream,"RSET",NIL);
    strcpy (tmp,"FROM:<");	/* compose "MAIL FROM:<return-path>" */
    rfc822_address (tmp,env->return_path);
    strcat (tmp,">");
    if (stream->ok_8bitmime) strcat (tmp," BODY=8BITMIME");
  				/* send "MAIL FROM" command */
    if (!(smtp_send (stream,type,tmp) == SMTPOK)) return NIL;
  				/* negotiate the recipients */
!   if (env->to) smtp_rcpt (stream,env->to,&error);
!   if (env->cc) smtp_rcpt (stream,env->cc,&error);
!   if (env->bcc) smtp_rcpt (stream,env->bcc,&error);
    if (error) {			/* any recipients failed? */
        				/* reset the stream */
      smtp_send (stream,"RSET",NIL);
--- 144,170 ----
      smtp_fake (stream,SMTPHARDERROR,"No recipients specified");
      return NIL;
    }
+ 
+   /* Chris T */
+   if(! stream->ok_dsn && env->dsn) {
+     smtp_fake (stream,SMTPHARDERROR,"MDA doesnt support delivery notification");
+     env->dsn=0;
+     stream->ok_dsn=0;
+   }
    				/* make sure stream is in good shape */
    smtp_send (stream,"RSET",NIL);
    strcpy (tmp,"FROM:<");	/* compose "MAIL FROM:<return-path>" */
    rfc822_address (tmp,env->return_path);
    strcat (tmp,">");
    if (stream->ok_8bitmime) strcat (tmp," BODY=8BITMIME");
+   /* Chris T */
+   if (stream->ok_dsn) strcat (tmp," RET=HDRS");				
  				/* send "MAIL FROM" command */
    if (!(smtp_send (stream,type,tmp) == SMTPOK)) return NIL;
  				/* negotiate the recipients */
!   if (env->to) smtp_rcpt (stream,env->to,&error,stream->ok_dsn && env->dsn);
!   if (env->cc) smtp_rcpt (stream,env->cc,&error,stream->ok_dsn && env->dsn);
!   if (env->bcc) smtp_rcpt (stream,env->bcc,&error,0);
    if (error) {			/* any recipients failed? */
        				/* reset the stream */
      smtp_send (stream,"RSET",NIL);
***************
*** 205,211 ****
   *	    pointer to error flag
   */
  
! void smtp_rcpt (SMTPSTREAM *stream,ADDRESS *adr,long *error)
  {
    char tmp[MAILTMPLEN];
    while (adr) {
--- 214,220 ----
   *	    pointer to error flag
   */
  
! void smtp_rcpt (SMTPSTREAM *stream,ADDRESS *adr,long *error, int dsn)
  {
    char tmp[MAILTMPLEN];
    while (adr) {
***************
*** 215,220 ****
        strcpy (tmp,"TO:<");	/* compose "RCPT TO:<return-path>" */
        rfc822_address (tmp,adr);
        strcat (tmp,">");
  				/* send "RCPT TO" command */
        if (!(smtp_send (stream,"RCPT",tmp) == SMTPOK)) {
  	*error = T;		/* note that an error occurred */
--- 224,231 ----
        strcpy (tmp,"TO:<");	/* compose "RCPT TO:<return-path>" */
        rfc822_address (tmp,adr);
        strcat (tmp,">");
+       /* Chris T */
+       if(dsn) strcat(tmp," NOTIFY=SUCCESS");
  				/* send "RCPT TO" command */
        if (!(smtp_send (stream,"RCPT",tmp) == SMTPOK)) {
  	*error = T;		/* note that an error occurred */
***************
*** 280,285 ****
  	     && (!tmp[4] || tmp[4] == ' ')) {
        if (tmp[4]) stream->size = atoi (tmp+5);
        stream->ok_size = T;
      }
  				/* defined by SMTP Service Extensions */
      else if (j == (((long) 'S' << 24) + ((long) 'E' << 16) + ('N' << 8) + 'D')
--- 291,299 ----
  	     && (!tmp[4] || tmp[4] == ' ')) {
        if (tmp[4]) stream->size = atoi (tmp+5);
        stream->ok_size = T;
+     } /* Chris T */
+     else if (j == (((long) 'D' << 24) + ((long) 'S' << 16) + ('N' << 8))) {
+       stream->ok_dsn = T;
      }
  				/* defined by SMTP Service Extensions */
      else if (j == (((long) 'S' << 24) + ((long) 'E' << 16) + ('N' << 8) + 'D')
*** ./imap/ANSI/c-client/smtp.h	Wed Feb  7 00:09:54 1996
--- ./imap/ANSI/c-client/smtp.h	Tue Nov 26 12:06:25 1996
***************
*** 74,79 ****
    unsigned int ok_turn : 1;	/* supports TURN */
    unsigned int ok_size : 1;	/* supports SIZE */
    unsigned int ok_8bitmime : 1;	/* supports 8-bit MIME */
  } SMTPSTREAM;
  
  /* Coddle certain compilers' 6-character symbol limitation */
--- 74,81 ----
    unsigned int ok_turn : 1;	/* supports TURN */
    unsigned int ok_size : 1;	/* supports SIZE */
    unsigned int ok_8bitmime : 1;	/* supports 8-bit MIME */
+   /* Chris T */
+   unsigned int ok_dsn : 1;	/* supports DSN */
  } SMTPSTREAM;
  
  /* Coddle certain compilers' 6-character symbol limitation */
***************
*** 101,107 ****
  long smtp_mail (SMTPSTREAM *stream,char *type,ENVELOPE *msg,BODY *body);
  void smtp_debug (SMTPSTREAM *stream);
  void smtp_nodebug (SMTPSTREAM *stream);
! void smtp_rcpt (SMTPSTREAM *stream,ADDRESS *adr,long *error);
  long smtp_send (SMTPSTREAM *stream,char *command,char *args);
  long smtp_reply (SMTPSTREAM *stream);
  long smtp_fake (SMTPSTREAM *stream,long code,char *text);
--- 103,109 ----
  long smtp_mail (SMTPSTREAM *stream,char *type,ENVELOPE *msg,BODY *body);
  void smtp_debug (SMTPSTREAM *stream);
  void smtp_nodebug (SMTPSTREAM *stream);
! void smtp_rcpt (SMTPSTREAM *stream,ADDRESS *adr,long *error,int);
  long smtp_send (SMTPSTREAM *stream,char *command,char *args);
  long smtp_reply (SMTPSTREAM *stream);
  long smtp_fake (SMTPSTREAM *stream,long code,char *text);
*** ./imap/non-ANSI/c-client/mail.h	Tue Jun  4 00:05:38 1996
--- ./imap/non-ANSI/c-client/mail.h	Tue Nov 26 12:00:33 1996
***************
*** 202,207 ****
    char *newsgroups;		/* USENET newsgroups */
    char *followup_to;		/* USENET reply newsgroups */
    char *references;		/* USENET references */
  } ENVELOPE;
  
  /* Primary body types */
--- 202,210 ----
    char *newsgroups;		/* USENET newsgroups */
    char *followup_to;		/* USENET reply newsgroups */
    char *references;		/* USENET references */
+ 
+   /* Chris T */
+   int dsn;
  } ENVELOPE;
  
  /* Primary body types */
*** ./imap/non-ANSI/c-client/smtp.c	Fri Jun 28 21:26:40 1996
--- ./imap/non-ANSI/c-client/smtp.c	Tue Nov 26 12:00:33 1996
***************
*** 154,171 ****
      smtp_fake (stream,SMTPHARDERROR,"No recipients specified");
      return NIL;
    }
    				/* make sure stream is in good shape */
    smtp_send (stream,"RSET",NIL);
    strcpy (tmp,"FROM:<");	/* compose "MAIL FROM:<return-path>" */
    rfc822_address (tmp,env->return_path);
    strcat (tmp,">");
    if (stream->ok_8bitmime) strcat (tmp," BODY=8BITMIME");
  				/* send "MAIL FROM" command */
    if (!(smtp_send (stream,type,tmp) == SMTPOK)) return NIL;
  				/* negotiate the recipients */
!   if (env->to) smtp_rcpt (stream,env->to,&error);
!   if (env->cc) smtp_rcpt (stream,env->cc,&error);
!   if (env->bcc) smtp_rcpt (stream,env->bcc,&error);
    if (error) {			/* any recipients failed? */
        				/* reset the stream */
      smtp_send (stream,"RSET",NIL);
--- 154,180 ----
      smtp_fake (stream,SMTPHARDERROR,"No recipients specified");
      return NIL;
    }
+ 
+   /* Chris T */
+   if(! stream->ok_dsn && env->dsn) {
+     smtp_fake (stream,SMTPHARDERROR,"MDA doesnt support delivery notification");
+     env->dsn=0;
+     stream->ok_dsn=0;
+   }
    				/* make sure stream is in good shape */
    smtp_send (stream,"RSET",NIL);
    strcpy (tmp,"FROM:<");	/* compose "MAIL FROM:<return-path>" */
    rfc822_address (tmp,env->return_path);
    strcat (tmp,">");
    if (stream->ok_8bitmime) strcat (tmp," BODY=8BITMIME");
+   /* Chris T */
+   if (stream->ok_dsn) strcat (tmp," RET=HDRS");				
  				/* send "MAIL FROM" command */
    if (!(smtp_send (stream,type,tmp) == SMTPOK)) return NIL;
  				/* negotiate the recipients */
!   if (env->to) smtp_rcpt (stream,env->to,&error,stream->ok_dsn && env->dsn);
!   if (env->cc) smtp_rcpt (stream,env->cc,&error,stream->ok_dsn && env->dsn);
!   if (env->bcc) smtp_rcpt (stream,env->bcc,&error,0);
    if (error) {			/* any recipients failed? */
        				/* reset the stream */
      smtp_send (stream,"RSET",NIL);
***************
*** 217,226 ****
   *	    pointer to error flag
   */
  
! void smtp_rcpt (stream,adr,error)
  	SMTPSTREAM *stream;
  	ADDRESS *adr;
  	long *error;
  {
    char tmp[MAILTMPLEN];
    while (adr) {
--- 226,236 ----
   *	    pointer to error flag
   */
  
! void smtp_rcpt (stream,adr,error,dsn)
  	SMTPSTREAM *stream;
  	ADDRESS *adr;
  	long *error;
+ 	int dsn;
  {
    char tmp[MAILTMPLEN];
    while (adr) {
***************
*** 230,235 ****
        strcpy (tmp,"TO:<");	/* compose "RCPT TO:<return-path>" */
        rfc822_address (tmp,adr);
        strcat (tmp,">");
  				/* send "RCPT TO" command */
        if (!(smtp_send (stream,"RCPT",tmp) == SMTPOK)) {
  	*error = T;		/* note that an error occurred */
--- 240,247 ----
        strcpy (tmp,"TO:<");	/* compose "RCPT TO:<return-path>" */
        rfc822_address (tmp,adr);
        strcat (tmp,">");
+       /* Chris T */
+       if(dsn) strcat(tmp," NOTIFY=SUCCESS");
  				/* send "RCPT TO" command */
        if (!(smtp_send (stream,"RCPT",tmp) == SMTPOK)) {
  	*error = T;		/* note that an error occurred */
***************
*** 299,304 ****
  	     && (!tmp[4] || tmp[4] == ' ')) {
        if (tmp[4]) stream->size = atoi (tmp+5);
        stream->ok_size = T;
      }
  				/* defined by SMTP Service Extensions */
      else if (j == (((long) 'S' << 24) + ((long) 'E' << 16) + ('N' << 8) + 'D')
--- 311,319 ----
  	     && (!tmp[4] || tmp[4] == ' ')) {
        if (tmp[4]) stream->size = atoi (tmp+5);
        stream->ok_size = T;
+     } /* Chris T */
+     else if (j == (((long) 'D' << 24) + ((long) 'S' << 16) + ('N' << 8))) {
+       stream->ok_dsn = T;
      }
  				/* defined by SMTP Service Extensions */
      else if (j == (((long) 'S' << 24) + ((long) 'E' << 16) + ('N' << 8) + 'D')
*** ./imap/non-ANSI/c-client/smtp.h	Wed Feb  7 00:13:04 1996
--- ./imap/non-ANSI/c-client/smtp.h	Tue Nov 26 12:00:33 1996
***************
*** 74,79 ****
    unsigned int ok_turn : 1;	/* supports TURN */
    unsigned int ok_size : 1;	/* supports SIZE */
    unsigned int ok_8bitmime : 1;	/* supports 8-bit MIME */
  } SMTPSTREAM;
  
  /* Coddle certain compilers' 6-character symbol limitation */
--- 74,81 ----
    unsigned int ok_turn : 1;	/* supports TURN */
    unsigned int ok_size : 1;	/* supports SIZE */
    unsigned int ok_8bitmime : 1;	/* supports 8-bit MIME */
+   /* Chris T */
+   unsigned int ok_dsn : 1;	/* supports DSN */
  } SMTPSTREAM;
  
  /* Coddle certain compilers' 6-character symbol limitation */
*** ./pine/init.c	Thu Jul 11 00:05:31 1996
--- ./pine/init.c	Tue Nov 26 12:00:57 1996
***************
*** 1351,1356 ****
  	{"enable-cruise-mode-delete",		F_ENABLE_TAB_DELETES},
  	{"enable-dot-files",			F_ENABLE_DOT_FILES},
  	{"enable-dot-folders",			F_ENABLE_DOT_FOLDERS},
  	{"enable-flag-cmd",			F_ENABLE_FLAG},
  	{"enable-flag-screen-implicitly",	F_FLAG_SCREEN_DFLT},
  	{"enable-full-header-cmd",		F_ENABLE_FULL_HDR},
--- 1351,1358 ----
  	{"enable-cruise-mode-delete",		F_ENABLE_TAB_DELETES},
  	{"enable-dot-files",			F_ENABLE_DOT_FILES},
  	{"enable-dot-folders",			F_ENABLE_DOT_FOLDERS},
+ 	/* Chris T */
+ 	{"enable-dsn",				F_ENABLE_DSN},
  	{"enable-flag-cmd",			F_ENABLE_FLAG},
  	{"enable-flag-screen-implicitly",	F_FLAG_SCREEN_DFLT},
  	{"enable-full-header-cmd",		F_ENABLE_FULL_HDR},
*** ./pine/other.c	Thu Jul 11 00:05:59 1996
--- ./pine/other.c	Tue Nov 26 12:00:58 1996
***************
*** 2442,2447 ****
  	  case F_ALLOW_TALK:
  	    return(h_config_allow_talk);
  #endif
  	  case F_ENABLE_MOUSE:
  	    return(h_config_enable_mouse);
  	  case F_ENABLE_XTERM_NEWMAIL:
--- 2442,2450 ----
  	  case F_ALLOW_TALK:
  	    return(h_config_allow_talk);
  #endif
+ 	  /* Chris T */
+ 	  case F_ENABLE_DSN:
+ 	    return(h_config_enable_dsn);
  	  case F_ENABLE_MOUSE:
  	    return(h_config_enable_mouse);
  	  case F_ENABLE_XTERM_NEWMAIL:
*** ./pine/pine.h	Thu Jul 11 19:15:44 1996
--- ./pine/pine.h	Tue Nov 26 12:00:58 1996
***************
*** 1155,1160 ****
  #define	F_ALLOW_GOTO		   82
  #define F_LAST_FEATURE		   82		 /* RESET WITH NEW FEATURES */
  
  #if (F_LAST_FEATURE > (LARGEST_BITMAP - 1))
     Whoa!  Too many features!
  #endif
--- 1155,1163 ----
  #define	F_ALLOW_GOTO		   82
  #define F_LAST_FEATURE		   82		 /* RESET WITH NEW FEATURES */
  
+ /* Chris T */
+ #define	F_ENABLE_DSN		   83
+ 
  #if (F_LAST_FEATURE > (LARGEST_BITMAP - 1))
     Whoa!  Too many features!
  #endif
*** ./pine/send.c	Mon Jul  8 19:10:50 1996
--- ./pine/send.c	Tue Nov 26 12:01:00 1996
***************
*** 164,169 ****
  static long	   send_bytes_sent, send_bytes_to_send;
  static char	  *sending_filter_requested;
  static char	   verbose_requested, background_requested;
  static METAENV	  *send_header = NULL;

--- 164,171 ----
  static long	   send_bytes_sent, send_bytes_to_send;
  static char	  *sending_filter_requested;
  static char	   verbose_requested, background_requested;
+ /* Chris T */
+ static char       dsn_requested;
  static METAENV	  *send_header = NULL;

***************
*** 2885,2890 ****
  		pf_nobody->writehdr  = 1;
  		pf_nobody->localcopy = 1;
  	    }
  
  #if	defined(BACKGROUND_POST) && defined(SIGCHLD)
  	    /*
--- 2887,2899 ----
  		pf_nobody->writehdr  = 1;
  		pf_nobody->localcopy = 1;
  	    }
+ 	    /* Chris T */
+ 	    if(dsn_requested) {
+ 		outgoing->dsn = 1;
+ 	    } else {
+ 		outgoing->dsn = 0;
+           }
+ 	
  
  #if	defined(BACKGROUND_POST) && defined(SIGCHLD)
  	    /*
***************
*** 3358,3363 ****
  send_exit_for_pico()
  {
      int	       i, rv, c, verbose_label = 0, bg_label = 0, old_suspend;
      char      *rstr = NULL, *p, *lc;
      void     (*redraw)() = ps_global->redrawer;
      ESCKEY_S   opts[9];
--- 3367,3374 ----
  send_exit_for_pico()
  {
      int	       i, rv, c, verbose_label = 0, bg_label = 0, old_suspend;
+ /* Chris T */
+     int      ct;
      char      *rstr = NULL, *p, *lc;
      void     (*redraw)() = ps_global->redrawer;
      ESCKEY_S   opts[9];
***************
*** 3520,3525 ****
  /* BUG: test kmpopped stuff? */
  	rv = radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
  			   'y', 'x', NO_HELP, RB_NORM);
  	if(rv == 'y'){				/* user ACCEPTS! */
  	    break;
  	}
--- 3531,3556 ----
  /* BUG: test kmpopped stuff? */
  	rv = radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
  			   'y', 'x', NO_HELP, RB_NORM);
+ /* Chris T */
+     
+         if(F_ON(F_ENABLE_DSN, ps_global) && rv != 'n' && rv != 'x') {
+                static ESCKEY_S dsn_opt[] = {
+                     {'n', 'n', "N", "No"},
+                     {'y', 'y', "Y", "Yes"},
+                     {-1, 0, NULL, NULL}
+                 };
+ 		ct = radio_buttons("Delivery notification ? ", -FOOTER_ROWS(ps_global), dsn_opt,
+ 			   'n', 'x', NO_HELP, RB_NORM);
+ 		if(ct == 'y') {
+ 			dsn_requested=1;
+ 		} else if(ct == 'n') {
+ 			dsn_requested=0;
+ 		} else if(ct == 'x') {
+ 			rv = 'x';
+ 		        rstr = "Send Cancelled";
+ 		        break;
+ 		}
+ 	}
  	if(rv == 'y'){				/* user ACCEPTS! */
  	    break;
  	}
***************
*** 3999,4005 ****
       * If the user's asked for it, and we find that the first text
       * part (attachments all get b64'd) is non-7bit, ask for ESMTP.
       */
!     if(F_ON(F_ENABLE_8BIT, ps_global) && (bp = first_text_8bit(body)))
         smtp_opts |= SOP_ESMTP;
  
  #ifdef	DEBUG
--- 4030,4037 ----
       * If the user's asked for it, and we find that the first text
       * part (attachments all get b64'd) is non-7bit, ask for ESMTP.
       */
! /* Chris T */
!     if((F_ON(F_ENABLE_8BIT, ps_global) && (bp = first_text_8bit(body))) || F_ON(F_ENABLE_DSN,ps_global))
         smtp_opts |= SOP_ESMTP;
  
  #ifdef	DEBUG
*** ./pine/pine.hlp	Fri Jun 21 01:45:20 1996
--- ./pine/pine.hlp	Tue Nov 26 12:35:20 1996
***************
*** 159,164 ****
   o Hooks for integral file transfer between desktop computer & Unix Pine
   o Builtin signature editor
   o Improved user feedback when Pine is busy or waiting
  
  This release also includes a stand-alone version of Pine's internal
  file browser, named \"pilot\" --for \"Pine's Lister Of Things\", and an
--- 159,165 ----
   o Hooks for integral file transfer between desktop computer & Unix Pine
   o Builtin signature editor
   o Improved user feedback when Pine is busy or waiting
+  o DSN support for sendmail
  
  This release also includes a stand-alone version of Pine's internal
  file browser, named \"pilot\" --for \"Pine's Lister Of Things\", and an
***************
*** 365,370 ****
   o enable-8bit-nntp-posting
   o enable-cruise-mode        (SPACE acts like tab when at end of msg)
   o enable-cruise-mode-delete (look at it once, then it disappears)
   o enable-dot-files          (file browser normally hides dot files)
   o enable-dot-folders        (folder lister normally hides them)
   o enable-flag-screen-implicitly
--- 366,372 ----
   o enable-8bit-nntp-posting
   o enable-cruise-mode        (SPACE acts like tab when at end of msg)
   o enable-cruise-mode-delete (look at it once, then it disappears)
+  o enable-dsn
   o enable-dot-files          (file browser normally hides dot files)
   o enable-dot-folders        (folder lister normally hides them)
   o enable-flag-screen-implicitly
***************
*** 5449,5454 ****
  Note, this feature relies on your system's mail transport agent or
  configured \"smtp-server\" having the negotiation mechanism introduced in
  \"Extended SMTP\" (ESMTP) and the specific extension called \"8BITMIME\". 
  
  ESMTP allows for graceful migration to upgraded mail transfer agents, but
  it is possible that this feature might cause problems for some servers. 

--- 5451,5472 ----
  Note, this feature relies on your system's mail transport agent or
  configured \"smtp-server\" having the negotiation mechanism introduced in
  \"Extended SMTP\" (ESMTP) and the specific extension called \"8BITMIME\". 
+ 
+ ESMTP allows for graceful migration to upgraded mail transfer agents, but
+ it is possible that this feature might cause problems for some servers. 
+ 
+ <End of help on this topic>
+ ====== h_config_enable_dsn =====
+         FEATURE: enable-dsn
+ 
+ This feature affects Pine's behavior when sending mail.  
+ 
+ DSN (Delivery Service Notification) sends a message back to
+ the sender when the message is delivered to the recipient.
+ 
+ Note, this feature relies on your system's mail transport agent or
+ configured \"smtp-server\" having the negotiation mechanism introduced in
+ \"Extended SMTP\" (ESMTP) and the specific extension called \"DSN\". 
  
  ESMTP allows for graceful migration to upgraded mail transfer agents, but
  it is possible that this feature might cause problems for some servers. 

---- Cut Here -------- Cut Here -------- Cut Here -------- Cut Here ----

-- 
------------------------------------------------------------------------------
		Chris Taylor:	[email-masked]  
	Coventry University, Computing Services.    Tel: (01203) 838641
------------------------------------------------------------------------------