commit 0d7c2351b4913b2faae78239472e39a509a3f7f8
parent 1436518f9dad063bbfb8dc5595b9c744d025557c
Author: sin <sin@2f30.org>
Date: Thu, 20 Nov 2014 13:50:18 +0000
Remove csplit(1)
Get rid of it for now as it is not really widely used. We can do
a simple implementation when time comes.
Remove the table from README because it is not easy to edit unless
you use emacs.
Diffstat:
M | Makefile | | | 1 | - |
M | README | | | 159 | ------------------------------------------------------------------------------- |
M | TODO | | | 1 | - |
D | csplit.1 | | | 166 | ------------------------------------------------------------------------------- |
D | csplit.c | | | 451 | ------------------------------------------------------------------------------- |
5 files changed, 0 insertions(+), 778 deletions(-)
diff --git a/Makefile b/Makefile
@@ -67,7 +67,6 @@ BIN =\
cols\
comm\
cp\
- csplit\
cut\
date\
dirname\
diff --git a/README b/README
@@ -4,165 +4,6 @@ sbase - suckless unix tools
sbase is a collection of unix tools that are inherently portable
across UNIX and UNIX-like systems.
-The following programs are currently implemented:
-
-+---------+-----------+--------+
-|UTILITY |POSIX |FEATURES|
-| |CONFORMANCE|MISSING |
-+---------+-----------+--------+
-|basename | | |
-+---------+-----------+--------+
-|cal | | |
-+---------+-----------+--------+
-|cat | | |
-+---------+-----------+--------+
-|chgrp | | |
-+---------+-----------+--------+
-|chmod | | |
-+---------+-----------+--------+
-|chown | | |
-+---------+-----------+--------+
-|chroot | | |
-+---------+-----------+--------+
-|cksum | | |
-+---------+-----------+--------+
-|cmp | | |
-+---------+-----------+--------+
-|col | | |
-+---------+-----------+--------+
-|cols | | |
-+---------+-----------+--------+
-|comm | | |
-+---------+-----------+--------+
-|cp | | |
-+---------+-----------+--------+
-|csplit | | |
-+---------+-----------+--------+
-|cut | | |
-+---------+-----------+--------+
-|date | | |
-+---------+-----------+--------+
-|dirname | | |
-+---------+-----------+--------+
-|du | | |
-+---------+-----------+--------+
-|echo | | |
-+---------+-----------+--------+
-|env | | |
-+---------+-----------+--------+
-|expand | | |
-+---------+-----------+--------+
-|expr | | |
-+---------+-----------+--------+
-|false | | |
-+---------+-----------+--------+
-|fold | | |
-+---------+-----------+--------+
-|grep | | |
-+---------+-----------+--------+
-|head | | |
-+---------+-----------+--------+
-|hostname | | |
-+---------+-----------+--------+
-|kill | | |
-+---------+-----------+--------+
-|link | | |
-+---------+-----------+--------+
-|ln | | |
-+---------+-----------+--------+
-|logname | | |
-+---------+-----------+--------+
-|ls | | |
-+---------+-----------+--------+
-|md5sum | | |
-+---------+-----------+--------+
-|mkdir | | |
-+---------+-----------+--------+
-|mkfifo | | |
-+---------+-----------+--------+
-|mktemp | | |
-+---------+-----------+--------+
-|mv | | |
-+---------+-----------+--------+
-|nice | | |
-+---------+-----------+--------+
-|nl | | |
-+---------+-----------+--------+
-|nohup | | |
-+---------+-----------+--------+
-|paste | | |
-+---------+-----------+--------+
-|printenv | | |
-+---------+-----------+--------+
-|printf | | |
-+---------+-----------+--------+
-|pwd | | |
-+---------+-----------+--------+
-|readlink | | |
-+---------+-----------+--------+
-|renice | | |
-+---------+-----------+--------+
-|rm | | |
-+---------+-----------+--------+
-|rmdir | | |
-+---------+-----------+--------+
-|sleep | | |
-+---------+-----------+--------+
-|setsid | | |
-+---------+-----------+--------+
-|sort | | |
-+---------+-----------+--------+
-|split | | |
-+---------+-----------+--------+
-|sponge | | |
-+---------+-----------+--------+
-|strings | | |
-+---------+-----------+--------+
-|sync | | |
-+---------+-----------+--------+
-|tail | | |
-+---------+-----------+--------+
-|tar | | |
-+---------+-----------+--------+
-|tee | | |
-+---------+-----------+--------+
-|test | | |
-+---------+-----------+--------+
-|touch | | |
-+---------+-----------+--------+
-|tr | | |
-+---------+-----------+--------+
-|true | | |
-+---------+-----------+--------+
-|tty | | |
-+---------+-----------+--------+
-|uudecode | | |
-+---------+-----------+--------+
-|uuencode | | |
-+---------+-----------+--------+
-|uname | | |
-+---------+-----------+--------+
-|unexpand | | |
-+---------+-----------+--------+
-|uniq | | |
-+---------+-----------+--------+
-|unlink | | |
-+---------+-----------+--------+
-|seq | | |
-+---------+-----------+--------+
-|sha1sum | | |
-+---------+-----------+--------+
-|sha256sum| | |
-+---------+-----------+--------+
-|sha512sum| | |
-+---------+-----------+--------+
-|wc | | |
-+---------+-----------+--------+
-|xargs | | |
-+---------+-----------+--------+
-|yes | | |
-+---------+-----------+--------+
-
The complement of sbase is ubase[1] which is Linux-specific and
provides all the non-portable tools. Together they are intended to
form a base system similar to busybox but much smaller and suckless.
diff --git a/TODO b/TODO
@@ -26,7 +26,6 @@ tput
The following programs have been imported from OpenBSD and need
replacing or cleaning up:
-csplit
col
printf
diff --git a/csplit.1 b/csplit.1
@@ -1,166 +0,0 @@
-.\" $OpenBSD: csplit.1,v 1.11 2014/02/04 13:26:36 jmc Exp $
-.\"
-.\" Copyright (c) 2002 Tim J. Robbins.
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD: src/usr.bin/csplit/csplit.1,v 1.11 2005/01/25 22:29:51 tjr Exp $
-.\"
-.Dd $Mdocdate: February 4 2014 $
-.Dt CSPLIT 1
-.Os
-.Sh NAME
-.Nm csplit
-.Nd split files based on context
-.Sh SYNOPSIS
-.Nm
-.Op Fl ks
-.Op Fl f Ar prefix
-.Op Fl n Ar number
-.Ar file args ...
-.Sh DESCRIPTION
-The
-.Nm
-utility splits
-.Ar file
-into pieces using the patterns
-.Ar args .
-If
-.Ar file
-is
-a dash
-.Pq Sq - ,
-.Nm
-reads from standard input.
-.Pp
-Files are created with a prefix of
-.Dq xx
-and two decimal digits.
-The size of each file is written to standard output
-as it is created.
-If an error occurs whilst files are being created,
-or a
-.Dv HUP ,
-.Dv INT ,
-or
-.Dv TERM
-signal is received,
-all files previously written are removed.
-.Pp
-The options are as follows:
-.Bl -tag -width indent
-.It Fl f Ar prefix
-Create file names beginning with
-.Ar prefix ,
-instead of
-.Dq xx .
-.It Fl k
-Do not remove previously created files if an error occurs or a
-.Dv HUP ,
-.Dv INT ,
-or
-.Dv TERM
-signal is received.
-.It Fl n Ar number
-Create file names beginning with
-.Ar number
-of decimal digits after the prefix,
-instead of 2.
-.It Fl s
-Do not write the size of each output file to standard output as it is
-created.
-.El
-.Pp
-The
-.Ar args
-operands may be a combination of the following patterns:
-.Bl -tag -width indent
-.It Xo
-.Sm off
-.No / Ar regexp No /
-.Op Oo Cm + | - Oc Ar offset
-.Sm on
-.Xc
-Create a file containing the input from the current line to (but not including)
-the next line matching the given basic regular expression.
-An optional
-.Ar offset
-from the line that matched may be specified.
-.It Xo
-.Sm off
-.No % Ar regexp No %
-.Op Oo Cm + | - Oc Ar offset
-.Sm on
-.Xc
-Same as above but a file is not created for the output.
-.It Ar line_no
-Create containing the input from the current line to (but not including)
-the specified line number.
-.It { Ns Ar num Ns }
-Repeat the previous pattern the specified number of times.
-If it follows a line number pattern, a new file will be created for each
-.Ar line_no
-lines,
-.Ar num
-times.
-The first line of the file is line number 1 for historic reasons.
-.El
-.Pp
-After all the patterns have been processed, the remaining input data
-(if there is any) will be written to a new file.
-.Pp
-Requesting to split at a line before the current line number or past the
-end of the file will result in an error.
-.Sh EXIT STATUS
-.Ex -std csplit
-.Sh EXAMPLES
-Split the
-.Xr mdoc 7
-file
-.Pa foo.1
-into one file for each section (up to 21):
-.Pp
-.Dl "$ csplit -k foo.1 '%^\e.Sh%' '/^\e.Sh/' '{20}'"
-.Pp
-Split standard input after the first 99 lines and every 100 lines thereafter:
-.Pp
-.Dl "$ csplit -k - 100 '{19}'"
-.Sh SEE ALSO
-.Xr sed 1 ,
-.Xr split 1 ,
-.Xr re_format 7
-.Sh STANDARDS
-The
-.Nm
-utility is compliant with the
-.St -p1003.1-2008
-specification.
-.Sh HISTORY
-A
-.Nm
-command appeared in PWB
-.Ux .
-.Sh BUGS
-Input lines are limited to
-.Dv LINE_MAX
-(2048) bytes in length.
diff --git a/csplit.c b/csplit.c
@@ -1,451 +0,0 @@
-/* $OpenBSD: csplit.c,v 1.5 2014/05/20 01:25:23 guenther Exp $ */
-/* $FreeBSD: src/usr.bin/csplit/csplit.c,v 1.9 2004/03/22 11:15:03 tjr Exp $ */
-
-/*-
- * Copyright (c) 2002 Tim J. Robbins.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * csplit -- split files based on context
- *
- * This utility splits its input into numbered output files by line number
- * or by a regular expression. Regular expression matches have an optional
- * offset with them, allowing the split to occur a specified number of
- * lines before or after the match.
- *
- * To handle negative offsets, we stop reading when the match occurs and
- * store the offset that the file should have been split at, then use
- * this output file as input until all the "overflowed" lines have been read.
- * The file is then closed and truncated to the correct length.
- *
- * We assume that the output files can be seeked upon (ie. they cannot be
- * symlinks to named pipes or character devices), but make no such
- * assumption about the input.
- */
-
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#include <regex.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "util.h"
-
-static void cleanup(void);
-static void do_lineno(const char *);
-static void do_rexp(const char *);
-static char *get_line(void);
-static void handlesig(int);
-static FILE *newfile(void);
-static void toomuch(FILE *, long);
-static void usage(void);
-
-/*
- * Command line options
- */
-static const char *prefix; /* File name prefix */
-static long sufflen; /* Number of decimal digits for suffix */
-static int sflag; /* Suppress output of file names */
-static int kflag; /* Keep output if error occurs */
-
-/*
- * Other miscellaneous globals (XXX too many)
- */
-static long lineno; /* Current line number in input file */
-static long reps; /* Number of repetitions for this pattern */
-static long nfiles; /* Number of files output so far */
-static long maxfiles; /* Maximum number of files we can create */
-static char currfile[PATH_MAX]; /* Current output file */
-static const char *infn; /* Name of the input file */
-static FILE *infile; /* Input file handle */
-static FILE *overfile; /* Overflow file for toomuch() */
-static off_t truncofs; /* Offset this file should be truncated at */
-static int doclean; /* Should cleanup() remove output? */
-
-int
-main(int argc, char *argv[])
-{
- struct sigaction sa;
- long i;
- const char *expr;
- char *ep, *p;
- FILE *ofp;
-
- kflag = sflag = 0;
- prefix = "xx";
- sufflen = 2;
-
- ARGBEGIN {
- case 'f':
- prefix = EARGF(usage());
- break;
- case 'k':
- kflag = 1;
- break;
- case 'n':
- sufflen = estrtol(EARGF(usage()), 10);
- break;
- case 's':
- sflag = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (sufflen + strlen(prefix) >= PATH_MAX)
- eprintf("name too long\n");
-
- if ((infn = *argv++) == NULL)
- usage();
- if (strcmp(infn, "-") == 0) {
- infile = stdin;
- infn = "stdin";
- } else if ((infile = fopen(infn, "r")) == NULL)
- eprintf("fopen %s:", infn);
-
- if (!kflag) {
- doclean = 1;
- atexit(cleanup);
- sa.sa_flags = 0;
- sa.sa_handler = handlesig;
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGINT);
- sigaddset(&sa.sa_mask, SIGTERM);
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- }
-
- lineno = 0;
- nfiles = 0;
- truncofs = 0;
- overfile = NULL;
-
- /* Ensure 10^sufflen < LONG_MAX. */
- for (maxfiles = 1, i = 0; i < sufflen; i++) {
- if (maxfiles > LONG_MAX / 10)
- eprintf("%ld: suffix too long (limit %ld)\n",
- sufflen, i);
- maxfiles *= 10;
- }
-
- /* Create files based on supplied patterns. */
- while (nfiles < maxfiles - 1 && (expr = *argv++) != NULL) {
- /* Look ahead & see if this pattern has any repetitions. */
- if (*argv != NULL && **argv == '{') {
- errno = 0;
- reps = strtol(*argv + 1, &ep, 10);
- if (reps < 0 || *ep != '}' || errno != 0)
- eprintf("%s: bad repetition count\n", *argv + 1);
- argv++;
- } else
- reps = 0;
-
- if (*expr == '/' || *expr == '%') {
- do {
- do_rexp(expr);
- } while (reps-- != 0 && nfiles < maxfiles - 1);
- } else if (isdigit((unsigned char)*expr))
- do_lineno(expr);
- else
- eprintf("%s: unrecognised pattern\n", expr);
- }
-
- /* Copy the rest into a new file. */
- if (!feof(infile)) {
- ofp = newfile();
- while ((p = get_line()) != NULL && fputs(p, ofp) == 0)
- ;
- if (!sflag)
- printf("%jd\n", (intmax_t)ftello(ofp));
- if (fclose(ofp) != 0)
- eprintf("fclose %s:", currfile);
- }
-
- toomuch(NULL, 0);
- doclean = 0;
-
- return (0);
-}
-
-static void
-usage(void)
-{
- eprintf("usage: %s [-ks] [-f prefix] [-n number] file args ...\n", argv0);
-}
-
-/* ARGSUSED */
-static void
-handlesig(int sig)
-{
- const char msg[] = "csplit: caught signal, cleaning up\n";
-
- write(STDERR_FILENO, msg, sizeof(msg) - 1);
- cleanup();
- _exit(2);
-}
-
-/* Create a new output file. */
-static FILE *
-newfile(void)
-{
- FILE *fp;
-
- if ((size_t)snprintf(currfile, sizeof(currfile), "%s%0*ld", prefix,
- (int)sufflen, nfiles) >= sizeof(currfile))
- eprintf("%s: name too long\n", currfile);
- if ((fp = fopen(currfile, "w+")) == NULL)
- eprintf("fopen %s:", currfile);
- nfiles++;
-
- return (fp);
-}
-
-/* Remove partial output, called before exiting. */
-static void
-cleanup(void)
-{
- char fnbuf[PATH_MAX];
- long i;
-
- if (!doclean)
- return;
-
- /*
- * NOTE: One cannot portably assume to be able to call snprintf() from
- * inside a signal handler. It is, however, safe to do on OpenBSD.
- */
- for (i = 0; i < nfiles; i++) {
- snprintf(fnbuf, sizeof(fnbuf), "%s%0*ld", prefix,
- (int)sufflen, i);
- unlink(fnbuf);
- }
-}
-
-/* Read a line from the input into a static buffer. */
-static char *
-get_line(void)
-{
- static char lbuf[LINE_MAX];
- FILE *src;
-
- src = overfile != NULL ? overfile : infile;
-
-again: if (fgets(lbuf, sizeof(lbuf), src) == NULL) {
- if (src == overfile) {
- src = infile;
- goto again;
- }
- return (NULL);
- }
- if (ferror(src))
- eprintf("%s: read error:", infn);
- lineno++;
-
- return (lbuf);
-}
-
-/* Conceptually rewind the input (as obtained by get_line()) back `n' lines. */
-static void
-toomuch(FILE *ofp, long n)
-{
- char buf[BUFSIZ];
- size_t i, nread;
-
- if (overfile != NULL) {
- /*
- * Truncate the previous file we overflowed into back to
- * the correct length, close it.
- */
- if (fflush(overfile) != 0)
- eprintf("overflow\n");
- if (ftruncate(fileno(overfile), truncofs) != 0)
- eprintf("overflow\n");
- if (fclose(overfile) != 0)
- eprintf("overflow\n");
- overfile = NULL;
- }
-
- if (n == 0)
- /* Just tidying up */
- return;
-
- lineno -= n;
-
- /*
- * Wind the overflow file backwards to `n' lines before the
- * current one.
- */
- do {
- if (ftello(ofp) < (off_t)sizeof(buf))
- rewind(ofp);
- else
- fseeko(ofp, -(off_t)sizeof(buf), SEEK_CUR);
- if (ferror(ofp))
- eprintf("%s: can't seek:", currfile);
- if ((nread = fread(buf, 1, sizeof(buf), ofp)) == 0)
- eprintf("can't read overflowed output\n");
- if (fseeko(ofp, -(off_t)nread, SEEK_CUR) != 0)
- eprintf("fseeko %s:", currfile);
- for (i = 1; i <= nread; i++)
- if (buf[nread - i] == '\n' && n-- == 0)
- break;
- if (ftello(ofp) == 0)
- break;
- } while (n > 0);
- if (fseeko(ofp, (off_t)(nread - i + 1), SEEK_CUR) != 0)
- eprintf("fseeko %s:", currfile);
-
- /*
- * get_line() will read from here. Next call will truncate to
- * truncofs in this file.
- */
- overfile = ofp;
- truncofs = ftello(overfile);
-}
-
-/* Handle splits for /regexp/ and %regexp% patterns. */
-static void
-do_rexp(const char *expr)
-{
- regex_t cre;
- intmax_t nwritten;
- long ofs;
- int first;
- char *ecopy, *ep, *p, *pofs, *re;
- FILE *ofp;
-
- if ((ecopy = strdup(expr)) == NULL)
- eprintf("strdup:");
-
- re = ecopy + 1;
- if ((pofs = strrchr(ecopy, *expr)) == NULL || pofs[-1] == '\\')
- eprintf("%s: missing trailing %c\n", expr, *expr);
- *pofs++ = '\0';
-
- if (*pofs != '\0') {
- errno = 0;
- ofs = strtol(pofs, &ep, 10);
- if (*ep != '\0' || errno != 0)
- eprintf("%s: bad offset\n", pofs);
- } else
- ofs = 0;
-
- eregcomp(&cre, re, REG_NOSUB);
-
- if (*expr == '/')
- /* /regexp/: Save results to a file. */
- ofp = newfile();
- else {
- /* %regexp%: Make a temporary file for overflow. */
- if ((ofp = tmpfile()) == NULL)
- eprintf("tmpfile:");
- }
-
- /* Read and output lines until we get a match. */
- first = 1;
- while ((p = get_line()) != NULL) {
- if (fputs(p, ofp) != 0)
- break;
- if (!first && regexec(&cre, p, 0, NULL, 0) == 0)
- break;
- first = 0;
- }
-
- if (p == NULL)
- eprintf("%s: no match\n", re);
-
- if (ofs <= 0) {
- /*
- * Negative (or zero) offset: throw back any lines we should
- * not have read yet.
- */
- if (p != NULL) {
- toomuch(ofp, -ofs + 1);
- nwritten = (intmax_t)truncofs;
- } else
- nwritten = (intmax_t)ftello(ofp);
- } else {
- /*
- * Positive offset: copy the requested number of lines
- * after the match.
- */
- while (--ofs > 0 && (p = get_line()) != NULL)
- fputs(p, ofp);
- toomuch(NULL, 0);
- nwritten = (intmax_t)ftello(ofp);
- if (fclose(ofp) != 0)
- eprintf("fclose %s:", currfile);
- }
-
- if (!sflag && *expr == '/')
- printf("%jd\n", nwritten);
-
- regfree(&cre);
- free(ecopy);
-}
-
-/* Handle splits based on line number. */
-static void
-do_lineno(const char *expr)
-{
- long lastline, tgtline;
- char *ep, *p;
- FILE *ofp;
-
- errno = 0;
- tgtline = strtol(expr, &ep, 10);
- if (tgtline <= 0 || errno != 0 || *ep != '\0')
- eprintf("%s: bad line number\n", expr);
- lastline = tgtline;
- if (lastline <= lineno)
- eprintf("%s: can't go backwards\n", expr);
-
- while (nfiles < maxfiles - 1) {
- ofp = newfile();
- while (lineno + 1 != lastline) {
- if ((p = get_line()) == NULL)
- eprintf("%ld: out of range\n", lastline);
- if (fputs(p, ofp) != 0)
- break;
- }
- if (!sflag)
- printf("%jd\n", (intmax_t)ftello(ofp));
- if (fclose(ofp) != 0)
- eprintf("fclose %s:", currfile);
- if (reps-- == 0)
- break;
- lastline += tgtline;
- }
-}