finger

finger fortune@hhvn.uk
git clone https://hhvn.uk/finger
git clone git://hhvn.uk/finger
Log | Files | Refs | LICENSE

finger.c (2716B)


      1 /* Copyright (c) 2021 hhvn <dev@hhvn.uk> */
      2 
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 #include <stdarg.h>
      7 #include <libgen.h>
      8 #include <unistd.h>
      9 #include <netdb.h>
     10 #include <errno.h>
     11 #include <sys/types.h>
     12 #include <sys/socket.h>
     13 #include "arg.h"
     14 
     15 #define EXIT_USAGE 2
     16 #ifndef __OpenBSD__
     17 #define pledge(a,b) 0
     18 #endif
     19 
     20 enum { ISUSER, ISHOST, ISPORT };
     21 char *user_dflt = "";
     22 char *host_dflt = "localhost";
     23 char *port_dflt = "79";
     24 
     25 char *argv0;
     26 int verbose = 0;
     27 
     28 void
     29 usage(void) {
     30 	fprintf(stderr, "usage: %s [-lv] [user]@[host[:port]] ...\n", basename(argv0));
     31 	exit(EXIT_USAGE);
     32 }
     33 
     34 void 
     35 die(const int exitc, const char *format, ...) {
     36 	va_list ap;
     37 
     38 	va_start(ap, format);
     39 	fprintf(stderr, "Fatal: ");
     40 	vfprintf(stderr, format, ap);
     41 	va_end(ap);
     42 
     43 	exit(exitc);
     44 }
     45 
     46 void
     47 finger(char *user, char *host, char *port, int w) {
     48 	struct addrinfo hints;
     49 	struct addrinfo *ai;
     50 	char buf;
     51 	int sret, sock;
     52 
     53 	memset(&hints, 0, sizeof(hints));
     54 	hints.ai_family = AF_UNSPEC;
     55 	hints.ai_socktype = SOCK_STREAM;
     56 
     57 	if ((sret = getaddrinfo(host, port, &hints, &ai)) != 0 || ai == NULL)
     58 		die(1, "%s%s: %s:%s\n", verbose ? "getaddrinfo(): " : "", gai_strerror(sret), host, port);
     59 	if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == 1)
     60 		die(1, "%s%s: %s:%s\n", verbose ? "socket(): " : "", strerror(errno), host, port);
     61 	if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1)
     62 		die(1, "%s%s: %s:%s\n", verbose ? "connect(): " : "", strerror(errno), host, port);
     63 
     64 	freeaddrinfo(ai);
     65 	
     66 	if (strcmp(port, "79") == 0)
     67 		printf("[%s@%s]\n", user, host);
     68 	else
     69 		printf("[%s@%s:%s]\n", user, host, port);
     70 
     71 	dprintf(sock, "%s\r\n", user);
     72 	while (read(sock, &buf, sizeof(char)) != 0)
     73 		if (buf != '\r')
     74 			printf("%c", buf);
     75 
     76 	printf("\n"); /* add extra newline */
     77 }
     78 
     79 int
     80 main(int argc, char *argv[]) {
     81 	char *user,
     82 	     *host,
     83 	     *port;
     84 	int sendw = 0;
     85 	int segment;
     86 	int i;
     87 
     88 	ARGBEGIN {
     89 	case 'l':
     90 		sendw = 1;
     91 		break;
     92 	case 'v':
     93 		verbose = 1;
     94 		break;
     95 	default:
     96 		usage();
     97 	} ARGEND;
     98 
     99 	if (pledge("stdio inet dns", NULL) == -1)
    100 		die(1, "pledge: %s\n", strerror(errno));
    101 
    102 	if (argc < 1)
    103 		die(1, "no targets specified\n");
    104 
    105 	for (i=0; i < argc; i++) {
    106 		user = user_dflt;
    107 		host = host_dflt;
    108 		port = port_dflt;
    109 
    110 		segment = ISUSER;
    111 		user = argv[i];
    112 		for (; argv[i] && *argv[i]; argv[i]++) {
    113 			if (segment == ISUSER && *argv[i] == '@') {
    114 				*argv[i] = '\0';
    115 				host = argv[i]+1;
    116 				segment = ISHOST;
    117 			}
    118 			if (segment == ISHOST && *argv[i] == ':') {
    119 				*argv[i] = '\0';
    120 				port = argv[i]+1;
    121 				segment = ISPORT;
    122 			}
    123 		}
    124 
    125 		if (host[0] == '\0')
    126 			die(1, "no hostname\n");
    127 		if (port[0] == '\0')
    128 			die(1, "no port\n");
    129 		finger(user, host, port, sendw);
    130 	}
    131 
    132 	return EXIT_SUCCESS;
    133 }