#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <error.h>
#include <string.h>
#include "attr-sets.h"
#include "process.h"

/*
 * require_uid - ensure a collected attribute set contains a specific UID
 * @set: attribute set generated by read_proc_status()
 * @uid: numeric user identifier expected in the set
 * @label: description for error reporting when the lookup fails
 */
static void require_uid(attr_sets_entry_t *set, unsigned int uid,
			const char *label)
{
	if (!attr_set_check_int(set, (int64_t)uid))
		error(1, 0, "%s uid %u not found", label, uid);
}

/*
 * main - validate UID collection helper records credential variants
 *
 * Return: 0 when all expected user IDs are reported, or terminate via error()
 * if any lookup fails during the exercise.
 */
int main(void)
{
	struct proc_status_info info = {
		.ppid = -1,
		.uid = NULL,
		.groups = NULL,
		.comm = NULL
	};
	attr_sets_entry_t *uids;
	FILE *status;
	char buf[4096];
	int saw_uid_line = 0;

	if (read_proc_status(getpid(), PROC_STAT_UID, &info) != 0)
		error(1, 0, "Unable to obtain uid set");

	uids = info.uid;
	info.uid = NULL;

	if (!uids)
		error(1, 0, "Unable to obtain uid set");

	status = fopen("/proc/self/status", "rt");
	if (!status)
		error(1, errno, "fopen /proc/self/status");

	while (fgets(buf, sizeof(buf), status)) {
		if (memcmp(buf, "Uid:", 4) == 0) {
			unsigned int real_uid = 0, eff_uid = 0;
			unsigned int saved_uid = 0, fs_uid = 0;
			int fields = sscanf(buf, "Uid: %u %u %u %u",
					    &real_uid, &eff_uid,
					    &saved_uid, &fs_uid);

			if (fields >= 1)
				require_uid(uids, real_uid, "Real");
			if (fields >= 2)
				require_uid(uids, eff_uid, "Effective");
//			if (fields >= 3)
//				require_uid(uids, saved_uid, "Saved");
			if (fields >= 4)
				require_uid(uids, fs_uid, "Filesystem");
			saw_uid_line = 1;
			break;
		}
	}

	fclose(status);

	if (!saw_uid_line)
		error(1, 0, "Uid line not found in /proc/self/status");

	attr_set_destroy(uids);

	return 0;
}
