sbase

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

commit f66b47bc6f7ce63409855668d0d1550b83638609
parent 4d38f6068500104693796059da3950a2de296af3
Author: stateless <stateless@archlinux.us>
Date:   Sat Jun 15 15:17:57 +0100

Add readlink

Signed-off-by: Christoph Lohmann <20h@r-36.net>

Diffstat:
Makefile | 1+
readlink.1 | 25+++++++++++++++++++++++++
readlink.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile @@ -51,6 +51,7 @@ SRC = \ paste.c \ printenv.c \ pwd.c \ + readlink.c \ renice.c \ rm.c \ rmdir.c \ diff --git a/readlink.1 b/readlink.1 @@ -0,0 +1,25 @@ +.TH READLINK 1 sbase\-VERSION +.SH NAME +readlink \- print value of a symbolic link or canonical file name +.SH SYNOPSIS +.B readlink +.RB [ \-fn ] +.IR file +.SH DESCRIPTION +The readlink utility when invoked with the pathname of a symbolic link as +its argument dereferences the symbolic link and prints the name of target +on standard output. If the -f option is not specified and readlink is +invoked with an argument other than the pathname of a symbolic link, it +exits with a nonzero exit code without printing anything. +.SH OPTIONS +.TP +.B \-f +Canonicalize by following every symlink in every component of the +given path recursively. The argument does not need to be a symbolic +link. +.TP +.B \-n +Do not output the trailing newline. +.SH SEE ALSO +.IR readlink (2), +.IR realpath (3) diff --git a/readlink.c b/readlink.c @@ -0,0 +1,55 @@ +/* See LICENSE file for copyright and license details. */ +#include <unistd.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "util.h" + +static void +usage(void) +{ + eprintf("usage: %s [-fn] file\n", argv0); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char buf[PATH_MAX]; + bool nflag = false; + bool fflag = false; + + ARGBEGIN { + case 'f': + fflag = true; + break; + case 'n': + nflag = true; + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + if (strlen(argv[0]) > PATH_MAX - 1) + exit(1); + + if (fflag) { + if (realpath(argv[0], buf) == NULL) + exit(1); + } else { + if (readlink(argv[0], buf, sizeof(buf)) < 0) + exit(1); + } + + printf("%s", buf); + if (!nflag) + putchar('\n'); + + return 0; +}