/*-
 * Copyright (c) 2023 Mateusz Guzik
 *
 * Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that the
 * following conditions are met:
 *
 * 1. Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions and
 *    the following disclaimer in the documentation and/or
 *    other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */

/*
 * _XOPEN_SOURCE hides _SC_NPROCESSORS_* on some BSDs
 */
/* #define _XOPEN_SOURCE 700 */

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <getopt.h>

#ifndef _SC_NPROCESSORS_CONF
#error "_SC_NPROCESSORS_CONF not defined, system incompatible"
#endif

#ifndef _SC_NPROCESSORS_ONLN
#error "_SC_NPROCESSORS_ONLN not defined, system incompatible"
#endif

static void
usage(const char* progname)
{
	fprintf(stderr, "usage: %s [-a] [-i #]\n", progname);
	exit(2);
}

int
main(int argc, char *argv[])
{
	char *progname;
	char *endptr;
	int ch, all;
	long ignore, cpus;

	ignore = 0;
	all = 0;
	
	progname = argv[0];
	while ((ch = getopt(argc, argv, "ai:")) >= 0) {
		switch (ch) {
		case 'a':
			all = 1;
			break;
		case 'i':
			ignore = strtol(optarg, &endptr, 10);
			if (ignore < 0 || *endptr || errno) {
				fprintf(stderr, "%s: bad ignore count: %s\n",
				        progname, optarg);
				exit(2);
			}
			break;
		default:
			usage(progname);
		}
	}

	argc -= optind;
	argv += optind;

	if (argc)
		usage(progname);
	
	if (all)
		cpus = sysconf(_SC_NPROCESSORS_CONF);
	else
		cpus = sysconf(_SC_NPROCESSORS_ONLN);

	if (cpus < 0) {
		fprintf(stderr, "%s: sysconf: %s", progname, strerror(errno));
		exit(1);
	}

	if (ignore >= cpus)
		cpus = 1;
	else
		cpus -= ignore;

	printf("%li\n", cpus);

	return 0;
}
