/*
 * Copyright (C) 2000-2002 ASANO Masahiro
 */

#include <sys/types.h>
#include <unistd.h>
#include "crash.h"
/*#include <linux/tasks.h>*/

PRIVATE addr_t task(), fs_struct(), mm_struct(), files_struct();
const commandtable_t command_task_struct =
	{"task_struct", task, "[-f] [address]", "print task_struct table"};
const commandtable_t command_fs_struct =
	{"fs_struct", fs_struct, "address", "print fs_struct table"};
const commandtable_t command_mm_struct =
	{"mm_struct", mm_struct, "[-v] address", "print mm_struct table\n  -v  show vm_area_struct"};
const commandtable_t command_files_struct =
	{"files_struct", files_struct, "address", "print files_struct table"};

extern addr_t print_task();
extern addr_t print_fs_struct();
extern addr_t print_mm_struct();
extern addr_t print_files_struct();

addr_t init_task_addr;

PRIVATE addr_t
task()
{
	int i, c;
	int full = 0, sw = 0;
	addr_t addr = 0;
	extern void prhead_task();

	while ((c = getopt(argcnt, args, "fn:")) != EOF) {
		switch (c) {
		case 'f':
			full = 1;
			break;
		case 'n':
			sw = strtol(optarg, NULL, 0);
			break;
		default:
			THROW(usage);
		}
	}

	if (!full) prhead_task(sw);
	if (argcnt > optind) {
		for (i = optind; i < argcnt; i++) {
			addr = getaddr(args[i]);
			if (full) prhead_task(sw);
			addr = print_task(addr, full, sw);
		}
	} else {
		GETADDR(init_task);
		addr = init_task_addr;
		do {
			if (full) prhead_task(sw);
			addr = print_task(addr, full, sw);
		} while (addr != init_task_addr);
	}
	if (!full) prhead_task(sw);
	return addr;
}

PRIVATE addr_t
fs_struct()
{
	int c;

	while ((c = getopt(argcnt, args, "")) != EOF) {
		THROW(usage);
	}

	if (argcnt == optind) {
		THROW(usage);
	}
	while (args[optind]) {
		(void)print_fs_struct(getaddr(args[optind]));
		optind++;
	}
	return 0;
}

PRIVATE addr_t
mm_struct()
{
	int c;
	int vflag = 0;
	addr_t addr = 0;

	while ((c = getopt(argcnt, args, "v")) != EOF) {
		switch (c) {
		case 'v':
			vflag = 1;
			break;
		default:
			THROW(usage);
		}
	}

	if (argcnt == optind) {
		THROW(usage);
	}
	while (args[optind]) {
		addr = print_mm_struct(getaddr(args[optind]), vflag);
		optind++;
	}
	return addr;
}

PRIVATE addr_t
files_struct()
{
	int c;

	while ((c = getopt(argcnt, args, "")) != EOF) {
		THROW(usage);
	}

	if (argcnt == optind) {
		THROW(usage);
	}
	while (args[optind]) {
		(void)print_files_struct(getaddr(args[optind]));
		optind++;
	}
	return 0;
}
