summaryrefslogtreecommitdiff
path: root/tools/perf/util/usage.c
blob: 0a1a885a5914eb6cd6a0b3de6e8a7ec0115791d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * usage.c
 *
 * Various reporting routines.
 * Originally copied from GIT source.
 *
 * Copyright (C) Linus Torvalds, 2005
 */
#include "util.h"
#include "debug.h"

static void report(const char *prefix, const char *err, va_list params)
{
	char msg[1024];
	vsnprintf(msg, sizeof(msg), err, params);
	fprintf(stderr, " %s%s\n", prefix, msg);
}

static NORETURN void usage_builtin(const char *err)
{
	fprintf(stderr, "\n Usage: %s\n", err);
	exit(129);
}

static NORETURN void die_builtin(const char *err, va_list params)
{
	report(" Fatal: ", err, params);
	exit(128);
}

static void error_builtin(const char *err, va_list params)
{
	report(" Error: ", err, params);
}

static void warn_builtin(const char *warn, va_list params)
{
	report(" Warning: ", warn, params);
}

/* If we are in a dlopen()ed .so write to a global variable would segfault
 * (ugh), so keep things static. */
static void (*usage_routine)(const char *err) NORETURN = usage_builtin;
static void (*die_routine)(const char *err, va_list params) NORETURN = die_builtin;
static void (*error_routine)(const char *err, va_list params) = error_builtin;
static void (*warn_routine)(const char *err, va_list params) = warn_builtin;

void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN)
{
	die_routine = routine;
}

void usage(const char *err)
{
	usage_routine(err);
}

void die(const char *err, ...)
{
	va_list params;

	va_start(params, err);
	die_routine(err, params);
	va_end(params);
}

int error(const char *err, ...)
{
	va_list params;

	va_start(params, err);
	error_routine(err, params);
	va_end(params);
	return -1;
}

void warning(const char *warn, ...)
{
	va_list params;

	va_start(params, warn);
	warn_routine(warn, params);
	va_end(params);
}

uid_t parse_target_uid(const char *str)
{
	struct passwd pwd, *result;
	char buf[1024];

	if (str == NULL)
		return UINT_MAX;

	getpwnam_r(str, &pwd, buf, sizeof(buf), &result);

	if (result == NULL) {
		char *endptr;
		int uid = strtol(str, &endptr, 10);

		if (*endptr != '\0') {
			ui__error("Invalid user %s\n", str);
			return UINT_MAX - 1;
		}

		getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);

		if (result == NULL) {
			ui__error("Problems obtaining information for user %s\n",
				  str);
			return UINT_MAX - 1;
		}
	}

	return result->pw_uid;
}

void perf_target__validate(struct perf_target *target)
{
	if (target->pid)
		target->tid = target->pid;

	/* CPU and PID are mutually exclusive */
	if (target->tid && target->cpu_list) {
		ui__warning("WARNING: PID switch overriding CPU\n");
		sleep(1);
		target->cpu_list = NULL;
	}

	/* UID and PID are mutually exclusive */
	if (target->tid && target->uid_str) {
		ui__warning("PID/TID switch overriding UID\n");
		sleep(1);
		target->uid_str = NULL;
	}
}