From jester@core.usrlib.org  Tue Feb 19 18:56:59 2002
Return-Path: <jester@core.usrlib.org>
Received: from core.usrlib.org (cc2-24.217.114.114.charter-stl.com [24.217.114.114])
	by hub.freebsd.org (Postfix) with ESMTP id A491137B41F
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 19 Feb 2002 18:56:57 -0800 (PST)
Received: by core.usrlib.org (Postfix, from userid 1001)
	id 59D8AA811; Tue, 19 Feb 2002 20:56:47 -0600 (CST)
Message-Id: <20020220025647.59D8AA811@core.usrlib.org>
Date: Tue, 19 Feb 2002 20:56:47 -0600 (CST)
From: Andrew Hesford <jester@core.usrlib.org>
Reply-To: Andrew Hesford <ajh3@cec.wustl.edu>
To: FreeBSD-gnats-submit@freebsd.org
Cc: jester@core.usrlib.org
Subject: Maildir support in login(1)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         35129
>Category:       bin
>Synopsis:       Maildir support in login(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Tue Feb 19 19:00:03 PST 2002
>Closed-Date:    Fri Mar 8 20:13:24 PST 2002
>Last-Modified:  Fri Mar 08 20:14:38 PST 2002
>Originator:     Andrew Hesford
>Release:        FreeBSD 4.5-STABLE i386
>Organization:
>Environment:
System: FreeBSD core.usrlib.org 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 13 03:22:55 CST 2002 jester@core.usrlib.org:/usr/src/sys/compile/CORE i386


	
>Description:
	login(1) checks a user's mbox file upon login, and if it finds
	messages, reports to the user if there is mail (and whether or
	not it is new). For systems where Qmail Maildir is used for
	mail, this functionality is lost. I have produced a patch that
	will use the $MAILDIR/cur and $MAILDIR/new directories to 
	determine if a user has mail (and whether or not it is new). It
	will then report this on login, just as with mbox mail files.
>How-To-Repeat:
	On a system using Maildir, send messages to a user, then login
	as that user. Notice that login(1) does not report "You have new
	mail." Likewise, after reading and saving the messages, logging
	in will not produce a "You have mail." message.
>Fix:
	This diff can be applied to /usr/src/usr.bin/login/. It makes
	login(1) look for $MAILDIR if $MAIL is unset, and if $MAILDIR is
	defined, uses $MAILDIR/cur and $MAILDIR/new to find read and
	unread mail, respectively. Broken Maildir folders (missing cur
	and new) will simply cause login(1) to ignore the mail prompt.
	Should it be desired, the code can also be redone to print the
	message counts (new and previously-read messages). The following
	diff can be applied by changing to the /usr/src/usr.bin/login/
	directory and running `patch < login.diff`.

	:::: BEGIN login.diff ::::


*** login.c.orig	Tue Feb 19 20:25:37 2002
--- login.c	Tue Feb 19 20:25:47 2002
***************
*** 53,59 ****
--- 53,61 ----
  
  #include <sys/copyright.h>
  #include <sys/param.h>
+ #include <sys/types.h>
  #include <sys/stat.h>
+ #include <fts.h>
  #include <sys/socket.h>
  #include <sys/time.h>
  #include <sys/resource.h>
***************
*** 167,172 ****
--- 169,179 ----
  	char tname[sizeof(_PATH_TTY) + 10];
  	char *shell = NULL;
  	login_cap_t *lc = NULL;
+ 	int use_mdir = 0;
+ 	FTS *ftsp;
+ 	char *mdbuf[3];
+ 	FTSENT *ftse;
+ 	int mdopt = FTS_NOCHDIR | FTS_NOSTAT | FTS_LOGICAL;
  #ifdef USE_PAM
  	pid_t pid;
  	int e;
***************
*** 690,701 ****
  		cw = getenv("MAIL");	/* $MAIL may have been set by class */
  		if (cw != NULL)
  			strlcpy(tbuf, cw, sizeof(tbuf));
! 		else
! 			snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR,
! 			    pwd->pw_name);
! 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
  			(void)printf("You have %smail.\n",
  			    (st.st_mtime > st.st_atime) ? "new " : "");
  	}
  
  	login_close(lc);
--- 697,743 ----
  		cw = getenv("MAIL");	/* $MAIL may have been set by class */
  		if (cw != NULL)
  			strlcpy(tbuf, cw, sizeof(tbuf));
! 		else {
! 			cw = getenv("MAILDIR");
! 			if (cw != NULL) {
! 				strlcpy(tbuf, cw, sizeof(tbuf));
! 				use_mdir = 1;
! 			}
! 			else
! 				snprintf(tbuf, sizeof(tbuf), "%s/%s",
! 						_PATH_MAILDIR, pwd->pw_name);
! 		}
! 		if (!use_mdir && stat(tbuf, &st) == 0 && st.st_size != 0)
  			(void)printf("You have %smail.\n",
  			    (st.st_mtime > st.st_atime) ? "new " : "");
+ 		else if (use_mdir && stat(tbuf, &st) == 0 &&
+ 				(st.st_mode & S_IFDIR) != 0) {
+ 			mdbuf[0] = (char*)malloc(sizeof(tbuf));
+ 			bzero(mdbuf[0], sizeof(mdbuf[0]));
+ 			mdbuf[1] = (char*)malloc(sizeof(tbuf));
+ 			bzero(mdbuf[1], sizeof(mdbuf[1]));
+ 			snprintf(mdbuf[0], sizeof(tbuf), "%s/new", tbuf);
+ 			snprintf(mdbuf[1], sizeof(tbuf), "%s/cur", tbuf);
+ 			if ((ftsp = fts_open(mdbuf, mdopt, NULL)) != NULL) {
+ 				int ncount = 0, ocount = 0;
+ 				ftse = fts_read(ftsp);
+ 				while ((ftse = fts_read(ftsp)) != NULL &&
+ 						strncmp(ftse->fts_name, "new",
+ 							sizeof(char)*4) != 0)
+ 					ncount++;
+ 				ftse = fts_read(ftsp);
+ 				while ((ftse = fts_read(ftsp)) != NULL &&
+ 						strncmp(ftse->fts_name, "cur",
+ 							sizeof(char)*4) != 0)
+ 					ocount++;
+ 				if (ncount > 0)
+ 					(void)printf("You have new mail.\n");
+ 				else if (ocount > 0)
+ 					(void)printf("You have mail.\n");
+ 				fts_close(ftsp);
+ 			}
+ 		}
+ 			
  	}
  
  	login_close(lc);

*** login.1.orig	Tue Feb 19 20:25:57 2002
--- login.1	Tue Feb 19 20:26:01 2002
***************
*** 173,179 ****
  login account records
  .It Pa /var/mail/user
  system mailboxes
! .It Pa \&.hushlogin
  makes login quieter
  .It Pa /etc/auth.conf
  configure authentication services
--- 173,181 ----
  login account records
  .It Pa /var/mail/user
  system mailboxes
! .It Pa ~/Maildir
! Maildir mailbox (used if $MAIL is unset)
! .It Pa ~/\&.hushlogin
  makes login quieter
  .It Pa /etc/auth.conf
  configure authentication services


>Release-Note:
>Audit-Trail:

From: Andrew Hesford <jester@core.usrlib.org>
To: freebsd-gnats-submit@FreeBSD.org, ajh3@cec.wustl.edu
Cc:  
Subject: Re: bin/35129: Maildir support in login(1)
Date: Tue, 19 Feb 2002 23:53:39 -0600

 After some extra thought, I have changed the patch a bit. Whereas before
 login(1) would go through $MAILDIR/new and count every message, and then
 count every message in $MAILDIR/cur, I have reduced it to counting at
 most four directory entries.
 
 Now I simply call fts_read() twice on $MAILDIR/new to see if there are
 files in that directory. If there are, each call to fts_read() will
 produce an FTSENT structure with a different fts_name field: the first
 will be the directory, and the second will be some file. If there are no
 files in the directory, each FTSENT structure will contain the directory
 name in its fts_name field.
 
 If there are files in $MAILDIR/new, login(1) prints "You have new mail."
 and forgets about Maildir. Otherwise, it repeats the fts_read() process
 for $MAILDIR/cur.
 
 The reasoning behind the first patch was to count new and old messages,
 to display a count; however, I decided against that but did not change
 the process. After some secondary thought I realized that this new
 method is superior, because at worst-case there are four fts_read()
 calls.
 
 I don't think there are bugs in this... I'll leave that to everybody
 else to determine. :) I'm sure many people who rely on Maildir will find
 this useful (or a superior scheme if you can think of one).
 
 ::: BEGIN login.diff :::
 
 *** login.c.orig	Tue Feb 19 23:35:27 2002
 --- login.c	Tue Feb 19 23:39:03 2002
 ***************
 *** 53,59 ****
 --- 53,61 ----
   
   #include <sys/copyright.h>
   #include <sys/param.h>
 + #include <sys/types.h>
   #include <sys/stat.h>
 + #include <fts.h>
   #include <sys/socket.h>
   #include <sys/time.h>
   #include <sys/resource.h>
 ***************
 *** 167,172 ****
 --- 169,179 ----
   	char tname[sizeof(_PATH_TTY) + 10];
   	char *shell = NULL;
   	login_cap_t *lc = NULL;
 + 	int use_mdir = 0;
 + 	FTS *ftsp;
 + 	char *mdbuf[2];
 + 	FTSENT *ftse[2];
 + 	int mdopt = FTS_NOCHDIR | FTS_NOSTAT | FTS_LOGICAL;
   #ifdef USE_PAM
   	pid_t pid;
   	int e;
 ***************
 *** 690,701 ****
   		cw = getenv("MAIL");	/* $MAIL may have been set by class */
   		if (cw != NULL)
   			strlcpy(tbuf, cw, sizeof(tbuf));
 ! 		else
 ! 			snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR,
 ! 			    pwd->pw_name);
 ! 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
   			(void)printf("You have %smail.\n",
   			    (st.st_mtime > st.st_atime) ? "new " : "");
   	}
   
   	login_close(lc);
 --- 697,745 ----
   		cw = getenv("MAIL");	/* $MAIL may have been set by class */
   		if (cw != NULL)
   			strlcpy(tbuf, cw, sizeof(tbuf));
 ! 		else {
 ! 			cw = getenv("MAILDIR");
 ! 			if (cw != NULL) {
 ! 				strlcpy(tbuf, cw, sizeof(tbuf));
 ! 				use_mdir = 1;
 ! 			}
 ! 			else
 ! 				snprintf(tbuf, sizeof(tbuf), "%s/%s",
 ! 						_PATH_MAILDIR, pwd->pw_name);
 ! 		}
 ! 		if (!use_mdir && stat(tbuf, &st) == 0 && st.st_size != 0)
   			(void)printf("You have %smail.\n",
   			    (st.st_mtime > st.st_atime) ? "new " : "");
 + 		/*
 + 		 * The only way to check Maildir for messages is to read
 + 		 * the directories... use fts(3) for this.
 + 		 */
 + 		else if (use_mdir && stat(tbuf, &st) == 0 &&
 + 				(st.st_mode & S_IFDIR) != 0) {
 + 			mdbuf[0] = (char*)malloc(sizeof(tbuf));
 + 			bzero(mdbuf[0], sizeof(tbuf));
 + 			snprintf(mdbuf[0], sizeof(tbuf), "%s/new", tbuf);
 + 			if ((ftsp = fts_open(mdbuf, mdopt, NULL)) != NULL) {
 + 			    ftse[0] = fts_read(ftsp);
 + 			    ftse[1] = fts_read(ftsp);
 + 			    fts_close(ftsp);
 + 			    if (strcmp(ftse[0]->fts_name,
 + 					ftse[1]->fts_name) != 0)
 + 			        (void)printf("You have new mail.\n");
 + 			    else {
 + 			        snprintf(mdbuf[0], sizeof(tbuf),
 + 						"%s/cur", tbuf);
 + 				if ((ftsp=fts_open(mdbuf,mdopt, NULL))!=NULL) {
 + 				    ftse[0] = fts_read(ftsp);
 + 				    ftse[1] = fts_read(ftsp);
 + 				    fts_close(ftsp);
 + 				    if (strcmp(ftse[0]->fts_name,
 + 						ftse[1]->fts_name) != 0)
 + 				        (void)printf("You have mail.\n");
 + 				}
 + 			    }
 + 			}
 + 		}
   	}
   
   	login_close(lc);
 *** login.1.orig	Tue Feb 19 23:35:27 2002
 --- login.1	Tue Feb 19 23:38:28 2002
 ***************
 *** 173,179 ****
   login account records
   .It Pa /var/mail/user
   system mailboxes
 ! .It Pa \&.hushlogin
   makes login quieter
   .It Pa /etc/auth.conf
   configure authentication services
 --- 173,181 ----
   login account records
   .It Pa /var/mail/user
   system mailboxes
 ! .It Pa ~/Maildir
 ! Maildir mailbox (used if $MAIL is unset)
 ! .It Pa ~/\&.hushlogin
   makes login quieter
   .It Pa /etc/auth.conf
   configure authentication services
 
 ::: END login.diff :::
 -- 
 Andrew Hesford, Washington University
 ajh3@cec.wustl.edu, jester@usrlib.org
 :- Fortune of the Moment -:
 I've given up reading books; I find it takes my mind off myself.

From: Peter Pentchev <roam@ringlet.net>
To: Andrew Hesford <ajh3@cec.wustl.edu>
Cc: FreeBSD-gnats-submit@freebsd.org, jester@core.usrlib.org
Subject: Re: bin/35129: Maildir support in login(1)
Date: Wed, 20 Feb 2002 09:16:23 +0200

 On Tue, Feb 19, 2002 at 08:56:47PM -0600, Andrew Hesford wrote:
 > 
 > >Number:         35129
 > >Category:       bin
 > >Synopsis:       Maildir support in login(1)
 > >Originator:     Andrew Hesford
 > 	
 > >Description:
 > 	login(1) checks a user's mbox file upon login, and if it finds
 > 	messages, reports to the user if there is mail (and whether or
 > 	not it is new). For systems where Qmail Maildir is used for
 > 	mail, this functionality is lost. I have produced a patch that
 > 	will use the $MAILDIR/cur and $MAILDIR/new directories to 
 > 	determine if a user has mail (and whether or not it is new). It
 > 	will then report this on login, just as with mbox mail files.
 
 With all due respect for your work (and thank you for it!), I believe
 that this might be better done as a PAM module, so it could be used
 by other login methods not involving login(1) (like SSH with UseLogin
 set to 'no', as I do on most of my machines).
 
 I started work on a pam_mailcheck module a while ago, but Real Life(tm)
 and Real Work(tm) kind of overtook it..  I think that your patches
 to login(1) might as well serve as a nice prod :)  And in the meantime,
 thanks again for your patches - they may serve well until pam_mailcheck
 is ready :)
 
 G'luck,
 Peter
 
 -- 
 Peter Pentchev	roam@ringlet.net	roam@FreeBSD.org
 PGP key:	http://people.FreeBSD.org/~roam/roam.key.asc
 Key fingerprint	FDBA FD79 C26F 3C51 C95E  DF9E ED18 B68D 1619 4553
 I've heard that this sentence is a rumor.
State-Changed-From-To: open->closed 
State-Changed-By: dd 
State-Changed-When: Fri Mar 8 20:13:24 PST 2002 
State-Changed-Why:  
As Peter points out, this probably doesn't belong in login.  Besides, 
if we add this, should we also add support for mh mailboxes?  How about 
<some great, new mailbox formar>?  This sort of thing should be generalized 
(Peter suggests PAM, which seems appropriate) so that modifications to login 
aren't necessary every time someone comes up with a new mailbox format. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=35129 
>Unformatted:
