sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit 9f9ea07e6cf302dd20adf4d5c7ae817e3535283c
parent 726973dcd581724dd52979612c52562f162102b0
Author: Connor Lane Smith <cls@lubutu.com>
Date:   Thu Jun  2 13:03:34 +0100

add sort
Diffstat:
Makefile | 4++--
sort.1 | 15+++++++++++++++
sort.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile @@ -5,8 +5,8 @@ LIB = util/afgets.o util/agetcwd.o util/concat.o util/enmasse.o util/eprintf.o \ util/recurse.o SRC = basename.c cat.c chmod.c chown.c date.c dirname.c echo.c false.c grep.c \ - head.c ln.c ls.c mkdir.c mkfifo.c nl.c pwd.c rm.c sleep.c tail.c tee.c \ - touch.c true.c wc.c + head.c ln.c ls.c mkdir.c mkfifo.c nl.c pwd.c rm.c sleep.c sort.c tail.c \ + tee.c touch.c true.c wc.c OBJ = $(SRC:.c=.o) $(LIB) BIN = $(SRC:.c=) MAN = $(SRC:.c=.1) diff --git a/sort.1 b/sort.1 @@ -0,0 +1,15 @@ +.TH NL 1 sbase\-VERSION +.SH NAME +sort \- sort lines +.SH SYNOPSIS +.B sort +.RB [ \-r ] +.RI [ file ...] +.SH DESCRIPTION +.B sort +writes the sorted concatenation of the given files to stdout. If no file is +given, sort reads from stdin. +.SH OPTIONS +.TP +.BI \-r +reverses the sort. diff --git a/sort.c b/sort.c @@ -0,0 +1,71 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "text.h" +#include "util.h" + +static int linecmp(const char **, const char **); +static void getlines(FILE *, const char *); + +static bool rflag = false; +static char **lines = NULL; +static long nlines = 0; + +int +main(int argc, char *argv[]) +{ + char c; + long i; + FILE *fp; + + while((c = getopt(argc, argv, "r")) != -1) + switch(c) { + case 'r': + rflag = true; + break; + default: + exit(EXIT_FAILURE); + } + if(optind == argc) + getlines(stdin, "<stdin>"); + else for(; optind < argc; optind++) { + if(!(fp = fopen(argv[optind], "r"))) + eprintf("fopen %s:", argv[optind]); + getlines(fp, argv[optind]); + fclose(fp); + } + qsort(lines, nlines, sizeof *lines, (int (*)(const void *, const void *))linecmp); + + for(i = 0; i < nlines; i++) { + fputs(lines[i], stdout); + free(lines[i]); + } + free(lines); + + return EXIT_SUCCESS; +} + +void +getlines(FILE *fp, const char *str) +{ + char *line = NULL; + size_t size = 0; + + while(afgets(&line, &size, fp)) { + if(!(lines = realloc(lines, ++nlines * sizeof *lines))) + eprintf("realloc:"); + if(!(lines[nlines-1] = malloc(strlen(line)+1))) + eprintf("malloc:"); + strcpy(lines[nlines-1], line); + } + free(line); +} + +int +linecmp(const char **a, const char **b) +{ + return strcmp(*a, *b) * (rflag ? -1 : +1); +}