mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-29 16:44:03 +00:00
Import some parts of CSRG 4.4BSD-Lite2 usr.bin sources to fix tree build.
This commit is contained in:
parent
ed00518230
commit
0da30e9aa7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/CSRG/dist/; revision=23690
139
usr.bin/basename/basename.c
Normal file
139
usr.bin/basename/basename.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)basename.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *p;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1 && argc != 2)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* (1) If string is // it is implementation defined whether steps (2)
|
||||
* through (5) are skipped or processed.
|
||||
*
|
||||
* (2) If string consists entirely of slash characters, string shall
|
||||
* be set to a single slash character. In this case, skip steps
|
||||
* (3) through (5).
|
||||
*/
|
||||
for (p = *argv;; ++p) {
|
||||
if (!*p) {
|
||||
if (p > *argv)
|
||||
(void)printf("/\n");
|
||||
else
|
||||
(void)printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
if (*p != '/')
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* (3) If there are any trailing slash characters in string, they
|
||||
* shall be removed.
|
||||
*/
|
||||
for (; *p; ++p)
|
||||
continue;
|
||||
while (*--p == '/')
|
||||
continue;
|
||||
*++p = '\0';
|
||||
|
||||
/*
|
||||
* (4) If there are any slash characters remaining in string, the
|
||||
* prefix of string up to an including the last slash character
|
||||
* in string shall be removed.
|
||||
*/
|
||||
while (--p >= *argv)
|
||||
if (*p == '/')
|
||||
break;
|
||||
++p;
|
||||
|
||||
/*
|
||||
* (5) If the suffix operand is present, is not identical to the
|
||||
* characters remaining in string, and is identical to a suffix
|
||||
* of the characters remaining in string, the suffix suffix
|
||||
* shall be removed from string.
|
||||
*/
|
||||
if (*++argv) {
|
||||
int suffixlen, stringlen, off;
|
||||
|
||||
suffixlen = strlen(*argv);
|
||||
stringlen = strlen(p);
|
||||
|
||||
if (suffixlen < stringlen) {
|
||||
off = stringlen - suffixlen;
|
||||
if (!strcmp(p + off, *argv))
|
||||
p[off] = '\0';
|
||||
}
|
||||
}
|
||||
(void)printf("%s\n", p);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: basename string [suffix]\n");
|
||||
exit(1);
|
||||
}
|
538
usr.bin/col/col.c
Normal file
538
usr.bin/col/col.c
Normal file
@ -0,0 +1,538 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Michael Rendell of the Memorial University of Newfoundland.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1990, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)col.c 8.5 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BS '\b' /* backspace */
|
||||
#define TAB '\t' /* tab */
|
||||
#define SPACE ' ' /* space */
|
||||
#define NL '\n' /* newline */
|
||||
#define CR '\r' /* carriage return */
|
||||
#define ESC '\033' /* escape */
|
||||
#define SI '\017' /* shift in to normal character set */
|
||||
#define SO '\016' /* shift out to alternate character set */
|
||||
#define VT '\013' /* vertical tab (aka reverse line feed) */
|
||||
#define RLF '\007' /* ESC-07 reverse line feed */
|
||||
#define RHLF '\010' /* ESC-010 reverse half-line feed */
|
||||
#define FHLF '\011' /* ESC-011 forward half-line feed */
|
||||
|
||||
/* build up at least this many lines before flushing them out */
|
||||
#define BUFFER_MARGIN 32
|
||||
|
||||
typedef char CSET;
|
||||
|
||||
typedef struct char_str {
|
||||
#define CS_NORMAL 1
|
||||
#define CS_ALTERNATE 2
|
||||
short c_column; /* column character is in */
|
||||
CSET c_set; /* character set (currently only 2) */
|
||||
char c_char; /* character in question */
|
||||
} CHAR;
|
||||
|
||||
typedef struct line_str LINE;
|
||||
struct line_str {
|
||||
CHAR *l_line; /* characters on the line */
|
||||
LINE *l_prev; /* previous line */
|
||||
LINE *l_next; /* next line */
|
||||
int l_lsize; /* allocated sizeof l_line */
|
||||
int l_line_len; /* strlen(l_line) */
|
||||
int l_needs_sort; /* set if chars went in out of order */
|
||||
int l_max_col; /* max column in the line */
|
||||
};
|
||||
|
||||
LINE *alloc_line __P((void));
|
||||
void dowarn __P((int));
|
||||
void flush_line __P((LINE *));
|
||||
void flush_lines __P((int));
|
||||
void flush_blanks __P((void));
|
||||
void free_line __P((LINE *));
|
||||
void usage __P((void));
|
||||
void wrerr __P((void));
|
||||
void *xmalloc __P((void *, size_t));
|
||||
|
||||
CSET last_set; /* char_set of last char printed */
|
||||
LINE *lines;
|
||||
int compress_spaces; /* if doing space -> tab conversion */
|
||||
int fine; /* if `fine' resolution (half lines) */
|
||||
int max_bufd_lines; /* max # lines to keep in memory */
|
||||
int nblank_lines; /* # blanks after last flushed line */
|
||||
int no_backspaces; /* if not to output any backspaces */
|
||||
|
||||
#define PUTC(ch) \
|
||||
if (putchar(ch) == EOF) \
|
||||
wrerr();
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
CHAR *c;
|
||||
CSET cur_set; /* current character set */
|
||||
LINE *l; /* current line */
|
||||
int extra_lines; /* # of lines above first line */
|
||||
int cur_col; /* current column */
|
||||
int cur_line; /* line number of current position */
|
||||
int max_line; /* max value of cur_line */
|
||||
int this_line; /* line l points to */
|
||||
int nflushd_lines; /* number of lines that were flushed */
|
||||
int adjust, opt, warned;
|
||||
|
||||
max_bufd_lines = 128;
|
||||
compress_spaces = 1; /* compress spaces into tabs */
|
||||
while ((opt = getopt(argc, argv, "bfhl:x")) != EOF)
|
||||
switch (opt) {
|
||||
case 'b': /* do not output backspaces */
|
||||
no_backspaces = 1;
|
||||
break;
|
||||
case 'f': /* allow half forward line feeds */
|
||||
fine = 1;
|
||||
break;
|
||||
case 'h': /* compress spaces into tabs */
|
||||
compress_spaces = 1;
|
||||
break;
|
||||
case 'l': /* buffered line count */
|
||||
if ((max_bufd_lines = atoi(optarg)) <= 0) {
|
||||
(void)fprintf(stderr,
|
||||
"col: bad -l argument %s.\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'x': /* do not compress spaces into tabs */
|
||||
compress_spaces = 0;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (optind != argc)
|
||||
usage();
|
||||
|
||||
/* this value is in half lines */
|
||||
max_bufd_lines *= 2;
|
||||
|
||||
adjust = cur_col = extra_lines = warned = 0;
|
||||
cur_line = max_line = nflushd_lines = this_line = 0;
|
||||
cur_set = last_set = CS_NORMAL;
|
||||
lines = l = alloc_line();
|
||||
|
||||
while ((ch = getchar()) != EOF) {
|
||||
if (!isgraph(ch)) {
|
||||
switch (ch) {
|
||||
case BS: /* can't go back further */
|
||||
if (cur_col == 0)
|
||||
continue;
|
||||
--cur_col;
|
||||
continue;
|
||||
case CR:
|
||||
cur_col = 0;
|
||||
continue;
|
||||
case ESC: /* just ignore EOF */
|
||||
switch(getchar()) {
|
||||
case RLF:
|
||||
cur_line -= 2;
|
||||
break;
|
||||
case RHLF:
|
||||
cur_line--;
|
||||
break;
|
||||
case FHLF:
|
||||
cur_line++;
|
||||
if (cur_line > max_line)
|
||||
max_line = cur_line;
|
||||
}
|
||||
continue;
|
||||
case NL:
|
||||
cur_line += 2;
|
||||
if (cur_line > max_line)
|
||||
max_line = cur_line;
|
||||
cur_col = 0;
|
||||
continue;
|
||||
case SPACE:
|
||||
++cur_col;
|
||||
continue;
|
||||
case SI:
|
||||
cur_set = CS_NORMAL;
|
||||
continue;
|
||||
case SO:
|
||||
cur_set = CS_ALTERNATE;
|
||||
continue;
|
||||
case TAB: /* adjust column */
|
||||
cur_col |= 7;
|
||||
++cur_col;
|
||||
continue;
|
||||
case VT:
|
||||
cur_line -= 2;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Must stuff ch in a line - are we at the right one? */
|
||||
if (cur_line != this_line - adjust) {
|
||||
LINE *lnew;
|
||||
int nmove;
|
||||
|
||||
adjust = 0;
|
||||
nmove = cur_line - this_line;
|
||||
if (!fine) {
|
||||
/* round up to next line */
|
||||
if (cur_line & 1) {
|
||||
adjust = 1;
|
||||
nmove++;
|
||||
}
|
||||
}
|
||||
if (nmove < 0) {
|
||||
for (; nmove < 0 && l->l_prev; nmove++)
|
||||
l = l->l_prev;
|
||||
if (nmove) {
|
||||
if (nflushd_lines == 0) {
|
||||
/*
|
||||
* Allow backup past first
|
||||
* line if nothing has been
|
||||
* flushed yet.
|
||||
*/
|
||||
for (; nmove < 0; nmove++) {
|
||||
lnew = alloc_line();
|
||||
l->l_prev = lnew;
|
||||
lnew->l_next = l;
|
||||
l = lines = lnew;
|
||||
extra_lines++;
|
||||
}
|
||||
} else {
|
||||
if (!warned++)
|
||||
dowarn(cur_line);
|
||||
cur_line -= nmove;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* may need to allocate here */
|
||||
for (; nmove > 0 && l->l_next; nmove--)
|
||||
l = l->l_next;
|
||||
for (; nmove > 0; nmove--) {
|
||||
lnew = alloc_line();
|
||||
lnew->l_prev = l;
|
||||
l->l_next = lnew;
|
||||
l = lnew;
|
||||
}
|
||||
}
|
||||
this_line = cur_line + adjust;
|
||||
nmove = this_line - nflushd_lines;
|
||||
if (nmove >= max_bufd_lines + BUFFER_MARGIN) {
|
||||
nflushd_lines += nmove - max_bufd_lines;
|
||||
flush_lines(nmove - max_bufd_lines);
|
||||
}
|
||||
}
|
||||
/* grow line's buffer? */
|
||||
if (l->l_line_len + 1 >= l->l_lsize) {
|
||||
int need;
|
||||
|
||||
need = l->l_lsize ? l->l_lsize * 2 : 90;
|
||||
l->l_line = (CHAR *)xmalloc((void *) l->l_line,
|
||||
(unsigned) need * sizeof(CHAR));
|
||||
l->l_lsize = need;
|
||||
}
|
||||
c = &l->l_line[l->l_line_len++];
|
||||
c->c_char = ch;
|
||||
c->c_set = cur_set;
|
||||
c->c_column = cur_col;
|
||||
/*
|
||||
* If things are put in out of order, they will need sorting
|
||||
* when it is flushed.
|
||||
*/
|
||||
if (cur_col < l->l_max_col)
|
||||
l->l_needs_sort = 1;
|
||||
else
|
||||
l->l_max_col = cur_col;
|
||||
cur_col++;
|
||||
}
|
||||
if (max_line == 0)
|
||||
exit(0); /* no lines, so just exit */
|
||||
|
||||
/* goto the last line that had a character on it */
|
||||
for (; l->l_next; l = l->l_next)
|
||||
this_line++;
|
||||
flush_lines(this_line - nflushd_lines + extra_lines + 1);
|
||||
|
||||
/* make sure we leave things in a sane state */
|
||||
if (last_set != CS_NORMAL)
|
||||
PUTC('\017');
|
||||
|
||||
/* flush out the last few blank lines */
|
||||
nblank_lines = max_line - this_line;
|
||||
if (max_line & 1)
|
||||
nblank_lines++;
|
||||
else if (!nblank_lines)
|
||||
/* missing a \n on the last line? */
|
||||
nblank_lines = 2;
|
||||
flush_blanks();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
flush_lines(nflush)
|
||||
int nflush;
|
||||
{
|
||||
LINE *l;
|
||||
|
||||
while (--nflush >= 0) {
|
||||
l = lines;
|
||||
lines = l->l_next;
|
||||
if (l->l_line) {
|
||||
flush_blanks();
|
||||
flush_line(l);
|
||||
}
|
||||
nblank_lines++;
|
||||
if (l->l_line)
|
||||
(void)free((void *)l->l_line);
|
||||
free_line(l);
|
||||
}
|
||||
if (lines)
|
||||
lines->l_prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a number of newline/half newlines. If fine flag is set, nblank_lines
|
||||
* is the number of half line feeds, otherwise it is the number of whole line
|
||||
* feeds.
|
||||
*/
|
||||
void
|
||||
flush_blanks()
|
||||
{
|
||||
int half, i, nb;
|
||||
|
||||
half = 0;
|
||||
nb = nblank_lines;
|
||||
if (nb & 1) {
|
||||
if (fine)
|
||||
half = 1;
|
||||
else
|
||||
nb++;
|
||||
}
|
||||
nb /= 2;
|
||||
for (i = nb; --i >= 0;)
|
||||
PUTC('\n');
|
||||
if (half) {
|
||||
PUTC('\033');
|
||||
PUTC('9');
|
||||
if (!nb)
|
||||
PUTC('\r');
|
||||
}
|
||||
nblank_lines = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a line to stdout taking care of space to tab conversion (-h flag)
|
||||
* and character set shifts.
|
||||
*/
|
||||
void
|
||||
flush_line(l)
|
||||
LINE *l;
|
||||
{
|
||||
CHAR *c, *endc;
|
||||
int nchars, last_col, this_col;
|
||||
|
||||
last_col = 0;
|
||||
nchars = l->l_line_len;
|
||||
|
||||
if (l->l_needs_sort) {
|
||||
static CHAR *sorted;
|
||||
static int count_size, *count, i, save, sorted_size, tot;
|
||||
|
||||
/*
|
||||
* Do an O(n) sort on l->l_line by column being careful to
|
||||
* preserve the order of characters in the same column.
|
||||
*/
|
||||
if (l->l_lsize > sorted_size) {
|
||||
sorted_size = l->l_lsize;
|
||||
sorted = (CHAR *)xmalloc((void *)sorted,
|
||||
(unsigned)sizeof(CHAR) * sorted_size);
|
||||
}
|
||||
if (l->l_max_col >= count_size) {
|
||||
count_size = l->l_max_col + 1;
|
||||
count = (int *)xmalloc((void *)count,
|
||||
(unsigned)sizeof(int) * count_size);
|
||||
}
|
||||
memset((char *)count, 0, sizeof(int) * l->l_max_col + 1);
|
||||
for (i = nchars, c = l->l_line; --i >= 0; c++)
|
||||
count[c->c_column]++;
|
||||
|
||||
/*
|
||||
* calculate running total (shifted down by 1) to use as
|
||||
* indices into new line.
|
||||
*/
|
||||
for (tot = 0, i = 0; i <= l->l_max_col; i++) {
|
||||
save = count[i];
|
||||
count[i] = tot;
|
||||
tot += save;
|
||||
}
|
||||
|
||||
for (i = nchars, c = l->l_line; --i >= 0; c++)
|
||||
sorted[count[c->c_column]++] = *c;
|
||||
c = sorted;
|
||||
} else
|
||||
c = l->l_line;
|
||||
while (nchars > 0) {
|
||||
this_col = c->c_column;
|
||||
endc = c;
|
||||
do {
|
||||
++endc;
|
||||
} while (--nchars > 0 && this_col == endc->c_column);
|
||||
|
||||
/* if -b only print last character */
|
||||
if (no_backspaces)
|
||||
c = endc - 1;
|
||||
|
||||
if (this_col > last_col) {
|
||||
int nspace = this_col - last_col;
|
||||
|
||||
if (compress_spaces && nspace > 1) {
|
||||
int ntabs;
|
||||
|
||||
ntabs = this_col / 8 - last_col / 8;
|
||||
nspace -= ntabs * 8;
|
||||
while (--ntabs >= 0)
|
||||
PUTC('\t');
|
||||
}
|
||||
while (--nspace >= 0)
|
||||
PUTC(' ');
|
||||
last_col = this_col;
|
||||
}
|
||||
last_col++;
|
||||
|
||||
for (;;) {
|
||||
if (c->c_set != last_set) {
|
||||
switch (c->c_set) {
|
||||
case CS_NORMAL:
|
||||
PUTC('\017');
|
||||
break;
|
||||
case CS_ALTERNATE:
|
||||
PUTC('\016');
|
||||
}
|
||||
last_set = c->c_set;
|
||||
}
|
||||
PUTC(c->c_char);
|
||||
if (++c >= endc)
|
||||
break;
|
||||
PUTC('\b');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define NALLOC 64
|
||||
|
||||
static LINE *line_freelist;
|
||||
|
||||
LINE *
|
||||
alloc_line()
|
||||
{
|
||||
LINE *l;
|
||||
int i;
|
||||
|
||||
if (!line_freelist) {
|
||||
l = (LINE *)xmalloc((void *)NULL, sizeof(LINE) * NALLOC);
|
||||
line_freelist = l;
|
||||
for (i = 1; i < NALLOC; i++, l++)
|
||||
l->l_next = l + 1;
|
||||
l->l_next = NULL;
|
||||
}
|
||||
l = line_freelist;
|
||||
line_freelist = l->l_next;
|
||||
|
||||
memset(l, 0, sizeof(LINE));
|
||||
return (l);
|
||||
}
|
||||
|
||||
void
|
||||
free_line(l)
|
||||
LINE *l;
|
||||
{
|
||||
|
||||
l->l_next = line_freelist;
|
||||
line_freelist = l;
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(p, size)
|
||||
void *p;
|
||||
size_t size;
|
||||
{
|
||||
|
||||
if (!(p = (void *)realloc(p, size)))
|
||||
err(1, NULL);
|
||||
return (p);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: col [-bfx] [-l nline]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
wrerr()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "col: write error.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
dowarn(line)
|
||||
int line;
|
||||
{
|
||||
|
||||
warnx("warning: can't back up %s",
|
||||
line < 0 ? "past first line" : "-- line already flushed");
|
||||
}
|
168
usr.bin/colrm/colrm.c
Normal file
168
usr.bin/colrm/colrm.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)colrm.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define TAB 8
|
||||
|
||||
void err __P((const char *, ...));
|
||||
void check __P((FILE *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register u_long column, start, stop;
|
||||
register int ch;
|
||||
char *p;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
start = stop = 0;
|
||||
switch(argc) {
|
||||
case 2:
|
||||
stop = strtol(argv[1], &p, 10);
|
||||
if (stop <= 0 || *p)
|
||||
err("illegal column -- %s", argv[1]);
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
start = strtol(argv[0], &p, 10);
|
||||
if (start <= 0 || *p)
|
||||
err("illegal column -- %s", argv[0]);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (stop && start > stop)
|
||||
err("illegal start and stop columns");
|
||||
|
||||
for (column = 0;;) {
|
||||
switch (ch = getchar()) {
|
||||
case EOF:
|
||||
check(stdin);
|
||||
break;
|
||||
case '\b':
|
||||
if (column)
|
||||
--column;
|
||||
break;
|
||||
case '\n':
|
||||
column = 0;
|
||||
break;
|
||||
case '\t':
|
||||
column = (column + TAB) & ~(TAB - 1);
|
||||
break;
|
||||
default:
|
||||
++column;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((!start || column < start || stop && column > stop) &&
|
||||
putchar(ch) == EOF)
|
||||
check(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
check(stream)
|
||||
FILE *stream;
|
||||
{
|
||||
if (feof(stream))
|
||||
exit(0);
|
||||
if (ferror(stream))
|
||||
err("%s: %s",
|
||||
stream == stdin ? "stdin" : "stdout", strerror(errno));
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: colrm [start [stop]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "colrm: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
305
usr.bin/column/column.c
Normal file
305
usr.bin/column/column.c
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)column.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void c_columnate __P((void));
|
||||
void *emalloc __P((int));
|
||||
void input __P((FILE *));
|
||||
void maketbl __P((void));
|
||||
void print __P((void));
|
||||
void r_columnate __P((void));
|
||||
void usage __P((void));
|
||||
|
||||
int termwidth = 80; /* default terminal width */
|
||||
|
||||
int entries; /* number of records */
|
||||
int eval; /* exit value */
|
||||
int maxlength; /* longest record */
|
||||
char **list; /* array of pointers to records */
|
||||
char *separator = "\t "; /* field separator for table option */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct winsize win;
|
||||
FILE *fp;
|
||||
int ch, tflag, xflag;
|
||||
char *p;
|
||||
|
||||
if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
|
||||
if (p = getenv("COLUMNS"))
|
||||
termwidth = atoi(p);
|
||||
} else
|
||||
termwidth = win.ws_col;
|
||||
|
||||
tflag = xflag = 0;
|
||||
while ((ch = getopt(argc, argv, "c:s:tx")) != EOF)
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
termwidth = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
separator = optarg;
|
||||
break;
|
||||
case 't':
|
||||
tflag = 1;
|
||||
break;
|
||||
case 'x':
|
||||
xflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!*argv)
|
||||
input(stdin);
|
||||
else for (; *argv; ++argv)
|
||||
if (fp = fopen(*argv, "r")) {
|
||||
input(fp);
|
||||
(void)fclose(fp);
|
||||
} else {
|
||||
warn("%s", *argv);
|
||||
eval = 1;
|
||||
}
|
||||
|
||||
if (!entries)
|
||||
exit(eval);
|
||||
|
||||
if (tflag)
|
||||
maketbl();
|
||||
else if (maxlength >= termwidth)
|
||||
print();
|
||||
else if (xflag)
|
||||
c_columnate();
|
||||
else
|
||||
r_columnate();
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
#define TAB 8
|
||||
void
|
||||
c_columnate()
|
||||
{
|
||||
int chcnt, col, cnt, endcol, numcols;
|
||||
char **lp;
|
||||
|
||||
maxlength = (maxlength + TAB) & ~(TAB - 1);
|
||||
numcols = termwidth / maxlength;
|
||||
endcol = maxlength;
|
||||
for (chcnt = col = 0, lp = list;; ++lp) {
|
||||
chcnt += printf("%s", *lp);
|
||||
if (!--entries)
|
||||
break;
|
||||
if (++col == numcols) {
|
||||
chcnt = col = 0;
|
||||
endcol = maxlength;
|
||||
putchar('\n');
|
||||
} else {
|
||||
while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
|
||||
(void)putchar('\t');
|
||||
chcnt = cnt;
|
||||
}
|
||||
endcol += maxlength;
|
||||
}
|
||||
}
|
||||
if (chcnt)
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void
|
||||
r_columnate()
|
||||
{
|
||||
int base, chcnt, cnt, col, endcol, numcols, numrows, row;
|
||||
|
||||
maxlength = (maxlength + TAB) & ~(TAB - 1);
|
||||
numcols = termwidth / maxlength;
|
||||
numrows = entries / numcols;
|
||||
if (entries % numcols)
|
||||
++numrows;
|
||||
|
||||
for (row = 0; row < numrows; ++row) {
|
||||
endcol = maxlength;
|
||||
for (base = row, chcnt = col = 0; col < numcols; ++col) {
|
||||
chcnt += printf("%s", list[base]);
|
||||
if ((base += numrows) >= entries)
|
||||
break;
|
||||
while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
|
||||
(void)putchar('\t');
|
||||
chcnt = cnt;
|
||||
}
|
||||
endcol += maxlength;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print()
|
||||
{
|
||||
int cnt;
|
||||
char **lp;
|
||||
|
||||
for (cnt = entries, lp = list; cnt--; ++lp)
|
||||
(void)printf("%s\n", *lp);
|
||||
}
|
||||
|
||||
typedef struct _tbl {
|
||||
char **list;
|
||||
int cols, *len;
|
||||
} TBL;
|
||||
#define DEFCOLS 25
|
||||
|
||||
void
|
||||
maketbl()
|
||||
{
|
||||
TBL *t;
|
||||
int coloff, cnt;
|
||||
char *p, **lp;
|
||||
int *lens, maxcols;
|
||||
TBL *tbl;
|
||||
char **cols;
|
||||
|
||||
t = tbl = emalloc(entries * sizeof(TBL));
|
||||
cols = emalloc((maxcols = DEFCOLS) * sizeof(char *));
|
||||
lens = emalloc(maxcols * sizeof(int));
|
||||
for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
|
||||
for (coloff = 0, p = *lp; cols[coloff] = strtok(p, separator);
|
||||
p = NULL)
|
||||
if (++coloff == maxcols) {
|
||||
if (!(cols = realloc(cols, (u_int)maxcols +
|
||||
DEFCOLS * sizeof(char *))) ||
|
||||
!(lens = realloc(lens,
|
||||
(u_int)maxcols + DEFCOLS * sizeof(int))))
|
||||
err(1, NULL);
|
||||
memset((char *)lens + maxcols * sizeof(int),
|
||||
0, DEFCOLS * sizeof(int));
|
||||
maxcols += DEFCOLS;
|
||||
}
|
||||
t->list = emalloc(coloff * sizeof(char *));
|
||||
t->len = emalloc(coloff * sizeof(int));
|
||||
for (t->cols = coloff; --coloff >= 0;) {
|
||||
t->list[coloff] = cols[coloff];
|
||||
t->len[coloff] = strlen(cols[coloff]);
|
||||
if (t->len[coloff] > lens[coloff])
|
||||
lens[coloff] = t->len[coloff];
|
||||
}
|
||||
}
|
||||
for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
|
||||
for (coloff = 0; coloff < t->cols - 1; ++coloff)
|
||||
(void)printf("%s%*s", t->list[coloff],
|
||||
lens[coloff] - t->len[coloff] + 2, " ");
|
||||
(void)printf("%s\n", t->list[coloff]);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFNUM 1000
|
||||
#define MAXLINELEN (LINE_MAX + 1)
|
||||
|
||||
void
|
||||
input(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
static int maxentry;
|
||||
int len;
|
||||
char *p, buf[MAXLINELEN];
|
||||
|
||||
if (!list)
|
||||
list = emalloc((maxentry = DEFNUM) * sizeof(char *));
|
||||
while (fgets(buf, MAXLINELEN, fp)) {
|
||||
for (p = buf; *p && isspace(*p); ++p);
|
||||
if (!*p)
|
||||
continue;
|
||||
if (!(p = strchr(p, '\n'))) {
|
||||
warnx("line too long");
|
||||
eval = 1;
|
||||
continue;
|
||||
}
|
||||
*p = '\0';
|
||||
len = p - buf;
|
||||
if (maxlength < len)
|
||||
maxlength = len;
|
||||
if (entries == maxentry) {
|
||||
maxentry += DEFNUM;
|
||||
if (!(list = realloc(list,
|
||||
(u_int)maxentry * sizeof(char *))))
|
||||
err(1, NULL);
|
||||
}
|
||||
list[entries++] = strdup(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
emalloc(size)
|
||||
int size;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!(p = malloc(size)))
|
||||
err(1, NULL);
|
||||
memset(p, 0, size);
|
||||
return (p);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: column [-tx] [-c columns] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
187
usr.bin/comm/comm.c
Normal file
187
usr.bin/comm/comm.c
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Case Larsen.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)comm.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAXLINELEN (LINE_MAX + 1)
|
||||
|
||||
char *tabs[] = { "", "\t", "\t\t" };
|
||||
|
||||
FILE *file __P((char *));
|
||||
void show __P((FILE *, char *, char *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int comp, file1done, file2done, read1, read2;
|
||||
int ch, flag1, flag2, flag3;
|
||||
FILE *fp1, *fp2;
|
||||
char *col1, *col2, *col3;
|
||||
char **p, line1[MAXLINELEN], line2[MAXLINELEN];
|
||||
|
||||
flag1 = flag2 = flag3 = 1;
|
||||
while ((ch = getopt(argc, argv, "-123")) != EOF)
|
||||
switch(ch) {
|
||||
case '-':
|
||||
--optind;
|
||||
goto done;
|
||||
case '1':
|
||||
flag1 = 0;
|
||||
break;
|
||||
case '2':
|
||||
flag2 = 0;
|
||||
break;
|
||||
case '3':
|
||||
flag3 = 0;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
done: argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 2)
|
||||
usage();
|
||||
|
||||
fp1 = file(argv[0]);
|
||||
fp2 = file(argv[1]);
|
||||
|
||||
/* for each column printed, add another tab offset */
|
||||
p = tabs;
|
||||
col1 = col2 = col3 = NULL;
|
||||
if (flag1)
|
||||
col1 = *p++;
|
||||
if (flag2)
|
||||
col2 = *p++;
|
||||
if (flag3)
|
||||
col3 = *p;
|
||||
|
||||
for (read1 = read2 = 1;;) {
|
||||
/* read next line, check for EOF */
|
||||
if (read1)
|
||||
file1done = !fgets(line1, MAXLINELEN, fp1);
|
||||
if (read2)
|
||||
file2done = !fgets(line2, MAXLINELEN, fp2);
|
||||
|
||||
/* if one file done, display the rest of the other file */
|
||||
if (file1done) {
|
||||
if (!file2done && col2)
|
||||
show(fp2, col2, line2);
|
||||
break;
|
||||
}
|
||||
if (file2done) {
|
||||
if (!file1done && col1)
|
||||
show(fp1, col1, line1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* lines are the same */
|
||||
if (!(comp = strcmp(line1, line2))) {
|
||||
read1 = read2 = 1;
|
||||
if (col3)
|
||||
(void)printf("%s%s", col3, line1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* lines are different */
|
||||
if (comp < 0) {
|
||||
read1 = 1;
|
||||
read2 = 0;
|
||||
if (col1)
|
||||
(void)printf("%s%s", col1, line1);
|
||||
} else {
|
||||
read1 = 0;
|
||||
read2 = 1;
|
||||
if (col2)
|
||||
(void)printf("%s%s", col2, line2);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
show(fp, offset, buf)
|
||||
FILE *fp;
|
||||
char *offset, *buf;
|
||||
{
|
||||
|
||||
do {
|
||||
(void)printf("%s%s", offset, buf);
|
||||
} while (fgets(buf, MAXLINELEN, fp));
|
||||
}
|
||||
|
||||
FILE *
|
||||
file(name)
|
||||
char *name;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (!strcmp(name, "-"))
|
||||
return (stdin);
|
||||
if ((fp = fopen(name, "r")) == NULL) {
|
||||
(void)fprintf(stderr, "comm: %s: %s\n", name, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return (fp);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: comm [-123] file1 file2\n");
|
||||
exit(1);
|
||||
}
|
298
usr.bin/cut/cut.c
Normal file
298
usr.bin/cut/cut.c
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int cflag;
|
||||
char dchar;
|
||||
int dflag;
|
||||
int fflag;
|
||||
int sflag;
|
||||
|
||||
void c_cut __P((FILE *, char *));
|
||||
void err __P((const char *, ...));
|
||||
void f_cut __P((FILE *, char *));
|
||||
void get_list __P((char *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FILE *fp;
|
||||
void (*fcn) __P((FILE *, char *));
|
||||
int ch;
|
||||
|
||||
dchar = '\t'; /* default delimiter is \t */
|
||||
|
||||
while ((ch = getopt(argc, argv, "c:d:f:s")) != EOF)
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
fcn = c_cut;
|
||||
get_list(optarg);
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dchar = *optarg;
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
get_list(optarg);
|
||||
fcn = f_cut;
|
||||
fflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (fflag) {
|
||||
if (cflag)
|
||||
usage();
|
||||
} else if (!cflag || dflag || sflag)
|
||||
usage();
|
||||
|
||||
if (*argv)
|
||||
for (; *argv; ++argv) {
|
||||
if (!(fp = fopen(*argv, "r")))
|
||||
err("%s: %s\n", *argv, strerror(errno));
|
||||
fcn(fp, *argv);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
else
|
||||
fcn(stdin, "stdin");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int autostart, autostop, maxval;
|
||||
|
||||
char positions[_POSIX2_LINE_MAX + 1];
|
||||
|
||||
void
|
||||
get_list(list)
|
||||
char *list;
|
||||
{
|
||||
register int setautostart, start, stop;
|
||||
register char *pos;
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* set a byte in the positions array to indicate if a field or
|
||||
* column is to be selected; use +1, it's 1-based, not 0-based.
|
||||
* This parser is less restrictive than the Draft 9 POSIX spec.
|
||||
* POSIX doesn't allow lists that aren't in increasing order or
|
||||
* overlapping lists. We also handle "-3-5" although there's no
|
||||
* real reason too.
|
||||
*/
|
||||
for (; p = strtok(list, ", \t"); list = NULL) {
|
||||
setautostart = start = stop = 0;
|
||||
if (*p == '-') {
|
||||
++p;
|
||||
setautostart = 1;
|
||||
}
|
||||
if (isdigit(*p)) {
|
||||
start = stop = strtol(p, &p, 10);
|
||||
if (setautostart && start > autostart)
|
||||
autostart = start;
|
||||
}
|
||||
if (*p == '-') {
|
||||
if (isdigit(p[1]))
|
||||
stop = strtol(p + 1, &p, 10);
|
||||
if (*p == '-') {
|
||||
++p;
|
||||
if (!autostop || autostop > stop)
|
||||
autostop = stop;
|
||||
}
|
||||
}
|
||||
if (*p)
|
||||
err("[-cf] list: illegal list value\n");
|
||||
if (!stop || !start)
|
||||
err("[-cf] list: values may not include zero\n");
|
||||
if (stop > _POSIX2_LINE_MAX)
|
||||
err("[-cf] list: %d too large (max %d)\n",
|
||||
stop, _POSIX2_LINE_MAX);
|
||||
if (maxval < stop)
|
||||
maxval = stop;
|
||||
for (pos = positions + start; start++ <= stop; *pos++ = 1);
|
||||
}
|
||||
|
||||
/* overlapping ranges */
|
||||
if (autostop && maxval > autostop)
|
||||
maxval = autostop;
|
||||
|
||||
/* set autostart */
|
||||
if (autostart)
|
||||
memset(positions + 1, '1', autostart);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
c_cut(fp, fname)
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
register int ch, col;
|
||||
register char *pos;
|
||||
|
||||
for (;;) {
|
||||
pos = positions + 1;
|
||||
for (col = maxval; col; --col) {
|
||||
if ((ch = getc(fp)) == EOF)
|
||||
return;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
if (*pos++)
|
||||
(void)putchar(ch);
|
||||
}
|
||||
if (ch != '\n')
|
||||
if (autostop)
|
||||
while ((ch = getc(fp)) != EOF && ch != '\n')
|
||||
(void)putchar(ch);
|
||||
else
|
||||
while ((ch = getc(fp)) != EOF && ch != '\n');
|
||||
(void)putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
f_cut(fp, fname)
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
register int ch, field, isdelim;
|
||||
register char *pos, *p, sep;
|
||||
int output;
|
||||
char lbuf[_POSIX2_LINE_MAX + 1];
|
||||
|
||||
for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) {
|
||||
output = 0;
|
||||
for (isdelim = 0, p = lbuf;; ++p) {
|
||||
if (!(ch = *p))
|
||||
err("%s: line too long.\n", fname);
|
||||
/* this should work if newline is delimiter */
|
||||
if (ch == sep)
|
||||
isdelim = 1;
|
||||
if (ch == '\n') {
|
||||
if (!isdelim && !sflag)
|
||||
(void)printf("%s", lbuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isdelim)
|
||||
continue;
|
||||
|
||||
pos = positions + 1;
|
||||
for (field = maxval, p = lbuf; field; --field, ++pos) {
|
||||
if (*pos) {
|
||||
if (output++)
|
||||
(void)putchar(sep);
|
||||
while ((ch = *p++) != '\n' && ch != sep)
|
||||
(void)putchar(ch);
|
||||
} else
|
||||
while ((ch = *p++) != '\n' && ch != sep);
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
if (ch != '\n')
|
||||
if (autostop) {
|
||||
if (output)
|
||||
(void)putchar(sep);
|
||||
for (; (ch = *p) != '\n'; ++p)
|
||||
(void)putchar(ch);
|
||||
} else
|
||||
for (; (ch = *p) != '\n'; ++p);
|
||||
(void)putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage:\tcut -c list [file1 ...]\n\tcut -f list [-s] [-d delim] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "cut: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
145
usr.bin/dirname/dirname.c
Normal file
145
usr.bin/dirname/dirname.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)dirname.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *p;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* (1) If string is //, skip steps (2) through (5).
|
||||
* (2) If string consists entirely of slash characters, string
|
||||
* shall be set to a single slash character. In this case,
|
||||
* skip steps (3) through (8).
|
||||
*/
|
||||
for (p = *argv;; ++p) {
|
||||
if (!*p) {
|
||||
if (p > *argv)
|
||||
(void)printf("/\n");
|
||||
else
|
||||
(void)printf(".\n");
|
||||
exit(0);
|
||||
}
|
||||
if (*p != '/')
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* (3) If there are any trailing slash characters in string, they
|
||||
* shall be removed.
|
||||
*/
|
||||
for (; *p; ++p);
|
||||
while (*--p == '/')
|
||||
continue;
|
||||
*++p = '\0';
|
||||
|
||||
/*
|
||||
* (4) If there are no slash characters remaining in string,
|
||||
* string shall be set to a single period character. In this
|
||||
* case skip steps (5) through (8).
|
||||
*
|
||||
* (5) If there are any trailing nonslash characters in string,
|
||||
* they shall be removed.
|
||||
*/
|
||||
while (--p >= *argv)
|
||||
if (*p == '/')
|
||||
break;
|
||||
++p;
|
||||
if (p == *argv) {
|
||||
(void)printf(".\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* (6) If the remaining string is //, it is implementation defined
|
||||
* whether steps (7) and (8) are skipped or processed.
|
||||
*
|
||||
* This case has already been handled, as part of steps (1) and (2).
|
||||
*/
|
||||
|
||||
/*
|
||||
* (7) If there are any trailing slash characters in string, they
|
||||
* shall be removed.
|
||||
*/
|
||||
while (--p >= *argv)
|
||||
if (*p != '/')
|
||||
break;
|
||||
++p;
|
||||
|
||||
/*
|
||||
* (8) If the remaining string is empty, string shall be set to
|
||||
* a single slash character.
|
||||
*/
|
||||
*p = '\0';
|
||||
(void)printf("%s\n", p == *argv ? "/" : *argv);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: dirname path\n");
|
||||
exit(1);
|
||||
}
|
230
usr.bin/du/du.c
Normal file
230
usr.bin/du/du.c
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Newcomb.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int linkchk __P((FTSENT *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FTS *fts;
|
||||
FTSENT *p;
|
||||
long blocksize;
|
||||
int ftsoptions, listdirs, listfiles;
|
||||
int Hflag, Lflag, Pflag, aflag, ch, notused, rval, sflag;
|
||||
char **save;
|
||||
|
||||
save = argv;
|
||||
Hflag = Lflag = Pflag = aflag = sflag = 0;
|
||||
ftsoptions = FTS_PHYSICAL;
|
||||
while ((ch = getopt(argc, argv, "HLPasx")) != EOF)
|
||||
switch (ch) {
|
||||
case 'H':
|
||||
Hflag = 1;
|
||||
Lflag = Pflag = 0;
|
||||
break;
|
||||
case 'L':
|
||||
Lflag = 1;
|
||||
Hflag = Pflag = 0;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
Hflag = Lflag = 0;
|
||||
break;
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case 'x':
|
||||
ftsoptions |= FTS_XDEV;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Because of the way that fts(3) works, logical walks will not count
|
||||
* the blocks actually used by symbolic links. We rationalize this by
|
||||
* noting that users computing logical sizes are likely to do logical
|
||||
* copies, so not counting the links is correct. The real reason is
|
||||
* that we'd have to re-implement the kernel's symbolic link traversing
|
||||
* algorithm to get this right. If, for example, you have relative
|
||||
* symbolic links referencing other relative symbolic links, it gets
|
||||
* very nasty, very fast. The bottom line is that it's documented in
|
||||
* the man page, so it's a feature.
|
||||
*/
|
||||
if (Hflag)
|
||||
ftsoptions |= FTS_COMFOLLOW;
|
||||
if (Lflag) {
|
||||
ftsoptions &= ~FTS_PHYSICAL;
|
||||
ftsoptions |= FTS_LOGICAL;
|
||||
}
|
||||
|
||||
if (aflag) {
|
||||
if (sflag)
|
||||
usage();
|
||||
listdirs = listfiles = 1;
|
||||
} else if (sflag)
|
||||
listdirs = listfiles = 0;
|
||||
else {
|
||||
listfiles = 0;
|
||||
listdirs = 1;
|
||||
}
|
||||
|
||||
if (!*argv) {
|
||||
argv = save;
|
||||
argv[0] = ".";
|
||||
argv[1] = NULL;
|
||||
}
|
||||
|
||||
(void)getbsize(¬used, &blocksize);
|
||||
blocksize /= 512;
|
||||
|
||||
if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
for (rval = 0; (p = fts_read(fts)) != NULL;)
|
||||
switch (p->fts_info) {
|
||||
case FTS_D: /* Ignore. */
|
||||
break;
|
||||
case FTS_DP:
|
||||
p->fts_parent->fts_number +=
|
||||
p->fts_number += p->fts_statp->st_blocks;
|
||||
/*
|
||||
* If listing each directory, or not listing files
|
||||
* or directories and this is post-order of the
|
||||
* root of a traversal, display the total.
|
||||
*/
|
||||
if (listdirs || !listfiles && !p->fts_level)
|
||||
(void)printf("%ld\t%s\n",
|
||||
howmany(p->fts_number, blocksize),
|
||||
p->fts_path);
|
||||
break;
|
||||
case FTS_DC: /* Ignore. */
|
||||
break;
|
||||
case FTS_DNR: /* Warn, continue. */
|
||||
case FTS_ERR:
|
||||
case FTS_NS:
|
||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||
rval = 1;
|
||||
break;
|
||||
default:
|
||||
if (p->fts_statp->st_nlink > 1 && linkchk(p))
|
||||
break;
|
||||
/*
|
||||
* If listing each file, or a non-directory file was
|
||||
* the root of a traversal, display the total.
|
||||
*/
|
||||
if (listfiles || !p->fts_level)
|
||||
(void)printf("%qd\t%s\n",
|
||||
howmany(p->fts_statp->st_blocks, blocksize),
|
||||
p->fts_path);
|
||||
p->fts_parent->fts_number += p->fts_statp->st_blocks;
|
||||
}
|
||||
if (errno)
|
||||
err(1, "fts_read");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
typedef struct _ID {
|
||||
dev_t dev;
|
||||
ino_t inode;
|
||||
} ID;
|
||||
|
||||
int
|
||||
linkchk(p)
|
||||
FTSENT *p;
|
||||
{
|
||||
static ID *files;
|
||||
static int maxfiles, nfiles;
|
||||
ID *fp, *start;
|
||||
ino_t ino;
|
||||
dev_t dev;
|
||||
|
||||
ino = p->fts_statp->st_ino;
|
||||
dev = p->fts_statp->st_dev;
|
||||
if ((start = files) != NULL)
|
||||
for (fp = start + nfiles - 1; fp >= start; --fp)
|
||||
if (ino == fp->inode && dev == fp->dev)
|
||||
return (1);
|
||||
|
||||
if (nfiles == maxfiles && (files = realloc((char *)files,
|
||||
(u_int)(sizeof(ID) * (maxfiles += 128)))) == NULL)
|
||||
err(1, "");
|
||||
files[nfiles].inode = ino;
|
||||
files[nfiles].dev = dev;
|
||||
++nfiles;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: du [-H | -L | -P] [-a | -s] [-x] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
461
usr.bin/find/find.1
Normal file
461
usr.bin/find/find.1
Normal file
@ -0,0 +1,461 @@
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)find.1 8.7 (Berkeley) 5/9/95
|
||||
.\"
|
||||
.Dd May 9, 1995
|
||||
.Dt FIND 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm find
|
||||
.Nd walk a file hierarchy
|
||||
.Sh SYNOPSIS
|
||||
.Nm find
|
||||
.Op Fl H | Fl L | Fl P
|
||||
.Op Fl Xdx
|
||||
.Op Fl f Ar file
|
||||
.Op Ar file ...
|
||||
.Ar expression
|
||||
.Sh DESCRIPTION
|
||||
.Nm Find
|
||||
recursively descends the directory tree for each
|
||||
.Ar file
|
||||
listed, evaluating an
|
||||
.Ar expression
|
||||
(composed of the ``primaries'' and ``operands'' listed below) in terms
|
||||
of each file in the tree.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width Ds
|
||||
.It Fl H
|
||||
The
|
||||
.Fl H
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2)
|
||||
returned for each symbolic link specified on the command line to be
|
||||
those of the file referenced by the link, not the link itself.
|
||||
If the referenced file does not exist, the file information and type will
|
||||
be for the link itself. File information of all symbolic links not on
|
||||
the command line is that of the link itself.
|
||||
.It Fl L
|
||||
The
|
||||
.Fl L
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2)
|
||||
returned for each symbolic link to be those of the file referenced by the
|
||||
link, not the link itself.
|
||||
If the referenced file does not exist, the file information and type will
|
||||
be for the link itself.
|
||||
.It Fl P
|
||||
The
|
||||
.Fl P
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2)
|
||||
returned for each symbolic link to be those of the link itself.
|
||||
.It Fl X
|
||||
The
|
||||
.Fl X
|
||||
option is a modification to permit
|
||||
.Nm
|
||||
to be safely used in conjunction with
|
||||
.Xr xargs 1 .
|
||||
If a file name contains any of the delimiting characters used by
|
||||
.Xr xargs ,
|
||||
a diagnostic message is displayed on standard error, and the file
|
||||
is skipped.
|
||||
The delimiting characters include single (`` ' '') and double (`` " '')
|
||||
quotes, backslash (``\e''), space, tab and newline characters.
|
||||
.It Fl d
|
||||
The
|
||||
.Fl d
|
||||
option causes
|
||||
.Nm find
|
||||
to perform a depth\-first traversal, i.e. directories
|
||||
are visited in post\-order and all entries in a directory will be acted
|
||||
on before the directory itself.
|
||||
By default,
|
||||
.Nm find
|
||||
visits directories in pre\-order, i.e. before their contents.
|
||||
Note, the default is
|
||||
.Ar not
|
||||
a breadth\-first traversal.
|
||||
.It Fl f
|
||||
The
|
||||
.Fl f
|
||||
option specifies a file hierarchy for
|
||||
.Nm find
|
||||
to traverse.
|
||||
File hierarchies may also be specified as the operands immediately
|
||||
following the options.
|
||||
.It Fl x
|
||||
The
|
||||
.Fl x
|
||||
option prevents
|
||||
.Nm find
|
||||
from descending into directories that have a device number different
|
||||
than that of the file from which the descent began.
|
||||
.El
|
||||
.Sh PRIMARIES
|
||||
.Bl -tag -width Ds
|
||||
.It Ic -atime Ar n
|
||||
True if the difference between the file last access time and the time
|
||||
.Nm find
|
||||
was started, rounded up to the next full 24\-hour period, is
|
||||
.Ar n
|
||||
24\-hour periods.
|
||||
.It Ic -ctime Ar n
|
||||
True if the difference between the time of last change of file status
|
||||
information and the time
|
||||
.Nm find
|
||||
was started, rounded up to the next full 24\-hour period, is
|
||||
.Ar n
|
||||
24\-hour periods.
|
||||
.It Ic -exec Ar utility Op argument ... ;
|
||||
True if the program named
|
||||
.Ar utility
|
||||
returns a zero value as its exit status.
|
||||
Optional arguments may be passed to the utility.
|
||||
The expression must be terminated by a semicolon (``;'').
|
||||
If the string ``{}'' appears anywhere in the utility name or the
|
||||
arguments it is replaced by the pathname of the current file.
|
||||
.Ar Utility
|
||||
will be executed from the directory from which
|
||||
.Nm find
|
||||
was executed.
|
||||
.It Ic -fstype Ar type
|
||||
True if the file is contained in a file system of type
|
||||
.Ar type .
|
||||
The
|
||||
.Xr sysctl 8
|
||||
command can be used to find out the types of filesystems
|
||||
that are available on the system:
|
||||
.Bd -literal -offset indent
|
||||
sysctl vfs
|
||||
.Ed
|
||||
In addition, there are two pseudo-types, ``local'' and ``rdonly''.
|
||||
The former matches any file system physically mounted on the system where
|
||||
the
|
||||
.Nm find
|
||||
is being executed and the latter matches any file system which is
|
||||
mounted read-only.
|
||||
.It Ic -group Ar gname
|
||||
True if the file belongs to the group
|
||||
.Ar gname .
|
||||
If
|
||||
.Ar gname
|
||||
is numeric and there is no such group name, then
|
||||
.Ar gname
|
||||
is treated as a group id.
|
||||
.It Ic -inum Ar n
|
||||
True if the file has inode number
|
||||
.Ar n .
|
||||
.It Ic -links Ar n
|
||||
True if the file has
|
||||
.Ar n
|
||||
links.
|
||||
.It Ic -ls
|
||||
This primary always evaluates to true.
|
||||
The following information for the current file is written to standard output:
|
||||
its inode number, size in 512\-byte blocks, file permissions, number of hard
|
||||
links, owner, group, size in bytes, last modification time, and pathname.
|
||||
If the file is a block or character special file, the major and minor numbers
|
||||
will be displayed instead of the size in bytes.
|
||||
If the file is a symbolic link, the pathname of the linked\-to file will be
|
||||
displayed preceded by ``\->''.
|
||||
The format is identical to that produced by ``ls \-dgils''.
|
||||
.It Ic -mtime Ar n
|
||||
True if the difference between the file last modification time and the time
|
||||
.Nm find
|
||||
was started, rounded up to the next full 24\-hour period, is
|
||||
.Ar n
|
||||
24\-hour periods.
|
||||
.It Ic \&-ok Ar utility Op argument ... ;
|
||||
The
|
||||
.Ic \&-ok
|
||||
primary is identical to the
|
||||
.Ic -exec
|
||||
primary with the exception that
|
||||
.Nm find
|
||||
requests user affirmation for the execution of the utility by printing
|
||||
a message to the terminal and reading a response.
|
||||
If the response is other than ``y'' the command is not executed and the
|
||||
value of the
|
||||
.Ar \&ok
|
||||
expression is false.
|
||||
.It Ic -name Ar pattern
|
||||
True if the last component of the pathname being examined matches
|
||||
.Ar pattern .
|
||||
Special shell pattern matching characters (``['', ``]'', ``*'', and ``?'')
|
||||
may be used as part of
|
||||
.Ar pattern .
|
||||
These characters may be matched explicitly by escaping them with a
|
||||
backslash (``\e'').
|
||||
.It Ic -newer Ar file
|
||||
True if the current file has a more recent last modification time than
|
||||
.Ar file .
|
||||
.It Ic -nouser
|
||||
True if the file belongs to an unknown user.
|
||||
.It Ic -nogroup
|
||||
True if the file belongs to an unknown group.
|
||||
.It Ic -path Ar pattern
|
||||
True if the pathname being examined matches
|
||||
.Ar pattern .
|
||||
Special shell pattern matching characters (``['', ``]'', ``*'', and ``?'')
|
||||
may be used as part of
|
||||
.Ar pattern .
|
||||
These characters may be matched explicitly by escaping them with a
|
||||
backslash (``\e'').
|
||||
Slashes (``/'') are treated as normal characters and do not have to be
|
||||
matched explicitly.
|
||||
.It Ic -perm Op Fl Ns Ar mode
|
||||
The
|
||||
.Ar mode
|
||||
may be either symbolic (see
|
||||
.Xr chmod 1 )
|
||||
or an octal number.
|
||||
If the mode is symbolic, a starting value of zero is assumed and the
|
||||
mode sets or clears permissions without regard to the process' file mode
|
||||
creation mask.
|
||||
If the mode is octal, only bits 07777
|
||||
.Pf ( Dv S_ISUID
|
||||
|
|
||||
.Dv S_ISGID
|
||||
|
|
||||
.Dv S_ISTXT
|
||||
|
|
||||
.Dv S_IRWXU
|
||||
|
|
||||
.Dv S_IRWXG
|
||||
|
|
||||
.Dv S_IRWXO )
|
||||
of the file's mode bits participate
|
||||
in the comparison.
|
||||
If the mode is preceded by a dash (``\-''), this primary evaluates to true
|
||||
if at least all of the bits in the mode are set in the file's mode bits.
|
||||
If the mode is not preceded by a dash, this primary evaluates to true if
|
||||
the bits in the mode exactly match the file's mode bits.
|
||||
Note, the first character of a symbolic mode may not be a dash (``\-'').
|
||||
.It Ic -print
|
||||
This primary always evaluates to true.
|
||||
It prints the pathname of the current file to standard output.
|
||||
If none of
|
||||
.Ic -exec ,
|
||||
.Ic -ls ,
|
||||
or
|
||||
.Ic \&-ok
|
||||
is specified, the given expression shall be effectively replaced by
|
||||
.Cm \&( Ns Ar given\& expression Ns Cm \&)
|
||||
.Ic -print .
|
||||
.It Ic -prune
|
||||
This primary always evaluates to true.
|
||||
It causes
|
||||
.Nm find
|
||||
to not descend into the current file.
|
||||
Note, the
|
||||
.Ic -prune
|
||||
primary has no effect if the
|
||||
.Fl d
|
||||
option was specified.
|
||||
.It Ic -size Ar n Ns Op Cm c
|
||||
True if the file's size, rounded up, in 512\-byte blocks is
|
||||
.Ar n .
|
||||
If
|
||||
.Ar n
|
||||
is followed by a ``c'', then the primary is true if the
|
||||
file's size is
|
||||
.Ar n
|
||||
bytes.
|
||||
.It Ic -type Ar t
|
||||
True if the file is of the specified type.
|
||||
Possible file types are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width flag -offset indent -compact
|
||||
.It Cm b
|
||||
block special
|
||||
.It Cm c
|
||||
character special
|
||||
.It Cm d
|
||||
directory
|
||||
.It Cm f
|
||||
regular file
|
||||
.It Cm l
|
||||
symbolic link
|
||||
.It Cm p
|
||||
FIFO
|
||||
.It Cm s
|
||||
socket
|
||||
.El
|
||||
.Pp
|
||||
.It Ic -user Ar uname
|
||||
True if the file belongs to the user
|
||||
.Ar uname .
|
||||
If
|
||||
.Ar uname
|
||||
is numeric and there is no such user name, then
|
||||
.Ar uname
|
||||
is treated as a user id.
|
||||
.El
|
||||
.Pp
|
||||
All primaries which take a numeric argument allow the number to be
|
||||
preceded by a plus sign (``+'') or a minus sign (``\-'').
|
||||
A preceding plus sign means ``more than n'', a preceding minus sign means
|
||||
``less than n'' and neither means ``exactly n'' .
|
||||
.Sh OPERATORS
|
||||
The primaries may be combined using the following operators.
|
||||
The operators are listed in order of decreasing precedence.
|
||||
.Bl -tag -width (expression)
|
||||
.It Cm \&( Ns Ar expression Ns Cm \&)
|
||||
This evaluates to true if the parenthesized expression evaluates to
|
||||
true.
|
||||
.Pp
|
||||
.It Cm \&! Ns Ar expression
|
||||
This is the unary
|
||||
.Tn NOT
|
||||
operator.
|
||||
It evaluates to true if the expression is false.
|
||||
.Pp
|
||||
.It Ar expression Cm -and Ar expression
|
||||
.It Ar expression expression
|
||||
The
|
||||
.Cm -and
|
||||
operator is the logical
|
||||
.Tn AND
|
||||
operator.
|
||||
As it is implied by the juxtaposition of two expressions it does not
|
||||
have to be specified.
|
||||
The expression evaluates to true if both expressions are true.
|
||||
The second expression is not evaluated if the first expression is false.
|
||||
.Pp
|
||||
.It Ar expression Cm -or Ar expression
|
||||
The
|
||||
.Cm -or
|
||||
operator is the logical
|
||||
.Tn OR
|
||||
operator.
|
||||
The expression evaluates to true if either the first or the second expression
|
||||
is true.
|
||||
The second expression is not evaluated if the first expression is true.
|
||||
.El
|
||||
.Pp
|
||||
All operands and primaries must be separate arguments to
|
||||
.Nm find .
|
||||
Primaries which themselves take arguments expect each argument
|
||||
to be a separate argument to
|
||||
.Nm find .
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
The following examples are shown as given to the shell:
|
||||
.Bl -tag -width findx
|
||||
.It Li "find / \e! -name \*q*.c\*q -print"
|
||||
Print out a list of all the files whose names do not end in ``.c''.
|
||||
.It Li "find / -newer ttt -user wnj -print"
|
||||
Print out a list of all the files owned by user ``wnj'' that are newer
|
||||
than the file ``ttt''.
|
||||
.It Li "find / \e! \e( -newer ttt -user wnj \e) -print"
|
||||
Print out a list of all the files which are not both newer than ``ttt''
|
||||
and owned by ``wnj''.
|
||||
.It Li "find / \e( -newer ttt -or -user wnj \e) -print"
|
||||
Print out a list of all the files that are either owned by ``wnj'' or
|
||||
that are newer than ``ttt''.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chmod 1 ,
|
||||
.Xr locate 1 ,
|
||||
.Xr stat 2 ,
|
||||
.Xr fts 3 ,
|
||||
.Xr getgrent 3 ,
|
||||
.Xr getpwent 3 ,
|
||||
.Xr strmode 3 ,
|
||||
.Xr symlink 7
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm find
|
||||
utility syntax is a superset of the syntax specified by the
|
||||
.St -p1003.2
|
||||
standard.
|
||||
.Pp
|
||||
The
|
||||
.Fl s
|
||||
and
|
||||
.Fl X
|
||||
options and the
|
||||
.Ic -inum
|
||||
and
|
||||
.Ic -ls
|
||||
primaries are extensions to
|
||||
.St -p1003.2 .
|
||||
.Pp
|
||||
Historically, the
|
||||
.Fl d ,
|
||||
.Fl h
|
||||
and
|
||||
.Fl x
|
||||
options were implemented using the primaries ``\-depth'', ``\-follow'',
|
||||
and ``\-xdev''.
|
||||
These primaries always evaluated to true.
|
||||
As they were really global variables that took effect before the traversal
|
||||
began, some legal expressions could have unexpected results.
|
||||
An example is the expression ``\-print \-o \-depth''.
|
||||
As \-print always evaluates to true, the standard order of evaluation
|
||||
implies that \-depth would never be evaluated.
|
||||
This is not the case.
|
||||
.Pp
|
||||
The operator ``-or'' was implemented as ``\-o'', and the operator ``-and''
|
||||
was implemented as ``\-a''.
|
||||
.Pp
|
||||
Historic implementations of the
|
||||
.Ic exec
|
||||
and
|
||||
.Ic ok
|
||||
primaries did not replace the string ``{}'' in the utility name or the
|
||||
utility arguments if it had preceding or following non-whitespace characters.
|
||||
This version replaces it no matter where in the utility name or arguments
|
||||
it appears.
|
||||
.Sh BUGS
|
||||
The special characters used by
|
||||
.Nm find
|
||||
are also special characters to many shell programs.
|
||||
In particular, the characters ``*'', ``['', ``]'', ``?'', ``('', ``)'',
|
||||
``!'', ``\e'' and ``;'' may have to be escaped from the shell.
|
||||
.Pp
|
||||
As there is no delimiter separating options and file names or file
|
||||
names and the
|
||||
.Ar expression ,
|
||||
it is difficult to specify files named ``-xdev'' or ``!''.
|
||||
These problems are handled by the
|
||||
.Fl f
|
||||
option and the
|
||||
.Xr getopt 3
|
||||
``--'' construct.
|
202
usr.bin/find/find.c
Normal file
202
usr.bin/find/find.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)find.c 8.5 (Berkeley) 8/5/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
/*
|
||||
* find_formplan --
|
||||
* process the command line and create a "plan" corresponding to the
|
||||
* command arguments.
|
||||
*/
|
||||
PLAN *
|
||||
find_formplan(argv)
|
||||
char **argv;
|
||||
{
|
||||
PLAN *plan, *tail, *new;
|
||||
|
||||
/*
|
||||
* for each argument in the command line, determine what kind of node
|
||||
* it is, create the appropriate node type and add the new plan node
|
||||
* to the end of the existing plan. The resulting plan is a linked
|
||||
* list of plan nodes. For example, the string:
|
||||
*
|
||||
* % find . -name foo -newer bar -print
|
||||
*
|
||||
* results in the plan:
|
||||
*
|
||||
* [-name foo]--> [-newer bar]--> [-print]
|
||||
*
|
||||
* in this diagram, `[-name foo]' represents the plan node generated
|
||||
* by c_name() with an argument of foo and `-->' represents the
|
||||
* plan->next pointer.
|
||||
*/
|
||||
for (plan = tail = NULL; *argv;) {
|
||||
if (!(new = find_create(&argv)))
|
||||
continue;
|
||||
if (plan == NULL)
|
||||
tail = plan = new;
|
||||
else {
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the user didn't specify one of -print, -ok or -exec, then -print
|
||||
* is assumed so we bracket the current expression with parens, if
|
||||
* necessary, and add a -print node on the end.
|
||||
*/
|
||||
if (!isoutput) {
|
||||
if (plan == NULL) {
|
||||
new = c_print();
|
||||
tail = plan = new;
|
||||
} else {
|
||||
new = c_openparen();
|
||||
new->next = plan;
|
||||
plan = new;
|
||||
new = c_closeparen();
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
new = c_print();
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the command line has been completely processed into a search plan
|
||||
* except for the (, ), !, and -o operators. Rearrange the plan so
|
||||
* that the portions of the plan which are affected by the operators
|
||||
* are moved into operator nodes themselves. For example:
|
||||
*
|
||||
* [!]--> [-name foo]--> [-print]
|
||||
*
|
||||
* becomes
|
||||
*
|
||||
* [! [-name foo] ]--> [-print]
|
||||
*
|
||||
* and
|
||||
*
|
||||
* [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
|
||||
*
|
||||
* becomes
|
||||
*
|
||||
* [expr [-depth]-->[-name foo] ]--> [-print]
|
||||
*
|
||||
* operators are handled in order of precedence.
|
||||
*/
|
||||
|
||||
plan = paren_squish(plan); /* ()'s */
|
||||
plan = not_squish(plan); /* !'s */
|
||||
plan = or_squish(plan); /* -o's */
|
||||
return (plan);
|
||||
}
|
||||
|
||||
FTS *tree; /* pointer to top of FTS hierarchy */
|
||||
|
||||
/*
|
||||
* find_execute --
|
||||
* take a search plan and an array of search paths and executes the plan
|
||||
* over all FTSENT's returned for the given search paths.
|
||||
*/
|
||||
int
|
||||
find_execute(plan, paths)
|
||||
PLAN *plan; /* search plan */
|
||||
char **paths; /* array of pathnames to traverse */
|
||||
{
|
||||
register FTSENT *entry;
|
||||
PLAN *p;
|
||||
int rval;
|
||||
|
||||
if ((tree = fts_open(paths, ftsoptions, (int (*)())NULL)) == NULL)
|
||||
err(1, "ftsopen");
|
||||
|
||||
for (rval = 0; (entry = fts_read(tree)) != NULL;) {
|
||||
switch (entry->fts_info) {
|
||||
case FTS_D:
|
||||
if (isdepth)
|
||||
continue;
|
||||
break;
|
||||
case FTS_DP:
|
||||
if (!isdepth)
|
||||
continue;
|
||||
break;
|
||||
case FTS_DNR:
|
||||
case FTS_ERR:
|
||||
case FTS_NS:
|
||||
(void)fflush(stdout);
|
||||
warnx("%s: %s",
|
||||
entry->fts_path, strerror(entry->fts_errno));
|
||||
rval = 1;
|
||||
continue;
|
||||
#ifdef FTS_W
|
||||
case FTS_W:
|
||||
continue;
|
||||
#endif /* FTS_W */
|
||||
}
|
||||
#define BADCH " \t\n\\'\""
|
||||
if (isxargs && strpbrk(entry->fts_path, BADCH)) {
|
||||
(void)fflush(stdout);
|
||||
warnx("%s: illegal path", entry->fts_path);
|
||||
rval = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call all the functions in the execution plan until one is
|
||||
* false or all have been executed. This is where we do all
|
||||
* the work specified by the user on the command line.
|
||||
*/
|
||||
for (p = plan; p && (p->eval)(p, entry); p = p->next);
|
||||
}
|
||||
if (errno)
|
||||
err(1, "fts_read");
|
||||
return (rval);
|
||||
}
|
1055
usr.bin/find/function.c
Normal file
1055
usr.bin/find/function.c
Normal file
File diff suppressed because it is too large
Load Diff
154
usr.bin/find/main.c
Normal file
154
usr.bin/find/main.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1990, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
time_t now; /* time find was run */
|
||||
int dotfd; /* starting directory */
|
||||
int ftsoptions; /* options for the ftsopen(3) call */
|
||||
int isdeprecated; /* using deprecated syntax */
|
||||
int isdepth; /* do directories on post-order visit */
|
||||
int isoutput; /* user specified output operator */
|
||||
int isxargs; /* don't permit xargs delimiting chars */
|
||||
|
||||
static void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register char **p, **start;
|
||||
int Hflag, Lflag, Pflag, ch;
|
||||
|
||||
(void)time(&now); /* initialize the time-of-day */
|
||||
|
||||
p = start = argv;
|
||||
Hflag = Lflag = Pflag = 0;
|
||||
ftsoptions = FTS_NOSTAT | FTS_PHYSICAL;
|
||||
while ((ch = getopt(argc, argv, "HLPXdf:x")) != EOF)
|
||||
switch (ch) {
|
||||
case 'H':
|
||||
Hflag = 1;
|
||||
Lflag = Pflag = 0;
|
||||
break;
|
||||
case 'L':
|
||||
Lflag = 1;
|
||||
Hflag = Pflag = 0;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
Hflag = Lflag = 0;
|
||||
break;
|
||||
case 'X':
|
||||
isxargs = 1;
|
||||
break;
|
||||
case 'd':
|
||||
isdepth = 1;
|
||||
break;
|
||||
case 'f':
|
||||
*p++ = optarg;
|
||||
break;
|
||||
case 'x':
|
||||
ftsoptions |= FTS_XDEV;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (Hflag)
|
||||
ftsoptions |= FTS_COMFOLLOW;
|
||||
if (Lflag) {
|
||||
ftsoptions &= ~FTS_PHYSICAL;
|
||||
ftsoptions |= FTS_LOGICAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find first option to delimit the file list. The first argument
|
||||
* that starts with a -, or is a ! or a ( must be interpreted as a
|
||||
* part of the find expression, according to POSIX .2.
|
||||
*/
|
||||
for (; *argv != NULL; *p++ = *argv++) {
|
||||
if (argv[0][0] == '-')
|
||||
break;
|
||||
if ((argv[0][0] == '!' || argv[0][0] == '(') &&
|
||||
argv[0][1] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == start)
|
||||
usage();
|
||||
*p = NULL;
|
||||
|
||||
if ((dotfd = open(".", O_RDONLY, 0)) < 0)
|
||||
err(1, ".");
|
||||
|
||||
exit(find_execute(find_formplan(argv), start));
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: find [-H | -L | -P] [-Xdx] [-f file] [file ...] [expression]\n");
|
||||
exit(1);
|
||||
}
|
49
usr.bin/finger/extern.h
Normal file
49
usr.bin/finger/extern.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)extern.h 8.2 (Berkeley) 4/28/95
|
||||
*/
|
||||
|
||||
extern char tbuf[1024]; /* Temp buffer for anybody. */
|
||||
extern int entries; /* Number of people. */
|
||||
extern DB *db; /* Database. */
|
||||
|
||||
void enter_lastlog __P((PERSON *));
|
||||
PERSON *enter_person __P((struct passwd *));
|
||||
void enter_where __P((struct utmp *, PERSON *));
|
||||
PERSON *find_person __P((char *));
|
||||
void lflag_print __P((void));
|
||||
int match __P((struct passwd *, char *));
|
||||
void netfinger __P((char *));
|
||||
PERSON *palloc __P((void));
|
||||
char *prphone __P((char *));
|
||||
void sflag_print __P((void));
|
166
usr.bin/finger/finger.1
Normal file
166
usr.bin/finger/finger.1
Normal file
@ -0,0 +1,166 @@
|
||||
.\" Copyright (c) 1989, 1990, 1993, 1994
|
||||
.\" The Regents of the University of California. 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)finger.1 8.3 (Berkeley) 5/5/94
|
||||
.\"
|
||||
.Dd May 5, 1994
|
||||
.Dt FINGER 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm finger
|
||||
.Nd user information lookup program
|
||||
.Sh SYNOPSIS
|
||||
.Nm finger
|
||||
.Op Fl lmsp
|
||||
.Op Ar user ...
|
||||
.Op Ar user@host ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm finger
|
||||
displays information about the system users.
|
||||
.Pp
|
||||
Options are:
|
||||
.Bl -tag -width flag
|
||||
.It Fl s
|
||||
.Nm Finger
|
||||
displays the user's login name, real name, terminal name and write
|
||||
status (as a ``*'' before the terminal name if write permission is
|
||||
denied), idle time, login time, office location and office phone
|
||||
number.
|
||||
.Pp
|
||||
Idle time is in minutes if it is a single integer, hours and minutes
|
||||
if a ``:'' is present, or days if a ``d'' is present.
|
||||
Login time is displayed as month, day, hours and minutes, unless
|
||||
more than six months ago, in which case the year is displayed rather
|
||||
than the hours and minutes.
|
||||
.Pp
|
||||
Unknown devices as well as nonexistent idle and login times are
|
||||
displayed as single asterisks.
|
||||
.Pp
|
||||
.It Fl l
|
||||
Produces a multi-line format displaying all of the information
|
||||
described for the
|
||||
.Fl s
|
||||
option as well as the user's home directory, home phone number, login
|
||||
shell, and the contents of the files
|
||||
.Dq Pa .forward ,
|
||||
.Dq Pa .plan
|
||||
and
|
||||
.Dq Pa .project
|
||||
from the user's home directory.
|
||||
.Pp
|
||||
If idle time is at least a minute and less than a day, it is
|
||||
presented in the form ``hh:mm''.
|
||||
Idle times greater than a day are presented as ``d day[s]hh:mm''.
|
||||
.Pp
|
||||
Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''.
|
||||
Numbers specified as ten or seven digits are printed as the appropriate
|
||||
subset of that string.
|
||||
Numbers specified as five digits are printed as ``xN-NNNN''.
|
||||
.Pp
|
||||
If write permission is denied to the device, the phrase ``(messages off)''
|
||||
is appended to the line containing the device name.
|
||||
One entry per user is displayed with the
|
||||
.Fl l
|
||||
option; if a user is logged on multiple times, terminal information
|
||||
is repeated once per login.
|
||||
.Pp
|
||||
.It Fl p
|
||||
Prevents
|
||||
the
|
||||
.Fl l
|
||||
option of
|
||||
.Nm finger
|
||||
from displaying the contents of the
|
||||
.Dq Pa .forward ,
|
||||
.Dq Pa .plan
|
||||
and
|
||||
.Dq Pa .project
|
||||
files.
|
||||
.It Fl m
|
||||
Prevent matching of
|
||||
.Ar user
|
||||
names.
|
||||
.Ar User
|
||||
is usually a login name; however, matching will also be done on the
|
||||
users' real names, unless the
|
||||
.Fl m
|
||||
option is supplied.
|
||||
All name matching performed by
|
||||
.Nm finger
|
||||
is case insensitive.
|
||||
.El
|
||||
.Pp
|
||||
If no options are specified,
|
||||
.Nm finger
|
||||
defaults to the
|
||||
.Fl l
|
||||
style output if operands are provided, otherwise to the
|
||||
.Fl s
|
||||
style.
|
||||
Note that some fields may be missing, in either format, if information
|
||||
is not available for them.
|
||||
.Pp
|
||||
If no arguments are specified,
|
||||
.Nm finger
|
||||
will print an entry for each user currently logged into the system.
|
||||
.Pp
|
||||
.Nm Finger
|
||||
may be used to look up users on a remote machine.
|
||||
The format is to specify a
|
||||
.Ar user
|
||||
as
|
||||
.Dq Li user@host ,
|
||||
or
|
||||
.Dq Li @host ,
|
||||
where the default output
|
||||
format for the former is the
|
||||
.Fl l
|
||||
style, and the default output format for the latter is the
|
||||
.Fl s
|
||||
style.
|
||||
The
|
||||
.Fl l
|
||||
option is the only option that may be passed to a remote machine.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/log/lastlog -compact
|
||||
.It Pa /var/log/lastlog
|
||||
last login data base
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chpass 1 ,
|
||||
.Xr w 1 ,
|
||||
.Xr who 1 ,
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm finger
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
268
usr.bin/finger/finger.c
Normal file
268
usr.bin/finger/finger.c
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Finger prints out information about users. It is not portable since
|
||||
* certain fields (e.g. the full user name, office, and phone numbers) are
|
||||
* extracted from the gecos field of the passwd file which other UNIXes
|
||||
* may not have or may use for other things.
|
||||
*
|
||||
* There are currently two output formats; the short format is one line
|
||||
* per user and displays login name, tty, login time, real name, idle time,
|
||||
* and office location/phone number. The long format gives the same
|
||||
* information (in a more legible format) as well as home directory, shell,
|
||||
* mail info, and .plan/.project files.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <db.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
#include "finger.h"
|
||||
|
||||
DB *db;
|
||||
time_t now;
|
||||
int entries, lflag, mflag, pplan, sflag;
|
||||
char tbuf[1024];
|
||||
|
||||
static void loginlist __P((void));
|
||||
static void userlist __P((int, char **));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "lmps")) != EOF)
|
||||
switch(ch) {
|
||||
case 'l':
|
||||
lflag = 1; /* long format */
|
||||
break;
|
||||
case 'm':
|
||||
mflag = 1; /* force exact match of names */
|
||||
break;
|
||||
case 'p':
|
||||
pplan = 1; /* don't show .plan/.project */
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1; /* short format */
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
(void)fprintf(stderr,
|
||||
"usage: finger [-lmps] [login ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
(void)time(&now);
|
||||
setpassent(1);
|
||||
if (!*argv) {
|
||||
/*
|
||||
* Assign explicit "small" format if no names given and -l
|
||||
* not selected. Force the -s BEFORE we get names so proper
|
||||
* screening will be done.
|
||||
*/
|
||||
if (!lflag)
|
||||
sflag = 1; /* if -l not explicit, force -s */
|
||||
loginlist();
|
||||
if (entries == 0)
|
||||
(void)printf("No one logged on.\n");
|
||||
} else {
|
||||
userlist(argc, argv);
|
||||
/*
|
||||
* Assign explicit "large" format if names given and -s not
|
||||
* explicitly stated. Force the -l AFTER we get names so any
|
||||
* remote finger attempts specified won't be mishandled.
|
||||
*/
|
||||
if (!sflag)
|
||||
lflag = 1; /* if -s not explicit, force -l */
|
||||
}
|
||||
if (entries)
|
||||
if (lflag)
|
||||
lflag_print();
|
||||
else
|
||||
sflag_print();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
loginlist()
|
||||
{
|
||||
register PERSON *pn;
|
||||
DBT data, key;
|
||||
struct passwd *pw;
|
||||
struct utmp user;
|
||||
int r, sflag;
|
||||
char name[UT_NAMESIZE + 1];
|
||||
|
||||
if (!freopen(_PATH_UTMP, "r", stdin))
|
||||
err(1, "%s", _PATH_UTMP);
|
||||
name[UT_NAMESIZE] = NULL;
|
||||
while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
|
||||
if (!user.ut_name[0])
|
||||
continue;
|
||||
if ((pn = find_person(user.ut_name)) == NULL) {
|
||||
bcopy(user.ut_name, name, UT_NAMESIZE);
|
||||
if ((pw = getpwnam(name)) == NULL)
|
||||
continue;
|
||||
pn = enter_person(pw);
|
||||
}
|
||||
enter_where(&user, pn);
|
||||
}
|
||||
if (db && lflag)
|
||||
for (sflag = R_FIRST;; sflag = R_NEXT) {
|
||||
PERSON *tmp;
|
||||
|
||||
r = (*db->seq)(db, &key, &data, sflag);
|
||||
if (r == -1)
|
||||
err(1, "db seq");
|
||||
if (r == 1)
|
||||
break;
|
||||
memmove(&tmp, data.data, sizeof tmp);
|
||||
enter_lastlog(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
userlist(argc, argv)
|
||||
register int argc;
|
||||
register char **argv;
|
||||
{
|
||||
register PERSON *pn;
|
||||
DBT data, key;
|
||||
struct utmp user;
|
||||
struct passwd *pw;
|
||||
int r, sflag, *used, *ip;
|
||||
char **ap, **nargv, **np, **p;
|
||||
|
||||
if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL ||
|
||||
(used = calloc(argc, sizeof(int))) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
/* Pull out all network requests. */
|
||||
for (ap = p = argv, np = nargv; *p; ++p)
|
||||
if (index(*p, '@'))
|
||||
*np++ = *p;
|
||||
else
|
||||
*ap++ = *p;
|
||||
|
||||
*np++ = NULL;
|
||||
*ap++ = NULL;
|
||||
|
||||
if (!*argv)
|
||||
goto net;
|
||||
|
||||
/*
|
||||
* Traverse the list of possible login names and check the login name
|
||||
* and real name against the name specified by the user.
|
||||
*/
|
||||
if (mflag)
|
||||
for (p = argv; *p; ++p)
|
||||
if ((pw = getpwnam(*p)) != NULL)
|
||||
enter_person(pw);
|
||||
else
|
||||
(void)fprintf(stderr,
|
||||
"finger: %s: no such user\n", *p);
|
||||
else {
|
||||
while ((pw = getpwent()) != NULL)
|
||||
for (p = argv, ip = used; *p; ++p, ++ip)
|
||||
if (match(pw, *p)) {
|
||||
enter_person(pw);
|
||||
*ip = 1;
|
||||
}
|
||||
for (p = argv, ip = used; *p; ++p, ++ip)
|
||||
if (!*ip)
|
||||
(void)fprintf(stderr,
|
||||
"finger: %s: no such user\n", *p);
|
||||
}
|
||||
|
||||
/* Handle network requests. */
|
||||
net: for (p = nargv; *p;)
|
||||
netfinger(*p++);
|
||||
|
||||
if (entries == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Scan thru the list of users currently logged in, saving
|
||||
* appropriate data whenever a match occurs.
|
||||
*/
|
||||
if (!freopen(_PATH_UTMP, "r", stdin))
|
||||
err(1, "%s", _PATH_UTMP);
|
||||
while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
|
||||
if (!user.ut_name[0])
|
||||
continue;
|
||||
if ((pn = find_person(user.ut_name)) == NULL)
|
||||
continue;
|
||||
enter_where(&user, pn);
|
||||
}
|
||||
if (db)
|
||||
for (sflag = R_FIRST;; sflag = R_NEXT) {
|
||||
PERSON *tmp;
|
||||
|
||||
r = (*db->seq)(db, &key, &data, sflag);
|
||||
if (r == -1)
|
||||
err(1, "db seq");
|
||||
if (r == 1)
|
||||
break;
|
||||
memmove(&tmp, data.data, sizeof tmp);
|
||||
enter_lastlog(tmp);
|
||||
}
|
||||
}
|
336
usr.bin/finger/lprint.c
Normal file
336
usr.bin/finger/lprint.c
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <db.h>
|
||||
#include <err.h>
|
||||
#include <pwd.h>
|
||||
#include <utmp.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
#include "finger.h"
|
||||
|
||||
#define LINE_LEN 80
|
||||
#define TAB_LEN 8 /* 8 spaces between tabs */
|
||||
#define _PATH_FORWARD ".forward"
|
||||
#define _PATH_PLAN ".plan"
|
||||
#define _PATH_PROJECT ".project"
|
||||
|
||||
static int demi_print __P((char *, int));
|
||||
static void lprint __P((PERSON *));
|
||||
static int show_text __P((char *, char *, char *));
|
||||
static void vputc __P((int));
|
||||
|
||||
void
|
||||
lflag_print()
|
||||
{
|
||||
extern int pplan;
|
||||
register PERSON *pn;
|
||||
register int sflag, r;
|
||||
PERSON *tmp;
|
||||
DBT data, key;
|
||||
|
||||
for (sflag = R_FIRST;; sflag = R_NEXT) {
|
||||
r = (*db->seq)(db, &key, &data, sflag);
|
||||
if (r == -1)
|
||||
err(1, "db seq");
|
||||
if (r == 1)
|
||||
break;
|
||||
memmove(&tmp, data.data, sizeof tmp);
|
||||
pn = tmp;
|
||||
if (sflag != R_FIRST)
|
||||
putchar('\n');
|
||||
lprint(pn);
|
||||
if (!pplan) {
|
||||
(void)show_text(pn->dir,
|
||||
_PATH_FORWARD, "Mail forwarded to");
|
||||
(void)show_text(pn->dir, _PATH_PROJECT, "Project");
|
||||
if (!show_text(pn->dir, _PATH_PLAN, "Plan"))
|
||||
(void)printf("No Plan.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lprint(pn)
|
||||
register PERSON *pn;
|
||||
{
|
||||
extern time_t now;
|
||||
register struct tm *delta;
|
||||
register WHERE *w;
|
||||
register int cpr, len, maxlen;
|
||||
struct tm *tp;
|
||||
int oddfield;
|
||||
char *t, *tzn;
|
||||
|
||||
/*
|
||||
* long format --
|
||||
* login name
|
||||
* real name
|
||||
* home directory
|
||||
* shell
|
||||
* office, office phone, home phone if available
|
||||
*/
|
||||
(void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s",
|
||||
pn->name, pn->realname, pn->dir);
|
||||
(void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL);
|
||||
|
||||
/*
|
||||
* try and print office, office phone, and home phone on one line;
|
||||
* if that fails, do line filling so it looks nice.
|
||||
*/
|
||||
#define OFFICE_TAG "Office"
|
||||
#define OFFICE_PHONE_TAG "Office Phone"
|
||||
oddfield = 0;
|
||||
if (pn->office && pn->officephone &&
|
||||
strlen(pn->office) + strlen(pn->officephone) +
|
||||
sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) {
|
||||
(void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s",
|
||||
OFFICE_TAG, pn->office, prphone(pn->officephone));
|
||||
oddfield = demi_print(tbuf, oddfield);
|
||||
} else {
|
||||
if (pn->office) {
|
||||
(void)snprintf(tbuf, sizeof(tbuf), "%s: %s",
|
||||
OFFICE_TAG, pn->office);
|
||||
oddfield = demi_print(tbuf, oddfield);
|
||||
}
|
||||
if (pn->officephone) {
|
||||
(void)snprintf(tbuf, sizeof(tbuf), "%s: %s",
|
||||
OFFICE_PHONE_TAG, prphone(pn->officephone));
|
||||
oddfield = demi_print(tbuf, oddfield);
|
||||
}
|
||||
}
|
||||
if (pn->homephone) {
|
||||
(void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone",
|
||||
prphone(pn->homephone));
|
||||
oddfield = demi_print(tbuf, oddfield);
|
||||
}
|
||||
if (oddfield)
|
||||
putchar('\n');
|
||||
|
||||
/*
|
||||
* long format con't: * if logged in
|
||||
* terminal
|
||||
* idle time
|
||||
* if messages allowed
|
||||
* where logged in from
|
||||
* if not logged in
|
||||
* when last logged in
|
||||
*/
|
||||
/* find out longest device name for this user for formatting */
|
||||
for (w = pn->whead, maxlen = -1; w != NULL; w = w->next)
|
||||
if ((len = strlen(w->tty)) > maxlen)
|
||||
maxlen = len;
|
||||
/* find rest of entries for user */
|
||||
for (w = pn->whead; w != NULL; w = w->next) {
|
||||
switch (w->info) {
|
||||
case LOGGEDIN:
|
||||
tp = localtime(&w->loginat);
|
||||
t = asctime(tp);
|
||||
tzn = tp->tm_zone;
|
||||
cpr = printf("On since %.16s (%s) on %s",
|
||||
t, tzn, w->tty);
|
||||
/*
|
||||
* idle time is tough; if have one, print a comma,
|
||||
* then spaces to pad out the device name, then the
|
||||
* idle time. Follow with a comma if a remote login.
|
||||
*/
|
||||
delta = gmtime(&w->idletime);
|
||||
if (delta->tm_yday || delta->tm_hour || delta->tm_min) {
|
||||
cpr += printf("%-*s idle ",
|
||||
maxlen - strlen(w->tty) + 1, ",");
|
||||
if (delta->tm_yday > 0) {
|
||||
cpr += printf("%d day%s ",
|
||||
delta->tm_yday,
|
||||
delta->tm_yday == 1 ? "" : "s");
|
||||
}
|
||||
cpr += printf("%d:%02d",
|
||||
delta->tm_hour, delta->tm_min);
|
||||
if (*w->host) {
|
||||
putchar(',');
|
||||
++cpr;
|
||||
}
|
||||
}
|
||||
if (!w->writable)
|
||||
cpr += printf(" (messages off)");
|
||||
break;
|
||||
case LASTLOG:
|
||||
if (w->loginat == 0) {
|
||||
(void)printf("Never logged in.");
|
||||
break;
|
||||
}
|
||||
tp = localtime(&w->loginat);
|
||||
t = asctime(tp);
|
||||
tzn = tp->tm_zone;
|
||||
if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2)
|
||||
cpr =
|
||||
printf("Last login %.16s %.4s (%s) on %s",
|
||||
t, t + 20, tzn, w->tty);
|
||||
else
|
||||
cpr = printf("Last login %.16s (%s) on %s",
|
||||
t, tzn, w->tty);
|
||||
break;
|
||||
}
|
||||
if (*w->host) {
|
||||
if (LINE_LEN < (cpr + 6 + strlen(w->host)))
|
||||
(void)printf("\n ");
|
||||
(void)printf(" from %s", w->host);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
demi_print(str, oddfield)
|
||||
char *str;
|
||||
int oddfield;
|
||||
{
|
||||
static int lenlast;
|
||||
int lenthis, maxlen;
|
||||
|
||||
lenthis = strlen(str);
|
||||
if (oddfield) {
|
||||
/*
|
||||
* We left off on an odd number of fields. If we haven't
|
||||
* crossed the midpoint of the screen, and we have room for
|
||||
* the next field, print it on the same line; otherwise,
|
||||
* print it on a new line.
|
||||
*
|
||||
* Note: we insist on having the right hand fields start
|
||||
* no less than 5 tabs out.
|
||||
*/
|
||||
maxlen = 5 * TAB_LEN;
|
||||
if (maxlen < lenlast)
|
||||
maxlen = lenlast;
|
||||
if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) +
|
||||
lenthis) <= LINE_LEN) {
|
||||
while(lenlast < (4 * TAB_LEN)) {
|
||||
putchar('\t');
|
||||
lenlast += TAB_LEN;
|
||||
}
|
||||
(void)printf("\t%s\n", str); /* force one tab */
|
||||
} else {
|
||||
(void)printf("\n%s", str); /* go to next line */
|
||||
oddfield = !oddfield; /* this'll be undone below */
|
||||
}
|
||||
} else
|
||||
(void)printf("%s", str);
|
||||
oddfield = !oddfield; /* toggle odd/even marker */
|
||||
lenlast = lenthis;
|
||||
return(oddfield);
|
||||
}
|
||||
|
||||
static int
|
||||
show_text(directory, file_name, header)
|
||||
char *directory, *file_name, *header;
|
||||
{
|
||||
struct stat sb;
|
||||
register FILE *fp;
|
||||
register int ch, cnt, lastc;
|
||||
register char *p;
|
||||
int fd, nr;
|
||||
|
||||
(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name);
|
||||
if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) ||
|
||||
sb.st_size == 0)
|
||||
return(0);
|
||||
|
||||
/* If short enough, and no newlines, show it on a single line.*/
|
||||
if (sb.st_size <= LINE_LEN - strlen(header) - 5) {
|
||||
nr = read(fd, tbuf, sizeof(tbuf));
|
||||
if (nr <= 0) {
|
||||
(void)close(fd);
|
||||
return(0);
|
||||
}
|
||||
for (p = tbuf, cnt = nr; cnt--; ++p)
|
||||
if (*p == '\n')
|
||||
break;
|
||||
if (cnt <= 1) {
|
||||
(void)printf("%s: ", header);
|
||||
for (p = tbuf, cnt = nr; cnt--; ++p)
|
||||
vputc(lastc = *p);
|
||||
if (lastc != '\n')
|
||||
(void)putchar('\n');
|
||||
(void)close(fd);
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
(void)lseek(fd, 0L, SEEK_SET);
|
||||
}
|
||||
if ((fp = fdopen(fd, "r")) == NULL)
|
||||
return(0);
|
||||
(void)printf("%s:\n", header);
|
||||
while ((ch = getc(fp)) != EOF)
|
||||
vputc(lastc = ch);
|
||||
if (lastc != '\n')
|
||||
(void)putchar('\n');
|
||||
(void)fclose(fp);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
vputc(ch)
|
||||
register int ch;
|
||||
{
|
||||
int meta;
|
||||
|
||||
if (!isascii(ch)) {
|
||||
(void)putchar('M');
|
||||
(void)putchar('-');
|
||||
ch = toascii(ch);
|
||||
meta = 1;
|
||||
} else
|
||||
meta = 0;
|
||||
if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n'))
|
||||
(void)putchar(ch);
|
||||
else {
|
||||
(void)putchar('^');
|
||||
(void)putchar(ch == '\177' ? '?' : ch | 0100);
|
||||
}
|
||||
}
|
149
usr.bin/finger/net.c
Normal file
149
usr.bin/finger/net.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)net.c 8.4 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <db.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <utmp.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "finger.h"
|
||||
|
||||
void
|
||||
netfinger(name)
|
||||
char *name;
|
||||
{
|
||||
extern int lflag;
|
||||
register FILE *fp;
|
||||
register int c, lastc;
|
||||
struct in_addr defaddr;
|
||||
struct hostent *hp, def;
|
||||
struct servent *sp;
|
||||
struct sockaddr_in sin;
|
||||
int s;
|
||||
char *alist[1], *host;
|
||||
|
||||
if (!(host = rindex(name, '@')))
|
||||
return;
|
||||
*host++ = NULL;
|
||||
if (isdigit(*host) && (defaddr.s_addr = inet_addr(host)) != -1) {
|
||||
def.h_name = host;
|
||||
def.h_addr_list = alist;
|
||||
def.h_addr = (char *)&defaddr;
|
||||
def.h_length = sizeof(struct in_addr);
|
||||
def.h_addrtype = AF_INET;
|
||||
def.h_aliases = 0;
|
||||
hp = &def;
|
||||
} else if (!(hp = gethostbyname(host))) {
|
||||
(void)fprintf(stderr,
|
||||
"finger: unknown host: %s\n", host);
|
||||
return;
|
||||
}
|
||||
if (!(sp = getservbyname("finger", "tcp"))) {
|
||||
(void)fprintf(stderr, "finger: tcp/finger: unknown service\n");
|
||||
return;
|
||||
}
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
|
||||
sin.sin_port = sp->s_port;
|
||||
if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
|
||||
perror("finger: socket");
|
||||
return;
|
||||
}
|
||||
|
||||
/* have network connection; identify the host connected with */
|
||||
(void)printf("[%s]\n", hp->h_name);
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
perror("finger: connect");
|
||||
(void)close(s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* -l flag for remote fingerd */
|
||||
if (lflag)
|
||||
write(s, "/W ", 3);
|
||||
/* send the name followed by <CR><LF> */
|
||||
(void)write(s, name, strlen(name));
|
||||
(void)write(s, "\r\n", 2);
|
||||
|
||||
/*
|
||||
* Read from the remote system; once we're connected, we assume some
|
||||
* data. If none arrives, we hang until the user interrupts.
|
||||
*
|
||||
* If we see a <CR> or a <CR> with the high bit set, treat it as
|
||||
* a newline; if followed by a newline character, only output one
|
||||
* newline.
|
||||
*
|
||||
* Otherwise, all high bits are stripped; if it isn't printable and
|
||||
* it isn't a space, we can simply set the 7th bit. Every ASCII
|
||||
* character with bit 7 set is printable.
|
||||
*/
|
||||
lastc = 0;
|
||||
if ((fp = fdopen(s, "r")) != NULL)
|
||||
while ((c = getc(fp)) != EOF) {
|
||||
c &= 0x7f;
|
||||
if (c == 0x0d) {
|
||||
if (lastc == '\r') /* ^M^M - skip dupes */
|
||||
continue;
|
||||
c = '\n';
|
||||
lastc = '\r';
|
||||
} else {
|
||||
if (!isprint(c) && !isspace(c))
|
||||
c |= 0x40;
|
||||
if (lastc != '\r' || c != '\n')
|
||||
lastc = c;
|
||||
else {
|
||||
lastc = '\n';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
if (lastc != '\n')
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
(void)fclose(fp);
|
||||
}
|
151
usr.bin/finger/sprint.c
Normal file
151
usr.bin/finger/sprint.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)sprint.c 8.3 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <db.h>
|
||||
#include <err.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <utmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "finger.h"
|
||||
|
||||
static void stimeprint __P((WHERE *));
|
||||
|
||||
void
|
||||
sflag_print()
|
||||
{
|
||||
extern time_t now;
|
||||
register PERSON *pn;
|
||||
register WHERE *w;
|
||||
register int sflag, r;
|
||||
register char *p;
|
||||
PERSON *tmp;
|
||||
DBT data, key;
|
||||
|
||||
/*
|
||||
* short format --
|
||||
* login name
|
||||
* real name
|
||||
* terminal name (the XX of ttyXX)
|
||||
* if terminal writeable (add an '*' to the terminal name
|
||||
* if not)
|
||||
* if logged in show idle time and day logged in, else
|
||||
* show last login date and time. If > 6 moths,
|
||||
* show year instead of time.
|
||||
* office location
|
||||
* office phone
|
||||
*/
|
||||
#define MAXREALNAME 20
|
||||
(void)printf("%-*s %-*s %s\n", UT_NAMESIZE, "Login", MAXREALNAME,
|
||||
"Name", "Tty Idle Login Time Office Office Phone");
|
||||
|
||||
for (sflag = R_FIRST;; sflag = R_NEXT) {
|
||||
r = (*db->seq)(db, &key, &data, sflag);
|
||||
if (r == -1)
|
||||
err(1, "db seq");
|
||||
if (r == 1)
|
||||
break;
|
||||
memmove(&tmp, data.data, sizeof tmp);
|
||||
pn = tmp;
|
||||
|
||||
for (w = pn->whead; w != NULL; w = w->next) {
|
||||
(void)printf("%-*.*s %-*.*s ", UT_NAMESIZE, UT_NAMESIZE,
|
||||
pn->name, MAXREALNAME, MAXREALNAME,
|
||||
pn->realname ? pn->realname : "");
|
||||
if (!w->loginat) {
|
||||
(void)printf(" * * No logins ");
|
||||
goto office;
|
||||
}
|
||||
(void)putchar(w->info == LOGGEDIN && !w->writable ?
|
||||
'*' : ' ');
|
||||
if (*w->tty)
|
||||
(void)printf("%-2.2s ",
|
||||
w->tty[0] != 't' || w->tty[1] != 't' ||
|
||||
w->tty[2] != 'y' ? w->tty : w->tty + 3);
|
||||
else
|
||||
(void)printf(" ");
|
||||
if (w->info == LOGGEDIN) {
|
||||
stimeprint(w);
|
||||
(void)printf(" ");
|
||||
} else
|
||||
(void)printf(" * ");
|
||||
p = ctime(&w->loginat);
|
||||
(void)printf("%.6s", p + 4);
|
||||
if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2)
|
||||
(void)printf(" %.4s", p + 20);
|
||||
else
|
||||
(void)printf(" %.5s", p + 11);
|
||||
office: if (pn->office)
|
||||
(void)printf(" %-10.10s", pn->office);
|
||||
else if (pn->officephone)
|
||||
(void)printf(" %-10.10s", " ");
|
||||
if (pn->officephone)
|
||||
(void)printf(" %-.15s",
|
||||
prphone(pn->officephone));
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stimeprint(w)
|
||||
WHERE *w;
|
||||
{
|
||||
register struct tm *delta;
|
||||
|
||||
delta = gmtime(&w->idletime);
|
||||
if (!delta->tm_yday)
|
||||
if (!delta->tm_hour)
|
||||
if (!delta->tm_min)
|
||||
(void)printf(" ");
|
||||
else
|
||||
(void)printf("%5d", delta->tm_min);
|
||||
else
|
||||
(void)printf("%2d:%02d",
|
||||
delta->tm_hour, delta->tm_min);
|
||||
else
|
||||
(void)printf("%4dd", delta->tm_yday);
|
||||
}
|
357
usr.bin/finger/util.c
Normal file
357
usr.bin/finger/util.c
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <db.h>
|
||||
#include <err.h>
|
||||
#include <pwd.h>
|
||||
#include <utmp.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
#include "finger.h"
|
||||
|
||||
static void find_idle_and_ttywrite __P((WHERE *));
|
||||
static void userinfo __P((PERSON *, struct passwd *));
|
||||
static WHERE *walloc __P((PERSON *));
|
||||
|
||||
int
|
||||
match(pw, user)
|
||||
struct passwd *pw;
|
||||
char *user;
|
||||
{
|
||||
register char *p, *t;
|
||||
char name[1024];
|
||||
|
||||
if (!strcasecmp(pw->pw_name, user))
|
||||
return(1);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Why do we skip asterisks!?!?
|
||||
*/
|
||||
(void)strcpy(p = tbuf, pw->pw_gecos);
|
||||
if (*p == '*')
|
||||
++p;
|
||||
|
||||
/* Ampersands get replaced by the login name. */
|
||||
if ((p = strtok(p, ",")) == NULL)
|
||||
return(0);
|
||||
|
||||
for (t = name; (*t = *p) != '\0'; ++p)
|
||||
if (*t == '&') {
|
||||
(void)strcpy(t, pw->pw_name);
|
||||
while (*++t);
|
||||
}
|
||||
else
|
||||
++t;
|
||||
for (t = name; (p = strtok(t, "\t ")) != NULL; t = NULL)
|
||||
if (!strcasecmp(p, user))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
enter_lastlog(pn)
|
||||
register PERSON *pn;
|
||||
{
|
||||
register WHERE *w;
|
||||
static int opened, fd;
|
||||
struct lastlog ll;
|
||||
char doit = 0;
|
||||
|
||||
/* some systems may not maintain lastlog, don't report errors. */
|
||||
if (!opened) {
|
||||
fd = open(_PATH_LASTLOG, O_RDONLY, 0);
|
||||
opened = 1;
|
||||
}
|
||||
if (fd == -1 ||
|
||||
lseek(fd, (long)pn->uid * sizeof(ll), SEEK_SET) !=
|
||||
(long)pn->uid * sizeof(ll) ||
|
||||
read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
|
||||
/* as if never logged in */
|
||||
ll.ll_line[0] = ll.ll_host[0] = NULL;
|
||||
ll.ll_time = 0;
|
||||
}
|
||||
if ((w = pn->whead) == NULL)
|
||||
doit = 1;
|
||||
else if (ll.ll_time != 0) {
|
||||
/* if last login is earlier than some current login */
|
||||
for (; !doit && w != NULL; w = w->next)
|
||||
if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
|
||||
doit = 1;
|
||||
/*
|
||||
* and if it's not any of the current logins
|
||||
* can't use time comparison because there may be a small
|
||||
* discrepency since login calls time() twice
|
||||
*/
|
||||
for (w = pn->whead; doit && w != NULL; w = w->next)
|
||||
if (w->info == LOGGEDIN &&
|
||||
strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
|
||||
doit = 0;
|
||||
}
|
||||
if (doit) {
|
||||
w = walloc(pn);
|
||||
w->info = LASTLOG;
|
||||
bcopy(ll.ll_line, w->tty, UT_LINESIZE);
|
||||
w->tty[UT_LINESIZE] = 0;
|
||||
bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
|
||||
w->host[UT_HOSTSIZE] = 0;
|
||||
w->loginat = ll.ll_time;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
enter_where(ut, pn)
|
||||
struct utmp *ut;
|
||||
PERSON *pn;
|
||||
{
|
||||
register WHERE *w;
|
||||
|
||||
w = walloc(pn);
|
||||
w->info = LOGGEDIN;
|
||||
bcopy(ut->ut_line, w->tty, UT_LINESIZE);
|
||||
w->tty[UT_LINESIZE] = 0;
|
||||
bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
|
||||
w->host[UT_HOSTSIZE] = 0;
|
||||
w->loginat = (time_t)ut->ut_time;
|
||||
find_idle_and_ttywrite(w);
|
||||
}
|
||||
|
||||
PERSON *
|
||||
enter_person(pw)
|
||||
register struct passwd *pw;
|
||||
{
|
||||
DBT data, key;
|
||||
PERSON *pn;
|
||||
|
||||
if (db == NULL &&
|
||||
(db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
key.data = pw->pw_name;
|
||||
key.size = strlen(pw->pw_name);
|
||||
|
||||
switch ((*db->get)(db, &key, &data, 0)) {
|
||||
case 0:
|
||||
memmove(&pn, data.data, sizeof pn);
|
||||
return (pn);
|
||||
default:
|
||||
case -1:
|
||||
err(1, "db get");
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
++entries;
|
||||
pn = palloc();
|
||||
userinfo(pn, pw);
|
||||
pn->whead = NULL;
|
||||
|
||||
data.size = sizeof(PERSON *);
|
||||
data.data = &pn;
|
||||
if ((*db->put)(db, &key, &data, 0))
|
||||
err(1, "db put");
|
||||
return (pn);
|
||||
}
|
||||
}
|
||||
|
||||
PERSON *
|
||||
find_person(name)
|
||||
char *name;
|
||||
{
|
||||
register int cnt;
|
||||
DBT data, key;
|
||||
PERSON *p;
|
||||
char buf[UT_NAMESIZE + 1];
|
||||
|
||||
if (!db)
|
||||
return(NULL);
|
||||
|
||||
/* Name may be only UT_NAMESIZE long and not NUL terminated. */
|
||||
for (cnt = 0; cnt < UT_NAMESIZE && *name; ++name, ++cnt)
|
||||
buf[cnt] = *name;
|
||||
buf[cnt] = '\0';
|
||||
key.data = buf;
|
||||
key.size = cnt;
|
||||
|
||||
if ((*db->get)(db, &key, &data, 0))
|
||||
return (NULL);
|
||||
memmove(&p, data.data, sizeof p);
|
||||
return (p);
|
||||
}
|
||||
|
||||
PERSON *
|
||||
palloc()
|
||||
{
|
||||
PERSON *p;
|
||||
|
||||
if ((p = malloc((u_int) sizeof(PERSON))) == NULL)
|
||||
err(1, NULL);
|
||||
return(p);
|
||||
}
|
||||
|
||||
static WHERE *
|
||||
walloc(pn)
|
||||
register PERSON *pn;
|
||||
{
|
||||
register WHERE *w;
|
||||
|
||||
if ((w = malloc((u_int) sizeof(WHERE))) == NULL)
|
||||
err(1, NULL);
|
||||
if (pn->whead == NULL)
|
||||
pn->whead = pn->wtail = w;
|
||||
else {
|
||||
pn->wtail->next = w;
|
||||
pn->wtail = w;
|
||||
}
|
||||
w->next = NULL;
|
||||
return(w);
|
||||
}
|
||||
|
||||
char *
|
||||
prphone(num)
|
||||
char *num;
|
||||
{
|
||||
register char *p;
|
||||
int len;
|
||||
static char pbuf[15];
|
||||
|
||||
/* don't touch anything if the user has their own formatting */
|
||||
for (p = num; *p; ++p)
|
||||
if (!isdigit(*p))
|
||||
return(num);
|
||||
len = p - num;
|
||||
p = pbuf;
|
||||
switch(len) {
|
||||
case 11: /* +0-123-456-7890 */
|
||||
*p++ = '+';
|
||||
*p++ = *num++;
|
||||
*p++ = '-';
|
||||
/* FALLTHROUGH */
|
||||
case 10: /* 012-345-6789 */
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
*p++ = '-';
|
||||
/* FALLTHROUGH */
|
||||
case 7: /* 012-3456 */
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
break;
|
||||
case 5: /* x0-1234 */
|
||||
*p++ = 'x';
|
||||
*p++ = *num++;
|
||||
break;
|
||||
default:
|
||||
return(num);
|
||||
}
|
||||
*p++ = '-';
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
*p++ = *num++;
|
||||
*p = '\0';
|
||||
return(pbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
find_idle_and_ttywrite(w)
|
||||
register WHERE *w;
|
||||
{
|
||||
extern time_t now;
|
||||
struct stat sb;
|
||||
|
||||
(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty);
|
||||
if (stat(tbuf, &sb) < 0) {
|
||||
warn(tbuf);
|
||||
return;
|
||||
}
|
||||
w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
|
||||
|
||||
#define TALKABLE 0220 /* tty is writable if 220 mode */
|
||||
w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
userinfo(pn, pw)
|
||||
register PERSON *pn;
|
||||
register struct passwd *pw;
|
||||
{
|
||||
register char *p, *t;
|
||||
char *bp, name[1024];
|
||||
|
||||
pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
|
||||
|
||||
pn->uid = pw->pw_uid;
|
||||
pn->name = strdup(pw->pw_name);
|
||||
pn->dir = strdup(pw->pw_dir);
|
||||
pn->shell = strdup(pw->pw_shell);
|
||||
|
||||
/* why do we skip asterisks!?!? */
|
||||
(void)strcpy(bp = tbuf, pw->pw_gecos);
|
||||
if (*bp == '*')
|
||||
++bp;
|
||||
|
||||
/* ampersands get replaced by the login name */
|
||||
if (!(p = strsep(&bp, ",")))
|
||||
return;
|
||||
for (t = name; (*t = *p) != '\0'; ++p)
|
||||
if (*t == '&') {
|
||||
(void)strcpy(t, pw->pw_name);
|
||||
if (islower(*t))
|
||||
*t = toupper(*t);
|
||||
while (*++t);
|
||||
}
|
||||
else
|
||||
++t;
|
||||
pn->realname = strdup(name);
|
||||
pn->office = ((p = strsep(&bp, ",")) && *p) ?
|
||||
strdup(p) : NULL;
|
||||
pn->officephone = ((p = strsep(&bp, ",")) && *p) ?
|
||||
strdup(p) : NULL;
|
||||
pn->homephone = ((p = strsep(&bp, ",")) && *p) ?
|
||||
strdup(p) : NULL;
|
||||
}
|
748
usr.bin/fstat/fstat.c
Normal file
748
usr.bin/fstat/fstat.c
Normal file
@ -0,0 +1,748 @@
|
||||
/*-
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/unpcb.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/filedesc.h>
|
||||
#define KERNEL
|
||||
#include <sys/file.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <ufs/ufs/inode.h>
|
||||
#undef KERNEL
|
||||
#define NFS
|
||||
#include <sys/mount.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#undef NFS
|
||||
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <nlist.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEXT -1
|
||||
#define CDIR -2
|
||||
#define RDIR -3
|
||||
#define TRACE -4
|
||||
|
||||
typedef struct devs {
|
||||
struct devs *next;
|
||||
long fsid;
|
||||
ino_t ino;
|
||||
char *name;
|
||||
} DEVS;
|
||||
DEVS *devs;
|
||||
|
||||
struct filestat {
|
||||
long fsid;
|
||||
long fileid;
|
||||
mode_t mode;
|
||||
u_long size;
|
||||
dev_t rdev;
|
||||
};
|
||||
|
||||
#ifdef notdef
|
||||
struct nlist nl[] = {
|
||||
{ "" },
|
||||
};
|
||||
#endif
|
||||
|
||||
int fsflg, /* show files on same filesystem as file(s) argument */
|
||||
pflg, /* show files open by a particular pid */
|
||||
uflg; /* show files open by a particular (effective) user */
|
||||
int checkfile; /* true if restricting to particular files or filesystems */
|
||||
int nflg; /* (numerical) display f.s. and rdev as dev_t */
|
||||
int vflg; /* display errors in locating kernel data objects etc... */
|
||||
|
||||
#define dprintf if (vflg) fprintf
|
||||
|
||||
struct file **ofiles; /* buffer of pointers to file structures */
|
||||
int maxfiles;
|
||||
#define ALLOC_OFILES(d) \
|
||||
if ((d) > maxfiles) { \
|
||||
free(ofiles); \
|
||||
ofiles = malloc((d) * sizeof(struct file *)); \
|
||||
if (ofiles == NULL) { \
|
||||
fprintf(stderr, "fstat: %s\n", strerror(errno)); \
|
||||
exit(1); \
|
||||
} \
|
||||
maxfiles = (d); \
|
||||
}
|
||||
|
||||
/*
|
||||
* a kvm_read that returns true if everything is read
|
||||
*/
|
||||
#define KVM_READ(kaddr, paddr, len) \
|
||||
(kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (len))
|
||||
|
||||
kvm_t *kd;
|
||||
|
||||
int ufs_filestat(), nfs_filestat();
|
||||
void dofiles(), getinetproto(), socktrans();
|
||||
void usage(), vtrans();
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
register struct passwd *passwd;
|
||||
struct kinfo_proc *p, *plast;
|
||||
int arg, ch, what;
|
||||
char *memf, *nlistf;
|
||||
char buf[_POSIX2_LINE_MAX];
|
||||
int cnt;
|
||||
|
||||
arg = 0;
|
||||
what = KERN_PROC_ALL;
|
||||
nlistf = memf = NULL;
|
||||
while ((ch = getopt(argc, argv, "fnp:u:vNM")) != EOF)
|
||||
switch((char)ch) {
|
||||
case 'f':
|
||||
fsflg = 1;
|
||||
break;
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
nlistf = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
nflg = 1;
|
||||
break;
|
||||
case 'p':
|
||||
if (pflg++)
|
||||
usage();
|
||||
if (!isdigit(*optarg)) {
|
||||
fprintf(stderr,
|
||||
"fstat: -p requires a process id\n");
|
||||
usage();
|
||||
}
|
||||
what = KERN_PROC_PID;
|
||||
arg = atoi(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
if (uflg++)
|
||||
usage();
|
||||
if (!(passwd = getpwnam(optarg))) {
|
||||
fprintf(stderr, "%s: unknown uid\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
what = KERN_PROC_UID;
|
||||
arg = passwd->pw_uid;
|
||||
break;
|
||||
case 'v':
|
||||
vflg = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (*(argv += optind)) {
|
||||
for (; *argv; ++argv) {
|
||||
if (getfname(*argv))
|
||||
checkfile = 1;
|
||||
}
|
||||
if (!checkfile) /* file(s) specified, but none accessable */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ALLOC_OFILES(256); /* reserve space for file pointers */
|
||||
|
||||
if (fsflg && !checkfile) {
|
||||
/* -f with no files means use wd */
|
||||
if (getfname(".") == 0)
|
||||
exit(1);
|
||||
checkfile = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard setgid privileges if not the running kernel so that bad
|
||||
* guys can't print interesting stuff from kernel memory.
|
||||
*/
|
||||
if (nlistf != NULL || memf != NULL)
|
||||
setgid(getgid());
|
||||
|
||||
if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) {
|
||||
fprintf(stderr, "fstat: %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef notdef
|
||||
if (kvm_nlist(kd, nl) != 0) {
|
||||
fprintf(stderr, "fstat: no namelist: %s\n", kvm_geterr(kd));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) {
|
||||
fprintf(stderr, "fstat: %s\n", kvm_geterr(kd));
|
||||
exit(1);
|
||||
}
|
||||
if (nflg)
|
||||
printf("%s",
|
||||
"USER CMD PID FD DEV INUM MODE SZ|DV R/W");
|
||||
else
|
||||
printf("%s",
|
||||
"USER CMD PID FD MOUNT INUM MODE SZ|DV R/W");
|
||||
if (checkfile && fsflg == 0)
|
||||
printf(" NAME\n");
|
||||
else
|
||||
putchar('\n');
|
||||
|
||||
for (plast = &p[cnt]; p < plast; ++p) {
|
||||
if (p->kp_proc.p_stat == SZOMB)
|
||||
continue;
|
||||
dofiles(p);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *Uname, *Comm;
|
||||
int Pid;
|
||||
|
||||
#define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \
|
||||
switch(i) { \
|
||||
case TEXT: \
|
||||
printf(" text"); \
|
||||
break; \
|
||||
case CDIR: \
|
||||
printf(" wd"); \
|
||||
break; \
|
||||
case RDIR: \
|
||||
printf(" root"); \
|
||||
break; \
|
||||
case TRACE: \
|
||||
printf(" tr"); \
|
||||
break; \
|
||||
default: \
|
||||
printf(" %4d", i); \
|
||||
break; \
|
||||
}
|
||||
|
||||
/*
|
||||
* print open files attributed to this process
|
||||
*/
|
||||
void
|
||||
dofiles(kp)
|
||||
struct kinfo_proc *kp;
|
||||
{
|
||||
int i, last;
|
||||
struct file file;
|
||||
struct filedesc0 filed0;
|
||||
#define filed filed0.fd_fd
|
||||
struct proc *p = &kp->kp_proc;
|
||||
struct eproc *ep = &kp->kp_eproc;
|
||||
|
||||
extern char *user_from_uid();
|
||||
|
||||
Uname = user_from_uid(ep->e_ucred.cr_uid, 0);
|
||||
Pid = p->p_pid;
|
||||
Comm = p->p_comm;
|
||||
|
||||
if (p->p_fd == NULL)
|
||||
return;
|
||||
if (!KVM_READ(p->p_fd, &filed0, sizeof (filed0))) {
|
||||
dprintf(stderr, "can't read filedesc at %x for pid %d\n",
|
||||
p->p_fd, Pid);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* root directory vnode, if one
|
||||
*/
|
||||
if (filed.fd_rdir)
|
||||
vtrans(filed.fd_rdir, RDIR, FREAD);
|
||||
/*
|
||||
* current working directory vnode
|
||||
*/
|
||||
vtrans(filed.fd_cdir, CDIR, FREAD);
|
||||
/*
|
||||
* ktrace vnode, if one
|
||||
*/
|
||||
if (p->p_tracep)
|
||||
vtrans(p->p_tracep, TRACE, FREAD|FWRITE);
|
||||
/*
|
||||
* open files
|
||||
*/
|
||||
#define FPSIZE (sizeof (struct file *))
|
||||
ALLOC_OFILES(filed.fd_lastfile+1);
|
||||
if (filed.fd_nfiles > NDFILE) {
|
||||
if (!KVM_READ(filed.fd_ofiles, ofiles,
|
||||
(filed.fd_lastfile+1) * FPSIZE)) {
|
||||
dprintf(stderr,
|
||||
"can't read file structures at %x for pid %d\n",
|
||||
filed.fd_ofiles, Pid);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
bcopy(filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE);
|
||||
for (i = 0; i <= filed.fd_lastfile; i++) {
|
||||
if (ofiles[i] == NULL)
|
||||
continue;
|
||||
if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) {
|
||||
dprintf(stderr, "can't read file %d at %x for pid %d\n",
|
||||
i, ofiles[i], Pid);
|
||||
continue;
|
||||
}
|
||||
if (file.f_type == DTYPE_VNODE)
|
||||
vtrans((struct vnode *)file.f_data, i, file.f_flag);
|
||||
else if (file.f_type == DTYPE_SOCKET) {
|
||||
if (checkfile == 0)
|
||||
socktrans((struct socket *)file.f_data, i);
|
||||
}
|
||||
else {
|
||||
dprintf(stderr,
|
||||
"unknown file type %d for file %d of pid %d\n",
|
||||
file.f_type, i, Pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vtrans(vp, i, flag)
|
||||
struct vnode *vp;
|
||||
int i;
|
||||
int flag;
|
||||
{
|
||||
struct vnode vn;
|
||||
struct filestat fst;
|
||||
char rw[3], mode[15];
|
||||
char *badtype = NULL, *filename, *getmnton();
|
||||
|
||||
filename = badtype = NULL;
|
||||
if (!KVM_READ(vp, &vn, sizeof (struct vnode))) {
|
||||
dprintf(stderr, "can't read vnode at %x for pid %d\n",
|
||||
vp, Pid);
|
||||
return;
|
||||
}
|
||||
if (vn.v_type == VNON || vn.v_tag == VT_NON)
|
||||
badtype = "none";
|
||||
else if (vn.v_type == VBAD)
|
||||
badtype = "bad";
|
||||
else
|
||||
switch (vn.v_tag) {
|
||||
case VT_UFS:
|
||||
if (!ufs_filestat(&vn, &fst))
|
||||
badtype = "error";
|
||||
break;
|
||||
case VT_MFS:
|
||||
if (!ufs_filestat(&vn, &fst))
|
||||
badtype = "error";
|
||||
break;
|
||||
case VT_NFS:
|
||||
if (!nfs_filestat(&vn, &fst))
|
||||
badtype = "error";
|
||||
break;
|
||||
default: {
|
||||
static char unknown[10];
|
||||
sprintf(badtype = unknown, "?(%x)", vn.v_tag);
|
||||
break;;
|
||||
}
|
||||
}
|
||||
if (checkfile) {
|
||||
int fsmatch = 0;
|
||||
register DEVS *d;
|
||||
|
||||
if (badtype)
|
||||
return;
|
||||
for (d = devs; d != NULL; d = d->next)
|
||||
if (d->fsid == fst.fsid) {
|
||||
fsmatch = 1;
|
||||
if (d->ino == fst.fileid) {
|
||||
filename = d->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fsmatch == 0 || (filename == NULL && fsflg == 0))
|
||||
return;
|
||||
}
|
||||
PREFIX(i);
|
||||
if (badtype) {
|
||||
(void)printf(" - - %10s -\n", badtype);
|
||||
return;
|
||||
}
|
||||
if (nflg)
|
||||
(void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid));
|
||||
else
|
||||
(void)printf(" %-8s", getmnton(vn.v_mount));
|
||||
if (nflg)
|
||||
(void)sprintf(mode, "%o", fst.mode);
|
||||
else
|
||||
strmode(fst.mode, mode);
|
||||
(void)printf(" %6d %10s", fst.fileid, mode);
|
||||
switch (vn.v_type) {
|
||||
case VBLK:
|
||||
case VCHR: {
|
||||
char *name;
|
||||
|
||||
if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ?
|
||||
S_IFCHR : S_IFBLK)) == NULL))
|
||||
printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev));
|
||||
else
|
||||
printf(" %6s", name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf(" %6d", fst.size);
|
||||
}
|
||||
rw[0] = '\0';
|
||||
if (flag & FREAD)
|
||||
strcat(rw, "r");
|
||||
if (flag & FWRITE)
|
||||
strcat(rw, "w");
|
||||
printf(" %2s", rw);
|
||||
if (filename && !fsflg)
|
||||
printf(" %s", filename);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
int
|
||||
ufs_filestat(vp, fsp)
|
||||
struct vnode *vp;
|
||||
struct filestat *fsp;
|
||||
{
|
||||
struct inode inode;
|
||||
|
||||
if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
|
||||
dprintf(stderr, "can't read inode at %x for pid %d\n",
|
||||
VTOI(vp), Pid);
|
||||
return 0;
|
||||
}
|
||||
fsp->fsid = inode.i_dev & 0xffff;
|
||||
fsp->fileid = (long)inode.i_number;
|
||||
fsp->mode = (mode_t)inode.i_mode;
|
||||
fsp->size = (u_long)inode.i_size;
|
||||
fsp->rdev = inode.i_rdev;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
nfs_filestat(vp, fsp)
|
||||
struct vnode *vp;
|
||||
struct filestat *fsp;
|
||||
{
|
||||
struct nfsnode nfsnode;
|
||||
register mode_t mode;
|
||||
|
||||
if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
|
||||
dprintf(stderr, "can't read nfsnode at %x for pid %d\n",
|
||||
VTONFS(vp), Pid);
|
||||
return 0;
|
||||
}
|
||||
fsp->fsid = nfsnode.n_vattr.va_fsid;
|
||||
fsp->fileid = nfsnode.n_vattr.va_fileid;
|
||||
fsp->size = nfsnode.n_size;
|
||||
fsp->rdev = nfsnode.n_vattr.va_rdev;
|
||||
mode = (mode_t)nfsnode.n_vattr.va_mode;
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
mode |= S_IFREG;
|
||||
break;
|
||||
case VDIR:
|
||||
mode |= S_IFDIR;
|
||||
break;
|
||||
case VBLK:
|
||||
mode |= S_IFBLK;
|
||||
break;
|
||||
case VCHR:
|
||||
mode |= S_IFCHR;
|
||||
break;
|
||||
case VLNK:
|
||||
mode |= S_IFLNK;
|
||||
break;
|
||||
case VSOCK:
|
||||
mode |= S_IFSOCK;
|
||||
break;
|
||||
case VFIFO:
|
||||
mode |= S_IFIFO;
|
||||
break;
|
||||
};
|
||||
fsp->mode = mode;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
getmnton(m)
|
||||
struct mount *m;
|
||||
{
|
||||
static struct mount mount;
|
||||
static struct mtab {
|
||||
struct mtab *next;
|
||||
struct mount *m;
|
||||
char mntonname[MNAMELEN];
|
||||
} *mhead = NULL;
|
||||
register struct mtab *mt;
|
||||
|
||||
for (mt = mhead; mt != NULL; mt = mt->next)
|
||||
if (m == mt->m)
|
||||
return (mt->mntonname);
|
||||
if (!KVM_READ(m, &mount, sizeof(struct mount))) {
|
||||
fprintf(stderr, "can't read mount table at %x\n", m);
|
||||
return (NULL);
|
||||
}
|
||||
if ((mt = malloc(sizeof (struct mtab))) == NULL) {
|
||||
fprintf(stderr, "fstat: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
mt->m = m;
|
||||
bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
|
||||
mt->next = mhead;
|
||||
mhead = mt;
|
||||
return (mt->mntonname);
|
||||
}
|
||||
|
||||
void
|
||||
socktrans(sock, i)
|
||||
struct socket *sock;
|
||||
int i;
|
||||
{
|
||||
static char *stypename[] = {
|
||||
"unused", /* 0 */
|
||||
"stream", /* 1 */
|
||||
"dgram", /* 2 */
|
||||
"raw", /* 3 */
|
||||
"rdm", /* 4 */
|
||||
"seqpak" /* 5 */
|
||||
};
|
||||
#define STYPEMAX 5
|
||||
struct socket so;
|
||||
struct protosw proto;
|
||||
struct domain dom;
|
||||
struct inpcb inpcb;
|
||||
struct unpcb unpcb;
|
||||
int len;
|
||||
char dname[32], *strcpy();
|
||||
|
||||
PREFIX(i);
|
||||
|
||||
/* fill in socket */
|
||||
if (!KVM_READ(sock, &so, sizeof(struct socket))) {
|
||||
dprintf(stderr, "can't read sock at %x\n", sock);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* fill in protosw entry */
|
||||
if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
|
||||
dprintf(stderr, "can't read protosw at %x", so.so_proto);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* fill in domain */
|
||||
if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
|
||||
dprintf(stderr, "can't read domain at %x\n", proto.pr_domain);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if ((len = kvm_read(kd, (u_long)dom.dom_name, dname,
|
||||
sizeof(dname) - 1)) < 0) {
|
||||
dprintf(stderr, "can't read domain name at %x\n",
|
||||
dom.dom_name);
|
||||
dname[0] = '\0';
|
||||
}
|
||||
else
|
||||
dname[len] = '\0';
|
||||
|
||||
if ((u_short)so.so_type > STYPEMAX)
|
||||
printf("* %s ?%d", dname, so.so_type);
|
||||
else
|
||||
printf("* %s %s", dname, stypename[so.so_type]);
|
||||
|
||||
/*
|
||||
* protocol specific formatting
|
||||
*
|
||||
* Try to find interesting things to print. For tcp, the interesting
|
||||
* thing is the address of the tcpcb, for udp and others, just the
|
||||
* inpcb (socket pcb). For unix domain, its the address of the socket
|
||||
* pcb and the address of the connected pcb (if connected). Otherwise
|
||||
* just print the protocol number and address of the socket itself.
|
||||
* The idea is not to duplicate netstat, but to make available enough
|
||||
* information for further analysis.
|
||||
*/
|
||||
switch(dom.dom_family) {
|
||||
case AF_INET:
|
||||
getinetproto(proto.pr_protocol);
|
||||
if (proto.pr_protocol == IPPROTO_TCP ) {
|
||||
if (so.so_pcb) {
|
||||
if (kvm_read(kd, (u_long)so.so_pcb,
|
||||
(char *)&inpcb, sizeof(struct inpcb))
|
||||
!= sizeof(struct inpcb)) {
|
||||
dprintf(stderr,
|
||||
"can't read inpcb at %x\n",
|
||||
so.so_pcb);
|
||||
goto bad;
|
||||
}
|
||||
printf(" %x", (int)inpcb.inp_ppcb);
|
||||
}
|
||||
}
|
||||
else if (so.so_pcb)
|
||||
printf(" %x", (int)so.so_pcb);
|
||||
break;
|
||||
case AF_UNIX:
|
||||
/* print address of pcb and connected pcb */
|
||||
if (so.so_pcb) {
|
||||
printf(" %x", (int)so.so_pcb);
|
||||
if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb,
|
||||
sizeof(struct unpcb)) != sizeof(struct unpcb)){
|
||||
dprintf(stderr, "can't read unpcb at %x\n",
|
||||
so.so_pcb);
|
||||
goto bad;
|
||||
}
|
||||
if (unpcb.unp_conn) {
|
||||
char shoconn[4], *cp;
|
||||
|
||||
cp = shoconn;
|
||||
if (!(so.so_state & SS_CANTRCVMORE))
|
||||
*cp++ = '<';
|
||||
*cp++ = '-';
|
||||
if (!(so.so_state & SS_CANTSENDMORE))
|
||||
*cp++ = '>';
|
||||
*cp = '\0';
|
||||
printf(" %s %x", shoconn,
|
||||
(int)unpcb.unp_conn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* print protocol number and socket address */
|
||||
printf(" %d %x", proto.pr_protocol, (int)sock);
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
bad:
|
||||
printf("* error\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* getinetproto --
|
||||
* print name of protocol number
|
||||
*/
|
||||
void
|
||||
getinetproto(number)
|
||||
int number;
|
||||
{
|
||||
char *cp;
|
||||
|
||||
switch(number) {
|
||||
case IPPROTO_IP:
|
||||
cp = "ip"; break;
|
||||
case IPPROTO_ICMP:
|
||||
cp ="icmp"; break;
|
||||
case IPPROTO_GGP:
|
||||
cp ="ggp"; break;
|
||||
case IPPROTO_TCP:
|
||||
cp ="tcp"; break;
|
||||
case IPPROTO_EGP:
|
||||
cp ="egp"; break;
|
||||
case IPPROTO_PUP:
|
||||
cp ="pup"; break;
|
||||
case IPPROTO_UDP:
|
||||
cp ="udp"; break;
|
||||
case IPPROTO_IDP:
|
||||
cp ="idp"; break;
|
||||
case IPPROTO_RAW:
|
||||
cp ="raw"; break;
|
||||
default:
|
||||
printf(" %d", number);
|
||||
return;
|
||||
}
|
||||
printf(" %s", cp);
|
||||
}
|
||||
|
||||
getfname(filename)
|
||||
char *filename;
|
||||
{
|
||||
struct stat statbuf;
|
||||
DEVS *cur;
|
||||
|
||||
if (stat(filename, &statbuf)) {
|
||||
fprintf(stderr, "fstat: %s: %s\n", filename, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
if ((cur = malloc(sizeof(DEVS))) == NULL) {
|
||||
fprintf(stderr, "fstat: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
cur->next = devs;
|
||||
devs = cur;
|
||||
|
||||
cur->ino = statbuf.st_ino;
|
||||
cur->fsid = statbuf.st_dev & 0xffff;
|
||||
cur->name = filename;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: fstat [-fnv] [-p pid] [-u user] [-N system] [-M core] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
182
usr.bin/head/head.c
Normal file
182
usr.bin/head/head.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 1980, 1987, 1992, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1987, 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* head - give the first few lines of a stream or of each of a set of files
|
||||
*
|
||||
* Bill Joy UCB August 24, 1977
|
||||
*/
|
||||
|
||||
void err __P((int, const char *, ...));
|
||||
void head __P((FILE *, int));
|
||||
void obsolete __P((char *[]));
|
||||
void usage __P((void));
|
||||
|
||||
int eval;
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register int ch;
|
||||
FILE *fp;
|
||||
int first, linecnt;
|
||||
char *ep;
|
||||
|
||||
obsolete(argv);
|
||||
linecnt = 10;
|
||||
while ((ch = getopt(argc, argv, "n:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'n':
|
||||
linecnt = strtol(optarg, &ep, 10);
|
||||
if (*ep || linecnt <= 0)
|
||||
err(1, "illegal line count -- %s", optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (*argv)
|
||||
for (first = 1; *argv; ++argv) {
|
||||
if ((fp = fopen(*argv, "r")) == NULL) {
|
||||
err(0, "%s: %s", *argv, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (argc > 1) {
|
||||
(void)printf("%s==> %s <==\n",
|
||||
first ? "" : "\n", *argv);
|
||||
first = 0;
|
||||
}
|
||||
head(fp, linecnt);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
else
|
||||
head(stdin, linecnt);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
head(fp, cnt)
|
||||
FILE *fp;
|
||||
register int cnt;
|
||||
{
|
||||
register int ch;
|
||||
|
||||
while (cnt--)
|
||||
while ((ch = getc(fp)) != EOF) {
|
||||
if (putchar(ch) == EOF)
|
||||
err(1, "stdout: %s", strerror(errno));
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
obsolete(argv)
|
||||
char *argv[];
|
||||
{
|
||||
char *ap;
|
||||
|
||||
while (ap = *++argv) {
|
||||
/* Return if "--" or not "-[0-9]*". */
|
||||
if (ap[0] != '-' || ap[1] == '-' || !isdigit(ap[1]))
|
||||
return;
|
||||
if ((ap = malloc(strlen(*argv) + 2)) == NULL)
|
||||
err(1, "%s", strerror(errno));
|
||||
ap[0] = '-';
|
||||
ap[1] = 'n';
|
||||
(void)strcpy(ap + 2, *argv + 1);
|
||||
*argv = ap;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: head [-n lines] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(int fatal, const char *fmt, ...)
|
||||
#else
|
||||
err(fatal, fmt, va_alist)
|
||||
int fatal;
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "head: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
if (fatal)
|
||||
exit(1);
|
||||
eval = 1;
|
||||
}
|
129
usr.bin/hexdump/hexsyntax.c
Normal file
129
usr.bin/hexdump/hexsyntax.c
Normal file
@ -0,0 +1,129 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)hexsyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
off_t skip; /* bytes to skip */
|
||||
|
||||
void
|
||||
newsyntax(argc, argvp)
|
||||
int argc;
|
||||
char ***argvp;
|
||||
{
|
||||
extern enum _vflag vflag;
|
||||
extern FS *fshead;
|
||||
extern int length;
|
||||
int ch;
|
||||
char *p, **argv;
|
||||
|
||||
argv = *argvp;
|
||||
while ((ch = getopt(argc, argv, "bcde:f:n:os:vx")) != EOF)
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"");
|
||||
break;
|
||||
case 'c':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"");
|
||||
break;
|
||||
case 'd':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"");
|
||||
break;
|
||||
case 'e':
|
||||
add(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
addfile(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
if ((length = atoi(optarg)) < 0)
|
||||
err("%s: bad length value", optarg);
|
||||
break;
|
||||
case 'o':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"");
|
||||
break;
|
||||
case 's':
|
||||
if ((skip = strtol(optarg, &p, 0)) < 0)
|
||||
err("%s: bad skip value", optarg);
|
||||
switch(*p) {
|
||||
case 'b':
|
||||
skip *= 512;
|
||||
break;
|
||||
case 'k':
|
||||
skip *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
skip *= 1048576;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
vflag = ALL;
|
||||
break;
|
||||
case 'x':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"");
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!fshead) {
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
|
||||
}
|
||||
|
||||
*argvp += optind;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"hexdump: [-bcdovx] [-e fmt] [-f fmt_file] [-n length] [-s skip] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
265
usr.bin/hexdump/odsyntax.c
Normal file
265
usr.bin/hexdump/odsyntax.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
int deprecated;
|
||||
|
||||
static void odoffset __P((int, char ***));
|
||||
static void odprecede __P((void));
|
||||
|
||||
void
|
||||
oldsyntax(argc, argvp)
|
||||
int argc;
|
||||
char ***argvp;
|
||||
{
|
||||
extern enum _vflag vflag;
|
||||
extern FS *fshead;
|
||||
int ch;
|
||||
char **argv;
|
||||
|
||||
deprecated = 1;
|
||||
argv = *argvp;
|
||||
while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
odprecede();
|
||||
add("16/1 \"%3_u \" \"\\n\"");
|
||||
break;
|
||||
case 'B':
|
||||
case 'o':
|
||||
odprecede();
|
||||
add("8/2 \" %06o \" \"\\n\"");
|
||||
break;
|
||||
case 'b':
|
||||
odprecede();
|
||||
add("16/1 \"%03o \" \"\\n\"");
|
||||
break;
|
||||
case 'c':
|
||||
odprecede();
|
||||
add("16/1 \"%3_c \" \"\\n\"");
|
||||
break;
|
||||
case 'd':
|
||||
odprecede();
|
||||
add("8/2 \" %05u \" \"\\n\"");
|
||||
break;
|
||||
case 'D':
|
||||
odprecede();
|
||||
add("4/4 \" %010u \" \"\\n\"");
|
||||
break;
|
||||
case 'e': /* undocumented in od */
|
||||
case 'F':
|
||||
odprecede();
|
||||
add("2/8 \" %21.14e \" \"\\n\"");
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
odprecede();
|
||||
add("4/4 \" %14.7e \" \"\\n\"");
|
||||
break;
|
||||
case 'H':
|
||||
case 'X':
|
||||
odprecede();
|
||||
add("4/4 \" %08x \" \"\\n\"");
|
||||
break;
|
||||
case 'h':
|
||||
case 'x':
|
||||
odprecede();
|
||||
add("8/2 \" %04x \" \"\\n\"");
|
||||
break;
|
||||
case 'I':
|
||||
case 'L':
|
||||
case 'l':
|
||||
odprecede();
|
||||
add("4/4 \" %11d \" \"\\n\"");
|
||||
break;
|
||||
case 'i':
|
||||
odprecede();
|
||||
add("8/2 \" %6d \" \"\\n\"");
|
||||
break;
|
||||
case 'O':
|
||||
odprecede();
|
||||
add("4/4 \" %011o \" \"\\n\"");
|
||||
break;
|
||||
case 'v':
|
||||
vflag = ALL;
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
case 's':
|
||||
case 'w':
|
||||
case '?':
|
||||
default:
|
||||
(void)fprintf(stderr,
|
||||
"od: od(1) has been deprecated for hexdump(1).\n");
|
||||
if (ch != '?')
|
||||
(void)fprintf(stderr,
|
||||
"od: hexdump(1) compatibility doesn't support the -%c option%s\n",
|
||||
ch, ch == 's' ? "; see strings(1)." : ".");
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!fshead) {
|
||||
add("\"%07.7_Ao\n\"");
|
||||
add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\"");
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
*argvp += optind;
|
||||
|
||||
if (argc)
|
||||
odoffset(argc, argvp);
|
||||
}
|
||||
|
||||
static void
|
||||
odoffset(argc, argvp)
|
||||
int argc;
|
||||
char ***argvp;
|
||||
{
|
||||
extern off_t skip;
|
||||
register char *num, *p;
|
||||
int base;
|
||||
char *end;
|
||||
|
||||
/*
|
||||
* The offset syntax of od(1) was genuinely bizarre. First, if
|
||||
* it started with a plus it had to be an offset. Otherwise, if
|
||||
* there were at least two arguments, a number or lower-case 'x'
|
||||
* followed by a number makes it an offset. By default it was
|
||||
* octal; if it started with 'x' or '0x' it was hex. If it ended
|
||||
* in a '.', it was decimal. If a 'b' or 'B' was appended, it
|
||||
* multiplied the number by 512 or 1024 byte units. There was
|
||||
* no way to assign a block count to a hex offset.
|
||||
*
|
||||
* We assume it's a file if the offset is bad.
|
||||
*/
|
||||
p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
|
||||
|
||||
if (*p != '+' && (argc < 2 ||
|
||||
(!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1])))))
|
||||
return;
|
||||
|
||||
base = 0;
|
||||
/*
|
||||
* skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
|
||||
* set base.
|
||||
*/
|
||||
if (p[0] == '+')
|
||||
++p;
|
||||
if (p[0] == 'x' && isxdigit(p[1])) {
|
||||
++p;
|
||||
base = 16;
|
||||
} else if (p[0] == '0' && p[1] == 'x') {
|
||||
p += 2;
|
||||
base = 16;
|
||||
}
|
||||
|
||||
/* skip over the number */
|
||||
if (base == 16)
|
||||
for (num = p; isxdigit(*p); ++p);
|
||||
else
|
||||
for (num = p; isdigit(*p); ++p);
|
||||
|
||||
/* check for no number */
|
||||
if (num == p)
|
||||
return;
|
||||
|
||||
/* if terminates with a '.', base is decimal */
|
||||
if (*p == '.') {
|
||||
if (base)
|
||||
return;
|
||||
base = 10;
|
||||
}
|
||||
|
||||
skip = strtol(num, &end, base ? base : 8);
|
||||
|
||||
/* if end isn't the same as p, we got a non-octal digit */
|
||||
if (end != p) {
|
||||
skip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*p)
|
||||
if (*p == 'B') {
|
||||
skip *= 1024;
|
||||
++p;
|
||||
} else if (*p == 'b') {
|
||||
skip *= 512;
|
||||
++p;
|
||||
}
|
||||
|
||||
if (*p) {
|
||||
skip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the offset uses a non-octal base, the base of the offset
|
||||
* is changed as well. This isn't pretty, but it's easy.
|
||||
*/
|
||||
#define TYPE_OFFSET 7
|
||||
if (base == 16) {
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
|
||||
} else if (base == 10) {
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
|
||||
}
|
||||
|
||||
/* Terminate file list. */
|
||||
(*argvp)[1] = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
odprecede()
|
||||
{
|
||||
static int first = 1;
|
||||
|
||||
if (first) {
|
||||
first = 0;
|
||||
add("\"%07.7_Ao\n\"");
|
||||
add("\"%07.7_ao \"");
|
||||
} else
|
||||
add("\" \"");
|
||||
}
|
215
usr.bin/join/join.1
Normal file
215
usr.bin/join/join.1
Normal file
@ -0,0 +1,215 @@
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)join.1 8.3 (Berkeley) 4/28/95
|
||||
.\"
|
||||
.Dd April 28, 1995
|
||||
.Dt JOIN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm join
|
||||
.Nd relational database operator
|
||||
.Sh SYNOPSIS
|
||||
.Nm join
|
||||
.Oo
|
||||
.Fl a Ar file_number | Fl v Ar file_number
|
||||
.Oc
|
||||
.Op Fl e Ar string
|
||||
.Op Fl j Ar file_number field
|
||||
.Op Fl o Ar list
|
||||
.Bk -words
|
||||
.Ek
|
||||
.Op Fl t Ar char
|
||||
.Op Fl \&1 Ar field
|
||||
.Op Fl \&2 Ar field
|
||||
.Ar file1
|
||||
.Ar file2
|
||||
.Sh DESCRIPTION
|
||||
The join utility performs an ``equality join'' on the specified files
|
||||
and writes the result to the standard output.
|
||||
The ``join field'' is the field in each file by which the files are compared.
|
||||
The first field in each line is used by default.
|
||||
There is one line in the output for each pair of lines in
|
||||
.Ar file1
|
||||
and
|
||||
.Ar file2
|
||||
which have identical join fields.
|
||||
Each output line consists of the join field, the remaining fields from
|
||||
.Ar file1
|
||||
and then the remaining fields from
|
||||
.Ar file2 .
|
||||
.Pp
|
||||
The default field separators are tab and space characters.
|
||||
In this case, multiple tabs and spaces count as a single field separator,
|
||||
and leading tabs and spaces are ignored.
|
||||
The default output field separator is a single space character.
|
||||
.Pp
|
||||
Many of the options use file and field numbers.
|
||||
Both file numbers and field numbers are 1 based, i.e. the first file on
|
||||
the command line is file number 1 and the first field is field number 1.
|
||||
The following options are available:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl a Ar file_number
|
||||
In addition to the default output, produce a line for each unpairable
|
||||
line in file
|
||||
.Ar file_number .
|
||||
(The argument to
|
||||
.Fl a
|
||||
must not be preceded by a space; see the
|
||||
.Sx COMPATIBILITY
|
||||
section.)
|
||||
.It Fl e Ar string
|
||||
Replace empty output fields with
|
||||
.Ar string .
|
||||
.It Fl o Ar list
|
||||
The
|
||||
.Fl o
|
||||
option specifies the fields that will be output from each file for
|
||||
each line with matching join fields.
|
||||
Each element of
|
||||
.Ar list
|
||||
has the form
|
||||
.Ql file_number.field ,
|
||||
where
|
||||
.Ar file_number
|
||||
is a file number and
|
||||
.Ar field
|
||||
is a field number.
|
||||
The elements of list must be either comma (``,'') or whitespace separated.
|
||||
(The latter requires quoting to protect it from the shell, or, a simpler
|
||||
approach is to use multiple
|
||||
.Fl o
|
||||
options.)
|
||||
.It Fl t Ar char
|
||||
Use character
|
||||
.Ar char
|
||||
as a field delimiter for both input and output.
|
||||
Every occurrence of
|
||||
.Ar char
|
||||
in a line is significant.
|
||||
.It Fl v Ar file_number
|
||||
Do not display the default output, but display a line for each unpairable
|
||||
line in file
|
||||
.Ar file_number .
|
||||
The options
|
||||
.Fl v Ar 1
|
||||
and
|
||||
.Fl v Ar 2
|
||||
may be specified at the same time.
|
||||
.It Fl 1 Ar field
|
||||
Join on the
|
||||
.Ar field Ns 'th
|
||||
field of file 1.
|
||||
.It Fl 2 Ar field
|
||||
Join on the
|
||||
.Ar field Ns 'th
|
||||
field of file 2.
|
||||
.El
|
||||
.Pp
|
||||
When the default field delimiter characters are used, the files to be joined
|
||||
should be ordered in the collating sequence of
|
||||
.Xr sort 1 ,
|
||||
using the
|
||||
.Fl b
|
||||
option, on the fields on which they are to be joined, otherwise
|
||||
.Nm join
|
||||
may not report all field matches.
|
||||
When the field delimiter characters are specified by the
|
||||
.Fl t
|
||||
option, the collating sequence should be the same as
|
||||
.Xr sort
|
||||
without the
|
||||
.Fl b
|
||||
option.
|
||||
.Pp
|
||||
If one of the arguments
|
||||
.Ar file1
|
||||
or
|
||||
.Ar file2
|
||||
is ``-'', the standard input is used.
|
||||
.Pp
|
||||
The
|
||||
.Nm join
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.Sh COMPATIBILITY
|
||||
For compatibility with historic versions of
|
||||
.Nm join ,
|
||||
the following options are available:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl a
|
||||
In addition to the default output, produce a line for each unpairable line
|
||||
in both file 1 and file 2.
|
||||
(To distinguish between this and
|
||||
.Fl a Ar file_number ,
|
||||
.Nm join
|
||||
currently requires that the latter not include any white space.)
|
||||
.It Fl j1 Ar field
|
||||
Join on the
|
||||
.Ar field Ns 'th
|
||||
field of file 1.
|
||||
.It Fl j2 Ar field
|
||||
Join on the
|
||||
.Ar field Ns 'th
|
||||
field of file 2.
|
||||
.It Fl j Ar field
|
||||
Join on the
|
||||
.Ar field Ns 'th
|
||||
field of both file 1 and file 2.
|
||||
.It Fl o Ar list ...
|
||||
Historical implementations of
|
||||
.Nm join
|
||||
permitted multiple arguments to the
|
||||
.Fl o
|
||||
option.
|
||||
These arguments were of the form ``file_number.field_number'' as described
|
||||
for the current
|
||||
.Fl o
|
||||
option.
|
||||
This has obvious difficulties in the presence of files named ``1.2''.
|
||||
.El
|
||||
.Pp
|
||||
These options are available only so historic shellscripts don't require
|
||||
modification and should not be used.
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm join
|
||||
command is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh SEE ALSO
|
||||
.Xr awk 1 ,
|
||||
.Xr comm 1 ,
|
||||
.Xr paste 1 ,
|
||||
.Xr sort 1 ,
|
||||
.Xr uniq 1
|
587
usr.bin/join/join.c
Normal file
587
usr.bin/join/join.c
Normal file
@ -0,0 +1,587 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Steve Hayman of the Computer Science Department, Indiana University,
|
||||
* Michiro Hikida and David Goodenough.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)join.c 8.6 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* There's a structure per input file which encapsulates the state of the
|
||||
* file. We repeatedly read lines from each file until we've read in all
|
||||
* the consecutive lines from the file with a common join field. Then we
|
||||
* compare the set of lines with an equivalent set from the other file.
|
||||
*/
|
||||
typedef struct {
|
||||
char *line; /* line */
|
||||
u_long linealloc; /* line allocated count */
|
||||
char **fields; /* line field(s) */
|
||||
u_long fieldcnt; /* line field(s) count */
|
||||
u_long fieldalloc; /* line field(s) allocated count */
|
||||
} LINE;
|
||||
|
||||
typedef struct {
|
||||
FILE *fp; /* file descriptor */
|
||||
u_long joinf; /* join field (-1, -2, -j) */
|
||||
int unpair; /* output unpairable lines (-a) */
|
||||
int number; /* 1 for file 1, 2 for file 2 */
|
||||
|
||||
LINE *set; /* set of lines with same field */
|
||||
int pushbool; /* if pushback is set */
|
||||
u_long pushback; /* line on the stack */
|
||||
u_long setcnt; /* set count */
|
||||
u_long setalloc; /* set allocated count */
|
||||
} INPUT;
|
||||
INPUT input1 = { NULL, 0, 0, 1, NULL, 0, 0, 0, },
|
||||
input2 = { NULL, 0, 0, 2, NULL, 0, 0, 0, };
|
||||
|
||||
typedef struct {
|
||||
u_long filenum; /* file number */
|
||||
u_long fieldno; /* field number */
|
||||
} OLIST;
|
||||
OLIST *olist; /* output field list */
|
||||
u_long olistcnt; /* output field list count */
|
||||
u_long olistalloc; /* output field allocated count */
|
||||
|
||||
int joinout = 1; /* show lines with matched join fields (-v) */
|
||||
int needsep; /* need separator character */
|
||||
int spans = 1; /* span multiple delimiters (-t) */
|
||||
char *empty; /* empty field replacement string (-e) */
|
||||
char *tabchar = " \t"; /* delimiter characters (-t) */
|
||||
|
||||
int cmp __P((LINE *, u_long, LINE *, u_long));
|
||||
void fieldarg __P((char *));
|
||||
void joinlines __P((INPUT *, INPUT *));
|
||||
void obsolete __P((char **));
|
||||
void outfield __P((LINE *, u_long, int));
|
||||
void outoneline __P((INPUT *, LINE *));
|
||||
void outtwoline __P((INPUT *, LINE *, INPUT *, LINE *));
|
||||
void slurp __P((INPUT *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
INPUT *F1, *F2;
|
||||
int aflag, ch, cval, vflag;
|
||||
char *end;
|
||||
|
||||
F1 = &input1;
|
||||
F2 = &input2;
|
||||
|
||||
aflag = vflag = 0;
|
||||
obsolete(argv);
|
||||
while ((ch = getopt(argc, argv, "\01a:e:j:1:2:o:t:v:")) != EOF) {
|
||||
switch (ch) {
|
||||
case '\01': /* See comment in obsolete(). */
|
||||
aflag = 1;
|
||||
F1->unpair = F2->unpair = 1;
|
||||
break;
|
||||
case '1':
|
||||
if ((F1->joinf = strtol(optarg, &end, 10)) < 1)
|
||||
errx(1, "-1 option field number less than 1");
|
||||
if (*end)
|
||||
errx(1, "illegal field number -- %s", optarg);
|
||||
--F1->joinf;
|
||||
break;
|
||||
case '2':
|
||||
if ((F2->joinf = strtol(optarg, &end, 10)) < 1)
|
||||
errx(1, "-2 option field number less than 1");
|
||||
if (*end)
|
||||
errx(1, "illegal field number -- %s", optarg);
|
||||
--F2->joinf;
|
||||
break;
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
switch(strtol(optarg, &end, 10)) {
|
||||
case 1:
|
||||
F1->unpair = 1;
|
||||
break;
|
||||
case 2:
|
||||
F2->unpair = 1;
|
||||
break;
|
||||
default:
|
||||
errx(1, "-a option file number not 1 or 2");
|
||||
break;
|
||||
}
|
||||
if (*end)
|
||||
errx(1, "illegal file number -- %s", optarg);
|
||||
break;
|
||||
case 'e':
|
||||
empty = optarg;
|
||||
break;
|
||||
case 'j':
|
||||
if ((F1->joinf = F2->joinf =
|
||||
strtol(optarg, &end, 10)) < 1)
|
||||
errx(1, "-j option field number less than 1");
|
||||
if (*end)
|
||||
errx(1, "illegal field number -- %s", optarg);
|
||||
--F1->joinf;
|
||||
--F2->joinf;
|
||||
break;
|
||||
case 'o':
|
||||
fieldarg(optarg);
|
||||
break;
|
||||
case 't':
|
||||
spans = 0;
|
||||
if (strlen(tabchar = optarg) != 1)
|
||||
errx(1, "illegal tab character specification");
|
||||
break;
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
joinout = 0;
|
||||
switch (strtol(optarg, &end, 10)) {
|
||||
case 1:
|
||||
F1->unpair = 1;
|
||||
break;
|
||||
case 2:
|
||||
F2->unpair = 1;
|
||||
break;
|
||||
default:
|
||||
errx(1, "-v option file number not 1 or 2");
|
||||
break;
|
||||
}
|
||||
if (*end)
|
||||
errx(1, "illegal file number -- %s", optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (aflag && vflag)
|
||||
errx(1, "the -a and -v options are mutually exclusive");
|
||||
|
||||
if (argc != 2)
|
||||
usage();
|
||||
|
||||
/* Open the files; "-" means stdin. */
|
||||
if (!strcmp(*argv, "-"))
|
||||
F1->fp = stdin;
|
||||
else if ((F1->fp = fopen(*argv, "r")) == NULL)
|
||||
err(1, "%s", *argv);
|
||||
++argv;
|
||||
if (!strcmp(*argv, "-"))
|
||||
F2->fp = stdin;
|
||||
else if ((F2->fp = fopen(*argv, "r")) == NULL)
|
||||
err(1, "%s", *argv);
|
||||
if (F1->fp == stdin && F2->fp == stdin)
|
||||
errx(1, "only one input file may be stdin");
|
||||
|
||||
slurp(F1);
|
||||
slurp(F2);
|
||||
while (F1->setcnt && F2->setcnt) {
|
||||
cval = cmp(F1->set, F1->joinf, F2->set, F2->joinf);
|
||||
if (cval == 0) {
|
||||
/* Oh joy, oh rapture, oh beauty divine! */
|
||||
if (joinout)
|
||||
joinlines(F1, F2);
|
||||
slurp(F1);
|
||||
slurp(F2);
|
||||
} else if (cval < 0) {
|
||||
/* File 1 takes the lead... */
|
||||
if (F1->unpair)
|
||||
joinlines(F1, NULL);
|
||||
slurp(F1);
|
||||
} else {
|
||||
/* File 2 takes the lead... */
|
||||
if (F2->unpair)
|
||||
joinlines(F2, NULL);
|
||||
slurp(F2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that one of the files is used up, optionally output any
|
||||
* remaining lines from the other file.
|
||||
*/
|
||||
if (F1->unpair)
|
||||
while (F1->setcnt) {
|
||||
joinlines(F1, NULL);
|
||||
slurp(F1);
|
||||
}
|
||||
if (F2->unpair)
|
||||
while (F2->setcnt) {
|
||||
joinlines(F2, NULL);
|
||||
slurp(F2);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
slurp(F)
|
||||
INPUT *F;
|
||||
{
|
||||
LINE *lp, *lastlp, tmp;
|
||||
size_t len;
|
||||
int cnt;
|
||||
char *bp, *fieldp;
|
||||
|
||||
/*
|
||||
* Read all of the lines from an input file that have the same
|
||||
* join field.
|
||||
*/
|
||||
F->setcnt = 0;
|
||||
for (lastlp = NULL;; ++F->setcnt, lastlp = lp) {
|
||||
/*
|
||||
* If we're out of space to hold line structures, allocate
|
||||
* more. Initialize the structure so that we know that this
|
||||
* is new space.
|
||||
*/
|
||||
if (F->setcnt == F->setalloc) {
|
||||
cnt = F->setalloc;
|
||||
F->setalloc += 50;
|
||||
if ((F->set = realloc(F->set,
|
||||
F->setalloc * sizeof(LINE))) == NULL)
|
||||
err(1, NULL);
|
||||
memset(F->set + cnt, 0, 50 * sizeof(LINE));
|
||||
|
||||
/* re-set lastlp in case it moved */
|
||||
if (lastlp != NULL)
|
||||
lastlp = &F->set[F->setcnt - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Get any pushed back line, else get the next line. Allocate
|
||||
* space as necessary. If taking the line from the stack swap
|
||||
* the two structures so that we don't lose space allocated to
|
||||
* either structure. This could be avoided by doing another
|
||||
* level of indirection, but it's probably okay as is.
|
||||
* but it's probably okay as is.
|
||||
*/
|
||||
lp = &F->set[F->setcnt];
|
||||
if (F->pushbool) {
|
||||
tmp = F->set[F->setcnt];
|
||||
F->set[F->setcnt] = F->set[F->pushback];
|
||||
F->set[F->pushback] = tmp;
|
||||
F->pushbool = 0;
|
||||
continue;
|
||||
}
|
||||
if ((bp = fgetln(F->fp, &len)) == NULL)
|
||||
return;
|
||||
if (lp->linealloc <= len + 1) {
|
||||
lp->linealloc += MAX(100, len + 1 - lp->linealloc);
|
||||
if ((lp->line =
|
||||
realloc(lp->line, lp->linealloc)) == NULL)
|
||||
err(1, NULL);
|
||||
}
|
||||
memmove(lp->line, bp, len);
|
||||
|
||||
/* Replace trailing newline, if it exists. */
|
||||
if (bp[len - 1] == '\n')
|
||||
lp->line[len - 1] = '\0';
|
||||
else
|
||||
lp->line[len] = '\0';
|
||||
bp = lp->line;
|
||||
|
||||
/* Split the line into fields, allocate space as necessary. */
|
||||
lp->fieldcnt = 0;
|
||||
while ((fieldp = strsep(&bp, tabchar)) != NULL) {
|
||||
if (spans && *fieldp == '\0')
|
||||
continue;
|
||||
if (lp->fieldcnt == lp->fieldalloc) {
|
||||
lp->fieldalloc += 50;
|
||||
if ((lp->fields = realloc(lp->fields,
|
||||
lp->fieldalloc * sizeof(char *))) == NULL)
|
||||
err(1, NULL);
|
||||
}
|
||||
lp->fields[lp->fieldcnt++] = fieldp;
|
||||
}
|
||||
|
||||
/* See if the join field value has changed. */
|
||||
if (lastlp != NULL && cmp(lp, F->joinf, lastlp, F->joinf)) {
|
||||
F->pushbool = 1;
|
||||
F->pushback = F->setcnt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cmp(lp1, fieldno1, lp2, fieldno2)
|
||||
LINE *lp1, *lp2;
|
||||
u_long fieldno1, fieldno2;
|
||||
{
|
||||
if (lp1->fieldcnt <= fieldno1)
|
||||
return (lp2->fieldcnt <= fieldno2 ? 0 : 1);
|
||||
if (lp2->fieldcnt <= fieldno2)
|
||||
return (-1);
|
||||
return (strcmp(lp1->fields[fieldno1], lp2->fields[fieldno2]));
|
||||
}
|
||||
|
||||
void
|
||||
joinlines(F1, F2)
|
||||
INPUT *F1, *F2;
|
||||
{
|
||||
int cnt1, cnt2;
|
||||
|
||||
/*
|
||||
* Output the results of a join comparison. The output may be from
|
||||
* either file 1 or file 2 (in which case the first argument is the
|
||||
* file from which to output) or from both.
|
||||
*/
|
||||
if (F2 == NULL) {
|
||||
for (cnt1 = 0; cnt1 < F1->setcnt; ++cnt1)
|
||||
outoneline(F1, &F1->set[cnt1]);
|
||||
return;
|
||||
}
|
||||
for (cnt1 = 0; cnt1 < F1->setcnt; ++cnt1)
|
||||
for (cnt2 = 0; cnt2 < F2->setcnt; ++cnt2)
|
||||
outtwoline(F1, &F1->set[cnt1], F2, &F2->set[cnt2]);
|
||||
}
|
||||
|
||||
void
|
||||
outoneline(F, lp)
|
||||
INPUT *F;
|
||||
LINE *lp;
|
||||
{
|
||||
int cnt;
|
||||
|
||||
/*
|
||||
* Output a single line from one of the files, according to the
|
||||
* join rules. This happens when we are writing unmatched single
|
||||
* lines. Output empty fields in the right places.
|
||||
*/
|
||||
if (olist)
|
||||
for (cnt = 0; cnt < olistcnt; ++cnt) {
|
||||
if (olist[cnt].filenum == F->number)
|
||||
outfield(lp, olist[cnt].fieldno, 0);
|
||||
else
|
||||
outfield(lp, 0, 1);
|
||||
}
|
||||
else
|
||||
for (cnt = 0; cnt < lp->fieldcnt; ++cnt)
|
||||
outfield(lp, cnt, 0);
|
||||
(void)printf("\n");
|
||||
if (ferror(stdout))
|
||||
err(1, "stdout");
|
||||
needsep = 0;
|
||||
}
|
||||
|
||||
void
|
||||
outtwoline(F1, lp1, F2, lp2)
|
||||
INPUT *F1, *F2;
|
||||
LINE *lp1, *lp2;
|
||||
{
|
||||
int cnt;
|
||||
|
||||
/* Output a pair of lines according to the join list (if any). */
|
||||
if (olist)
|
||||
for (cnt = 0; cnt < olistcnt; ++cnt)
|
||||
if (olist[cnt].filenum == 1)
|
||||
outfield(lp1, olist[cnt].fieldno, 0);
|
||||
else /* if (olist[cnt].filenum == 2) */
|
||||
outfield(lp2, olist[cnt].fieldno, 0);
|
||||
else {
|
||||
/*
|
||||
* Output the join field, then the remaining fields from F1
|
||||
* and F2.
|
||||
*/
|
||||
outfield(lp1, F1->joinf, 0);
|
||||
for (cnt = 0; cnt < lp1->fieldcnt; ++cnt)
|
||||
if (F1->joinf != cnt)
|
||||
outfield(lp1, cnt, 0);
|
||||
for (cnt = 0; cnt < lp2->fieldcnt; ++cnt)
|
||||
if (F2->joinf != cnt)
|
||||
outfield(lp2, cnt, 0);
|
||||
}
|
||||
(void)printf("\n");
|
||||
if (ferror(stdout))
|
||||
err(1, "stdout");
|
||||
needsep = 0;
|
||||
}
|
||||
|
||||
void
|
||||
outfield(lp, fieldno, out_empty)
|
||||
LINE *lp;
|
||||
u_long fieldno;
|
||||
int out_empty;
|
||||
{
|
||||
if (needsep++)
|
||||
(void)printf("%c", *tabchar);
|
||||
if (!ferror(stdout))
|
||||
if (lp->fieldcnt < fieldno || out_empty) {
|
||||
if (empty != NULL)
|
||||
(void)printf("%s", empty);
|
||||
} else {
|
||||
if (*lp->fields[fieldno] == '\0')
|
||||
return;
|
||||
(void)printf("%s", lp->fields[fieldno]);
|
||||
}
|
||||
if (ferror(stdout))
|
||||
err(1, "stdout");
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an output list argument "2.1, 1.3, 2.4" into an array of output
|
||||
* fields.
|
||||
*/
|
||||
void
|
||||
fieldarg(option)
|
||||
char *option;
|
||||
{
|
||||
u_long fieldno;
|
||||
char *end, *token;
|
||||
|
||||
while ((token = strsep(&option, ", \t")) != NULL) {
|
||||
if (*token == '\0')
|
||||
continue;
|
||||
if (token[0] != '1' && token[0] != '2' || token[1] != '.')
|
||||
errx(1, "malformed -o option field");
|
||||
fieldno = strtol(token + 2, &end, 10);
|
||||
if (*end)
|
||||
errx(1, "malformed -o option field");
|
||||
if (fieldno == 0)
|
||||
errx(1, "field numbers are 1 based");
|
||||
if (olistcnt == olistalloc) {
|
||||
olistalloc += 50;
|
||||
if ((olist = realloc(olist,
|
||||
olistalloc * sizeof(OLIST))) == NULL)
|
||||
err(1, NULL);
|
||||
}
|
||||
olist[olistcnt].filenum = token[0] - '0';
|
||||
olist[olistcnt].fieldno = fieldno - 1;
|
||||
++olistcnt;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
obsolete(argv)
|
||||
char **argv;
|
||||
{
|
||||
int len;
|
||||
char **p, *ap, *t;
|
||||
|
||||
while ((ap = *++argv) != NULL) {
|
||||
/* Return if "--". */
|
||||
if (ap[0] == '-' && ap[1] == '-')
|
||||
return;
|
||||
switch (ap[1]) {
|
||||
case 'a':
|
||||
/*
|
||||
* The original join allowed "-a", which meant the
|
||||
* same as -a1 plus -a2. POSIX 1003.2, Draft 11.2
|
||||
* only specifies this as "-a 1" and "a -2", so we
|
||||
* have to use another option flag, one that is
|
||||
* unlikely to ever be used or accidentally entered
|
||||
* on the command line. (Well, we could reallocate
|
||||
* the argv array, but that hardly seems worthwhile.)
|
||||
*/
|
||||
if (ap[2] == '\0')
|
||||
ap[1] = '\01';
|
||||
break;
|
||||
case 'j':
|
||||
/*
|
||||
* The original join allowed "-j[12] arg" and "-j arg".
|
||||
* Convert the former to "-[12] arg". Don't convert
|
||||
* the latter since getopt(3) can handle it.
|
||||
*/
|
||||
switch(ap[2]) {
|
||||
case '1':
|
||||
if (ap[3] != '\0')
|
||||
goto jbad;
|
||||
ap[1] = '1';
|
||||
ap[2] = '\0';
|
||||
break;
|
||||
case '2':
|
||||
if (ap[3] != '\0')
|
||||
goto jbad;
|
||||
ap[1] = '2';
|
||||
ap[2] = '\0';
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
jbad: errx(1, "illegal option -- %s", ap);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
/*
|
||||
* The original join allowed "-o arg arg".
|
||||
* Convert to "-o arg -o arg".
|
||||
*/
|
||||
if (ap[2] != '\0')
|
||||
break;
|
||||
for (p = argv + 2; *p; ++p) {
|
||||
if (p[0][0] != '1' &&
|
||||
p[0][0] != '2' || p[0][1] != '.')
|
||||
break;
|
||||
len = strlen(*p);
|
||||
if (len - 2 != strspn(*p + 2, "0123456789"))
|
||||
break;
|
||||
if ((t = malloc(len + 3)) == NULL)
|
||||
err(1, NULL);
|
||||
t[0] = '-';
|
||||
t[1] = 'o';
|
||||
memmove(t + 2, *p, len + 1);
|
||||
*p = t;
|
||||
}
|
||||
argv = p - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "%s%s\n",
|
||||
"usage: join [-a fileno | -v fileno ] [-e string] [-1 field] ",
|
||||
"[-2 field]\n [-o list] [-t char] file1 file2");
|
||||
exit(1);
|
||||
}
|
359
usr.bin/look/look.c
Normal file
359
usr.bin/look/look.c
Normal file
@ -0,0 +1,359 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* David Hitz of Auspex Systems, Inc.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)look.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* look -- find lines in a sorted list.
|
||||
*
|
||||
* The man page said that TABs and SPACEs participate in -d comparisons.
|
||||
* In fact, they were ignored. This implements historic practice, not
|
||||
* the manual page.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* FOLD and DICT convert characters to a normal form for comparison,
|
||||
* according to the user specified flags.
|
||||
*
|
||||
* DICT expects integers because it uses a non-character value to
|
||||
* indicate a character which should not participate in comparisons.
|
||||
*/
|
||||
#define EQUAL 0
|
||||
#define GREATER 1
|
||||
#define LESS (-1)
|
||||
#define NO_COMPARE (-2)
|
||||
|
||||
#define FOLD(c) (isascii(c) && isupper(c) ? tolower(c) : (c))
|
||||
#define DICT(c) (isascii(c) && isalnum(c) ? (c) : NO_COMPARE)
|
||||
|
||||
int dflag, fflag;
|
||||
|
||||
char *binary_search __P((char *, char *, char *));
|
||||
int compare __P((char *, char *, char *));
|
||||
void err __P((const char *fmt, ...));
|
||||
char *linear_search __P((char *, char *, char *));
|
||||
int look __P((char *, char *, char *));
|
||||
void print_from __P((char *, char *, char *));
|
||||
|
||||
static void usage __P((void));
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct stat sb;
|
||||
int ch, fd, termchar;
|
||||
char *back, *file, *front, *string, *p;
|
||||
|
||||
file = _PATH_WORDS;
|
||||
termchar = '\0';
|
||||
while ((ch = getopt(argc, argv, "dft:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
break;
|
||||
case 't':
|
||||
termchar = *optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
switch (argc) {
|
||||
case 2: /* Don't set -df for user. */
|
||||
string = *argv++;
|
||||
file = *argv;
|
||||
break;
|
||||
case 1: /* But set -df by default. */
|
||||
dflag = fflag = 1;
|
||||
string = *argv;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (termchar != '\0' && (p = strchr(string, termchar)) != NULL)
|
||||
*++p = '\0';
|
||||
|
||||
if ((fd = open(file, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
|
||||
err("%s: %s", file, strerror(errno));
|
||||
if (sb.st_size > SIZE_T_MAX)
|
||||
err("%s: %s", file, strerror(EFBIG));
|
||||
if ((front = mmap(NULL,
|
||||
(size_t)sb.st_size, PROT_READ, 0, fd, (off_t)0)) == NULL)
|
||||
err("%s: %s", file, strerror(errno));
|
||||
back = front + sb.st_size;
|
||||
exit(look(string, front, back));
|
||||
}
|
||||
|
||||
look(string, front, back)
|
||||
char *string, *front, *back;
|
||||
{
|
||||
register int ch;
|
||||
register char *readp, *writep;
|
||||
|
||||
/* Reformat string string to avoid doing it multiple times later. */
|
||||
for (readp = writep = string; ch = *readp++;) {
|
||||
if (fflag)
|
||||
ch = FOLD(ch);
|
||||
if (dflag)
|
||||
ch = DICT(ch);
|
||||
if (ch != NO_COMPARE)
|
||||
*(writep++) = ch;
|
||||
}
|
||||
*writep = '\0';
|
||||
|
||||
front = binary_search(string, front, back);
|
||||
front = linear_search(string, front, back);
|
||||
|
||||
if (front)
|
||||
print_from(string, front, back);
|
||||
return (front ? 0 : 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Binary search for "string" in memory between "front" and "back".
|
||||
*
|
||||
* This routine is expected to return a pointer to the start of a line at
|
||||
* *or before* the first word matching "string". Relaxing the constraint
|
||||
* this way simplifies the algorithm.
|
||||
*
|
||||
* Invariants:
|
||||
* front points to the beginning of a line at or before the first
|
||||
* matching string.
|
||||
*
|
||||
* back points to the beginning of a line at or after the first
|
||||
* matching line.
|
||||
*
|
||||
* Base of the Invariants.
|
||||
* front = NULL;
|
||||
* back = EOF;
|
||||
*
|
||||
* Advancing the Invariants:
|
||||
*
|
||||
* p = first newline after halfway point from front to back.
|
||||
*
|
||||
* If the string at "p" is not greater than the string to match,
|
||||
* p is the new front. Otherwise it is the new back.
|
||||
*
|
||||
* Termination:
|
||||
*
|
||||
* The definition of the routine allows it return at any point,
|
||||
* since front is always at or before the line to print.
|
||||
*
|
||||
* In fact, it returns when the chosen "p" equals "back". This
|
||||
* implies that there exists a string is least half as long as
|
||||
* (back - front), which in turn implies that a linear search will
|
||||
* be no more expensive than the cost of simply printing a string or two.
|
||||
*
|
||||
* Trying to continue with binary search at this point would be
|
||||
* more trouble than it's worth.
|
||||
*/
|
||||
#define SKIP_PAST_NEWLINE(p, back) \
|
||||
while (p < back && *p++ != '\n');
|
||||
|
||||
char *
|
||||
binary_search(string, front, back)
|
||||
register char *string, *front, *back;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = front + (back - front) / 2;
|
||||
SKIP_PAST_NEWLINE(p, back);
|
||||
|
||||
/*
|
||||
* If the file changes underneath us, make sure we don't
|
||||
* infinitely loop.
|
||||
*/
|
||||
while (p < back && back > front) {
|
||||
if (compare(string, p, back) == GREATER)
|
||||
front = p;
|
||||
else
|
||||
back = p;
|
||||
p = front + (back - front) / 2;
|
||||
SKIP_PAST_NEWLINE(p, back);
|
||||
}
|
||||
return (front);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first line that starts with string, linearly searching from front
|
||||
* to back.
|
||||
*
|
||||
* Return NULL for no such line.
|
||||
*
|
||||
* This routine assumes:
|
||||
*
|
||||
* o front points at the first character in a line.
|
||||
* o front is before or at the first line to be printed.
|
||||
*/
|
||||
char *
|
||||
linear_search(string, front, back)
|
||||
char *string, *front, *back;
|
||||
{
|
||||
while (front < back) {
|
||||
switch (compare(string, front, back)) {
|
||||
case EQUAL: /* Found it. */
|
||||
return (front);
|
||||
break;
|
||||
case LESS: /* No such string. */
|
||||
return (NULL);
|
||||
break;
|
||||
case GREATER: /* Keep going. */
|
||||
break;
|
||||
}
|
||||
SKIP_PAST_NEWLINE(front, back);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print as many lines as match string, starting at front.
|
||||
*/
|
||||
void
|
||||
print_from(string, front, back)
|
||||
register char *string, *front, *back;
|
||||
{
|
||||
for (; front < back && compare(string, front, back) == EQUAL; ++front) {
|
||||
for (; front < back && *front != '\n'; ++front)
|
||||
if (putchar(*front) == EOF)
|
||||
err("stdout: %s", strerror(errno));
|
||||
if (putchar('\n') == EOF)
|
||||
err("stdout: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return LESS, GREATER, or EQUAL depending on how the string1 compares with
|
||||
* string2 (s1 ??? s2).
|
||||
*
|
||||
* o Matches up to len(s1) are EQUAL.
|
||||
* o Matches up to len(s2) are GREATER.
|
||||
*
|
||||
* Compare understands about the -f and -d flags, and treats comparisons
|
||||
* appropriately.
|
||||
*
|
||||
* The string "s1" is null terminated. The string s2 is '\n' terminated (or
|
||||
* "back" terminated).
|
||||
*/
|
||||
int
|
||||
compare(s1, s2, back)
|
||||
register char *s1, *s2, *back;
|
||||
{
|
||||
register int ch;
|
||||
|
||||
for (; *s1 && s2 < back && *s2 != '\n'; ++s1, ++s2) {
|
||||
ch = *s2;
|
||||
if (fflag)
|
||||
ch = FOLD(ch);
|
||||
if (dflag)
|
||||
ch = DICT(ch);
|
||||
|
||||
if (ch == NO_COMPARE) {
|
||||
++s2; /* Ignore character in comparison. */
|
||||
continue;
|
||||
}
|
||||
if (*s1 != ch)
|
||||
return (*s1 < ch ? LESS : GREATER);
|
||||
}
|
||||
return (*s1 ? GREATER : EQUAL);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: look [-df] [-t char] string [file]\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "look: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(2);
|
||||
/* NOTREACHED */
|
||||
}
|
276
usr.bin/mt/mt.c
Normal file
276
usr.bin/mt/mt.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* mt --
|
||||
* magnetic tape manipulation program
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mtio.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct commands {
|
||||
char *c_name;
|
||||
int c_code;
|
||||
int c_ronly;
|
||||
} com[] = {
|
||||
{ "bsf", MTBSF, 1 },
|
||||
{ "bsr", MTBSR, 1 },
|
||||
{ "eof", MTWEOF, 0 },
|
||||
{ "fsf", MTFSF, 1 },
|
||||
{ "fsr", MTFSR, 1 },
|
||||
{ "offline", MTOFFL, 1 },
|
||||
{ "rewind", MTREW, 1 },
|
||||
{ "rewoffl", MTOFFL, 1 },
|
||||
{ "status", MTNOP, 1 },
|
||||
{ "weof", MTWEOF, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void err __P((const char *, ...));
|
||||
void printreg __P((char *, u_int, char *));
|
||||
void status __P((struct mtget *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register struct commands *comp;
|
||||
struct mtget mt_status;
|
||||
struct mtop mt_com;
|
||||
int ch, len, mtfd;
|
||||
char *p, *tape;
|
||||
|
||||
if ((tape = getenv("TAPE")) == NULL)
|
||||
tape = DEFTAPE;
|
||||
|
||||
while ((ch = getopt(argc, argv, "f:t:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'f':
|
||||
case 't':
|
||||
tape = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1 || argc > 2)
|
||||
usage();
|
||||
|
||||
len = strlen(p = *argv++);
|
||||
for (comp = com;; comp++) {
|
||||
if (comp->c_name == NULL)
|
||||
err("%s: unknown command", p);
|
||||
if (strncmp(p, comp->c_name, len) == 0)
|
||||
break;
|
||||
}
|
||||
if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0)
|
||||
err("%s: %s", tape, strerror(errno));
|
||||
if (comp->c_code != MTNOP) {
|
||||
mt_com.mt_op = comp->c_code;
|
||||
if (*argv) {
|
||||
mt_com.mt_count = strtol(*argv, &p, 10);
|
||||
if (mt_com.mt_count <= 0 || *p)
|
||||
err("%s: illegal count", *argv);
|
||||
}
|
||||
else
|
||||
mt_com.mt_count = 1;
|
||||
if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0)
|
||||
err("%s: %s: %s", tape, comp->c_name, strerror(errno));
|
||||
} else {
|
||||
if (ioctl(mtfd, MTIOCGET, &mt_status) < 0)
|
||||
err("%s", strerror(errno));
|
||||
status(&mt_status);
|
||||
}
|
||||
exit (0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#ifdef vax
|
||||
#include <vax/mba/mtreg.h>
|
||||
#include <vax/mba/htreg.h>
|
||||
|
||||
#include <vax/uba/utreg.h>
|
||||
#include <vax/uba/tmreg.h>
|
||||
#undef b_repcnt /* argh */
|
||||
#include <vax/uba/tsreg.h>
|
||||
#endif
|
||||
|
||||
#ifdef sun
|
||||
#include <sundev/tmreg.h>
|
||||
#include <sundev/arreg.h>
|
||||
#endif
|
||||
|
||||
#ifdef tahoe
|
||||
#include <tahoe/vba/cyreg.h>
|
||||
#endif
|
||||
|
||||
struct tape_desc {
|
||||
short t_type; /* type of magtape device */
|
||||
char *t_name; /* printing name */
|
||||
char *t_dsbits; /* "drive status" register */
|
||||
char *t_erbits; /* "error" register */
|
||||
} tapes[] = {
|
||||
#ifdef vax
|
||||
{ MT_ISTS, "ts11", 0, TSXS0_BITS },
|
||||
{ MT_ISHT, "tm03", HTDS_BITS, HTER_BITS },
|
||||
{ MT_ISTM, "tm11", 0, TMER_BITS },
|
||||
{ MT_ISMT, "tu78", MTDS_BITS, 0 },
|
||||
{ MT_ISUT, "tu45", UTDS_BITS, UTER_BITS },
|
||||
#endif
|
||||
#ifdef sun
|
||||
{ MT_ISCPC, "TapeMaster", TMS_BITS, 0 },
|
||||
{ MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS },
|
||||
#endif
|
||||
#ifdef tahoe
|
||||
{ MT_ISCY, "cipher", CYS_BITS, CYCW_BITS },
|
||||
#endif
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Interpret the status buffer returned
|
||||
*/
|
||||
void
|
||||
status(bp)
|
||||
register struct mtget *bp;
|
||||
{
|
||||
register struct tape_desc *mt;
|
||||
|
||||
for (mt = tapes;; mt++) {
|
||||
if (mt->t_type == 0) {
|
||||
(void)printf("%d: unknown tape drive type\n",
|
||||
bp->mt_type);
|
||||
return;
|
||||
}
|
||||
if (mt->t_type == bp->mt_type)
|
||||
break;
|
||||
}
|
||||
(void)printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid);
|
||||
printreg("ds", bp->mt_dsreg, mt->t_dsbits);
|
||||
printreg("\ner", bp->mt_erreg, mt->t_erbits);
|
||||
(void)putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a register a la the %b format of the kernel's printf.
|
||||
*/
|
||||
void
|
||||
printreg(s, v, bits)
|
||||
char *s;
|
||||
register u_int v;
|
||||
register char *bits;
|
||||
{
|
||||
register int i, any = 0;
|
||||
register char c;
|
||||
|
||||
if (bits && *bits == 8)
|
||||
printf("%s=%o", s, v);
|
||||
else
|
||||
printf("%s=%x", s, v);
|
||||
bits++;
|
||||
if (v && bits) {
|
||||
putchar('<');
|
||||
while (i = *bits++) {
|
||||
if (v & (1 << (i-1))) {
|
||||
if (any)
|
||||
putchar(',');
|
||||
any = 1;
|
||||
for (; (c = *bits) > 32; bits++)
|
||||
putchar(c);
|
||||
} else
|
||||
for (; *bits > 32; bits++)
|
||||
;
|
||||
}
|
||||
putchar('>');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: mt [-f device] command [ count ]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "mt: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
100
usr.bin/printenv/printenv.c
Normal file
100
usr.bin/printenv/printenv.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1987, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printenv.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage __P((void));
|
||||
|
||||
/*
|
||||
* printenv
|
||||
*
|
||||
* Bill Joy, UCB
|
||||
* February, 1979
|
||||
*/
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char **environ;
|
||||
register char *cp, **ep;
|
||||
register size_t len;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0) {
|
||||
for (ep = environ; *ep; ep++)
|
||||
(void)printf("%s\n", *ep);
|
||||
exit(0);
|
||||
}
|
||||
len = strlen(*argv);
|
||||
for (ep = environ; *ep; ep++)
|
||||
if (!memcmp(*ep, *argv, len)) {
|
||||
cp = *ep + len;
|
||||
if (!*cp || *cp == '=') {
|
||||
(void)printf("%s\n", *cp ? cp + 1 : cp);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printenv [name]\n");
|
||||
exit(1);
|
||||
}
|
110
usr.bin/rev/rev.c
Normal file
110
usr.bin/rev/rev.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*-
|
||||
* Copyright (c) 1987, 1992, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1987, 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rev.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register char *filename, *p, *t;
|
||||
FILE *fp;
|
||||
size_t len;
|
||||
int ch, rval;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
fp = stdin;
|
||||
filename = "stdin";
|
||||
rval = 0;
|
||||
do {
|
||||
if (*argv) {
|
||||
if ((fp = fopen(*argv, "r")) == NULL) {
|
||||
warn("%s", *argv);
|
||||
rval = 1;
|
||||
++argv;
|
||||
continue;
|
||||
}
|
||||
filename = *argv++;
|
||||
}
|
||||
while ((p = fgetln(fp, &len)) != NULL) {
|
||||
if (p[len - 1] == '\n')
|
||||
--len;
|
||||
t = p + len - 1;
|
||||
for (t = p + len - 1; t >= p; --t)
|
||||
putchar(*t);
|
||||
putchar('\n');
|
||||
}
|
||||
if (ferror(fp)) {
|
||||
warn("%s", filename);
|
||||
rval = 1;
|
||||
}
|
||||
(void)fclose(fp);
|
||||
} while(*argv);
|
||||
exit(rval);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: rev [file ...]\n");
|
||||
exit(1);
|
||||
}
|
342
usr.bin/tr/str.c
Normal file
342
usr.bin/tr/str.c
Normal file
@ -0,0 +1,342 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)str.c 8.2 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static int backslash __P((STR *));
|
||||
static int bracket __P((STR *));
|
||||
static int c_class __P((const void *, const void *));
|
||||
static void genclass __P((STR *));
|
||||
static void genequiv __P((STR *));
|
||||
static int genrange __P((STR *));
|
||||
static void genseq __P((STR *));
|
||||
|
||||
int
|
||||
next(s)
|
||||
register STR *s;
|
||||
{
|
||||
register int ch;
|
||||
|
||||
switch (s->state) {
|
||||
case EOS:
|
||||
return (0);
|
||||
case INFINITE:
|
||||
return (1);
|
||||
case NORMAL:
|
||||
switch (ch = *s->str) {
|
||||
case '\0':
|
||||
s->state = EOS;
|
||||
return (0);
|
||||
case '\\':
|
||||
s->lastch = backslash(s);
|
||||
break;
|
||||
case '[':
|
||||
if (bracket(s))
|
||||
return (next(s));
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
++s->str;
|
||||
s->lastch = ch;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We can start a range at any time. */
|
||||
if (s->str[0] == '-' && genrange(s))
|
||||
return (next(s));
|
||||
return (1);
|
||||
case RANGE:
|
||||
if (s->cnt-- == 0) {
|
||||
s->state = NORMAL;
|
||||
return (next(s));
|
||||
}
|
||||
++s->lastch;
|
||||
return (1);
|
||||
case SEQUENCE:
|
||||
if (s->cnt-- == 0) {
|
||||
s->state = NORMAL;
|
||||
return (next(s));
|
||||
}
|
||||
return (1);
|
||||
case SET:
|
||||
if ((s->lastch = s->set[s->cnt++]) == OOBCH) {
|
||||
s->state = NORMAL;
|
||||
return (next(s));
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
bracket(s)
|
||||
register STR *s;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
switch (s->str[1]) {
|
||||
case ':': /* "[:class:]" */
|
||||
if ((p = strstr(s->str + 2, ":]")) == NULL)
|
||||
return (0);
|
||||
*p = '\0';
|
||||
s->str += 2;
|
||||
genclass(s);
|
||||
s->str = p + 2;
|
||||
return (1);
|
||||
case '=': /* "[=equiv=]" */
|
||||
if ((p = strstr(s->str + 2, "=]")) == NULL)
|
||||
return (0);
|
||||
s->str += 2;
|
||||
genequiv(s);
|
||||
return (1);
|
||||
default: /* "[\###*n]" or "[#*n]" */
|
||||
if ((p = strpbrk(s->str + 2, "*]")) == NULL)
|
||||
return (0);
|
||||
if (p[0] != '*' || index(p, ']') == NULL)
|
||||
return (0);
|
||||
s->str += 1;
|
||||
genseq(s);
|
||||
return (1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int isalnum __P((int)),
|
||||
isalpha __P((int)),
|
||||
isblank __P((int)),
|
||||
isspace __P((int)),
|
||||
iscntrl __P((int)),
|
||||
isdigit __P((int)),
|
||||
isgraph __P((int)),
|
||||
islower __P((int)),
|
||||
isprint __P((int)),
|
||||
ispunct __P((int)),
|
||||
isupper __P((int)),
|
||||
isxdigit __P((int));
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*func) __P((int));
|
||||
int *set;
|
||||
} CLASS;
|
||||
|
||||
static CLASS classes[] = {
|
||||
{ "alnum", isalnum, },
|
||||
{ "alpha", isalpha, },
|
||||
{ "blank", isblank, },
|
||||
{ "cntrl", iscntrl, },
|
||||
{ "digit", isdigit, },
|
||||
{ "graph", isgraph, },
|
||||
{ "lower", islower, },
|
||||
{ "print", isupper, },
|
||||
{ "punct", ispunct, },
|
||||
{ "space", isspace, },
|
||||
{ "upper", isupper, },
|
||||
{ "xdigit", isxdigit, },
|
||||
};
|
||||
|
||||
static void
|
||||
genclass(s)
|
||||
STR *s;
|
||||
{
|
||||
register int cnt, (*func) __P((int));
|
||||
CLASS *cp, tmp;
|
||||
int *p;
|
||||
|
||||
tmp.name = s->str;
|
||||
if ((cp = (CLASS *)bsearch(&tmp, classes, sizeof(classes) /
|
||||
sizeof(CLASS), sizeof(CLASS), c_class)) == NULL)
|
||||
err("unknown class %s", s->str);
|
||||
|
||||
if ((cp->set = p = malloc((NCHARS + 1) * sizeof(int))) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
bzero(p, (NCHARS + 1) * sizeof(int));
|
||||
for (cnt = 0, func = cp->func; cnt < NCHARS; ++cnt)
|
||||
if ((func)(cnt))
|
||||
*p++ = cnt;
|
||||
*p = OOBCH;
|
||||
|
||||
s->cnt = 0;
|
||||
s->state = SET;
|
||||
s->set = cp->set;
|
||||
}
|
||||
|
||||
static int
|
||||
c_class(a, b)
|
||||
const void *a, *b;
|
||||
{
|
||||
return (strcmp(((CLASS *)a)->name, ((CLASS *)b)->name));
|
||||
}
|
||||
|
||||
/*
|
||||
* English doesn't have any equivalence classes, so for now
|
||||
* we just syntax check and grab the character.
|
||||
*/
|
||||
static void
|
||||
genequiv(s)
|
||||
STR *s;
|
||||
{
|
||||
if (*s->str == '\\') {
|
||||
s->equiv[0] = backslash(s);
|
||||
if (*s->str != '=')
|
||||
err("misplaced equivalence equals sign");
|
||||
} else {
|
||||
s->equiv[0] = s->str[0];
|
||||
if (s->str[1] != '=')
|
||||
err("misplaced equivalence equals sign");
|
||||
}
|
||||
s->str += 2;
|
||||
s->cnt = 0;
|
||||
s->state = SET;
|
||||
s->set = s->equiv;
|
||||
}
|
||||
|
||||
static int
|
||||
genrange(s)
|
||||
STR *s;
|
||||
{
|
||||
int stopval;
|
||||
char *savestart;
|
||||
|
||||
savestart = s->str;
|
||||
stopval = *++s->str == '\\' ? backslash(s) : *s->str++;
|
||||
if (stopval < (u_char)s->lastch) {
|
||||
s->str = savestart;
|
||||
return (0);
|
||||
}
|
||||
s->cnt = stopval - s->lastch + 1;
|
||||
s->state = RANGE;
|
||||
--s->lastch;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
genseq(s)
|
||||
STR *s;
|
||||
{
|
||||
char *ep;
|
||||
|
||||
if (s->which == STRING1)
|
||||
err("sequences only valid in string2");
|
||||
|
||||
if (*s->str == '\\')
|
||||
s->lastch = backslash(s);
|
||||
else
|
||||
s->lastch = *s->str++;
|
||||
if (*s->str != '*')
|
||||
err("misplaced sequence asterisk");
|
||||
|
||||
switch (*++s->str) {
|
||||
case '\\':
|
||||
s->cnt = backslash(s);
|
||||
break;
|
||||
case ']':
|
||||
s->cnt = 0;
|
||||
++s->str;
|
||||
break;
|
||||
default:
|
||||
if (isdigit(*s->str)) {
|
||||
s->cnt = strtol(s->str, &ep, 0);
|
||||
if (*ep == ']') {
|
||||
s->str = ep + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
err("illegal sequence count");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
s->state = s->cnt ? SEQUENCE : INFINITE;
|
||||
}
|
||||
|
||||
/* Use the #defines isXXX() here, DON'T use them above. */
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Translate \??? into a character. Up to 3 octal digits, if no digits either
|
||||
* an escape code or a literal character.
|
||||
*/
|
||||
static int
|
||||
backslash(s)
|
||||
register STR *s;
|
||||
{
|
||||
register int ch, cnt, val;
|
||||
|
||||
for (cnt = val = 0;;) {
|
||||
ch = *++s->str;
|
||||
if (!isascii(ch) || !isdigit(ch))
|
||||
break;
|
||||
val = val * 8 + ch - '0';
|
||||
if (++cnt == 3) {
|
||||
++s->str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cnt)
|
||||
return (val);
|
||||
if (ch != '\0')
|
||||
++s->str;
|
||||
switch (ch) {
|
||||
case 'a': /* escape characters */
|
||||
return ('\7');
|
||||
case 'b':
|
||||
return ('\b');
|
||||
case 'f':
|
||||
return ('\f');
|
||||
case 'n':
|
||||
return ('\n');
|
||||
case 'r':
|
||||
return ('\r');
|
||||
case 't':
|
||||
return ('\t');
|
||||
case 'v':
|
||||
return ('\13');
|
||||
case '\0': /* \" -> \ */
|
||||
s->state = EOS;
|
||||
return ('\\');
|
||||
default: /* \x" -> x */
|
||||
return (ch);
|
||||
}
|
||||
}
|
290
usr.bin/tr/tr.c
Normal file
290
usr.bin/tr/tr.c
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)tr.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static int string1[NCHARS] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ASCII */
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
}, string2[NCHARS];
|
||||
|
||||
STR s1 = { STRING1, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
|
||||
STR s2 = { STRING2, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
|
||||
|
||||
static void setup __P((int *, char *, STR *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int ch, cnt, lastch, *p;
|
||||
int cflag, dflag, sflag, isstring2;
|
||||
|
||||
cflag = dflag = sflag = 0;
|
||||
while ((ch = getopt(argc, argv, "cds")) != EOF)
|
||||
switch((char)ch) {
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
switch(argc) {
|
||||
case 0:
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
isstring2 = 0;
|
||||
break;
|
||||
case 2:
|
||||
isstring2 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* tr -ds [-c] string1 string2
|
||||
* Delete all characters (or complemented characters) in string1.
|
||||
* Squeeze all characters in string2.
|
||||
*/
|
||||
if (dflag && sflag) {
|
||||
if (!isstring2)
|
||||
usage();
|
||||
|
||||
setup(string1, argv[0], &s1, cflag);
|
||||
setup(string2, argv[1], &s2, 0);
|
||||
|
||||
for (lastch = OOBCH; (ch = getchar()) != EOF;)
|
||||
if (!string1[ch] && (!string2[ch] || lastch != ch)) {
|
||||
lastch = ch;
|
||||
(void)putchar(ch);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* tr -d [-c] string1
|
||||
* Delete all characters (or complemented characters) in string1.
|
||||
*/
|
||||
if (dflag) {
|
||||
if (isstring2)
|
||||
usage();
|
||||
|
||||
setup(string1, argv[0], &s1, cflag);
|
||||
|
||||
while ((ch = getchar()) != EOF)
|
||||
if (!string1[ch])
|
||||
(void)putchar(ch);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* tr -s [-c] string1
|
||||
* Squeeze all characters (or complemented characters) in string1.
|
||||
*/
|
||||
if (sflag && !isstring2) {
|
||||
setup(string1, argv[0], &s1, cflag);
|
||||
|
||||
for (lastch = OOBCH; (ch = getchar()) != EOF;)
|
||||
if (!string1[ch] || lastch != ch) {
|
||||
lastch = ch;
|
||||
(void)putchar(ch);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* tr [-cs] string1 string2
|
||||
* Replace all characters (or complemented characters) in string1 with
|
||||
* the character in the same position in string2. If the -s option is
|
||||
* specified, squeeze all the characters in string2.
|
||||
*/
|
||||
if (!isstring2)
|
||||
usage();
|
||||
|
||||
s1.str = argv[0];
|
||||
s2.str = argv[1];
|
||||
|
||||
if (cflag)
|
||||
for (cnt = NCHARS, p = string1; cnt--;)
|
||||
*p++ = OOBCH;
|
||||
|
||||
if (!next(&s2))
|
||||
err("empty string2");
|
||||
|
||||
/* If string2 runs out of characters, use the last one specified. */
|
||||
if (sflag)
|
||||
while (next(&s1)) {
|
||||
string1[s1.lastch] = ch = s2.lastch;
|
||||
string2[ch] = 1;
|
||||
(void)next(&s2);
|
||||
}
|
||||
else
|
||||
while (next(&s1)) {
|
||||
string1[s1.lastch] = ch = s2.lastch;
|
||||
(void)next(&s2);
|
||||
}
|
||||
|
||||
if (cflag)
|
||||
for (cnt = 0, p = string1; cnt < NCHARS; ++p, ++cnt)
|
||||
*p = *p == OOBCH ? ch : cnt;
|
||||
|
||||
if (sflag)
|
||||
for (lastch = OOBCH; (ch = getchar()) != EOF;) {
|
||||
ch = string1[ch];
|
||||
if (!string2[ch] || lastch != ch) {
|
||||
lastch = ch;
|
||||
(void)putchar(ch);
|
||||
}
|
||||
}
|
||||
else
|
||||
while ((ch = getchar()) != EOF)
|
||||
(void)putchar(string1[ch]);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static void
|
||||
setup(string, arg, str, cflag)
|
||||
int *string;
|
||||
char *arg;
|
||||
STR *str;
|
||||
int cflag;
|
||||
{
|
||||
register int cnt, *p;
|
||||
|
||||
str->str = arg;
|
||||
bzero(string, NCHARS * sizeof(int));
|
||||
while (next(str))
|
||||
string[str->lastch] = 1;
|
||||
if (cflag)
|
||||
for (p = string, cnt = NCHARS; cnt--; ++p)
|
||||
*p = !*p;
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: tr [-cs] string1 string2\n");
|
||||
(void)fprintf(stderr, " tr [-c] -d string1\n");
|
||||
(void)fprintf(stderr, " tr [-c] -s string1\n");
|
||||
(void)fprintf(stderr, " tr [-c] -ds string1 string2\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "tr: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
163
usr.bin/uname/uname.c
Normal file
163
usr.bin/uname/uname.c
Normal file
@ -0,0 +1,163 @@
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uname.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#define MFLAG 0x01
|
||||
#define NFLAG 0x02
|
||||
#define RFLAG 0x04
|
||||
#define SFLAG 0x08
|
||||
#define VFLAG 0x10
|
||||
u_int flags;
|
||||
int ch, mib[2];
|
||||
size_t len, tlen;
|
||||
char *p, *prefix, buf[1024];
|
||||
|
||||
flags = 0;
|
||||
while ((ch = getopt(argc, argv, "amnrsv")) != EOF)
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
flags |= (MFLAG | NFLAG | RFLAG | SFLAG | VFLAG);
|
||||
break;
|
||||
case 'm':
|
||||
flags |= MFLAG;
|
||||
break;
|
||||
case 'n':
|
||||
flags |= NFLAG;
|
||||
break;
|
||||
case 'r':
|
||||
flags |= RFLAG;
|
||||
break;
|
||||
case 's':
|
||||
flags |= SFLAG;
|
||||
break;
|
||||
case 'v':
|
||||
flags |= VFLAG;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc)
|
||||
usage();
|
||||
|
||||
if (!flags)
|
||||
flags |= SFLAG;
|
||||
|
||||
prefix = "";
|
||||
|
||||
if (flags & SFLAG) {
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_OSTYPE;
|
||||
len = sizeof(buf);
|
||||
if (sysctl(mib, 2, &buf, &len, NULL, 0) == -1)
|
||||
err(1, "sysctl");
|
||||
(void)printf("%s%.*s", prefix, len, buf);
|
||||
prefix = " ";
|
||||
}
|
||||
if (flags & NFLAG) {
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_HOSTNAME;
|
||||
len = sizeof(buf);
|
||||
if (sysctl(mib, 2, &buf, &len, NULL, 0) == -1)
|
||||
err(1, "sysctl");
|
||||
(void)printf("%s%.*s", prefix, len, buf);
|
||||
prefix = " ";
|
||||
}
|
||||
if (flags & RFLAG) {
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_OSRELEASE;
|
||||
len = sizeof(buf);
|
||||
if (sysctl(mib, 2, &buf, &len, NULL, 0) == -1)
|
||||
err(1, "sysctl");
|
||||
(void)printf("%s%.*s", prefix, len, buf);
|
||||
prefix = " ";
|
||||
}
|
||||
if (flags & VFLAG) {
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_VERSION;
|
||||
len = sizeof(buf);
|
||||
if (sysctl(mib, 2, &buf, &len, NULL, 0) == -1)
|
||||
err(1, "sysctl");
|
||||
for (p = buf, tlen = len; tlen--; ++p)
|
||||
if (*p == '\n' || *p == '\t')
|
||||
*p = ' ';
|
||||
(void)printf("%s%.*s", prefix, len, buf);
|
||||
prefix = " ";
|
||||
}
|
||||
if (flags & MFLAG) {
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_MACHINE;
|
||||
len = sizeof(buf);
|
||||
if (sysctl(mib, 2, &buf, &len, NULL, 0) == -1)
|
||||
err(1, "sysctl");
|
||||
(void)printf("%s%.*s", prefix, len, buf);
|
||||
prefix = " ";
|
||||
}
|
||||
(void)printf("\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: uname [-amnrsv]\n");
|
||||
exit(1);
|
||||
}
|
276
usr.bin/uniq/uniq.c
Normal file
276
usr.bin/uniq/uniq.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Case Larsen.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uniq.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAXLINELEN (8 * 1024)
|
||||
|
||||
int cflag, dflag, uflag;
|
||||
int numchars, numfields, repeats;
|
||||
|
||||
void err __P((const char *, ...));
|
||||
FILE *file __P((char *, char *));
|
||||
void show __P((FILE *, char *));
|
||||
char *skip __P((char *));
|
||||
void obsolete __P((char *[]));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register char *t1, *t2;
|
||||
FILE *ifp, *ofp;
|
||||
int ch;
|
||||
char *prevline, *thisline, *p;
|
||||
|
||||
obsolete(argv);
|
||||
while ((ch = getopt(argc, argv, "-cdf:s:u")) != EOF)
|
||||
switch (ch) {
|
||||
case '-':
|
||||
--optind;
|
||||
goto done;
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
numfields = strtol(optarg, &p, 10);
|
||||
if (numfields < 0 || *p)
|
||||
err("illegal field skip value: %s", optarg);
|
||||
break;
|
||||
case 's':
|
||||
numchars = strtol(optarg, &p, 10);
|
||||
if (numchars < 0 || *p)
|
||||
err("illegal character skip value: %s", optarg);
|
||||
break;
|
||||
case 'u':
|
||||
uflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
done: argc -= optind;
|
||||
argv +=optind;
|
||||
|
||||
/* If no flags are set, default is -d -u. */
|
||||
if (cflag) {
|
||||
if (dflag || uflag)
|
||||
usage();
|
||||
} else if (!dflag && !uflag)
|
||||
dflag = uflag = 1;
|
||||
|
||||
switch(argc) {
|
||||
case 0:
|
||||
ifp = stdin;
|
||||
ofp = stdout;
|
||||
break;
|
||||
case 1:
|
||||
ifp = file(argv[0], "r");
|
||||
ofp = stdout;
|
||||
break;
|
||||
case 2:
|
||||
ifp = file(argv[0], "r");
|
||||
ofp = file(argv[1], "w");
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
prevline = malloc(MAXLINELEN);
|
||||
thisline = malloc(MAXLINELEN);
|
||||
if (prevline == NULL || thisline == NULL)
|
||||
err("%s", strerror(errno));
|
||||
|
||||
if (fgets(prevline, MAXLINELEN, ifp) == NULL)
|
||||
exit(0);
|
||||
|
||||
while (fgets(thisline, MAXLINELEN, ifp)) {
|
||||
/* If requested get the chosen fields + character offsets. */
|
||||
if (numfields || numchars) {
|
||||
t1 = skip(thisline);
|
||||
t2 = skip(prevline);
|
||||
} else {
|
||||
t1 = thisline;
|
||||
t2 = prevline;
|
||||
}
|
||||
|
||||
/* If different, print; set previous to new value. */
|
||||
if (strcmp(t1, t2)) {
|
||||
show(ofp, prevline);
|
||||
t1 = prevline;
|
||||
prevline = thisline;
|
||||
thisline = t1;
|
||||
repeats = 0;
|
||||
} else
|
||||
++repeats;
|
||||
}
|
||||
show(ofp, prevline);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* show --
|
||||
* Output a line depending on the flags and number of repetitions
|
||||
* of the line.
|
||||
*/
|
||||
void
|
||||
show(ofp, str)
|
||||
FILE *ofp;
|
||||
char *str;
|
||||
{
|
||||
|
||||
if (cflag && *str)
|
||||
(void)fprintf(ofp, "%4d %s", repeats + 1, str);
|
||||
if (dflag && repeats || uflag && !repeats)
|
||||
(void)fprintf(ofp, "%s", str);
|
||||
}
|
||||
|
||||
char *
|
||||
skip(str)
|
||||
register char *str;
|
||||
{
|
||||
register int infield, nchars, nfields;
|
||||
|
||||
for (nfields = numfields, infield = 0; nfields && *str; ++str)
|
||||
if (isspace(*str)) {
|
||||
if (infield) {
|
||||
infield = 0;
|
||||
--nfields;
|
||||
}
|
||||
} else if (!infield)
|
||||
infield = 1;
|
||||
for (nchars = numchars; nchars-- && *str; ++str);
|
||||
return(str);
|
||||
}
|
||||
|
||||
FILE *
|
||||
file(name, mode)
|
||||
char *name, *mode;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(name, mode)) == NULL)
|
||||
err("%s: %s", name, strerror(errno));
|
||||
return(fp);
|
||||
}
|
||||
|
||||
void
|
||||
obsolete(argv)
|
||||
char *argv[];
|
||||
{
|
||||
int len;
|
||||
char *ap, *p, *start;
|
||||
|
||||
while (ap = *++argv) {
|
||||
/* Return if "--" or not an option of any form. */
|
||||
if (ap[0] != '-') {
|
||||
if (ap[0] != '+')
|
||||
return;
|
||||
} else if (ap[1] == '-')
|
||||
return;
|
||||
if (!isdigit(ap[1]))
|
||||
continue;
|
||||
/*
|
||||
* Digit signifies an old-style option. Malloc space for dash,
|
||||
* new option and argument.
|
||||
*/
|
||||
len = strlen(ap);
|
||||
if ((start = p = malloc(len + 3)) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
*p++ = '-';
|
||||
*p++ = ap[0] == '+' ? 's' : 'f';
|
||||
(void)strcpy(p, ap + 1);
|
||||
*argv = start;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: uniq [-c | -du] [-f fields] [-s chars] [input [output]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "uniq: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
Loading…
Reference in New Issue
Block a user