9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] [PATCH] Mail add option to open new mailbox given path
@ 2021-02-17 20:50 theinicke
  2021-02-21 22:20 ` ori
  0 siblings, 1 reply; 2+ messages in thread
From: theinicke @ 2021-02-17 20:50 UTC (permalink / raw)
  To: 9front

This patch adds an option to Mail were it interprets argument passed to it
as path of a new mailbox to open and display.
The path may be a relative path on the filesystem or an absolute one
which would be directly opened using upasfs(4).
On exit the mailbox is closed again.
Also NAIL -> ACMEMAIL and fix usage string.

Notes:
- Behaviour is reintroduced/amended from old Mail (before Nail).
- Thanks to Ori and Alex Musolino for providing feedback regarding this change.
- I directly quoted "." in man page instead of saying working directory,
   to make it obvious that we are talking about path on file system; maybe ugly.
- Hope this looks good now and is useful to some, else please let me know.

--
Tobias Heinicke

P.S.: For anyone who has followed earlier thread: I am sorry for all the noise.
@Ori: I haven't had time to reply you properly after I have realized
that some of my notes regarding your feedback were wrong
that's why I send previous patch.
As this one addresses all of your feedback + some further cosmetic changes
I hope this may be merged directly, if not please let me know.

diff -r 39b061370f36 sys/src/cmd/upas/Mail/mbox.c
--- a/sys/src/cmd/upas/Mail/mbox.c	Wed Feb 17 11:20:13 2021 +0100
+++ b/sys/src/cmd/upas/Mail/mbox.c	Wed Feb 17 21:12:43 2021 +0100
@@ -28,12 +28,14 @@
 char	*mailbox	= "mbox";
 char	*savebox	= "outgoing";
 char	*listfmt	= "%>48s\t<%f>";
+char *path	= ".";
 Mesg	dead = {.messageid="", .hash=42};
 
 Reprog	*mesgpat;
 
 int	threadsort = 1;
 int	sender;
+int	ispath;
 
 int	plumbsendfd;
 int	plumbseemailfd;
@@ -672,17 +674,26 @@
 	}
 }
 
+static int
+openctlfile(void)
+{
+	int fd;
+	char *path;
+
+	path = estrjoin(maildir, "/ctl", nil);
+	fd = open(path, OWRITE);
+	free(path);
+	return fd;
+}
+
 static void
 mbflush(char **, int)
 {
 	int i, j, ln, fd;
-	char *path;
 	Mesg *m, *p;
 
 	i = 0;
-	path = estrjoin(maildir, "/ctl", nil);
-	fd = open(path, OWRITE);
-	free(path);
+	fd = openctlfile();
 	if(fd == -1)
 		sysfatal("open mbox: %r");
 	while(i < mbox.nmesg){
@@ -975,10 +986,96 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-T] [-m mailfs] [-s] [-f format] [mbox]\n", argv0);
+	fprint(2, "usage: %s [-TOs] [-m maildir] [-f format] [-o outbox] [-p] [mbox]\n", argv0);
 	exits("usage");
 }
 
+static char*
+basename(char *path)
+{
+	char *base;
+	base = strrchr(path, '/');
+	if(base == nil)
+		base = path;
+	return base+1;
+}
+
+static char*
+absmboxpath(char *path)
+{
+	char *abspath;
+	char buf[512];
+	int fd, i;
+
+	/* If path is already absolute leave it mostly alone
+	(to allow opening another imap/pop directory),
+	otherwise get absolute path from relative one. */
+	if(*path == '/'){
+		i = strlen(path);
+		while(i > 0 && path[--i] == '/')
+			path[i] = '\0';
+		abspath = estrdup(path);
+	}else{
+		fd = open(path, OREAD);
+		if(fd < 0)
+			sysfatal("can't open %s: %r", path);
+	
+		if(fd2path(fd, buf, sizeof buf) != 0)
+			sysfatal("fd2path %s: %r", path);
+		close(fd);
+		abspath = estrdup(buf);
+	}
+
+	return abspath;
+}
+
+static void
+openmbox(char *path)
+{
+	int fd, i;
+	char err[ERRMAX];
+	char *name, *fsname, *abspath;
+
+	abspath = absmboxpath(path);
+	name = basename(abspath);
+
+	fd = openctlfile();
+	if(fd == -1)
+		sysfatal("open mbox: %r");
+
+	/* if mboxname is already taken try mboxname-0, ..., mboxname-9 */
+	fsname = estrdup(name);
+	for(i=0; i<10; i++){
+		if(fprint(fd, "open %s %s", abspath, fsname) >= 0)
+			break;
+		err[0] = '\0';
+		errstr(err, sizeof err);
+		if(strstr(err, "mbox name in use") == nil)
+			sysfatal("can't create directory %s for mail: %s", name, err);
+		free(fsname);
+		fsname = smprint("%s-%d", name, i);
+	}
+	if(i == 10)
+		sysfatal("can't open %s: %r", abspath);
+
+	mailbox = fsname;
+	free(abspath);
+	close(fd);
+}
+
+static void
+closembox(void)
+{
+	int fd;
+
+	fd = openctlfile();
+	if(fd == -1)
+		return;
+
+	fprint(fd, "close %s", mailbox);
+	close(fd);
+}
+
 void
 threadmain(int argc, char **argv)
 {
@@ -1017,6 +1114,9 @@
 	case 'o':
 		savebox = EARGF(usage());
 		break;
+	case 'p':
+		ispath++;
+		break;
 	default:
 		usage();
 		break;
@@ -1024,8 +1124,20 @@
 
 	if(argc > 1)
 		usage();
-	if(argc == 1)
-		mailbox = argv[0];
+	if(argc == 1) {
+		if(!ispath)
+			mailbox = argv[0];
+		else
+			path = argv[0];
+	}
+
+	if(ispath) {
+		openmbox(path);
+		if(atexit(closembox) == 0) {
+			closembox();
+			sysfatal("atexit: %r");
+		}
+	}
 
 	mesgpat = regcomp("([0-9]+)(/.*)?");
 	cwait = threadwaitchan();
diff -r 39b061370f36 sys/man/1/acmemail
--- a/sys/man/1/acmemail	Wed Feb 17 11:20:13 2021 +0100
+++ b/sys/man/1/acmemail	Wed Feb 17 21:25:55 2021 +0100
@@ -1,4 +1,4 @@
-.TH NAIL 1
+.TH ACMEMAIL 1
 .SH NAME
 Mail \- view mail in acme
 
@@ -6,7 +6,7 @@
 
 Mail
 [
-.B -OsT
+.B -TOs
 ]
 [
 .B -m
@@ -20,6 +20,12 @@
 .B -o
 .I outbox
 ]
+[
+.B -p
+]
+[
+.I mbox
+]
 
 .SH DESCRIPTION
 .PP
@@ -64,6 +70,13 @@
 Save a copy of outgoing messages to the mailbox
 .IR outbox ,
 instead of discarding them after they're enqueued.
+.TP
+.BI -p
+Indicates that mbox is a path to a new mailbox.
+An absolute path is passed to upasfs(4),
+relative path is first interpreted using fd2path(2).
+If no path is given, "." is used.
+Mailbox is closed upon exit.
 
 .PP
 Mail presents and acme interface for a upas/fs mailbox.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-02-22  2:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-17 20:50 [9front] [PATCH] Mail add option to open new mailbox given path theinicke
2021-02-21 22:20 ` ori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).