This commit is contained in:
Connor Lane Smith 2011-05-26 16:18:42 -01:00
parent 0236550c77
commit bf9626d408
9 changed files with 130 additions and 20 deletions

View File

@ -1,8 +1,10 @@
include config.mk include config.mk
LIB = util/afgets.o util/agetcwd.o util/enmasse.o util/eprintf.o util/recurse.o LIB = util/afgets.o util/agetcwd.o util/concat.o util/enmasse.o util/eprintf.o \
util/recurse.o
SRC = basename.c cat.c chown.c date.c dirname.c echo.c false.c grep.c head.c \ SRC = basename.c cat.c chown.c date.c dirname.c echo.c false.c grep.c head.c \
ln.c ls.c mkdir.c mkfifo.c pwd.c rm.c sleep.c tee.c touch.c true.c wc.c ln.c ls.c mkdir.c mkfifo.c pwd.c rm.c sleep.c tail.c tee.c touch.c \
true.c wc.c
OBJ = $(SRC:.c=.o) $(LIB) OBJ = $(SRC:.c=.o) $(LIB)
BIN = $(SRC:.c=) BIN = $(SRC:.c=)
MAN = $(SRC:.c=.1) MAN = $(SRC:.c=.1)

View File

@ -13,4 +13,5 @@ with any leading path components, and the
.IR suffix , .IR suffix ,
removed. removed.
.SH SEE ALSO .SH SEE ALSO
.IR dirname (1),
.IR basename (3) .IR basename (3)

20
cat.c
View File

@ -2,10 +2,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "text.h"
#include "util.h" #include "util.h"
static void cat(FILE *, const char *);
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -14,25 +13,12 @@ main(int argc, char *argv[])
if(getopt(argc, argv, "") != -1) if(getopt(argc, argv, "") != -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
if(optind == argc) if(optind == argc)
cat(stdin, "<stdin>"); concat(stdin, "<stdin>", stdout, "<stdout>");
else for(; optind < argc; optind++) { else for(; optind < argc; optind++) {
if(!(fp = fopen(argv[optind], "r"))) if(!(fp = fopen(argv[optind], "r")))
eprintf("fopen %s:", argv[optind]); eprintf("fopen %s:", argv[optind]);
cat(fp, argv[optind]); concat(fp, argv[optind], stdout, "<stdout>");
fclose(fp); fclose(fp);
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void
cat(FILE *fp, const char *str)
{
char buf[BUFSIZ];
size_t n;
while((n = fread(buf, 1, sizeof buf, fp)) > 0)
if(fwrite(buf, 1, n, stdout) != n)
eprintf("<stdout>: write error:");
if(ferror(fp))
eprintf("%s: read error:", str);
}

View File

@ -10,4 +10,5 @@ prints the
.I string .I string
with its final path component removed. with its final path component removed.
.SH SEE ALSO .SH SEE ALSO
.IR basename (1),
.IR dirname (3) .IR dirname (3)

2
head.1
View File

@ -14,3 +14,5 @@ reads from stdin.
.TP .TP
.BI \-n " lines" .BI \-n " lines"
outputs the given number of lines. outputs the given number of lines.
.SH SEE ALSO
.IR tail (1)

20
tail.1 Normal file
View File

@ -0,0 +1,20 @@
.TH TAIL 1 sbase\-VERSION
.SH NAME
tail \- output last part of a file
.SH SYNOPSIS
.B tail
.RB [ \-n
.IR lines ]
.RI [ file ]
.SH DESCRIPTION
.B tail
writes the first 10 lines of the file to stdout. If no file is given, tail
reads from stdin.
.SH OPTIONS
.TP
.BI \-n " lines"
outputs the given number of lines. If
.I lines
begins with '+' it is used as an offset from the beginning of the file.
.SH SEE ALSO
.IR head (1)

80
tail.c Normal file
View File

@ -0,0 +1,80 @@
/* See LICENSE file for copyright and license detaketails. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "text.h"
#include "util.h"
static void dropinit(FILE *, const char *, long);
static void taketail(FILE *, const char *, long);
static void (*tail)(FILE *, const char *, long) = taketail;
int
main(int argc, char *argv[])
{
char *end, c;
long n = 10;
FILE *fp;
while((c = getopt(argc, argv, "n:")) != -1)
switch(c) {
case 'n':
n = abs(strtol(optarg, &end, 0));
if(*end != '\0')
eprintf("%s: not a number\n", optarg);
if(optarg[0] == '+')
tail = dropinit;
break;
default:
exit(EXIT_FAILURE);
}
if(optind == argc)
tail(stdin, "<stdin>", n);
else if(optind == argc-1) {
if(!(fp = fopen(argv[optind], "r")))
eprintf("fopen %s:", argv[optind]);
tail(fp, argv[optind], n);
fclose(fp);
}
else
eprintf("usage: %s [-n lines] [file]\n", argv[0]);
return EXIT_SUCCESS;
}
void
dropinit(FILE *fp, const char *str, long n)
{
char buf[BUFSIZ];
long i = 0;
while(i < n && fgets(buf, sizeof buf, fp))
if(buf[strlen(buf)-1] == '\n')
i++;
concat(fp, str, stdout, "<stdout>");
}
void
taketail(FILE *fp, const char *str, long n)
{
char **ring;
long i, j;
size_t *size;
if(!(ring = calloc(n, sizeof *ring)) || !(size = calloc(n, sizeof *size)))
eprintf("calloc:");
for(i = j = 0; afgets(&ring[i], &size[i], fp); i = j = (i+1)%n)
;
do {
if(ring[j])
fputs(ring[j], stdout);
} while((j = (j+1)%n) != i);
free(ring);
free(size);
if(ferror(fp))
eprintf("%s: read error:", str);
}

3
text.h
View File

@ -1,3 +1,4 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
char *afgets(char **p, size_t *size, FILE *fp); char *afgets(char **, size_t *, FILE *);
void concat(FILE *, const char *, FILE *, const char *);

17
util/concat.c Normal file
View File

@ -0,0 +1,17 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include "../text.h"
#include "../util.h"
void
concat(FILE *fp1, const char *s1, FILE *fp2, const char *s2)
{
char buf[BUFSIZ];
size_t n;
while((n = fread(buf, 1, sizeof buf, fp1)) > 0)
if(fwrite(buf, 1, n, fp2) != n)
eprintf("%s: write error:", s2);
if(ferror(fp1))
eprintf("%s: read error:", s1);
}