Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Sep 1995 19:37:08 +0200
From:      Wolfram Schneider <wosch@cs.tu-berlin.de>
To:        current@freebsd.org
Subject:   from(1)
Message-ID:  <199509201737.TAA03936@caramba.cs.tu-berlin.de>

next in thread | raw e-mail | index | archive | help

Changes:
	- add missing includes files
	- minimal support for content-length
	- allow reading input from stdin (-f -)
	- Option '-c' print a count of matching lines
	- Option '-F' use 'From:' instead 'From' line
	- Option '-t' don't change access time
	- Option '-v' Invert the sense of matching, 
	              to select nonmatching lines.

Examples:
	count mails in archive:
		$ zcat hack.gz | from -c -f -
		47

	count non-freebsd mails in your mailbox:
		$ from -cvs freebsd.org
		3

	mails from Berlin:
		$ from -F -s berlin -f mbox
From: Thomas Graichen <graichen@omega.physik.fu-berlin.de>
From: Thomas Graichen <graichen@omega.physik.fu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>

--- /usr/src/usr.bin/from/from.c	Fri May 27 14:31:22 1994
+++ from.c	Wed Sep 20 17:03:44 1995
@@ -42,41 +42,90 @@
 #endif /* not lint */
 
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <ctype.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <paths.h>
+#include <string.h>
+#include <stdlib.h>
 
-main(argc, argv)
+#define CLEN "content-length:"
+#define FROM "From:"
+
+int f_from = 0; 	/* use `From:' field instead 'From' */
+int f_count = 0;	/* don't print from lines, print count only */
+int f_invert = 0;       /* invert searching */
+int f_atime = 0;        /* modify access time */
+int counter = 0;
+
+int match 	__P((char *line, char *sender));
+int match2 	__P((char *line, char *sender));
+void print_from __P((char *buf));
+
+
+void main(argc, argv)
 	int argc;
 	char **argv;
 {
 	extern char *optarg;
 	extern int optind;
+
 	struct passwd *pwd;
-	int ch, newline;
+	struct stat sb;
+	struct timeval tv[2];
+
+	int ch, newline, header, body;
 	char *file, *sender, *p;
 #if MAXPATHLEN > BUFSIZ
 	char buf[MAXPATHLEN];
+	char buf2[MAXPATHLEN];
 #else
 	char buf[BUFSIZ];
+	char buf2[BUFSIZ];
 #endif
 
 	file = sender = NULL;
-	while ((ch = getopt(argc, argv, "f:s:")) != EOF)
+
+	while ((ch = getopt(argc, argv, "?Fcf:s:tv")) != EOF)
 		switch((char)ch) {
+
+		/* use `From:' field instead 'From' */
+	        case 'F':
+			f_from = 1; 
+			break;
+		
+		/* don't print from lines, print count only */
+		case 'c':
+			f_count = 1;
+			break;
+
+		/* use file as mailbox */
 		case 'f':
 			file = optarg;
 			break;
+
+		/* use only mails from sender */
 		case 's':
 			sender = optarg;
 			for (p = sender; *p; ++p)
 				if (isupper(*p))
 					*p = tolower(*p);
 			break;
+
+		/* don't modify access time */
+		case 't':
+			f_atime = 1;
+			break;
+
+		case 'v':
+			f_invert = 1;
+			break;
+
 		case '?':
 		default:
-			fprintf(stderr, "usage: from [-f file] [-s sender] [user]\n");
+			fprintf(stderr, "usage: from [-Fctv] [-f file] [-s sender] [user]\n");
 			exit(1);
 		}
 	argv += optind;
@@ -90,34 +139,104 @@
 			}
 			file = pwd->pw_name;
 		}
-		(void)sprintf(buf, "%s/%s", _PATH_MAILDIR, file);
-		file = buf;
+		(void)sprintf(buf2, "%s/%s", _PATH_MAILDIR, file);
+		file = buf2;
 	}
-	if (!freopen(file, "r", stdin)) {
+
+	/* stdin */
+	if (!strcmp(file, "-")) {
+		f_atime = 0;	/* don't stat stdin */
+	}
+
+	/* redirect file to stdin */
+	else if (!freopen(file, "r", stdin)) {
 		fprintf(stderr, "from: can't read %s.\n", file);
 		exit(1);
+	} 
+
+	/* save atime */
+	else if (f_atime) {
+		if (stat(file, &sb) < 0) {
+			perror("stat");
+			exit(1);
+		}
+		tv[0].tv_sec  = sb.st_atime;
+		tv[0].tv_usec = sb.st_atime * 1000;
+		tv[1].tv_sec  = sb.st_mtime;
+		tv[1].tv_usec = sb.st_mtime * 1000;
 	}
+
+	header = body = 0;
 	for (newline = 1; fgets(buf, sizeof(buf), stdin);) {
+
+	        /* 
+		 * newline
+		 * begin (next line) or end of header 
+		 */  
 		if (*buf == '\n') {
 			newline = 1;
-			continue;
+
+			/* skip bytes in body (content-length) */
+			if (header && body > 0) {
+			    while(body--)
+				getc(stdin);
+			}
+			header = 0;
+			body = 0;
+		}
+
+		/* begin of header */
+		else if (newline && !strncmp(buf, "From ", 5)) {
+			if (!f_from)
+				if (!sender || match(buf + 5, sender))
+					print_from(buf);
+
+			header = 1;
+			newline = 0;
+		} 
+
+		/* found "^content-length: <bytes>" in header */
+		else if (header && 
+			 !strncasecmp(buf, CLEN, sizeof(CLEN) - 1) &&
+			 isblank(*(buf + sizeof(CLEN) - 1))) { 
+
+			body = atoi(buf + sizeof(CLEN));
+		}
+
+		/* From: */
+		else if (header && f_from &&
+			 !strncasecmp(buf, FROM, sizeof(FROM) - 1) &&
+			 isblank(*(buf + sizeof(FROM) - 1))) { 
+
+			if (!sender || match2(buf + sizeof(FROM), sender))
+				print_from(buf);
+		}
+
+
+	}
+
+	/* print number (of matching or non-matching) mails */
+	if (f_count)
+		fprintf(stdout, "%d\n", counter);
+
+	/* reset access time */
+	if (f_atime) {
+		if (utimes(file, tv) < 0) {
+			perror("utimes");
+			exit(1);
 		}
-		if (newline && !strncmp(buf, "From ", 5) &&
-		    (!sender || match(buf + 5, sender)))
-			printf("%s", buf);
-		newline = 0;
 	}
 	exit(0);
 }
 
-match(line, sender)
+int match(line, sender)
 	register char *line, *sender;
 {
 	register char ch, pch, first, *p, *t;
 
 	for (first = *sender++;;) {
 		if (isspace(ch = *line))
-			return(0);
+			return(f_invert);
 		++line;
 		if (isupper(ch))
 			ch = tolower(ch);
@@ -125,7 +244,7 @@
 			continue;
 		for (p = sender, t = line;;) {
 			if (!(pch = *p++))
-				return(1);
+				return(!f_invert);
 			if (isupper(ch = *t++))
 				ch = tolower(ch);
 			if (ch != pch)
@@ -133,4 +252,27 @@
 		}
 	}
 	/* NOTREACHED */
+}
+
+int match2(line, sender)
+	register char *line, *sender;
+{
+	register char *p, *s;
+
+	for (; *line; line++) {
+		for (p = line, s = sender; tolower(*p) == *s; p++, s++);
+
+		if (*s == NULL)
+			return(!f_invert);
+	}
+	return(f_invert); 
+}
+
+void print_from(buf)
+	char *buf;
+{
+	if (f_count) 
+		counter++;
+	else
+		printf("%s", buf);
 }
--- /usr/src/usr.bin/from/from.1	Fri May 27 14:31:22 1994
+++ from.1	Wed Sep 20 16:52:01 1995
@@ -39,6 +39,7 @@
 .Nd print names of those who have sent mail
 .Sh SYNOPSIS
 .Nm from
+.Op Fl Fctv
 .Op Fl s Ar sender
 .Op Fl f Ar file
 .Op Ar user
@@ -49,6 +50,14 @@
 .Pp
 Options:
 .Bl -tag -width Fl
+
+.It Fl F
+Use 'From:' field instead 'From'.
+
+.It Fl c
+Suppress  normal  output;  instead print a count of
+matching lines.
+
 .It Fl f Ar file 
 The supplied file
 is examined instead of the invoker's mailbox.
@@ -61,6 +70,13 @@
 Only mail from addresses containing
 the
 supplied string are printed.
+
+.It Fl t
+Don't change access time of mailbox.
+
+.It Fl v
+Invert the sense of matching, to select nonmatching lines.
+
 .El
 .Pp
 If





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199509201737.TAA03936>