1/*
2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <OS.h>
12
13#include <system_info.h>
14#include <util/KMessage.h>
15
16
17extern const char* __progname;
18
19
20static void
21print_usage(bool error)
22{
23	fprintf(error ? stderr : stdout,
24		"Usage: %s [ <teamID> [ <events> ] ]\n"
25		"  teamID  - The team ID of the team to watch or -1 for all teams\n"
26		"            (-1 is the default).\n"
27		"  events  - A string specifying the events to watch, consisting of:\n"
28		"            'C': team creation\n"
29		"            'D': team deletion\n"
30		"            'c': thread creation\n"
31		"            'd': thread deletion\n"
32		"            'p': thread properties\n"
33		"            The default is all events.\n",
34		__progname);
35}
36
37
38static void
39print_usage_and_exit(bool error)
40{
41	print_usage(error);
42	exit(error ? 1 : 0);
43}
44
45
46int
47main(int argc, const char* const* argv)
48{
49	int32 watchTeam = -1;
50	uint32 watchEvents = B_WATCH_SYSTEM_ALL;
51
52	if (argc > 3)
53		print_usage_and_exit(true);
54
55	if (argc > 1) {
56		const char* arg = argv[1];
57		if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
58			print_usage_and_exit(false);
59
60		// first parameter is the team ID
61		watchTeam = atol(arg);
62
63		if (argc > 2) {
64			// second parameter is the events string
65			arg = argv[2];
66			watchEvents = 0;
67			while (*arg != '\0') {
68				switch (*arg) {
69					case 'C':
70						watchEvents |= B_WATCH_SYSTEM_TEAM_CREATION;
71						break;
72					case 'D':
73						watchEvents |= B_WATCH_SYSTEM_TEAM_DELETION;
74						break;
75					case 'c':
76						watchEvents |= B_WATCH_SYSTEM_THREAD_CREATION;
77						break;
78					case 'd':
79						watchEvents |= B_WATCH_SYSTEM_THREAD_DELETION;
80						break;
81					case 'p':
82						watchEvents |= B_WATCH_SYSTEM_THREAD_PROPERTIES;
83						break;
84					default:
85						print_usage_and_exit(true);
86				}
87				arg++;
88			}
89		}
90	}
91
92	// create a port
93	port_id port = create_port(10, "system watching test");
94	if (port < 0) {
95		fprintf(stderr, "Failed to create port: %s\n", strerror(port));
96		exit(1);
97	}
98
99	// start watching
100	status_t error = __start_watching_system(watchTeam, watchEvents, port, 0);
101	if (error != B_OK) {
102		fprintf(stderr, "Failed to start watching: %s\n", strerror(error));
103		exit(1);
104	}
105
106	// receive notifications
107	while (true) {
108		// read the message from the port
109		char buffer[1024];
110		int32 messageCode;
111		ssize_t bytesRead = read_port(port, &messageCode, buffer,
112			sizeof(buffer));
113		if (bytesRead < 0) {
114			if (bytesRead == B_INTERRUPTED)
115				continue;
116			fprintf(stderr, "Failed to read from port: %s\n",
117				strerror(bytesRead));
118			exit(1);
119		}
120
121		// create a KMessage
122		KMessage message;
123		error = message.SetTo((const void*)buffer, bytesRead);
124		if (error != B_OK) {
125			fprintf(stderr, "Failed to create message: %s\n", strerror(error));
126			continue;
127		}
128
129		message.Dump((void(*)(const char*,...))printf);
130
131		// check "what"
132		if (message.What() != B_SYSTEM_OBJECT_UPDATE)
133			fprintf(stderr, "Unexpected message what!\n");
134
135		// get opcode
136		int32 opcode = 0;
137		if (message.FindInt32("opcode", &opcode) != B_OK)
138			fprintf(stderr, "Failed to get message opcode!\n");
139
140		switch (opcode) {
141			case B_TEAM_CREATED:
142			{
143				printf("B_TEAM_CREATED: ");
144				int32 teamID;
145				if (message.FindInt32("team", &teamID) == B_OK)
146					printf("team: %" B_PRId32 "\n", teamID);
147				else
148					printf("no \"team\" field\n");
149
150				break;
151			}
152			case B_TEAM_DELETED:
153			{
154				printf("B_TEAM_DELETED: ");
155				int32 teamID;
156				if (message.FindInt32("team", &teamID) == B_OK)
157					printf("team: %" B_PRId32 "\n", teamID);
158				else
159					printf("no \"team\" field\n");
160
161				break;
162			}
163			case B_TEAM_EXEC:
164			{
165				printf("B_TEAM_EXEC: ");
166				int32 teamID;
167				if (message.FindInt32("team", &teamID) == B_OK)
168					printf("team: %" B_PRId32 "\n", teamID);
169				else
170					printf("no \"team\" field\n");
171
172				break;
173			}
174
175			case B_THREAD_CREATED:
176			{
177				printf("B_THREAD_CREATED: ");
178				int32 threadID;
179				if (message.FindInt32("thread", &threadID) == B_OK)
180					printf("thread: %" B_PRId32 "\n", threadID);
181				else
182					printf("no \"thread\" field\n");
183
184				break;
185			}
186			case B_THREAD_DELETED:
187			{
188				printf("B_THREAD_DELETED: ");
189				int32 threadID;
190				if (message.FindInt32("thread", &threadID) == B_OK)
191					printf("thread: %" B_PRId32 "\n", threadID);
192				else
193					printf("no \"thread\" field\n");
194
195				break;
196			}
197			case B_THREAD_NAME_CHANGED:
198			{
199				printf("B_THREAD_NAME_CHANGED: ");
200				int32 threadID;
201				if (message.FindInt32("thread", &threadID) == B_OK)
202					printf("thread: %" B_PRId32 "\n", threadID);
203				else
204					printf("no \"thread\" field\n");
205
206				break;
207			}
208
209			default:
210				fprintf(stderr, "Unknown opcode!\n");
211				break;
212		}
213	}
214
215	return 0;
216}
217