Hello, this is my first patch to OpenBSD. I look forward to feedback on code as well as process, communication, etc. Thank you in advance.
This patch adds a -c <bytes> argument to head(1). The behavior is intended to be the same as head on other systems, such as FreeBSD, NetBSD, macOS, and Linux. diff --git usr.bin/head/head.1 usr.bin/head/head.1 index 8f97660ef25..d3cb84dc462 100644 --- usr.bin/head/head.1 +++ usr.bin/head/head.1 @@ -34,17 +34,19 @@ .Os .Sh NAME .Nm head -.Nd display first few lines of files +.Nd display first few lines or bytes of files .Sh SYNOPSIS .Nm head -.Op Fl Ar count | Fl n Ar count +.Op Fl Ar count | Fl n Ar count | Fl c Ar bytes .Op Ar .Sh DESCRIPTION The .Nm utility copies the first .Ar count -lines of each specified +lines or +.Ar bytes +of each specified .Ar file to the standard output. If no files are named, @@ -63,6 +65,14 @@ lines of each input file to the standard output. .Ar count must be a positive decimal integer. .El +.Bl -tag -width Ds +.It Fl c Ar bytes +Copy the first +.Ar bytes +of each input file to the standard output. +.Ar bytes +must be a positive decimal integer. +.El .Pp If more than one file is specified, .Nm @@ -70,6 +80,12 @@ precedes the output of each file with the following, in order to distinguish files: .Pp .Dl ==> Ar file No <== +.Pp +It is an error to specify both +.Ar count +and +.Ar bytes +arguments. .Sh EXIT STATUS .Ex -std head .Sh EXAMPLES @@ -85,6 +101,13 @@ in the following way to, for example, display only line 500 from the file .Ar foo : .Pp .Dl $ head -n 500 foo | tail -1 +.Pp +.Nm +can be used in conjunction +.Xr urandom 4 +to create a random string of bytes: +.Pp +.Dl $ head -c 32 /dev/urandom | base64 .Sh SEE ALSO .Xr cat 1 , .Xr cut 1 , diff --git usr.bin/head/head.c usr.bin/head/head.c index 73670621524..1fc860929c9 100644 --- usr.bin/head/head.c +++ usr.bin/head/head.c @@ -37,7 +37,7 @@ #include <errno.h> #include <unistd.h> -int head_file(const char *, long, int); +int head_file(const char *, long, long, int); static void usage(void); /* @@ -51,7 +51,8 @@ main(int argc, char *argv[]) { const char *errstr; int ch; - long linecnt = 10; + long linecnt = -1; + long bytecnt = -1; int status = 0; if (pledge("stdio rpath", NULL) == -1) @@ -67,12 +68,17 @@ main(int argc, char *argv[]) argv++; } - while ((ch = getopt(argc, argv, "n:")) != -1) { + while ((ch = getopt(argc, argv, "n:c:")) != -1) { switch (ch) { case 'n': linecnt = strtonum(optarg, 1, LONG_MAX, &errstr); if (errstr != NULL) - errx(1, "count is %s: %s", errstr, optarg); + errx(1, "line count is %s: %s", errstr, optarg); + break; + case 'c': + bytecnt = strtonum(optarg, 1, LONG_MAX, &errstr); + if (errstr != NULL) + errx(1, "byte count is %s: %s", errstr, optarg); break; default: usage(); @@ -80,26 +86,32 @@ main(int argc, char *argv[]) } argc -= optind, argv += optind; + if (linecnt != -1 && bytecnt != -1) + errx(1, "cannot specify both line and byte counts"); + if (linecnt == -1 && bytecnt == -1) + linecnt = 10; + if (argc == 0) { if (pledge("stdio", NULL) == -1) err(1, "pledge"); - status = head_file(NULL, linecnt, 0); + status = head_file(NULL, linecnt, bytecnt, 0); } else { for (; *argv != NULL; argv++) - status |= head_file(*argv, linecnt, argc > 1); + status |= head_file(*argv, linecnt, bytecnt, argc > 1); } return status; } int -head_file(const char *path, long count, int need_header) +head_file(const char *path, long linecnt, long bytecnt, int need_header) { const char *name; FILE *fp; int ch, status = 0; static int first = 1; + long count = (linecnt != -1) ? linecnt : bytecnt; if (path != NULL) { name = path; @@ -122,7 +134,7 @@ head_file(const char *path, long count, int need_header) while ((ch = getc(fp)) != EOF) { if (putchar(ch) == EOF) err(1, "stdout"); - if (ch == '\n' && --count == 0) + if ((bytecnt != -1 || ch == '\n') && --count == 0) break; } if (ferror(fp)) { @@ -139,6 +151,6 @@ head_file(const char *path, long count, int need_header) static void usage(void) { - fputs("usage: head [-count | -n count] [file ...]\n", stderr); + fputs("usage: head [-count | -n count | -c bytes] [file ...]\n", stderr); exit(1); }