[Midnightbsd-cvs] src [6823] trunk/bin/cat: Introduce the l flag

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Oct 3 00:10:33 EDT 2014


Revision: 6823
          http://svnweb.midnightbsd.org/src/?rev=6823
Author:   laffer1
Date:     2014-10-03 00:10:32 -0400 (Fri, 03 Oct 2014)
Log Message:
-----------
Introduce the l flag

Set an exclusive advisory lock on the standard output file descriptor.

Modified Paths:
--------------
    trunk/bin/cat/cat.1
    trunk/bin/cat/cat.c

Modified: trunk/bin/cat/cat.1
===================================================================
--- trunk/bin/cat/cat.1	2014-10-03 03:59:08 UTC (rev 6822)
+++ trunk/bin/cat/cat.1	2014-10-03 04:10:32 UTC (rev 6823)
@@ -33,7 +33,7 @@
 .\" $FreeBSD: src/bin/cat/cat.1,v 1.25 2005/01/16 16:41:55 ru Exp $
 .\" $MidnightBSD: src/bin/cat/cat.1,v 1.4 2006/09/09 13:48:40 laffer1 Exp $
 .\"
-.Dd September 9, 2006
+.Dd January 29, 2013
 .Dt CAT 1
 .Os
 .Sh NAME
@@ -41,7 +41,7 @@
 .Nd concatenate and print files
 .Sh SYNOPSIS
 .Nm
-.Op Fl benstuv
+.Op Fl belnstuv
 .Op Fl D Ar date_fmt 
 .Op Ar
 .Sh DESCRIPTION
@@ -54,7 +54,7 @@
 If
 .Ar file
 is a single dash
-.Pq Sq \&-
+.Pq Sq Fl
 or absent,
 .Nm
 reads from the standard input.
@@ -81,6 +81,16 @@
 option), and display a dollar sign
 .Pq Ql \&$
 at the end of each line.
+.It Fl l
+Set an exclusive advisory lock on the standard output file descriptor.
+This lock is set using
+.Xr fcntl 2
+with the
+.Dv F_SETLKW
+command.
+If the output file is already locked,
+.Nm
+will block until the lock is acquired.
 .It Fl n
 Number the output lines, starting at 1.
 .It Fl s
@@ -120,7 +130,7 @@
 .Dl "cat file1"
 .Pp
 will print the contents of
-.Ar file1
+.Pa file1
 to the standard output.
 .Pp
 The command:
@@ -128,15 +138,15 @@
 .Dl "cat file1 file2 > file3"
 .Pp
 will sequentially print the contents of
-.Ar file1
+.Pa file1
 and
-.Ar file2
+.Pa file2
 to the file
-.Ar file3 ,
+.Pa file3 ,
 truncating
-.Ar file3
+.Pa file3
 if it already exists.
-See the manual page for your shell (i.e.,
+See the manual page for your shell (e.g.,
 .Xr sh 1 )
 for more information on redirection.
 .Pp
@@ -145,21 +155,21 @@
 .Dl "cat file1 - file2 - file3"
 .Pp
 will print the contents of
-.Ar file1 ,
+.Pa file1 ,
 print data it receives from the standard input until it receives an
 .Dv EOF
 .Pq Sq ^D
 character, print the contents of
-.Ar file2 ,
+.Pa file2 ,
 read and output contents of the standard input again, then finally output
 the contents of
-.Ar file3 .
+.Pa file3 .
 Note that if the standard input referred to a file, the second dash
 on the command-line would have no effect, since the entire contents of the file
 would have already been read and printed by
 .Nm
 when it encountered the first
-.Ql \&-
+.Sq Fl
 operand.
 .Pp
 The command:
@@ -193,7 +203,7 @@
 specification.
 .Pp
 The flags
-.Op Fl benstvD
+.Op Fl belnstvD
 are extensions to the specification.
 .Sh HISTORY
 A
@@ -208,7 +218,9 @@
 Because of the shell language mechanism used to perform output
 redirection, the command
 .Dq Li cat file1 file2 > file1
-will cause the original data in file1 to be destroyed!
+will cause the original data in
+.Pa file1
+to be destroyed!
 .Pp
 The
 .Nm

Modified: trunk/bin/cat/cat.c
===================================================================
--- trunk/bin/cat/cat.c	2014-10-03 03:59:08 UTC (rev 6822)
+++ trunk/bin/cat/cat.c	2014-10-03 04:10:32 UTC (rev 6823)
@@ -68,8 +68,8 @@
 
 #define	DATEPFX_MAXLEN	1024
 
-int bflag, eflag, nflag, sflag, tflag, vflag;
-int rval;
+static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
+static int rval;
 static time_t prev_time;
 static const char *datefmt;
 static char *datepfx;
@@ -85,14 +85,30 @@
 static int udom_open(const char *path, int flags);
 #endif
 
+/*
+ * Memory strategy threshold, in pages: if physmem is larger than this,
+ * use a large buffer.
+ */
+#define	PHYSPAGES_THRESHOLD (32 * 1024)
+
+/* Maximum buffer size in bytes - do not allow it to grow larger than this. */
+#define	BUFSIZE_MAX (2 * 1024 * 1024)
+
+/*
+ * Small (default) buffer size in bytes. It's inefficient for this to be
+ * smaller than MAXPHYS.
+ */
+#define	BUFSIZE_SMALL (MAXPHYS)
+
 int
 main(int argc, char *argv[])
 {
 	int ch;
+	struct flock stdout_lock;
 
 	setlocale(LC_CTYPE, "");
 
-	while ((ch = getopt(argc, argv, "bD:enstuv")) != -1)
+	while ((ch = getopt(argc, argv, "bD:elnstuv")) != -1)
 		switch (ch) {
 		case 'b':
 			bflag = nflag = 1;	/* -b implies -n */
@@ -100,6 +116,9 @@
 		case 'e':
 			eflag = vflag = 1;	/* -e implies -v */
 			break;
+		case 'l':
+			lflag = 1;
+			break;
 		case 'n':
 			nflag = 1;
 			break;
@@ -123,6 +142,15 @@
 		}
 	argv += optind;
 
+	if (lflag) {
+		stdout_lock.l_len = 0;
+		stdout_lock.l_start = 0;
+		stdout_lock.l_type = F_WRLCK;
+		stdout_lock.l_whence = SEEK_SET;
+		if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1)
+			err(EXIT_FAILURE, "stdout");
+	}
+
 	/* 
          * Test date format so the user will get an error sooner
          * rather than later
@@ -144,7 +172,7 @@
 static void
 usage(void)
 {
-	fprintf(stderr, "usage: cat [-benstuv] [-D datefmt] [file ...]\n");
+	fprintf(stderr, "usage: cat [-belnstuv] [-D datefmt] [file ...]\n");
 	exit(1);
 	/* NOTREACHED */
 }
@@ -152,18 +180,17 @@
 static void
 scanfiles(char *argv[], int cooked)
 {
-	int i = 0;
+	int fd, i;
 	char *path;
 	FILE *fp;
 
+	i = 0;
 	while ((path = argv[i]) != NULL || i == 0) {
-		int fd;
-
 		if (path == NULL || strcmp(path, "-") == 0) {
 			filename = "stdin";
 			fd = STDIN_FILENO;
 		} else {
-		filename = path;
+			filename = path;
 			fd = open(path, O_RDONLY);
 #ifndef NO_UDOM_SUPPORT
 			if (fd < 0 && errno == EOPNOTSUPP)
@@ -272,9 +299,17 @@
 	if (buf == NULL) {
 		if (fstat(wfd, &sbuf))
 			err(1, "stdout");
-		bsize = MAX(sbuf.st_blksize, 1024);
+		if (S_ISREG(sbuf.st_mode)) {
+			/* If there's plenty of RAM, use a large copy buffer */
+			if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
+				bsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+			else
+				bsize = BUFSIZE_SMALL;
+		} else
+			bsize = MAX(sbuf.st_blksize,
+			    (blksize_t)sysconf(_SC_PAGESIZE));
 		if ((buf = malloc(bsize)) == NULL)
-			err(1, "buffer");
+			err(1, "malloc() failure of IO buffer");
 	}
 	while ((nr = read(rfd, buf, bsize)) > 0)
 		for (off = 0; nr; nr -= nw, off += nw)
@@ -358,7 +393,7 @@
 			break;
 		}
 	}
-	return(fd);
+	return (fd);
 }
 
 #endif



More information about the Midnightbsd-cvs mailing list