109d6a582SIngo Weinhold/*
209d6a582SIngo Weinhold * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
309d6a582SIngo Weinhold * Distributed under the terms of the MIT License.
409d6a582SIngo Weinhold */
509d6a582SIngo Weinhold
609d6a582SIngo Weinhold
709d6a582SIngo Weinhold#include <stdio.h>
809d6a582SIngo Weinhold#include <stdlib.h>
909d6a582SIngo Weinhold#include <string.h>
1009d6a582SIngo Weinhold
1109d6a582SIngo Weinhold#include <OS.h>
1209d6a582SIngo Weinhold
1309d6a582SIngo Weinhold#include <system_info.h>
1409d6a582SIngo Weinhold#include <util/KMessage.h>
1509d6a582SIngo Weinhold
1609d6a582SIngo Weinhold
1709d6a582SIngo Weinholdextern const char* __progname;
1809d6a582SIngo Weinhold
1909d6a582SIngo Weinhold
2009d6a582SIngo Weinholdstatic void
2109d6a582SIngo Weinholdprint_usage(bool error)
2209d6a582SIngo Weinhold{
2309d6a582SIngo Weinhold	fprintf(error ? stderr : stdout,
2409d6a582SIngo Weinhold		"Usage: %s [ <teamID> [ <events> ] ]\n"
2509d6a582SIngo Weinhold		"  teamID  - The team ID of the team to watch or -1 for all teams\n"
2609d6a582SIngo Weinhold		"            (-1 is the default).\n"
2709d6a582SIngo Weinhold		"  events  - A string specifying the events to watch, consisting of:\n"
2809d6a582SIngo Weinhold		"            'C': team creation\n"
2909d6a582SIngo Weinhold		"            'D': team deletion\n"
3009d6a582SIngo Weinhold		"            'c': thread creation\n"
3109d6a582SIngo Weinhold		"            'd': thread deletion\n"
3209d6a582SIngo Weinhold		"            'p': thread properties\n"
3309d6a582SIngo Weinhold		"            The default is all events.\n",
3409d6a582SIngo Weinhold		__progname);
3509d6a582SIngo Weinhold}
3609d6a582SIngo Weinhold
3709d6a582SIngo Weinhold
3809d6a582SIngo Weinholdstatic void
3909d6a582SIngo Weinholdprint_usage_and_exit(bool error)
4009d6a582SIngo Weinhold{
4109d6a582SIngo Weinhold	print_usage(error);
4209d6a582SIngo Weinhold	exit(error ? 1 : 0);
4309d6a582SIngo Weinhold}
4409d6a582SIngo Weinhold
4509d6a582SIngo Weinhold
4609d6a582SIngo Weinholdint
4709d6a582SIngo Weinholdmain(int argc, const char* const* argv)
4809d6a582SIngo Weinhold{
4909d6a582SIngo Weinhold	int32 watchTeam = -1;
5009d6a582SIngo Weinhold	uint32 watchEvents = B_WATCH_SYSTEM_ALL;
5109d6a582SIngo Weinhold
5209d6a582SIngo Weinhold	if (argc > 3)
5309d6a582SIngo Weinhold		print_usage_and_exit(true);
5409d6a582SIngo Weinhold
5509d6a582SIngo Weinhold	if (argc > 1) {
5609d6a582SIngo Weinhold		const char* arg = argv[1];
5709d6a582SIngo Weinhold		if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
5809d6a582SIngo Weinhold			print_usage_and_exit(false);
5909d6a582SIngo Weinhold
6009d6a582SIngo Weinhold		// first parameter is the team ID
6109d6a582SIngo Weinhold		watchTeam = atol(arg);
6209d6a582SIngo Weinhold
6309d6a582SIngo Weinhold		if (argc > 2) {
6409d6a582SIngo Weinhold			// second parameter is the events string
6509d6a582SIngo Weinhold			arg = argv[2];
6609d6a582SIngo Weinhold			watchEvents = 0;
6709d6a582SIngo Weinhold			while (*arg != '\0') {
6809d6a582SIngo Weinhold				switch (*arg) {
6909d6a582SIngo Weinhold					case 'C':
7009d6a582SIngo Weinhold						watchEvents |= B_WATCH_SYSTEM_TEAM_CREATION;
7109d6a582SIngo Weinhold						break;
7209d6a582SIngo Weinhold					case 'D':
7309d6a582SIngo Weinhold						watchEvents |= B_WATCH_SYSTEM_TEAM_DELETION;
7409d6a582SIngo Weinhold						break;
7509d6a582SIngo Weinhold					case 'c':
7609d6a582SIngo Weinhold						watchEvents |= B_WATCH_SYSTEM_THREAD_CREATION;
7709d6a582SIngo Weinhold						break;
7809d6a582SIngo Weinhold					case 'd':
7909d6a582SIngo Weinhold						watchEvents |= B_WATCH_SYSTEM_THREAD_DELETION;
8009d6a582SIngo Weinhold						break;
8109d6a582SIngo Weinhold					case 'p':
8209d6a582SIngo Weinhold						watchEvents |= B_WATCH_SYSTEM_THREAD_PROPERTIES;
8309d6a582SIngo Weinhold						break;
8409d6a582SIngo Weinhold					default:
8509d6a582SIngo Weinhold						print_usage_and_exit(true);
8609d6a582SIngo Weinhold				}
8709d6a582SIngo Weinhold				arg++;
8809d6a582SIngo Weinhold			}
8909d6a582SIngo Weinhold		}
9009d6a582SIngo Weinhold	}
9109d6a582SIngo Weinhold
9209d6a582SIngo Weinhold	// create a port
9309d6a582SIngo Weinhold	port_id port = create_port(10, "system watching test");
9409d6a582SIngo Weinhold	if (port < 0) {
9509d6a582SIngo Weinhold		fprintf(stderr, "Failed to create port: %s\n", strerror(port));
9609d6a582SIngo Weinhold		exit(1);
9709d6a582SIngo Weinhold	}
9809d6a582SIngo Weinhold
9909d6a582SIngo Weinhold	// start watching
1006a5ce301SOliver Tappe	status_t error = __start_watching_system(watchTeam, watchEvents, port, 0);
10109d6a582SIngo Weinhold	if (error != B_OK) {
10209d6a582SIngo Weinhold		fprintf(stderr, "Failed to start watching: %s\n", strerror(error));
10309d6a582SIngo Weinhold		exit(1);
10409d6a582SIngo Weinhold	}
10509d6a582SIngo Weinhold
10609d6a582SIngo Weinhold	// receive notifications
10709d6a582SIngo Weinhold	while (true) {
10809d6a582SIngo Weinhold		// read the message from the port
10909d6a582SIngo Weinhold		char buffer[1024];
11009d6a582SIngo Weinhold		int32 messageCode;
11109d6a582SIngo Weinhold		ssize_t bytesRead = read_port(port, &messageCode, buffer,
11209d6a582SIngo Weinhold			sizeof(buffer));
11309d6a582SIngo Weinhold		if (bytesRead < 0) {
11409d6a582SIngo Weinhold			if (bytesRead == B_INTERRUPTED)
11509d6a582SIngo Weinhold				continue;
11609d6a582SIngo Weinhold			fprintf(stderr, "Failed to read from port: %s\n",
11709d6a582SIngo Weinhold				strerror(bytesRead));
11809d6a582SIngo Weinhold			exit(1);
11909d6a582SIngo Weinhold		}
12009d6a582SIngo Weinhold
12109d6a582SIngo Weinhold		// create a KMessage
12209d6a582SIngo Weinhold		KMessage message;
12309d6a582SIngo Weinhold		error = message.SetTo((const void*)buffer, bytesRead);
12409d6a582SIngo Weinhold		if (error != B_OK) {
12509d6a582SIngo Weinhold			fprintf(stderr, "Failed to create message: %s\n", strerror(error));
12609d6a582SIngo Weinhold			continue;
12709d6a582SIngo Weinhold		}
12809d6a582SIngo Weinhold
12909d6a582SIngo Weinhold		message.Dump((void(*)(const char*,...))printf);
13009d6a582SIngo Weinhold
13109d6a582SIngo Weinhold		// check "what"
13209d6a582SIngo Weinhold		if (message.What() != B_SYSTEM_OBJECT_UPDATE)
13309d6a582SIngo Weinhold			fprintf(stderr, "Unexpected message what!\n");
13409d6a582SIngo Weinhold
13509d6a582SIngo Weinhold		// get opcode
13609d6a582SIngo Weinhold		int32 opcode = 0;
13709d6a582SIngo Weinhold		if (message.FindInt32("opcode", &opcode) != B_OK)
13809d6a582SIngo Weinhold			fprintf(stderr, "Failed to get message opcode!\n");
13909d6a582SIngo Weinhold
14009d6a582SIngo Weinhold		switch (opcode) {
14109d6a582SIngo Weinhold			case B_TEAM_CREATED:
14209d6a582SIngo Weinhold			{
14309d6a582SIngo Weinhold				printf("B_TEAM_CREATED: ");
14409d6a582SIngo Weinhold				int32 teamID;
14509d6a582SIngo Weinhold				if (message.FindInt32("team", &teamID) == B_OK)
14609d6a582SIngo Weinhold					printf("team: %" B_PRId32 "\n", teamID);
14709d6a582SIngo Weinhold				else
14809d6a582SIngo Weinhold					printf("no \"team\" field\n");
14909d6a582SIngo Weinhold
15009d6a582SIngo Weinhold				break;
15109d6a582SIngo Weinhold			}
15209d6a582SIngo Weinhold			case B_TEAM_DELETED:
15309d6a582SIngo Weinhold			{
15409d6a582SIngo Weinhold				printf("B_TEAM_DELETED: ");
15509d6a582SIngo Weinhold				int32 teamID;
15609d6a582SIngo Weinhold				if (message.FindInt32("team", &teamID) == B_OK)
15709d6a582SIngo Weinhold					printf("team: %" B_PRId32 "\n", teamID);
15809d6a582SIngo Weinhold				else
15909d6a582SIngo Weinhold					printf("no \"team\" field\n");
16009d6a582SIngo Weinhold
16109d6a582SIngo Weinhold				break;
16209d6a582SIngo Weinhold			}
16309d6a582SIngo Weinhold			case B_TEAM_EXEC:
16409d6a582SIngo Weinhold			{
16509d6a582SIngo Weinhold				printf("B_TEAM_EXEC: ");
16609d6a582SIngo Weinhold				int32 teamID;
16709d6a582SIngo Weinhold				if (message.FindInt32("team", &teamID) == B_OK)
16809d6a582SIngo Weinhold					printf("team: %" B_PRId32 "\n", teamID);
16909d6a582SIngo Weinhold				else
17009d6a582SIngo Weinhold					printf("no \"team\" field\n");
17109d6a582SIngo Weinhold
17209d6a582SIngo Weinhold				break;
17309d6a582SIngo Weinhold			}
17409d6a582SIngo Weinhold
17509d6a582SIngo Weinhold			case B_THREAD_CREATED:
17609d6a582SIngo Weinhold			{
17709d6a582SIngo Weinhold				printf("B_THREAD_CREATED: ");
17809d6a582SIngo Weinhold				int32 threadID;
17909d6a582SIngo Weinhold				if (message.FindInt32("thread", &threadID) == B_OK)
18009d6a582SIngo Weinhold					printf("thread: %" B_PRId32 "\n", threadID);
18109d6a582SIngo Weinhold				else
18209d6a582SIngo Weinhold					printf("no \"thread\" field\n");
18309d6a582SIngo Weinhold
18409d6a582SIngo Weinhold				break;
18509d6a582SIngo Weinhold			}
18609d6a582SIngo Weinhold			case B_THREAD_DELETED:
18709d6a582SIngo Weinhold			{
18809d6a582SIngo Weinhold				printf("B_THREAD_DELETED: ");
18909d6a582SIngo Weinhold				int32 threadID;
19009d6a582SIngo Weinhold				if (message.FindInt32("thread", &threadID) == B_OK)
19109d6a582SIngo Weinhold					printf("thread: %" B_PRId32 "\n", threadID);
19209d6a582SIngo Weinhold				else
19309d6a582SIngo Weinhold					printf("no \"thread\" field\n");
19409d6a582SIngo Weinhold
19509d6a582SIngo Weinhold				break;
19609d6a582SIngo Weinhold			}
19709d6a582SIngo Weinhold			case B_THREAD_NAME_CHANGED:
19809d6a582SIngo Weinhold			{
19909d6a582SIngo Weinhold				printf("B_THREAD_NAME_CHANGED: ");
20009d6a582SIngo Weinhold				int32 threadID;
20109d6a582SIngo Weinhold				if (message.FindInt32("thread", &threadID) == B_OK)
20209d6a582SIngo Weinhold					printf("thread: %" B_PRId32 "\n", threadID);
20309d6a582SIngo Weinhold				else
20409d6a582SIngo Weinhold					printf("no \"thread\" field\n");
20509d6a582SIngo Weinhold
20609d6a582SIngo Weinhold				break;
20709d6a582SIngo Weinhold			}
20809d6a582SIngo Weinhold
20909d6a582SIngo Weinhold			default:
21009d6a582SIngo Weinhold				fprintf(stderr, "Unknown opcode!\n");
21109d6a582SIngo Weinhold				break;
21209d6a582SIngo Weinhold		}
21309d6a582SIngo Weinhold	}
21409d6a582SIngo Weinhold
21509d6a582SIngo Weinhold	return 0;
21609d6a582SIngo Weinhold}