coreutils

General Software Utilities
git clone http://git.omkov.net/coreutils
Log | Tree | Refs | README | LICENCE | Download

coreutils/src/rand.c (107 lines, 2.8 KiB) -rw-r--r-- blame download

0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
// rand.c, version 1.0.1
// OMKOV coreutils rand
// Copyright (C) 2020, Jakob Wakeling
// MIT Licence

#include "util/error.h"
#include "util/optget.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define VERSION "1.0.1"

#define aSIZE (sizeof (aset) - 1)
#define ASIZE (sizeof (Aset) - 1)
#define nSIZE (sizeof (nset) - 1)
#define sSIZE (sizeof (sset) - 1)

static struct lop lops[] = {
	{ "help",    ARG_NUL, 256 },
	{ "version", ARG_NUL, 257 },
	{ NULL, 0, 0 }
};

static const char aset[] = "abcdefghijklmnopqrstuvwxyz";
static const char Aset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char nset[] = "0123456789";
static const char sset[] = "!@#$%^&*";

static int       mode;
static uintmax_t len;

static void hlp(void);
static void ver(void);

int main(int ac, char *av[]) { A0 = av[0];
	struct opt opt = OPTGET_INIT; opt.str = "aAns"; opt.lops = lops;
	for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) {
	case 'a': { mode |= 1; break; }
	case 'A': { mode |= 2; break; }
	case 'n': { mode |= 4; break; }
	case 's': { mode |= 8; break; }
	case 256: { hlp(); return 0; }
	case 257: { ver(); return 0; }
	default: { return 1; }
	}
	
	if (!mode) { mode = 6; }
	if (opt.ind == ac) { len = 8; }
	else {
		register uintmax_t d; register char *p = av[opt.ind];
		for (; *p >= '0' && *p <= '9'; ++p) {
			d = (uintmax_t)*p - '0';
			if (len > (UINTMAX_MAX - d) / 10) { break; }
			len = len * 10 + d;
		}
		
		if (*p) { error(1, "%s: invalid length", av[opt.ind]); }
	}
	
	FILE *rand; char *set; unsigned setlen = 0, n;
	if (!(rand = fopen("/dev/urandom", "r"))) {
		error(1, "%s: %s", "/dev/urandom", serr());
	}
	
	if (mode & 1) { setlen += aSIZE; }
	if (mode & 2) { setlen += ASIZE; }
	if (mode & 4) { setlen += nSIZE; }
	if (mode & 8) { setlen += sSIZE; }
	
	if (!(set = (char *)malloc(setlen + 1))) {
		fclose(rand); error(1, "%s", serr());
	}
	
	if (mode & 1) { strcat(set, aset); }
	if (mode & 2) { strcat(set, Aset); }
	if (mode & 4) { strcat(set, nset); }
	if (mode & 8) { strcat(set, sset); }
	
	for (uintmax_t i = 0; i < len; ++i) {
		fread(&n, sizeof (unsigned long), 1, rand); n %= setlen;
		fputc(set[n], stdout);
	} fputc('\n', stdout);
	
	fclose(rand); free(set); return 0;
}

static void hlp(void) {
	puts("rand - generate random string\n");
	puts("usage: rand [-aAns] [length]\n");
	puts("options:");
	puts("  -a         Enable lowercase letters in the string output");
	puts("  -A         Enable uppercase letters in the string output");
	puts("  -n         Enable numbers in the string output");
	puts("  -s         Enable symbols '!@#$%^&*' in the string output");
	puts("  --help     Display help information");
	puts("  --version  Display version information");
}

static void ver(void) {
	puts("OMKOV coreutils rand, version " VERSION);
	puts("Copyright (C) 2020, Jakob Wakeling");
	puts("MIT Licence (https://opensource.org/licenses/MIT)");
}