1/*
2 * Copyright 2022, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Oscar Lesta <oscar.lesta@gmail.com>
7 */
8
9#include <stdio.h>
10#include <string.h>
11
12#include <OS.h>
13
14#include <extended_system_info.h>
15#include <extended_system_info_defs.h>
16#include <util/KMessage.h>
17
18
19static void
20usage(FILE* output = stdout)
21{
22	fprintf(output, "Return the process id(s) (PID) for the given process name.\n\n"
23		"Usage:\tpidof [-hsv] process_name\n"
24		"\t\t-h : Show this help.\n"
25		"\t\t-s : Print only the PID for the first matching process.\n"
26		"\t\t-v : Verbose output.\n"
27	);
28}
29
30
31int
32main(int argc, char* argv[])
33{
34	bool singleShot = false;
35	bool verbose = false;
36
37	int c;
38	while ((c = getopt(argc, argv, "hvs")) != -1) {
39		switch (c) {
40			case 'h':
41				usage();
42				return 0;
43			case 's':
44				singleShot = true;
45				break;
46			case 'v':
47				verbose = true;
48				break;
49			default:
50				usage(stderr);
51				return 1;
52		}
53	}
54
55	if ((argc == optind) || (argc - optind) > 1) {
56		if (verbose)
57			fprintf(stderr, "Error: A (single) process name is expected.\n");
58
59		usage(stderr);
60		return 1;
61	}
62
63	int32 cookie = 0;
64	team_info teamInfo;
65	bool processFound = false;
66	const char* processName = argv[argc - 1];
67
68	while (get_next_team_info(&cookie, &teamInfo) == B_OK) {
69		KMessage extendedInfo;
70		status_t status = get_extended_team_info(teamInfo.team, B_TEAM_INFO_BASIC, extendedInfo);
71
72		if (status == B_BAD_TEAM_ID) {
73			// The team might have simply ended between the last function calls.
74			continue;
75		} else if (status != B_OK) {
76			fprintf(stderr, "Error: get_extended_team_info() == 0x%" B_PRIx32 " (%s)\n",
77				status, strerror(status));
78			return 1;
79		}
80
81		const char* teamName = NULL;
82		if (extendedInfo.FindString("name", &teamName) != B_OK)
83			continue;
84
85		if (strcmp(teamName, processName) == 0) {
86			processFound = true;
87			printf("%" B_PRId32 "\n", teamInfo.team);
88			if (singleShot)
89				return 0;
90		}
91	}
92
93	if (verbose && !processFound)
94		fprintf(stderr, "Error: Process name not found.\n");
95
96	return processFound ? 0 : 1;
97}
98