-
Notifications
You must be signed in to change notification settings - Fork 7
/
filter.c
159 lines (136 loc) · 4.07 KB
/
filter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
@(#)File: $RCSfile: filter.c,v $
@(#)Version: $Revision: 2015.2 $
@(#)Last changed: $Date: 2015/02/17 04:53:03 $
@(#)Purpose: Classic File Filter
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 1987-89,1991,1993,1996-99,2002-05,2008,2012,2014-15
@(#)Product: SCC Version 8.0.3 (2022-05-30)
*/
/*TABSTOP=4*/
#include "filter.h"
#include "stderr.h"
#include <string.h>
#include <errno.h>
static char dash[] = "-";
static char *no_args[] = { dash, 0 };
static const char em_invoptnum[] = "invalid (negative) option number";
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_filter_c[];
const char jlss_id_filter_c[] = "@(#)$Id: filter.c,v 2015.2 2015/02/17 04:53:03 jleffler Exp $";
#endif /* lint */
/*
Purpose: Classic File Filter
Maintenance Log
---------------
09/03/1987 JL Original version stabilised
18/04/1988 JL Now pass fp and file name to function
15/12/1991 JL Upgrade for ANSI C
29/06/1993 JL Rename to filter and accept optind argument
15/10/1996 JL Remove non-ANSI support and ffilter(); rename file
31/03/1998 JL Add support for continuing on error opening a file
22/08/2003 JL Remove filter_setcontinue - always continue on error.
18/12/2004 JL Rename Filter to ClassicFilter; do not modify argv.
27/12/2014 JL Support filter_numfiles()
Arguments
---------
argc In: Number of arguments
argv In: Argument list of program
optind In: Offset in list to start at
function In: Function to process file
Comments
--------
1. For every non-flag option in the argument list, or standard input
if there are no non-flag arguments, run 'function' on file.
2. If a file name is '-', use standard input.
3. The optnum argument should normally be the value of optind as
supplied by getopt(3). But it should be the index of the first
non-flag argument.
*/
void filter(int argc, char **argv, int optnum, ClassicFilter function)
{
int i;
FILE *fp;
if (optnum < 0)
err_abort(em_invoptnum);
else if (optnum >= argc)
{
argc = 1;
argv = no_args;
optnum = 0;
}
filter_setnumfiles(argc - optnum);
for (i = optnum; i < argc; i++)
{
if (strcmp(argv[i], "-") == 0)
{
char name[] = "(standard input)";
(*function)(stdin, name);
}
else if ((fp = fopen(argv[i], "r")) != NULL)
{
(*function)(fp, argv[i]);
fclose(fp);
}
else
err_sysrem("failed to open file %s\n", argv[i]);
}
}
#ifdef TEST
/*
** Test program
** -- with no arguments, copies named files to standard output
** -- with -v argument, makes non-printing characters visible
** -- with -V argument, prints version information
*/
#include <ctype.h>
#include <unistd.h>
static void fcopy(FILE *f1, FILE *f2)
{
char buffer[BUFSIZ];
size_t n;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), f1)) > 0)
{
if (fwrite(buffer, sizeof(char), n, f2) != n)
err_error("write failed\n");
}
}
static void vis(FILE *fp, char *fn)
{
int c;
fprintf(stdout, "%s:\n", fn);
while ((c = getc(fp)) != EOF)
{
if (c == '\n' || c == '\t')
putchar(c);
else if (c > 127 || !isprint(c))
printf("\\%03o", c);
else
putchar(c);
}
}
static void cat(FILE *fp, char *fn)
{
fprintf(stdout, "%s:\n", fn);
fcopy(fp, stdout);
}
int main(int argc, char **argv)
{
int opt;
ClassicFilter f = cat;
err_setarg0(argv[0]);
opterr = 0;
while ((opt = getopt(argc, argv, "Vv")) != EOF)
{
if (opt == 'v')
f = vis;
else if (opt == 'V')
err_version("FILTER", "$Revision: 2015.2 $ ($Date: 2015/02/17 04:53:03 $)");
else
err_usage("[-vV] [file ...]");
}
filter(argc, argv, optind, f);
return(0);
}
#endif /* TEST */