diff --git a/Makefile b/Makefile index 9523e5f..3640757 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,27 @@ include config.mk -SRC = basename.c cat.c date.c echo.c false.c grep.c pwd.c rm.c sleep.c tee.c touch.c true.c wc.c -OBJ = $(SRC:.c=.o) util.o +LIB = util/enmasse.o util/eprintf.o +SRC = basename.c cat.c date.c echo.c false.c grep.c ln.c pwd.c rm.c sleep.c tee.c touch.c true.c wc.c +OBJ = $(SRC:.c=.o) $(LIB) BIN = $(SRC:.c=) MAN = $(SRC:.c=.1) all: $(BIN) $(OBJ): util.h -$(BIN): util.o +$(BIN): util.a .o: @echo CC -o $@ - @$(CC) -o $@ $< util.o $(LDFLAGS) + @$(CC) -o $@ $< util.a $(LDFLAGS) .c.o: @echo CC -c $< - @$(CC) -c $< $(CFLAGS) + @$(CC) -c -o $@ $< $(CFLAGS) + +util.a: $(LIB) + @echo AR rc $@ + @$(AR) rc $@ $(LIB) dist: clean @echo creating dist tarball @@ -28,4 +33,4 @@ dist: clean clean: @echo cleaning - @rm -f $(BIN) $(OBJ) + @rm -f $(BIN) $(OBJ) $(LIB) util.a diff --git a/config.mk b/config.mk index 375d87f..4436e7b 100644 --- a/config.mk +++ b/config.mk @@ -4,6 +4,8 @@ VERSION = 0.0 #CC = cc CC = musl-gcc +AR = ar + CPPFLAGS = -D_BSD_SOURCE CFLAGS = -Os -ansi -Wall -pedantic $(CPPFLAGS) LDFLAGS = -s -static diff --git a/ln.1 b/ln.1 new file mode 100644 index 0000000..6f00abb --- /dev/null +++ b/ln.1 @@ -0,0 +1,22 @@ +.TH LN 1 sbase\-VERSION +.SH NAME +ln \- make links between files +.SH SYNOPSIS +.B ln +.RB [ \-s ] +.I file +.RI [ name ] +.P +.B ln +.RB [ \-s ] +.RI [ files ...] +.RI [ directory ] +.SH DESCRIPTION +.B ln +creates a hard link to a given file, with the given name. If no name is given +it is linked into the current directory. If multiple files are listed they will +be linked into the given directory. +.SH OPTIONS +.TP +.B \-s +create a symbolic link. diff --git a/ln.c b/ln.c new file mode 100644 index 0000000..e61bb7c --- /dev/null +++ b/ln.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include "util.h" + +int +main(int argc, char *argv[]) +{ + bool sflag = false; + char c; + + while((c = getopt(argc, argv, "s")) != -1) + switch(c) { + case 's': + sflag = true; + break; + default: + exit(EXIT_FAILURE); + } + enmasse(argc - optind, &argv[optind], sflag ? symlink : link); + return EXIT_SUCCESS; +} diff --git a/util.h b/util.h index 9966622..ad0b4f7 100644 --- a/util.h +++ b/util.h @@ -1,3 +1,4 @@ /* See LICENSE file for copyright and license details. */ +void enmasse(int, char **, int (*)(const char *, const char *)); void eprintf(const char *, ...); diff --git a/util/enmasse.c b/util/enmasse.c new file mode 100644 index 0000000..d259cd3 --- /dev/null +++ b/util/enmasse.c @@ -0,0 +1,38 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include "../util.h" + +void +enmasse(int argc, char **argv, int (*fn)(const char *, const char *)) +{ + char *buf, *dir; + int i; + long size; + struct stat st; + + if(argc == 2 && !(stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode))) { + if(fn(argv[0], argv[1]) != 0) + eprintf("%s:", argv[1]); + return; + } + else if(argc == 1) + dir = "."; + else + dir = argv[--argc]; + + if((size = pathconf(dir, _PC_PATH_MAX)) < 0) + size = BUFSIZ; + if(!(buf = malloc(size))) + eprintf("malloc:"); + for(i = 0; i < argc; i++) { + snprintf(buf, size, "%s/%s", dir, basename(argv[i])); + if(fn(argv[i], buf) != 0) + eprintf("%s:", buf); + } + free(buf); +} diff --git a/util.c b/util/eprintf.c similarity index 94% rename from util.c rename to util/eprintf.c index eb3006d..60da3e8 100644 --- a/util.c +++ b/util/eprintf.c @@ -3,7 +3,7 @@ #include #include #include -#include "util.h" +#include "../util.h" void eprintf(const char *fmt, ...)