NetBSD Problem Report #47577

From www@NetBSD.org  Mon Feb 18 14:22:33 2013
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	by www.NetBSD.org (Postfix) with ESMTP id 3423563E500
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 18 Feb 2013 14:22:33 +0000 (UTC)
Message-Id: <20130218142231.41CE363E500@www.NetBSD.org>
Date: Mon, 18 Feb 2013 14:22:31 +0000 (UTC)
From: sdaoden@gmail.com
Reply-To: sdaoden@gmail.com
To: gnats-bugs@NetBSD.org
Subject: Mail(1)/mail(1)/mailx(1) gets stuck when current folder becomes accessible
X-Send-Pr-Version: www-1.0

>Number:         47577
>Category:       bin
>Synopsis:       Mail(1)/mail(1)/mailx(1) gets stuck when current folder becomes accessible
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 18 14:25:00 +0000 2013
>Last-Modified:  Mon Feb 25 19:20:04 +0000 2013
>Originator:     Steffen Nurpmeso
>Release:        6.99.16
>Organization:
>Environment:
NetBSD nhead 6.99.16 NetBSD 6.99.16 (GENERIC) #0: Mon Feb 11 21:12:26 UTC 2013  builds@b6.netbsd.org:/home/builds/ab/HEAD/amd64/201302111840Z-obj/home/builds/ab/HEAD/src/sys/arch/amd64/compile/GENERIC amd64

>Description:
Yes, and i forgot this one.
If you open a folder with a relative path, use the cd command to change the current working directory, then any action that needs to update the opened folder (as opposed to the temporary MBOX; e.g., switching to a different folder) will fail and claim that the opened folder is not accessible.
You need to cd to a path which turns the relative folder path accessible again to be able to continue.
This is just one facet of a basic architectural problem of Berkeley Mail, i.e., concurrent deletion of the current folder etc. still bails, but for this particular aspect the solution is easy.
>How-To-Repeat:
See desc.
>Fix:
--- cmd3.c.orig	2013-02-18 13:36:32.000000000 +0100
+++ cmd3.c	2013-02-18 13:35:36.000000000 +0100
@@ -201,7 +201,7 @@ help(void *v __unused)
 PUBLIC int
 schdir(void *v)
 {
-	char **arglist;
+	char rpath[PATHSIZE], **arglist;
 	const char *cp;

 	arglist = v;
@@ -210,6 +210,15 @@ schdir(void *v)
 	else
 		if ((cp = expand(*arglist)) == NULL)
 			return 1;
+
+	if (mailname[0] != '/') {
+		if (realpath(mailname, rpath) == NULL) {
+			perror("Cannot canonicalize path of current folder");
+			return 1;
+		}
+		(void)stpcpy(mailname, rpath);
+	}
+
 	if (chdir(cp) < 0) {
 		warn("%s", cp);
 		return 1;

>Audit-Trail:
From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Cc: 
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current folder becomes accessible
Date: Mon, 18 Feb 2013 10:49:26 -0500

 On Feb 18,  2:25pm, sdaoden@gmail.com (sdaoden@gmail.com) wrote:
 -- Subject: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current folde

 | If you open a folder with a relative path, use the cd command to change the current working directory, then any action that needs to update the opened folder (as opposed to the temporary MBOX; e.g., switching to a different folder) will fail and claim that the opened folder is not accessible.
 | You need to cd to a path which turns the relative folder path accessible again to be able to continue.
 | This is just one facet of a basic architectural problem of Berkeley Mail, i.e., concurrent deletion of the current folder etc. still bails, but for this particular aspect the solution is easy.

 I think it is better to canonicalize the name when the name is set? No?

 christos

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, sdaoden@gmail.com
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current
 folder becomes accessible
Date: Mon, 18 Feb 2013 19:19:07 +0100

 christos@zoulas.com (Christos Zoulas) wrote:
  | On Feb 18,  2:25pm, sdaoden@gmail.com (sdaoden@gmail.com) wrote:
  | -- Subject: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current =
 \
  |folde
  |=20
  || If you open a folder with a relative path, use the cd command to change=
  \
  |  the current working directory, then any action that needs to update the=
  \
  |  opened folder (as opposed to the temporary MBOX; e.g., switching to a \
  |  different folder) will fail and claim that the opened folder is not \
  |  accessible.
  || You need to cd to a path which turns the relative folder path accessibl=
 e \
  |  again to be able to continue.
  || This is just one facet of a basic architectural problem of Berkeley Mai=
 l, \
  |  i.e., concurrent deletion of the current folder etc. still bails, but f=
 or \
  |  this particular aspect the solution is easy.
  |=20
  | I think it is better to canonicalize the name when the name is set? No?

 Sure; "fi" etc. then always show an absolute path, which is often
 annoying imho, especially on 80 column terminals, though.
 I as a user would then really like to see some
 "/path1/[...]/folder" instead of "p1/p2/p3/p4/folder".  I, e.g.,
 often have problems with mksh(1) because that radically cuts job
 paths at 40 (or so) characters, so that i sometimes have to check
 ps(1) to know which job relates to what command.

 So then i would possibly consider a basename(3)/realpath(3) tuple
 (or, better, a path and an offset) from the begin on, the one for
 display and the other for file operations.

 Possibly overkill; I think even then i would delay the realpath(3)
 until this very command is used, because (1) it is very expensive
 (not that expensive with a getcwd() syscall, but still), and (2)
 it is completely useless unless the cd command is used.  I've just
 encountered the problem that the Berkeley codebase stucks
 completely unless the open folder comes into sight again, and that
 was an at-a-glance solution for this particular problem, which
 works automatically and without user interaction.

 I haven't considered yet the basename(3)/realpath(3) solution;
 hmmm; i think i look into that tomorrow, and come back with an
 alternative patch if it's easy to implement -- i couldn't tell how
 many places would need to be changed right now.

  | christos

 --steffen

From: christos@zoulas.com (Christos Zoulas)
To: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>, gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current folder becomes accessible
Date: Mon, 18 Feb 2013 13:51:03 -0500

 On Feb 18,  7:19pm, sdaoden@gmail.com (Steffen "Daode" Nurpmeso) wrote:
 -- Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current f

 | Sure; "fi" etc. then always show an absolute path, which is often
 | annoying imho, especially on 80 column terminals, though.

 So keep a "displayname" and a "resolvedname" so you always show the
 displayname. It is strange that the name will change when the user cds?
 Don't you agree?

 christos

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: christos@zoulas.com (Christos Zoulas)
Cc: gnats-admin@netbsd.org, gnats-bugs@NetBSD.org,
 netbsd-bugs@netbsd.org
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current
 folder becomes accessible
Date: Mon, 18 Feb 2013 20:07:55 +0100

 christos@zoulas.com (Christos Zoulas) wrote:
  |On Feb 18,  7:19pm, sdaoden@gmail.com (Steffen "Daode" Nurpmeso) wrote:
  |-- Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current \
  |f
  |
  || Sure; "fi" etc. then always show an absolute path, which is often
  || annoying imho, especially on 80 column terminals, though.
  |
  |So keep a "displayname" and a "resolvedname" so you always show the
  |displayname. It is strange that the name will change when the user cds?
  |Don't you agree?

 Sound good to me.
 I'll take a look tomorrow.

  |christos

 --steffen

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current
 folder becomes accessible
Date: Mon, 18 Feb 2013 21:54:39 +0100

 christos@zoulas.com (Christos Zoulas) wrote:
  || Sure; "fi" etc. then always show an absolute path, which is often
  || annoying imho, especially on 80 column terminals, though.
  |=20
  | So keep a "displayname" and a "resolvedname" so you always show the
  | displayname. It is strange that the name will change when the user cds?
  | Don't you agree?

 I took a quick look, and i think it'll be more complicated.
 I also think that my solution is too simple minded, for the
 Berkeley codebase as such, at least because lex.c:newfileinfo()
 tries to abbreviate folders which have the same path prefix as the
 value of the *folder* option to "+BOX"; all this is thus
 inherently broken ... so to say.

 I'll continue tomorrow, but append a diff that fixes usage of an
 inner-scope buffer that is used outside the scope.

  | christos

 --steffen

 --- lex.c.orig	2013-02-18 17:38:31.000000000 +0100
 +++ lex.c	2013-02-18 18:05:47.000000000 +0100
 @@ -974,7 +974,7 @@ newfileinfo(int omsgCount)
  {
  	struct message *mp;
  	int d, n, s, t, u, mdot;
 -	char fname[PATHSIZE];
 +	char fname[PATHSIZE], zname[PATHSIZE];
  	char *ename;
 =20
  	/*
 @@ -1021,7 +1021,6 @@ newfileinfo(int omsgCount)
  	}
  	ename =3D mailname;
  	if (getfold(fname, sizeof(fname)) >=3D 0) {
 -		char zname[PATHSIZE];
  		size_t l;
  		l =3D strlen(fname);
  		if (l < sizeof(fname) - 1)

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current
 folder becomes accessible
Date: Tue, 19 Feb 2013 18:10:12 +0100

  |The following reply was made to PR bin/47577; it has been noted by GNATS.
  |
  |From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
  |To: christos@zoulas.com (Christos Zoulas)
  |Cc: gnats-admin@netbsd.org, gnats-bugs@NetBSD.org,
  | netbsd-bugs@netbsd.org
  |Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current
  | folder becomes accessible
  |Date: Mon, 18 Feb 2013 20:07:55 +0100
  |
  | christos@zoulas.com (Christos Zoulas) wrote:
  ||On Feb 18,  7:19pm, sdaoden@gmail.com (Steffen "Daode" Nurpmeso) wrote:
  ||-- Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when \
  |  current \
  ||f
  ||
  ||| Sure; "fi" etc. then always show an absolute path, which is often
  ||| annoying imho, especially on 80 column terminals, though.
  ||
  ||So keep a "displayname" and a "resolvedname" so you always show the
  ||displayname. It is strange that the name will change when the user cds?
  ||Don't you agree?

 This seems to work after some testing; the actual display length
 can be controlled by adjusting sizeof(displayname).
 Forgive if i f..d up something, but don't think so.
 Ciao,

 --steffen

 --- fio.c.orig	2013-02-19 01:06:53.000000000 +0100
 +++ fio.c	2013-02-19 03:00:56.000000000 +0100
 @@ -392,14 +392,18 @@ fsize(FILE *iob)
  PUBLIC int
  getfold(char *name, size_t namesize)
  {
 +	char unres[PATHSIZE], res[PATHSIZE];
  	char *folder;
 =20
  	if ((folder =3D value(ENAME_FOLDER)) =3D=3D NULL)
  		return -1;
  	if (*folder =3D=3D '/')
 -		(void)strlcpy(name, folder, namesize);
 +		(void)strlcpy(unres, folder, sizeof unres);
  	else
 -		(void)snprintf(name, namesize, "%s/%s", homedir, folder);
 +		(void)snprintf(unres, sizeof unres, "%s/%s", homedir, folder);
 +	if (realpath(unres, res) =3D=3D NULL)
 +		err(EXIT_FAILURE, "Can't canonicalize *folder* `%s'", unres);
 +	(void)strlcpy(name, res, namesize);
  	return 0;
  }
 =20
 --- glob.h.orig	2013-02-18 17:39:46.000000000 +0100
 +++ glob.h	2013-02-19 03:02:37.000000000 +0100
 @@ -59,6 +59,7 @@ EXTERN FILE	*otf;				/* Output temp file
  EXTERN int	image;				/* File descriptor for image of msg */
  EXTERN FILE	*input;				/* Current command input file */
  EXTERN char	mailname[PATHSIZE];		/* Name of current file */
 +EXTERN char	displayname[80];		/* Prettyfied for display */
  EXTERN char	prevfile[PATHSIZE];		/* Name of previous file */
  EXTERN char	*tmpdir;			/* Path name of temp directory */
  EXTERN char	*homedir;			/* Path name of home directory */
 --- lex.c.orig	2013-02-18 17:38:31.000000000 +0100
 +++ lex.c	2013-02-19 03:05:58.000000000 +0100
 @@ -141,6 +141,45 @@ file_leak_check(void)
  }
  #endif /* DEBUG_FILE_LEAK */
 =20
 +static void
 +_update_mailname(char const *name)
 +{
 +	char tbuf[PATHSIZE];
 +	size_t l;
 +
 +	if (realpath(name, mailname) =3D=3D NULL)
 +		err(EXIT_FAILURE, "Can't canonicalize `%s'", name);
 +
 +	if (getfold(tbuf, sizeof tbuf) >=3D 0) {
 +		l =3D strlen(tbuf);
 +		if (l < sizeof(tbuf) - 1)
 +			tbuf[l++] =3D '/';
 +		if (strncmp(tbuf, mailname, l) =3D=3D 0) {
 +			char const *sep =3D "", *cp =3D mailname + l;
 +
 +			l =3D strlen(cp);
 +			if (l >=3D sizeof displayname) {
 +				cp +=3D l;
 +				cp -=3D sizeof(displayname) - 5;
 +				sep =3D "...";
 +			}
 +			(void)snprintf(displayname, sizeof displayname,
 +				"+%s%s", sep, cp);
 +			goto jleave;
 +		}
 +	}
 +
 +	l =3D strlen(mailname);
 +	if (l < sizeof displayname)
 +		strcpy(displayname, mailname);
 +	else {
 +		l -=3D sizeof(displayname) - 4 - sizeof(displayname) / 3;
 +		(void)snprintf(displayname, sizeof displayname, "%.*s...%s",
 +			(int)sizeof(displayname) / 3, mailname, mailname + l);
 +	}
 +jleave:	;
 +}
 +
  /*
   * Set the size of the message vector used to construct argument
   * lists to message list functions.
 @@ -232,11 +271,8 @@ setfile(const char *name)
  	shudclob =3D 1;
  	edit =3D isedit;
  	(void)strcpy(prevfile, mailname);
 -	if (name !=3D mailname) {
 -		(void)strcpy(mailname, name);
 -
 -		(void)strcpy(mailname, name);
 -	}
 +	if (name !=3D mailname)
 +		_update_mailname(name);
  	mailsize =3D fsize(ibuf);
  	(void)snprintf(tempname, sizeof(tempname),
  	    "%s/mail.RxXXXXXXXXXX", tmpdir);
 @@ -975,7 +1011,6 @@ newfileinfo(int omsgCount)
  	struct message *mp;
  	int d, n, s, t, u, mdot;
  	char fname[PATHSIZE];
 -	char *ename;
 =20
  	/*
  	 * Figure out where to set the 'dot'.  Use the first new or
 @@ -1019,23 +1054,10 @@ newfileinfo(int omsgCount)
  		if (mp->m_flag & MTAGGED)
  			t++;
  	}
 -	ename =3D mailname;
 -	if (getfold(fname, sizeof(fname)) >=3D 0) {
 -		char zname[PATHSIZE];
 -		size_t l;
 -		l =3D strlen(fname);
 -		if (l < sizeof(fname) - 1)
 -			fname[l++] =3D '/';
 -		if (strncmp(fname, mailname, l) =3D=3D 0) {
 -			(void)snprintf(zname, sizeof(zname), "+%s",
 -			    mailname + l);
 -			ename =3D zname;
 -		}
 -	}
  	/*
  	 * Display the statistics.
  	 */
 -	(void)printf("\"%s\": ", ename);
 +	(void)printf("\"%s\": ", displayname);
  	{
  		int cnt =3D get_abs_msgCount();
  		(void)printf("%d message%s", cnt, cnt =3D=3D 1 ? "" : "s");

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: bin/47577: Mail(1)/mail(1)/mailx(1) gets stuck when current
 folder becomes accessible
Date: Tue, 19 Feb 2013 18:26:49 +0100

 aaah, i get grazy, wrong lex.c.orig.

 --- fio.c.orig	2013-02-19 01:06:53.000000000 +0100
 +++ fio.c	2013-02-19 03:00:56.000000000 +0100
 @@ -392,14 +392,18 @@ fsize(FILE *iob)
  PUBLIC int
  getfold(char *name, size_t namesize)
  {
 +	char unres[PATHSIZE], res[PATHSIZE];
  	char *folder;
 =20
  	if ((folder =3D value(ENAME_FOLDER)) =3D=3D NULL)
  		return -1;
  	if (*folder =3D=3D '/')
 -		(void)strlcpy(name, folder, namesize);
 +		(void)strlcpy(unres, folder, sizeof unres);
  	else
 -		(void)snprintf(name, namesize, "%s/%s", homedir, folder);
 +		(void)snprintf(unres, sizeof unres, "%s/%s", homedir, folder);
 +	if (realpath(unres, res) =3D=3D NULL)
 +		err(EXIT_FAILURE, "Can't canonicalize *folder* `%s'", unres);
 +	(void)strlcpy(name, res, namesize);
  	return 0;
  }
 =20
 --- glob.h.orig	2013-02-18 17:39:46.000000000 +0100
 +++ glob.h	2013-02-19 03:02:37.000000000 +0100
 @@ -59,6 +59,7 @@ EXTERN FILE	*otf;				/* Output temp file
  EXTERN int	image;				/* File descriptor for image of msg */
  EXTERN FILE	*input;				/* Current command input file */
  EXTERN char	mailname[PATHSIZE];		/* Name of current file */
 +EXTERN char	displayname[80];		/* Prettyfied for display */
  EXTERN char	prevfile[PATHSIZE];		/* Name of previous file */
  EXTERN char	*tmpdir;			/* Path name of temp directory */
  EXTERN char	*homedir;			/* Path name of home directory */
 --- lex.c.orig	2013-02-19 03:23:22.000000000 +0100
 +++ lex.c	2013-02-19 03:05:58.000000000 +0100
 @@ -141,6 +141,45 @@ file_leak_check(void)
  }
  #endif /* DEBUG_FILE_LEAK */
 =20
 +static void
 +_update_mailname(char const *name)
 +{
 +	char tbuf[PATHSIZE];
 +	size_t l;
 +
 +	if (realpath(name, mailname) =3D=3D NULL)
 +		err(EXIT_FAILURE, "Can't canonicalize `%s'", name);
 +
 +	if (getfold(tbuf, sizeof tbuf) >=3D 0) {
 +		l =3D strlen(tbuf);
 +		if (l < sizeof(tbuf) - 1)
 +			tbuf[l++] =3D '/';
 +		if (strncmp(tbuf, mailname, l) =3D=3D 0) {
 +			char const *sep =3D "", *cp =3D mailname + l;
 +
 +			l =3D strlen(cp);
 +			if (l >=3D sizeof displayname) {
 +				cp +=3D l;
 +				cp -=3D sizeof(displayname) - 5;
 +				sep =3D "...";
 +			}
 +			(void)snprintf(displayname, sizeof displayname,
 +				"+%s%s", sep, cp);
 +			goto jleave;
 +		}
 +	}
 +
 +	l =3D strlen(mailname);
 +	if (l < sizeof displayname)
 +		strcpy(displayname, mailname);
 +	else {
 +		l -=3D sizeof(displayname) - 4 - sizeof(displayname) / 3;
 +		(void)snprintf(displayname, sizeof displayname, "%.*s...%s",
 +			(int)sizeof(displayname) / 3, mailname, mailname + l);
 +	}
 +jleave:	;
 +}
 +
  /*
   * Set the size of the message vector used to construct argument
   * lists to message list functions.
 @@ -233,7 +272,7 @@ setfile(const char *name)
  	edit =3D isedit;
  	(void)strcpy(prevfile, mailname);
  	if (name !=3D mailname)
 -		(void)strcpy(mailname, name);
 +		_update_mailname(name);
  	mailsize =3D fsize(ibuf);
  	(void)snprintf(tempname, sizeof(tempname),
  	    "%s/mail.RxXXXXXXXXXX", tmpdir);
 @@ -972,7 +1011,6 @@ newfileinfo(int omsgCount)
  	struct message *mp;
  	int d, n, s, t, u, mdot;
  	char fname[PATHSIZE];
 -	char *ename;
 =20
  	/*
  	 * Figure out where to set the 'dot'.  Use the first new or
 @@ -1016,23 +1054,10 @@ newfileinfo(int omsgCount)
  		if (mp->m_flag & MTAGGED)
  			t++;
  	}
 -	ename =3D mailname;
 -	if (getfold(fname, sizeof(fname)) >=3D 0) {
 -		char zname[PATHSIZE];
 -		size_t l;
 -		l =3D strlen(fname);
 -		if (l < sizeof(fname) - 1)
 -			fname[l++] =3D '/';
 -		if (strncmp(fname, mailname, l) =3D=3D 0) {
 -			(void)snprintf(zname, sizeof(zname), "+%s",
 -			    mailname + l);
 -			ename =3D zname;
 -		}
 -	}
  	/*
  	 * Display the statistics.
  	 */
 -	(void)printf("\"%s\": ", ename);
 +	(void)printf("\"%s\": ", displayname);
  	{
  		int cnt =3D get_abs_msgCount();
  		(void)printf("%d message%s", cnt, cnt =3D=3D 1 ? "" : "s");

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47577 CVS commit: src/usr.bin/mail
Date: Tue, 19 Feb 2013 12:43:33 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Tue Feb 19 17:43:33 UTC 2013

 Modified Files:
 	src/usr.bin/mail: fio.c glob.h lex.c

 Log Message:
 PR/47577: Steffen "Daode" Nurpmeso: Keep a resolved folder name together
 with a display name in order to keep track of current state when the directory
 is changed.


 To generate a diff of this commit:
 cvs rdiff -u -r1.36 -r1.37 src/usr.bin/mail/fio.c
 cvs rdiff -u -r1.12 -r1.13 src/usr.bin/mail/glob.h
 cvs rdiff -u -r1.41 -r1.42 src/usr.bin/mail/lex.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: PR/47577 CVS commit: src/usr.bin/mail
Date: Wed, 20 Feb 2013 13:44:50 +0100

 Hello,

  | Committed By:	christos
  | Date:		Tue Feb 19 17:43:33 UTC 2013
  |=20
  | Modified Files:
  | 	src/usr.bin/mail: fio.c glob.h lex.c
  |=20
  | Log Message:
  | PR/47577: Steffen "Daode" Nurpmeso: Keep a resolved folder name together
  | with a display name in order to keep track of current state when the \
  |directory
  | is changed.

 I'm not happy with the code after all -- it doesn't recognize
 concurrent changes of the *folder* option (and assign() and
 unset() do not check for special variables to perform necessary
 updates).
 So here is a refinement which is of smaller code size and prints
 correct results even if *folder* is modified on the fly.
 Thanks

 --steffen

 --- fio.c.orig	2013-02-19 06:58:25.000000000 +0100
 +++ fio.c	2013-02-19 07:09:47.000000000 +0100
 @@ -397,15 +397,15 @@ getfold(char *name, size_t namesize)
 =20
  	if ((folder =3D value(ENAME_FOLDER)) =3D=3D NULL)
  		return -1;
 -	if (*folder =3D=3D '/')
 -		(void)strlcpy(unres, folder, sizeof(unres));
 -	else
 +	if (*folder !=3D '/') {
  		(void)snprintf(unres, sizeof(unres), "%s/%s", homedir, folder);
 -	if (realpath(unres, res) =3D=3D NULL) {
 -		warn("Can't canonicalize folder `%s'", unres);
 -		(void)strlcpy(name, unres, namesize);
 -	} else
 -		(void)strlcpy(name, res, namesize);
 +		folder =3D unres;
 +	}
 +	if (realpath(folder, res) =3D=3D NULL)
 +		warn("Can't canonicalize folder `%s'", folder);
 +	else
 +		folder =3D res;
 +	(void)strlcpy(name, folder, namesize);
  	return 0;
  }
 =20
 --- lex.c.orig	2013-02-19 06:58:25.000000000 +0100
 +++ lex.c	2013-02-19 07:09:47.000000000 +0100
 @@ -147,7 +147,8 @@ update_mailname(const char *name)
  	char tbuf[PATHSIZE];
  	size_t l;
 =20
 -	if (realpath(name, mailname) =3D=3D NULL) {
 +	/* Don't realpath(3) if it's only an update request */
 +	if (name !=3D NULL && realpath(name, mailname) =3D=3D NULL) {
  		warn("Can't canonicalize `%s'", name);
  		return;
  	}
 @@ -272,8 +273,7 @@ setfile(const char *name)
  	shudclob =3D 1;
  	edit =3D isedit;
  	(void)strcpy(prevfile, mailname);
 -	if (name !=3D mailname)
 -		update_mailname(name);
 +	update_mailname(name !=3D mailname ? name : NULL);
  	mailsize =3D fsize(ibuf);
  	(void)snprintf(tempname, sizeof(tempname),
  	    "%s/mail.RxXXXXXXXXXX", tmpdir);
 @@ -1057,6 +1057,7 @@ newfileinfo(int omsgCount)
  	/*
  	 * Display the statistics.
  	 */
 +	update_mailname(NULL);
  	(void)printf("\"%s\": ", displayname);
  	{
  		int cnt =3D get_abs_msgCount();

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47577 CVS commit: src/usr.bin/mail
Date: Wed, 20 Feb 2013 09:38:14 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Feb 20 14:38:13 UTC 2013

 Modified Files:
 	src/usr.bin/mail: fio.c lex.c

 Log Message:
 PR/47577: Steffen "Daode" Nurpmeso: Refinement to previous to keep always
 keep track of the folder when it is updated.


 To generate a diff of this commit:
 cvs rdiff -u -r1.37 -r1.38 src/usr.bin/mail/fio.c
 cvs rdiff -u -r1.42 -r1.43 src/usr.bin/mail/lex.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: PR/47577 CVS commit: src/usr.bin/mail
Date: Mon, 25 Feb 2013 19:58:24 +0100

 ach, it's a mess!
 No thought of multibyte awareness until saturday, when doing
 something completely different..
 So this should make it multibyte aware (i hope).

 --steffen

 diff -Napru mail.orig/Makefile mail/Makefile
 --- mail.orig/Makefile	2013-02-25 14:58:37.000000000 +0100
 +++ mail/Makefile	2013-02-25 16:02:01.000000000 +0100
 @@ -8,6 +8,7 @@ USE_FORT?=3D yes	# data-driven bugs?
  USE_EDITLINE?=3Dyes
  MIME_SUPPORT?=3Dyes	# currently requires USE_EDITLINE
  CHARSET_SUPPORT?=3Dyes	# requires MIME_SUPPORT
 +WIDECHAR?=3Dyes		# avoid multibyte sequence -hickups- disruptions
  THREAD_SUPPORT?=3Dyes	# EXPERIMENTAL
 =20
  # Work around some problems in -current.
 @@ -52,6 +53,10 @@ CPPFLAGS+=3D	-DMIME_SUPPORT
  CPPFLAGS+=3D	-DCHARSET_SUPPORT
  .endif
 =20
 +.if ${WIDECHAR:Uno} =3D=3D "yes"
 +CPPFLAGS+=3D	-DWIDECHAR
 +.endif
 +
  LDADD+=3D		-lmagic -lz
  DPADD+=3D		${LIBMAGIC} ${LIBZ}
  .endif
 diff -Napru mail.orig/lex.c mail/lex.c
 --- mail.orig/lex.c	2013-02-25 14:58:37.000000000 +0100
 +++ mail/lex.c	2013-02-25 18:47:19.000000000 +0100
 @@ -40,6 +40,9 @@ __RCSID("$NetBSD: lex.c,v 1.43 2013/02/2
 =20
  #include <assert.h>
  #include <util.h>
 +#ifdef WIDECHAR
 +# include <wchar.h>
 +#endif
 =20
  #include "rcv.h"
  #include "extern.h"
 @@ -144,8 +147,8 @@ file_leak_check(void)
  static void
  update_mailname(const char *name)
  {
 -	char tbuf[PATHSIZE];
 -	size_t l;
 +	char tbuf[PATHSIZE], *mailp, *dispp;
 +	size_t i, j;
 =20
  	/* Don't realpath(3) if it's only an update request */
  	if (name !=3D NULL && realpath(name, mailname) =3D=3D NULL) {
 @@ -153,32 +156,41 @@ update_mailname(const char *name)
  		return;
  	}
 =20
 +	mailp =3D mailname;
 +	dispp =3D displayname;
 +
 +	/* Don't display an absolute path but "+FOLDER" if under *folder* */
  	if (getfold(tbuf, sizeof(tbuf)) >=3D 0) {
 -		l =3D strlen(tbuf);
 -		if (l < sizeof(tbuf) - 1)
 -			tbuf[l++] =3D '/';
 -		if (strncmp(tbuf, mailname, l) =3D=3D 0) {
 -			char const *sep =3D "", *cp =3D mailname + l;
 -
 -			l =3D strlen(cp);
 -			if (l >=3D sizeof(displayname)) {
 -				cp +=3D l;
 -				cp -=3D sizeof(displayname) - 5;
 -				sep =3D "...";
 -			}
 -			(void)snprintf(displayname, sizeof(displayname),
 -			    "+%s%s", sep, cp);
 -			return;
 +		i =3D strlen(tbuf);
 +		if (i < sizeof(tbuf) - 1)
 +			tbuf[i++] =3D '/';
 +		if (strncmp(tbuf, mailp, i) =3D=3D 0) {
 +			mailp +=3D i;
 +			*dispp++ =3D '+';
  		}
  	}
 =20
 -	l =3D strlen(mailname);
 -	if (l < sizeof(displayname))
 -		strcpy(displayname, mailname);
 +	/* We want to see the name of the folder .. on the screen */
 +	i =3D strlen(mailp);
 +	if (i < sizeof(displayname) - 1)
 +		memcpy(dispp, mailp, i + 1);
  	else {
 -		l -=3D sizeof(displayname) - 4 - sizeof(displayname) / 3;
 -		(void)snprintf(displayname, sizeof(displayname), "%.*s...%s",
 -			(int)sizeof(displayname) / 3, mailname, mailname + l);
 +#ifdef WIDECHAR
 +		size_t si =3D i;
 +#endif
 +		j =3D sizeof(displayname) / 3;
 +		i -=3D sizeof(displayname) - (1 /* "+" */ + 4) - j;
 +		/* Avoid disrupting multibyte sequences */
 +#ifdef WIDECHAR
 +		goto jmblen;
 +		while (i < si && mblen(mailp + i, si - i) < 0) {
 +			++i;
 +jmblen:
 +			mblen(NULL, 0);
 +		}
 +#endif
 +		(void)snprintf(dispp, sizeof(displayname) - 1, "%.*s...%s",
 +			(int)j, mailp, mailp + i);
  	}
  }
 =20

From: Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To: gnats-admin@netbsd.org, gnats-bugs@NetBSD.org,
 netbsd-bugs@netbsd.org
Cc: 
Subject: Re: PR/47577 CVS commit: src/usr.bin/mail
Date: Mon, 25 Feb 2013 20:06:08 +0100

 ..This may also be sufficient.
 (Just scream, i'll stop, then ...)

 --steffen

 diff -Napru mail.orig/lex.c mail/lex.c
 --- mail.orig/lex.c	2013-02-25 14:58:37.000000000 +0100
 +++ mail/lex.c	2013-02-25 20:04:28.000000000 +0100
 @@ -144,8 +144,8 @@ file_leak_check(void)
  static void
  update_mailname(const char *name)
  {
 -	char tbuf[PATHSIZE];
 -	size_t l;
 +	char tbuf[PATHSIZE], *mailp, *dispp;
 +	size_t si, i, j;
 =20
  	/* Don't realpath(3) if it's only an update request */
  	if (name !=3D NULL && realpath(name, mailname) =3D=3D NULL) {
 @@ -153,32 +153,37 @@ update_mailname(const char *name)
  		return;
  	}
 =20
 +	mailp =3D mailname;
 +	dispp =3D displayname;
 +
 +	/* Don't display an absolute path but "+FOLDER" if under *folder* */
  	if (getfold(tbuf, sizeof(tbuf)) >=3D 0) {
 -		l =3D strlen(tbuf);
 -		if (l < sizeof(tbuf) - 1)
 -			tbuf[l++] =3D '/';
 -		if (strncmp(tbuf, mailname, l) =3D=3D 0) {
 -			char const *sep =3D "", *cp =3D mailname + l;
 -
 -			l =3D strlen(cp);
 -			if (l >=3D sizeof(displayname)) {
 -				cp +=3D l;
 -				cp -=3D sizeof(displayname) - 5;
 -				sep =3D "...";
 -			}
 -			(void)snprintf(displayname, sizeof(displayname),
 -			    "+%s%s", sep, cp);
 -			return;
 +		i =3D strlen(tbuf);
 +		if (i < sizeof(tbuf) - 1)
 +			tbuf[i++] =3D '/';
 +		if (strncmp(tbuf, mailp, i) =3D=3D 0) {
 +			mailp +=3D i;
 +			*dispp++ =3D '+';
  		}
  	}
 =20
 -	l =3D strlen(mailname);
 -	if (l < sizeof(displayname))
 -		strcpy(displayname, mailname);
 +	/* We want to see the name of the folder .. on the screen */
 +	i =3D strlen(mailp);
 +	if (i < sizeof(displayname) - 1)
 +		memcpy(dispp, mailp, i + 1);
  	else {
 -		l -=3D sizeof(displayname) - 4 - sizeof(displayname) / 3;
 -		(void)snprintf(displayname, sizeof(displayname), "%.*s...%s",
 -			(int)sizeof(displayname) / 3, mailname, mailname + l);
 +		j =3D sizeof(displayname) / 3;
 +		si =3D i;
 +		i -=3D sizeof(displayname) - (1 /* "+" */ + 4) - j;
 +		/* Avoid disrupting multibyte sequences */
 +		goto jmblen;
 +		while (i < si && mblen(mailp + i, si - i) < 0) {
 +			++i;
 +jmblen:
 +			mblen(NULL, 0);
 +		}
 +		(void)snprintf(dispp, sizeof(displayname) - 1, "%.*s...%s",
 +			(int)j, mailp, mailp + i);
  	}
  }
 =20

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.