commit 2a49d14fd2c0c0dee69084fde6f8ab8716cd235d
Author: hhvn <dev@hhvn.uk>
Date: Sun, 6 Jun 2021 16:17:16 +0100
finger.c makefile arg.h strlcpy.c: init
Diffstat:
A | arg.h | | | 70 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | finger.c | | | 150 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | makefile | | | 24 | ++++++++++++++++++++++++ |
A | strlcpy.c | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 296 insertions(+), 0 deletions(-)
diff --git a/arg.h b/arg.h
@@ -0,0 +1,70 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ *
+ * 2012-2016 Christoph Lohmann <20h at r-36 dot net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][0] == '-'\
+ && argv[0][1];\
+ argc--, argv++) {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ int i_;\
+ for (i_ = 1, brk_ = 0, argv_ = argv;\
+ argv[0][i_] && !brk_;\
+ i_++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][i_];\
+ switch (argc_)
+
+#define ARGEND }\
+ }
+
+#define ARGC() argc_
+
+#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][i_+1] != '\0')?\
+ (&argv[0][i_+1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][i_+1] != '\0')?\
+ (&argv[0][i_+1]) :\
+ (argc--, argv++, argv[0])))
+
+#endif
diff --git a/finger.c b/finger.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "arg.h"
+
+#define EXIT_USAGE 2
+#define USER_DFLT ""
+#define HOST_DFLT "localhost"
+#define PORT_DFLT "79"
+
+enum { ISUSER, ISHOST, ISPORT };
+
+char *argv0;
+int verbose = 0;
+
+void
+usage(void) {
+ fprintf(stderr, "usage: %s [-lv] [user]@[host[:port]] ...\n", basename(argv0));
+ exit(EXIT_USAGE);
+}
+
+int
+die(const int exitc, const char *format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "Fatal: ");
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+
+ exit(exitc);
+}
+
+int
+read_line(int fd, char *dest, size_t len) {
+ size_t i = 0;
+ char c = 0;
+
+ do {
+ if (read(fd, &c, sizeof(char)) != sizeof(char))
+ return 0;
+ if (c != '\r')
+ dest[i++] = c;
+ } while (c != '\n' && i < len);
+
+ dest[i-1] = '\0';
+ return 1;
+}
+
+void
+finger(char *user, char *host, char *port, int w) {
+ struct addrinfo hints;
+ struct addrinfo *ai;
+ char buf[1024];
+ int sret, sock;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((sret = getaddrinfo(host, port, &hints, &ai)) != 0 || ai == NULL)
+ die(1, "%s%s\n", verbose ? "getaddrinfo(): " : "", gai_strerror(sret));
+ if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == 1)
+ die(1, "%s%s\n", verbose ? "socket(): " : "", strerror(errno));
+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1)
+ die(1, "%s%s\n", verbose ? "connect(): " : "", strerror(errno));
+
+ if (strcmp(port, "79") == 0)
+ printf("[%s@%s]\n", user, host);
+ else
+ printf("[%s@%s:%s]\n", user, host, port);
+
+ dprintf(sock, "%s\r\n", user);
+ while (read_line(sock, buf, sizeof(buf)) != 0)
+ printf("%s\n", buf);
+ return;
+}
+
+int
+main(int argc, char *argv[]) {
+ char user[128],
+ host[128],
+ port[128];
+ int sendw = 0;
+ int segment;
+ int i, j, k;
+
+ ARGBEGIN {
+ case 'l':
+ sendw = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc < 1)
+ die(1, "no targets specified\n");
+
+ for (i=0; i < argc; i++) {
+ segment = ISUSER;
+ for (j=k=0; argv[i] && argv[i][k]; j++, k++) {
+ switch (segment) {
+ case ISUSER:
+ if (argv[i][k] == '@') {
+ if (argv[i][k+1] == '\0' || argv[i][k+1] == ':')
+ die(1, "missing hostname in: %s\n", argv[i]);
+ user[j] = '\0';
+ segment++;
+ j = -1;
+ } else {
+ user[j] = argv[i][k];
+ }
+ break;
+ case ISHOST:
+ if (argv[i][k] == ':') {
+ if (argv[i][k+1] == '\0')
+ die(1, "missing port in: %s\n", argv[i]);
+ host[j] = '\0';
+ segment++;
+ j = -1;
+ } else {
+ host[j] = argv[i][k];
+ }
+ break;
+ case ISPORT:
+ port[j] = argv[i][k];
+ }
+ }
+
+ /* set defaults */
+ switch (segment) {
+ case ISUSER: strlcpy(host, HOST_DFLT, sizeof(host));
+ case ISHOST: strlcpy(port, PORT_DFLT, sizeof(port));
+ }
+
+ finger(user, host, port, sendw);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/makefile b/makefile
@@ -0,0 +1,24 @@
+PREFIX = /usr/local
+CC ?= cc
+OBJ = finger.o strlcpy.o
+BIN = finger
+COMMIT = `git log HEAD...HEAD~1 --pretty=format:%h`
+
+$(BIN): $(OBJ)
+ $(CC) -g $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ)
+
+.c.o:
+ $(CC) -g $(CFLAGS) $(LDFLAGS) -o $@ -c $<
+
+clean:
+ rm $(BIN) $(OBJ)
+
+install: $(BIN)
+ install -m0755 $(BIN) $(PREFIX)/bin/$(BIN)
+ sed "s/COMMIT/$(COMMIT)/" \
+ < $(BIN).8 \
+ > $(PREFIX)/share/man/man8/$(BIN).8
+
+uninstall:
+ -rm $(PREFIX)/bin/$(BIN)
+ -rm $(PREFIX)/share/man/man8/$(BIN).8
diff --git a/strlcpy.c b/strlcpy.c
@@ -0,0 +1,52 @@
+#ifndef __OpenBSD__
+/* $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $ */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy string src to buffer dst of size dsize. At most dsize-1
+ * chars will be copied. Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t dsize)
+{
+ const char *osrc = src;
+ size_t nleft = dsize;
+
+ /* Copy as many bytes as will fit. */
+ if (nleft != 0) {
+ while (--nleft != 0) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src. */
+ if (nleft == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+
+ return(src - osrc - 1); /* count does not include NUL */
+}
+#endif