/*
 * Copyright (C) 2011 Davidlohr Bueso <dave@gnu.org>
 *
 * procutils.c: General purpose procfs parsing utilities
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library Public License for more details.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>

#include "procutils.h"
#include "at.h"
#include "c.h"

/*
 * @pid: process ID for which we want to obtain the threads group
 *
 * Returns: newly allocated tasks structure
 */
struct proc_tasks *proc_open_tasks(pid_t pid)
{
	struct proc_tasks *tasks;
	char path[PATH_MAX];

	sprintf(path, "/proc/%d/task/", pid);

	tasks = malloc(sizeof(struct proc_tasks));
	if (tasks) {
		tasks->dir = opendir(path);
		if (tasks->dir)
			return tasks;
	}

	free(tasks);
	return NULL;
}

/*
 * @tasks: allocated tasks structure
 *
 * Returns: nothing
 */
void proc_close_tasks(struct proc_tasks *tasks)
{
	if (tasks && tasks->dir)
		closedir(tasks->dir);
	free(tasks);
}

/*
 * @tasks: allocated task structure
 * @tid: [output] one of the thread IDs belonging to the thread group
 *        If when an error occurs, it is set to 0.
 *
 * Returns: 0 on success, 1 on end, -1 on failure or no more threads
 */
int proc_next_tid(struct proc_tasks *tasks, pid_t *tid)
{
	struct dirent *d;
	char *end;

	if (!tasks || !tid)
		return -EINVAL;

	*tid = 0;
	errno = 0;

	do {
		d = readdir(tasks->dir);
		if (!d)
			return errno ? -1 : 1;		/* error or end-of-dir */

		if (!isdigit((unsigned char) *d->d_name))
			continue;
		errno = 0;
		*tid = (pid_t) strtol(d->d_name, &end, 10);
		if (errno || d->d_name == end || (end && *end))
			return -1;

	} while (!*tid);

	return 0;
}

struct proc_processes *proc_open_processes(void)
{
	struct proc_processes *ps;

	ps = calloc(1, sizeof(struct proc_processes));
	if (ps) {
		ps->dir = opendir("/proc");
		if (ps->dir)
			return ps;
	}

	free(ps);
	return NULL;
}

void proc_close_processes(struct proc_processes *ps)
{
	if (ps && ps->dir)
		closedir(ps->dir);
	free(ps);
}

void proc_processes_filter_by_name(struct proc_processes *ps, const char *name)
{
	ps->fltr_name = name;
	ps->has_fltr_name = name ? 1 : 0;
}

void proc_processes_filter_by_uid(struct proc_processes *ps, uid_t uid)
{
	ps->fltr_uid = uid;
	ps->has_fltr_uid = 1;
}

int proc_next_pid(struct proc_processes *ps, pid_t *pid)
{
	struct dirent *d;

	if (!ps || !pid)
		return -EINVAL;

	*pid = 0;
	errno = 0;

	do {
		char buf[BUFSIZ], *p;

		d = readdir(ps->dir);
		if (!d)
			return errno ? -1 : 1;		/* error or end-of-dir */


		if (!isdigit((unsigned char) *d->d_name))
			continue;

		/* filter out by UID */
		if (ps->has_fltr_uid) {
			struct stat st;

			if (fstat_at(dirfd(ps->dir), "/proc", d->d_name, &st, 0))
				continue;
			if (ps->fltr_uid != st.st_uid)
				continue;
		}

		/* filter out by NAME */
		if (ps->has_fltr_name) {
			char procname[256];
			FILE *f;

			snprintf(buf, sizeof(buf), "%s/stat", d->d_name);
			f = fopen_at(dirfd(ps->dir), "/proc", buf,
						O_CLOEXEC|O_RDONLY, "r");
			if (!f)
				continue;

			p = fgets(buf, sizeof(buf), f);
			fclose(f);
			if (!p)
				continue;

			if (sscanf(buf, "%*d (%255[^)])", procname) != 1)
				continue;

			/* ok, we got the process name. */
			if (strcmp(procname, ps->fltr_name) != 0)
				continue;
		}

		p = NULL;
		errno = 0;
		*pid = (pid_t) strtol(d->d_name, &p, 10);
		if (errno || d->d_name == p || (p && *p))
			return errno ? -errno : -1;

		return 0;
	} while (1);

	return 0;
}

#ifdef TEST_PROGRAM

static int test_tasks(int argc, char *argv[])
{
	pid_t tid, pid;
	struct proc_tasks *ts;

	if (argc != 2)
		return EXIT_FAILURE;

	pid = strtol(argv[1], (char **) NULL, 10);
	printf("PID=%d, TIDs:", pid);

	ts = proc_open_tasks(pid);
	if (!ts)
		err(EXIT_FAILURE, "open list of tasks failed");

	while (proc_next_tid(ts, &tid) == 0)
		printf(" %d", tid);

	printf("\n");
        proc_close_tasks(ts);
	return EXIT_SUCCESS;
}

static int test_processes(int argc, char *argv[])
{
	pid_t pid;
	struct proc_processes *ps;

	ps = proc_open_processes();
	if (!ps)
		err(EXIT_FAILURE, "open list of processes failed");

	if (argc >= 3 && strcmp(argv[1], "--name") == 0)
		proc_processes_filter_by_name(ps, argv[2]);

	if (argc >= 3 && strcmp(argv[1], "--uid") == 0)
		proc_processes_filter_by_uid(ps, (uid_t) atol(argv[2]));

	while (proc_next_pid(ps, &pid) == 0)
		printf(" %d", pid);

	printf("\n");
        proc_close_processes(ps);
	return EXIT_SUCCESS;
}

int main(int argc, char *argv[])
{
	if (argc < 2) {
		fprintf(stderr, "usage: %1$s --tasks <pid>\n"
				"       %1$s --processes [---name <name>] [--uid <uid>]\n",
				program_invocation_short_name);
		return EXIT_FAILURE;
	}

	if (strcmp(argv[1], "--tasks") == 0)
		return test_tasks(argc - 1, argv + 1);
	if (strcmp(argv[1], "--processes") == 0)
		return test_processes(argc - 1, argv + 1);

	return EXIT_FAILURE;
}
#endif /* TEST_PROGRAM */
