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.
This commit is contained in:
parent
1436518f9d
commit
0d7c2351b4
1
Makefile
1
Makefile
|
@ -67,7 +67,6 @@ BIN =\
|
||||||
cols\
|
cols\
|
||||||
comm\
|
comm\
|
||||||
cp\
|
cp\
|
||||||
csplit\
|
|
||||||
cut\
|
cut\
|
||||||
date\
|
date\
|
||||||
dirname\
|
dirname\
|
||||||
|
|
159
README
159
README
|
@ -4,165 +4,6 @@ sbase - suckless unix tools
|
||||||
sbase is a collection of unix tools that are inherently portable
|
sbase is a collection of unix tools that are inherently portable
|
||||||
across UNIX and UNIX-like systems.
|
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
|
The complement of sbase is ubase[1] which is Linux-specific and
|
||||||
provides all the non-portable tools. Together they are intended to
|
provides all the non-portable tools. Together they are intended to
|
||||||
form a base system similar to busybox but much smaller and suckless.
|
form a base system similar to busybox but much smaller and suckless.
|
||||||
|
|
1
TODO
1
TODO
|
@ -26,7 +26,6 @@ tput
|
||||||
The following programs have been imported from OpenBSD and need
|
The following programs have been imported from OpenBSD and need
|
||||||
replacing or cleaning up:
|
replacing or cleaning up:
|
||||||
|
|
||||||
csplit
|
|
||||||
col
|
col
|
||||||
printf
|
printf
|
||||||
|
|
||||||
|
|
166
csplit.1
166
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.
|
|
451
csplit.c
451
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;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user