Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 161244 | Differences between
and this patch

Collapse All | Expand All

(-)qlop.c (-72 / +134 lines)
Lines 1-492 Link Here
1
/*
1
/*
2
 * Copyright 2005-2006 Gentoo Foundation
2
 * Copyright 2005-2006 Gentoo Foundation
3
 * Distributed under the terms of the GNU General Public License v2
3
 * Distributed under the terms of the GNU General Public License v2
4
 * $Header: /var/cvsroot/gentoo-projects/portage-utils/qlop.c,v 1.36 2007/01/10 03:42:19 vapier Exp $
4
 * $Header: /var/cvsroot/gentoo-projects/portage-utils/qlop.c,v 1.36 2007/01/10 03:42:19 vapier Exp $
5
 *
5
 *
6
 * Copyright 2005-2006 Ned Ludd        - <solar@gentoo.org>
6
 * Copyright 2005-2006 Ned Ludd        - <solar@gentoo.org>
7
 * Copyright 2005-2006 Mike Frysinger  - <vapier@gentoo.org>
7
 * Copyright 2005-2006 Mike Frysinger  - <vapier@gentoo.org>
8
 */
8
 */
9
9
10
#ifdef APPLET_qlop
10
#ifdef APPLET_qlop
11
11
12
#ifdef __linux__
12
#ifdef __linux__
13
# include <asm/param.h>
13
# include <asm/param.h>
14
#endif
14
#endif
15
15
16
#ifdef __FreeBSD__
16
#ifdef __FreeBSD__
17
# include <kvm.h>
17
# include <kvm.h>
18
# include <sys/param.h>
18
# include <sys/param.h>
19
# include <sys/sysctl.h>
19
# include <sys/sysctl.h>
20
# include <sys/user.h>
20
# include <sys/user.h>
21
# include <sys/time.h>
21
# include <sys/time.h>
22
#endif
22
#endif
23
23
24
#define QLOP_DEFAULT_LOGFILE "/var/log/emerge.log"
24
#define QLOP_DEFAULT_LOGFILE "/var/log/emerge.log"
25
25
26
26
27
27
28
#define QLOP_FLAGS "gtluscf:F:H" COMMON_FLAGS
28
#define QLOP_FLAGS "gtluscf:F:H" COMMON_FLAGS
29
static struct option const qlop_long_opts[] = {
29
static struct option const qlop_long_opts[] = {
30
	{"gauge",     no_argument, NULL, 'g'},
30
	{"gauge",     no_argument, NULL, 'g'},
31
	{"time",      no_argument, NULL, 't'},
31
	{"time",      no_argument, NULL, 't'},
32
	{"human",     no_argument, NULL, 'H'},
32
	{"human",     no_argument, NULL, 'H'},
33
	{"list",      no_argument, NULL, 'l'},
33
	{"list",      no_argument, NULL, 'l'},
34
	{"unlist",    no_argument, NULL, 'u'},
34
	{"unlist",    no_argument, NULL, 'u'},
35
	{"sync",      no_argument, NULL, 's'},
35
	{"sync",      no_argument, NULL, 's'},
36
	{"current",   no_argument, NULL, 'c'},
36
	{"current",   no_argument, NULL, 'c'},
37
	{"logfile",    a_argument, NULL, 'f'},
37
	{"logfile",    a_argument, NULL, 'f'},
38
	COMMON_LONG_OPTS
38
	COMMON_LONG_OPTS
39
};
39
};
40
static const char *qlop_opts_help[] = {
40
static const char *qlop_opts_help[] = {
41
	"Gauge number of times a package has been merged",
41
	"Gauge number of times a package has been merged",
42
	"Calculate merge time for a specific package",
42
	"Calculate merge time for a specific package",
43
	"Print seconds in human readable format (needs -t)",
43
	"Print seconds in human readable format (needs -t)",
44
	"Show merge history",
44
	"Show merge history",
45
	"Show unmerge history",
45
	"Show unmerge history",
46
	"Show sync history",
46
	"Show sync history",
47
	"Show current emerging packages",
47
	"Show current emerging packages",
48
	"Read emerge logfile instead of " QLOP_DEFAULT_LOGFILE,
48
	"Read emerge logfile instead of " QLOP_DEFAULT_LOGFILE,
49
	COMMON_OPTS_HELP
49
	COMMON_OPTS_HELP
50
};
50
};
51
static const char qlop_rcsid[] = "$Id: qlop.c,v 1.36 2007/01/10 03:42:19 vapier Exp $";
51
static const char qlop_rcsid[] = "$Id: qlop.c,v 1.36 2007/01/10 03:42:19 vapier Exp $";
52
#define qlop_usage(ret) usage(ret, QLOP_FLAGS, qlop_long_opts, qlop_opts_help, lookup_applet_idx("qlop"))
52
#define qlop_usage(ret) usage(ret, QLOP_FLAGS, qlop_long_opts, qlop_opts_help, lookup_applet_idx("qlop"))
53
53
54
#define QLOP_LIST    0x01
54
#define QLOP_LIST    0x01
55
#define QLOP_UNLIST  0x02
55
#define QLOP_UNLIST  0x02
56
56
57
void print_seconds_for_earthlings(const unsigned long t);
57
void print_seconds_for_earthlings(const unsigned long t);
58
void print_seconds_for_earthlings(const unsigned long t) {
58
void print_seconds_for_earthlings(const unsigned long t) {
59
	unsigned dd, hh, mm, ss;
59
	unsigned dd, hh, mm, ss;
60
	unsigned long tt = t;
60
	unsigned long tt = t;
61
	ss = tt % 60; tt /= 60;
61
	ss = tt % 60; tt /= 60;
62
	mm = tt % 60; tt /= 60;
62
	mm = tt % 60; tt /= 60;
63
	hh = tt % 24; tt /= 24;
63
	hh = tt % 24; tt /= 24;
64
	dd = tt;
64
	dd = tt;
65
	if (dd) printf("%s%u%s day%s, ", GREEN, dd, NORM, (dd == 1 ? "" : "s"));
65
	if (dd) printf("%s%u%s day%s, ", GREEN, dd, NORM, (dd == 1 ? "" : "s"));
66
	if (hh) printf("%s%u%s hour%s, ", GREEN, hh, NORM, (hh == 1 ? "" : "s"));
66
	if (hh) printf("%s%u%s hour%s, ", GREEN, hh, NORM, (hh == 1 ? "" : "s"));
67
	if (mm) printf("%s%u%s minute%s, ", GREEN, mm, NORM, (mm == 1 ? "" : "s"));
67
	if (mm) printf("%s%u%s minute%s, ", GREEN, mm, NORM, (mm == 1 ? "" : "s"));
68
	printf("%s%u%s second%s", GREEN, ss, NORM, (ss == 1 ? "" : "s"));
68
	printf("%s%u%s second%s", GREEN, ss, NORM, (ss == 1 ? "" : "s"));
69
}
69
}
70
70
71
static const char *chop_ctime(time_t t);
71
static const char *chop_ctime(time_t t);
72
static const char *chop_ctime(time_t t)
72
static const char *chop_ctime(time_t t)
73
{
73
{
74
	static char ctime_out[50];
74
	static char ctime_out[50];
75
	char *p;
75
	char *p;
76
	snprintf(ctime_out, sizeof(ctime_out), "%s", ctime(&t));
76
	snprintf(ctime_out, sizeof(ctime_out), "%s", ctime(&t));
77
	if ((p = strchr(ctime_out, '\n')) != NULL)
77
	if ((p = strchr(ctime_out, '\n')) != NULL)
78
		*p = '\0';
78
		*p = '\0';
79
	return ctime_out;
79
	return ctime_out;
80
}
80
}
81
81
82
unsigned long show_merge_times(char *package, const char *logfile, int average, char human_readable);
82
unsigned long show_merge_times(char *package, const char *logfile, int average, char human_readable);
83
unsigned long show_merge_times(char *package, const char *logfile, int average, char human_readable)
83
unsigned long show_merge_times(char *package, const char *logfile, int average, char human_readable)
84
{
84
{
85
	FILE *fp;
85
	FILE *fp;
86
	char cat[126], buf[2][BUFSIZ];
86
	char cat[126], buf[2][BUFSIZ];
87
	char *pkg, *p;
87
	char *pkg, *p;
88
	unsigned long count, merge_time;
88
	unsigned long count, merge_time;
89
	time_t t[2];
89
	time_t t[2];
90
	depend_atom *atom;
90
	depend_atom *atom;
91
91
92
	t[0] = t[1] = 0UL;
92
	t[0] = t[1] = 0UL;
93
	count = merge_time = 0;
93
	count = merge_time = 0;
94
	cat[0] = 0;
94
	cat[0] = 0;
95
95
96
	if ((p = strchr(package, '/')) != NULL) {
96
	if ((p = strchr(package, '/')) != NULL) {
97
		pkg = p + 1;
97
		pkg = p + 1;
98
		strncpy(cat, package, sizeof(cat));
98
		strncpy(cat, package, sizeof(cat));
99
		if ((p = strchr(cat, '/')) != NULL)
99
		if ((p = strchr(cat, '/')) != NULL)
100
			*p = 0;
100
			*p = 0;
101
	} else {
101
	} else {
102
		pkg = package;
102
		pkg = package;
103
	}
103
	}
104
104
105
	DBG("Searching for %s in %s\n", pkg, logfile);
105
	DBG("Searching for %s in %s\n", pkg, logfile);
106
106
107
	if ((fp = fopen(logfile, "r")) == NULL) {
107
	if ((fp = fopen(logfile, "r")) == NULL) {
108
		warnp("Could not open logfile '%s'", logfile);
108
		warnp("Could not open logfile '%s'", logfile);
109
		return 1;
109
		return 1;
110
	}
110
	}
111
111
112
	while ((fgets(buf[0], sizeof(buf[0]), fp)) != NULL) {
112
	while ((fgets(buf[0], sizeof(buf[0]), fp)) != NULL) {
113
		if (strstr(buf[0], pkg) == NULL)
113
		if (strstr(buf[0], pkg) == NULL)
114
			continue;
114
			continue;
115
115
116
		if ((p = strchr(buf[0], '\n')) != NULL)
116
		if ((p = strchr(buf[0], '\n')) != NULL)
117
			*p = 0;
117
			*p = 0;
118
		if ((p = strchr(buf[0], ':')) == NULL)
118
		if ((p = strchr(buf[0], ':')) == NULL)
119
			continue;
119
			continue;
120
		*p = 0;
120
		*p = 0;
121
		t[0] = atol(buf[0]);
121
		t[0] = atol(buf[0]);
122
		strcpy(buf[1], p + 1);
122
		strcpy(buf[1], p + 1);
123
		rmspace(buf[1]);
123
		rmspace(buf[1]);
124
		if ((strncmp(buf[1], ">>> emerge (", 12)) == 0) {
124
		if ((strncmp(buf[1], ">>> emerge (", 12)) == 0) {
125
			char matched = 0;
125
			char matched = 0;
126
			if ((p = strchr(buf[1], ')')) == NULL)
126
			if ((p = strchr(buf[1], ')')) == NULL)
127
				continue;
127
				continue;
128
			*p = 0;
128
			*p = 0;
129
			strcpy(buf[0], p + 1);
129
			strcpy(buf[0], p + 1);
130
			rmspace(buf[0]);
130
			rmspace(buf[0]);
131
			if ((p = strchr(buf[0], ' ')) == NULL)
131
			if ((p = strchr(buf[0], ' ')) == NULL)
132
				continue;
132
				continue;
133
			*p = 0;
133
			*p = 0;
134
			if ((atom = atom_explode(buf[0])) == NULL)
134
			if ((atom = atom_explode(buf[0])) == NULL)
135
				continue;
135
				continue;
136
136
137
			if (*cat) {
137
			if (*cat) {
138
				if ((strcmp(cat, atom->CATEGORY) == 0) && (strcmp(pkg, atom->PN) == 0))
138
				if ((strcmp(cat, atom->CATEGORY) == 0) && (strcmp(pkg, atom->PN) == 0))
139
					matched = 1;
139
					matched = 1;
140
			} else if (strcmp(pkg, atom->PN) == 0)
140
			} else if (strcmp(pkg, atom->PN) == 0)
141
				matched = 1;
141
				matched = 1;
142
142
143
			if (matched) {
143
			if (matched) {
144
				while ((fgets(buf[0], sizeof(buf[0]), fp)) != NULL) {
144
				while ((fgets(buf[0], sizeof(buf[0]), fp)) != NULL) {
145
					if ((p = strchr(buf[0], '\n')) != NULL)
145
					if ((p = strchr(buf[0], '\n')) != NULL)
146
						*p = 0;
146
						*p = 0;
147
					if ((p = strchr(buf[0], ':')) == NULL)
147
					if ((p = strchr(buf[0], ':')) == NULL)
148
						continue;
148
						continue;
149
					*p = 0;
149
					*p = 0;
150
					t[1] = atol(buf[0]);
150
					t[1] = atol(buf[0]);
151
					strcpy(buf[1], p + 1);
151
					strcpy(buf[1], p + 1);
152
					rmspace(buf[1]);
152
					rmspace(buf[1]);
153
					if (*buf[1] == '*')
153
					if (*buf[1] == '*')
154
						break;
154
						break;
155
					if ((strncmp(buf[1], "::: completed emerge (", 22)) == 0) {
155
					if ((strncmp(buf[1], "::: completed emerge (", 22)) == 0) {
156
						if (!average) {
156
						if (!average) {
157
							strcpy(buf[1], "");
157
							strcpy(buf[1], "");
158
							if (verbose) {
158
							if (verbose) {
159
								if (atom->PR_int)
159
								if (atom->PR_int)
160
									snprintf(buf[1], sizeof(buf[1]), "-%s-r%i", atom->PV,  atom->PR_int);
160
									snprintf(buf[1], sizeof(buf[1]), "-%s-r%i", atom->PV,  atom->PR_int);
161
								else
161
								else
162
									snprintf(buf[1], sizeof(buf[1]), "-%s", atom->PV);
162
									snprintf(buf[1], sizeof(buf[1]), "-%s", atom->PV);
163
							}
163
							}
164
							printf("%s%s%s%s: %s: ", BLUE, atom->PN, buf[1], NORM, chop_ctime(t[0]));
164
							printf("%s%s%s%s: %s: ", BLUE, atom->PN, buf[1], NORM, chop_ctime(t[0]));
165
							if (human_readable)
165
							if (human_readable)
166
								print_seconds_for_earthlings(t[1] - t[0]);
166
								print_seconds_for_earthlings(t[1] - t[0]);
167
							else
167
							else
168
								printf("%s%lu%s seconds", GREEN, (t[1] - t[0]), NORM);
168
								printf("%s%lu%s seconds", GREEN, (t[1] - t[0]), NORM);
169
							puts("");
169
							puts("");
170
						}
170
						}
171
						merge_time += (t[1] - t[0]);
171
						merge_time += (t[1] - t[0]);
172
						count++;
172
						count++;
173
						break;
173
						break;
174
					}
174
					}
175
				}
175
				}
176
			}
176
			}
177
			atom_implode(atom);
177
			atom_implode(atom);
178
		}
178
		}
179
	}
179
	}
180
	fclose(fp);
180
	fclose(fp);
181
	if (count == 0)
181
	if (count == 0)
182
		return 0;
182
		return 0;
183
	if (average == 1) {
183
	if (average == 1) {
184
		printf("%s%s%s: ", BLUE, pkg, NORM);
184
		printf("%s%s%s: ", BLUE, pkg, NORM);
185
		if (human_readable)
185
		if (human_readable)
186
			print_seconds_for_earthlings(merge_time / count);
186
			print_seconds_for_earthlings(merge_time / count);
187
		else
187
		else
188
			printf("%s%lu%s seconds average", GREEN, merge_time / count, NORM);
188
			printf("%s%lu%s seconds average", GREEN, merge_time / count, NORM);
189
		printf(" for %s%lu%s merges\n", GREEN, count, NORM);
189
		printf(" for %s%lu%s merges\n", GREEN, count, NORM);
190
	} else {
190
	} else {
191
		printf("%s%s%s: %s%lu%s times\n", BLUE, pkg, NORM, GREEN, count, NORM);
191
		printf("%s%s%s: %s%lu%s times\n", BLUE, pkg, NORM, GREEN, count, NORM);
192
	}
192
	}
193
	return 0;
193
	return 0;
194
}
194
}
195
195
196
void show_emerge_history(char listflag, int argc, char **argv, const char *logfile);
196
void show_emerge_history(char listflag, int argc, char **argv, const char *logfile);
197
void show_emerge_history(char listflag, int argc, char **argv, const char *logfile)
197
void show_emerge_history(char listflag, int argc, char **argv, const char *logfile)
198
{
198
{
199
	FILE *fp;
199
	FILE *fp;
200
	char buf[BUFSIZ], merged;
200
	char buf[BUFSIZ], merged;
201
	char *p, *q;
201
	char *p, *q;
202
	int i;
202
	int i;
203
	time_t t;
203
	time_t t;
204
204
205
	if ((fp = fopen(logfile, "r")) == NULL) {
205
	if ((fp = fopen(logfile, "r")) == NULL) {
206
		warnp("Could not open logfile '%s'", logfile);
206
		warnp("Could not open logfile '%s'", logfile);
207
		return;
207
		return;
208
	}
208
	}
209
209
210
	while ((fgets(buf, sizeof(buf), fp)) != NULL) {
210
	while ((fgets(buf, sizeof(buf), fp)) != NULL) {
211
		if (strlen(buf) < 30)
211
		if (strlen(buf) < 30)
212
			continue;
212
			continue;
213
213
214
		for (i = 0; i < argc; ++i)
214
		for (i = 0; i < argc; ++i)
215
			if (strstr(buf, argv[i]) != NULL)
215
			if (strstr(buf, argv[i]) != NULL)
216
				break;
216
				break;
217
		if (argc && i == argc)
217
		if (argc && i == argc)
218
			continue;
218
			continue;
219
219
220
		if ((p = strchr(buf, '\n')) != NULL)
220
		if ((p = strchr(buf, '\n')) != NULL)
221
			*p = 0;
221
			*p = 0;
222
		if ((p = strchr(buf, ':')) == NULL)
222
		if ((p = strchr(buf, ':')) == NULL)
223
			continue;
223
			continue;
224
		*p = 0;
224
		*p = 0;
225
		q = p + 3;
225
		q = p + 3;
226
226
227
		t = (time_t) atol(buf);
227
		t = (time_t) atol(buf);
228
228
229
		if ((listflag & QLOP_LIST) && !strncmp(q, "::: completed emerge (", 22)) {
229
		if ((listflag & QLOP_LIST) && !strncmp(q, "::: completed emerge (", 22)) {
230
			merged = 1;
230
			merged = 1;
231
			if ((p = strchr(q, ')')) == NULL)
231
			if ((p = strchr(q, ')')) == NULL)
232
				continue;
232
				continue;
233
			q = p + 2;
233
			q = p + 2;
234
			if ((p = strchr(q, ' ')) == NULL)
234
			if ((p = strchr(q, ' ')) == NULL)
235
				continue;
235
				continue;
236
			*p = 0;
236
			*p = 0;
237
		} else if ((listflag & QLOP_UNLIST) && !strncmp(q, ">>> unmerge success: ", 21)) {
237
		} else if ((listflag & QLOP_UNLIST) && !strncmp(q, ">>> unmerge success: ", 21)) {
238
			merged = 0;
238
			merged = 0;
239
			if ((p = strchr(q, ':')) == NULL)
239
			if ((p = strchr(q, ':')) == NULL)
240
				continue;
240
				continue;
241
			q = p + 2;
241
			q = p + 2;
242
		}
242
		}
243
		else
243
		else
244
			continue;
244
			continue;
245
		if (!quiet)
245
		if (!quiet)
246
			printf("%s %s %s%s%s\n", chop_ctime(t), (merged ? ">>>" : "<<<"), (merged ? GREEN : RED), q, NORM);
246
			printf("%s %s %s%s%s\n", chop_ctime(t), (merged ? ">>>" : "<<<"), (merged ? GREEN : RED), q, NORM);
247
		else {
247
		else {
248
			depend_atom *atom;
248
			depend_atom *atom;
249
			atom = atom_explode(q);
249
			atom = atom_explode(q);
250
			if (quiet == 1)
250
			if (quiet == 1)
251
				printf("%s ", chop_ctime(t));
251
				printf("%s ", chop_ctime(t));
252
			if (quiet <= 2)
252
			if (quiet <= 2)
253
				printf("%s ", (merged ? ">>>" : "<<<"));
253
				printf("%s ", (merged ? ">>>" : "<<<"));
254
			printf("%s%s/%s%s\n", (merged ? GREEN : RED), atom->CATEGORY, atom->PN, NORM);
254
			printf("%s%s/%s%s\n", (merged ? GREEN : RED), atom->CATEGORY, atom->PN, NORM);
255
			atom_implode(atom);
255
			atom_implode(atom);
256
		}
256
		}
257
	}
257
	}
258
	fclose(fp);
258
	fclose(fp);
259
}
259
}
260
260
261
void show_sync_history(const char *logfile);
261
void show_sync_history(const char *logfile);
262
void show_sync_history(const char *logfile)
262
void show_sync_history(const char *logfile)
263
{
263
{
264
	FILE *fp;
264
	FILE *fp;
265
	char buf[BUFSIZ];
265
	char buf[BUFSIZ];
266
	char *p, *q;
266
	char *p, *q;
267
	time_t t;
267
	time_t t;
268
268
269
	if ((fp = fopen(logfile, "r")) == NULL) {
269
	if ((fp = fopen(logfile, "r")) == NULL) {
270
		warnp("Could not open logfile '%s'", logfile);
270
		warnp("Could not open logfile '%s'", logfile);
271
		return;
271
		return;
272
	}
272
	}
273
273
274
	while ((fgets(buf, sizeof(buf), fp)) != NULL) {
274
	while ((fgets(buf, sizeof(buf), fp)) != NULL) {
275
		if (strlen(buf) < 35)
275
		if (strlen(buf) < 35)
276
			continue;
276
			continue;
277
		if (strncmp(buf+12, "=== Sync completed with", 23) != 0)
277
		if (strncmp(buf+12, "=== Sync completed with", 23) != 0)
278
			continue;
278
			continue;
279
279
280
		if ((p = strchr(buf, '\n')) != NULL)
280
		if ((p = strchr(buf, '\n')) != NULL)
281
			*p = 0;
281
			*p = 0;
282
		if ((p = strchr(buf, ':')) == NULL)
282
		if ((p = strchr(buf, ':')) == NULL)
283
			continue;
283
			continue;
284
		*p = 0;
284
		*p = 0;
285
		q = p+2;
285
		q = p+2;
286
286
287
		t = (time_t)atol(buf);
287
		t = (time_t)atol(buf);
288
288
289
		if ((p = strstr(q, "with")) == NULL)
289
		if ((p = strstr(q, "with")) == NULL)
290
			continue;
290
			continue;
291
		q = p + 5;
291
		q = p + 5;
292
292
293
		printf("%s >>> %s%s%s\n", chop_ctime(t), GREEN, q, NORM);
293
		printf("%s >>> %s%s%s\n", chop_ctime(t), GREEN, q, NORM);
294
	}
294
	}
295
	fclose(fp);
295
	fclose(fp);
296
}
296
}
297
297
298
void show_current_emerge(void);
298
void print_current_emerge(const char *logfile, const depend_atom *pkg);
299
#if defined(__linux__) || defined(__FreeBSD__)
300
void print_current_emerge(const char *logfile, const depend_atom *pkg)
301
{
302
	FILE *fp;
303
	char buf[2][BUFSIZE];
304
	char *p;
305
	unsigned long count, merge_time, elapsed_time = 0;
306
	time_t start_date, t[2];
307
	depend_atom *atom;
308
309
	start_date = t[0] = t[1] = 0UL;
310
	count = merge_time = 0;
311
312
	DBG("Searching for %s in %s\n", pkg->PN, logfile);
313
314
	if ((fp = fopen(logfile, "r")) == NULL) {
315
		warnp("Could not open logfile '%s'", logfile);
316
		return;
317
	}
318
319
	while ((fgets(buf[0], sizeof(buf[0]), fp)) != NULL) {
320
		if (strstr(buf[0], pkg->PN) == NULL)
321
			continue;
322
323
		if ((p = strchr(buf[0], '\n')) != NULL)
324
			*p = 0;
325
		if ((p = strchr(buf[0], ':')) == NULL)
326
			continue;
327
		*p = 0;
328
		t[0] = atol(buf[0]);
329
		strcpy(buf[1], p + 1);
330
		rmspace(buf[1]);
331
		if ((strncmp(buf[1], ">>> emerge (", 12)) == 0) {
332
			char matched = 0;
333
			if ((p = strchr(buf[1], ')')) == NULL)
334
				continue;
335
			*p = 0;
336
			strcpy(buf[0], p + 1);
337
			rmspace(buf[0]);
338
			if ((p = strchr(buf[0], ' ')) == NULL)
339
				continue;
340
			*p = 0;
341
			if ((atom = atom_explode(buf[0])) == NULL)
342
				continue;
343
344
			if (pkg->CATEGORY) {
345
				if ((strcmp(pkg->CATEGORY, atom->CATEGORY) == 0) && (strcmp(pkg->PN, atom->PN) == 0))
346
					matched = 1;
347
			} else if (strcmp(pkg->PN, atom->PN) == 0)
348
				matched = 1;
349
350
			if (matched) {
351
				start_date = t[0];
352
				while ((fgets(buf[0], sizeof(buf[0]), fp)) != NULL) {
353
					if ((p = strchr(buf[0], '\n')) != NULL)
354
						*p = 0;
355
					if ((p = strchr(buf[0], ':')) == NULL)
356
						continue;
357
					*p = 0;
358
					t[1] = atol(buf[0]);
359
					strcpy(buf[1], p + 1);
360
					rmspace(buf[1]);
361
					if (*buf[1] == '*')
362
						break;
363
					if ((strncmp(buf[1], "::: completed emerge (", 22)) == 0) {
364
						merge_time += (t[1] - t[0]);
365
						count++;
366
						break;
367
					}
368
				}
369
			}
370
			atom_implode(atom);
371
		}
372
	}
373
	fclose(fp);
374
375
	elapsed_time = time(0) - start_date;
376
	printf(	" %s*%s %s%s%s%s\n"
377
			"     started: %s%s%s\n"
378
			"     elapsed: ",
379
	BOLD, NORM, BLUE, (pkg->CATEGORY ? strcat(pkg->CATEGORY, "/") : ""), pkg->P, NORM,
380
	GREEN, chop_ctime(start_date), NORM);
381
	print_seconds_for_earthlings(elapsed_time);
382
	printf("\n     ETA:     ");
383
	if (merge_time == 0)
384
		printf("Unknown");
385
	else if (merge_time / count < elapsed_time)
386
		printf("Sometime soon");
387
	else
388
		print_seconds_for_earthlings(merge_time / count - elapsed_time);
389
	puts("");
390
}
391
#else
392
void print_current_emerge(const char *logfile, const depend_atom *pkg)
393
{
394
	errf("not supported on your crapbox OS");
395
}
396
#endif
397
398
void show_current_emerge(const char *logfile);
299
#ifdef __linux__
399
#ifdef __linux__
300
void show_current_emerge(void)
400
void show_current_emerge(const char *logfile)
301
{
401
{
302
	DIR *proc;
402
	DIR *proc;
303
	struct dirent *de;
403
	struct dirent *de;
304
	pid_t pid;
404
	pid_t pid;
305
	char buf[BUFSIZE], bufstat[300];
405
	char buf[2][BUFSIZE], path[50];
306
	char path[50];
406
	char *p;
307
	char *p, *q;
407
	depend_atom *atom;
308
	unsigned long long start_time = 0;
309
	double uptime_secs;
310
	time_t start_date;
311
408
312
	if ((proc = opendir("/proc")) == NULL) {
409
	if ((proc = opendir("/proc")) == NULL) {
313
		warnp("Could not open /proc");
410
		warnp("Could not open /proc");
314
		return;
411
		return;
315
	}
412
	}
316
413
317
	while ((de = readdir(proc)) != NULL) {
414
	while ((de = readdir(proc)) != NULL) {
318
319
		if ((pid = (pid_t)atol(de->d_name)) == 0)
415
		if ((pid = (pid_t)atol(de->d_name)) == 0)
320
			continue;
416
			continue;
321
417
322
		/* portage renames the cmdline so the package name is first */
418
		/* portage renames the cmdline so the package name is first */
323
		snprintf(path, sizeof(path), "/proc/%i/cmdline", pid);
419
		snprintf(path, sizeof(path), "/proc/%i/cmdline", pid);
324
		if (!eat_file(path, buf, sizeof(buf)))
420
		if (!eat_file(path, buf[0], sizeof(buf[0])))
325
			continue;
421
			continue;
326
422
327
		if (buf[0] == '[' && (p = strchr(buf, ']')) != NULL && strstr(buf, "sandbox") != NULL) {
423
		if (buf[0][0] == '[' && (p = strchr(buf[0], ']')) != NULL && strstr(buf[0], "sandbox") != NULL) {
424
			/* try to fetch category from process env */
425
			snprintf(path, sizeof(path), "/proc/%i/environ", pid);
426
			if (eat_file(path, buf[1], sizeof(buf[1]))) {
427
				p = buf[1];
428
				while (strstr(p, "PORTAGE_BUILDDIR=") == NULL)
429
					p = strchr(p, '\0')+1;
430
				while (strchr(p, '/') != strrchr(p, '/'))
431
					p = strchr(p, '/')+1;
432
				if ((atom = atom_explode(p)) == NULL)
433
					continue;
434
			}
435
			/* fallback to packagename if not allowed */
436
			else {
328
			*p = '\0';
437
			*p = '\0';
329
			p = buf+1;
438
				if ((atom = atom_explode(buf[0]+1)) == NULL)
330
			q = p + strlen(p) + 1;
439
					continue;
331
440
			}
332
			/* open the stat file to figure out how long we have been running */
441
			print_current_emerge(logfile, atom);
333
			snprintf(path, sizeof(path), "/proc/%i/stat", pid);
442
			atom_implode(atom);
334
			if (!eat_file(path, bufstat, sizeof(bufstat)))
335
				continue;
336
337
			/* ripped from procps/proc/readproc.c */
338
			if ((q = strchr(bufstat, ')')) == NULL)
339
				continue;
340
			/* grab the start time */
341
			sscanf(q + 2,
342
				"%*c "
343
				"%*d %*d %*d %*d %*d "
344
				"%*u %*u %*u %*u %*u "
345
				"%*u %*u %*u %*u "
346
				"%*d %*d "
347
				"%*d "
348
				"%*d "
349
				"%Lu ",
350
				&start_time);
351
			/* get uptime */
352
			if (!eat_file("/proc/uptime", bufstat, sizeof(bufstat)))
353
				continue;
354
			sscanf(bufstat, "%lf", &uptime_secs);
355
356
			/* figure out when this thing started and then show it */
357
			start_date = time(0) - (uptime_secs - (start_time / HZ));
358
			printf(
359
				" %s*%s %s%s%s\n"
360
				"     started: %s%s%s\n"
361
				"     elapsed: ", /*%s%llu%s seconds\n",*/
362
				BOLD, NORM, BLUE, p, NORM,
363
				GREEN, chop_ctime(start_date), NORM);
364
			print_seconds_for_earthlings(uptime_secs - (start_time / HZ));
365
			puts(NORM);
366
		}
443
		}
367
	}
444
	}
368
445
369
	closedir(proc);
446
	closedir(proc);
370
371
	if (start_time == 0 && verbose)
372
		puts("No emerge processes located");
373
}
447
}
374
#elif defined(__FreeBSD__)
448
#elif defined(__FreeBSD__)
375
void show_current_emerge(void)
449
void show_current_emerge(const char *logfile)
376
{
450
{
377
	kvm_t *kd = NULL;
451
	kvm_t *kd = NULL;
378
	struct kinfo_proc *ip;
452
	struct kinfo_proc *ip;
379
	int i; int total_processes;
453
	int i, total_processes;
380
	char *p, *q;
454
	char *p;
381
	time_t start_date = 0;
455
	depend_atom *atom;
382
456
383
	if (! (kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open"))) {
457
	if (! (kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open"))) {
384
		warnp("Could not open kvm: %s", kvm_geterr(kd));
458
		warnp("Could not open kvm: %s", kvm_geterr(kd));
385
		return;
459
		return;
386
	}
460
	}
387
461
388
	ip = kvm_getprocs(kd, KERN_PROC_PROC, 0, &total_processes);
462
	ip = kvm_getprocs(kd, KERN_PROC_PROC, 0, &total_processes);
389
463
390
	for (i = 0; i < total_processes; i++) {
464
	for (i = 0; i < total_processes; i++) {
391
		char **proc_argv = NULL;
465
		char **proc_argv = NULL;
392
		char *buf = NULL;
466
		char *buf = NULL;
393
467
394
		if (strcmp(ip[i].ki_comm, "sandbox") != 0)
468
		if (strcmp(ip[i].ki_comm, "sandbox") != 0)
395
			continue;
469
			continue;
396
470
397
		proc_argv = kvm_getargv(kd, &(ip[i]), 0);
471
		proc_argv = kvm_getargv(kd, &(ip[i]), 0);
398
472
399
		if (!proc_argv || (buf = xstrdup(proc_argv[0])) == NULL ||
473
		if (!proc_argv || (buf = xstrdup(proc_argv[0])) == NULL ||
400
		    buf[0] != '[' || (p = strchr(buf, ']')) == NULL) {
474
		    buf[0] != '[' || (p = strchr(buf, ']')) == NULL) {
401
			free(buf);
475
			free(buf);
402
			continue;
476
			continue;
403
		}
477
		}
404
478
405
		*p = '\0';
479
		*p = '\0';
406
		p = buf+1;
480
		atom = atom_explode(buf+1);
407
		q = p + strlen(p) + 1;
481
		print_current_emerge(logfile, atom);
408
482
		atom_implode(atom);
409
		printf(
410
			" %s*%s %s%s%s\n"
411
			"     started: %s%s%s\n"
412
			"     elapsed: ", /*%s%llu%s seconds\n",*/
413
			BOLD, NORM, BLUE, p, NORM,
414
			GREEN, chop_ctime(ip[i].ki_start.tv_sec), NORM);
415
		print_seconds_for_earthlings(time(0) - ip[i].ki_start.tv_sec);
416
		puts(NORM);
417
418
		free(buf);
483
		free(buf);
419
	}
484
	}
420
421
	if (start_date == 0 && verbose)
422
		puts("No emerge processes located");
423
}
485
}
424
#else
486
#else
425
void show_current_emerge(void)
487
void show_current_emerge(const char *logfile)
426
{
488
{
427
	errf("not supported on your crapbox OS");
489
	errf("not supported on your crapbox OS");
428
}
490
}
429
#endif
491
#endif
430
492
431
int qlop_main(int argc, char **argv)
493
int qlop_main(int argc, char **argv)
432
{
494
{
433
	int i, average = 1;
495
	int i, average = 1;
434
	char do_time, do_list, do_unlist, do_sync, do_current, do_human_readable = 0;
496
	char do_time, do_list, do_unlist, do_sync, do_current, do_human_readable = 0;
435
	char *opt_logfile;
497
	char *opt_logfile;
436
	const char *logfile = QLOP_DEFAULT_LOGFILE;
498
	const char *logfile = QLOP_DEFAULT_LOGFILE;
437
499
438
	DBG("argc=%d argv[0]=%s argv[1]=%s",
500
	DBG("argc=%d argv[0]=%s argv[1]=%s",
439
		argc, argv[0], argc > 1 ? argv[1] : "NULL?");
501
		argc, argv[0], argc > 1 ? argv[1] : "NULL?");
440
502
441
	opt_logfile = NULL;
503
	opt_logfile = NULL;
442
	do_time = do_list = do_unlist = do_sync = do_current = 0;
504
	do_time = do_list = do_unlist = do_sync = do_current = 0;
443
505
444
	while ((i = GETOPT_LONG(QLOP, qlop, "")) != -1) {
506
	while ((i = GETOPT_LONG(QLOP, qlop, "")) != -1) {
445
		switch (i) {
507
		switch (i) {
446
			COMMON_GETOPTS_CASES(qlop)
508
			COMMON_GETOPTS_CASES(qlop)
447
509
448
			case 't': do_time = 1; break;
510
			case 't': do_time = 1; break;
449
			case 'l': do_list = 1; break;
511
			case 'l': do_list = 1; break;
450
			case 'u': do_unlist = 1; break;
512
			case 'u': do_unlist = 1; break;
451
			case 's': do_sync = 1; break;
513
			case 's': do_sync = 1; break;
452
			case 'c': do_current = 1; break;
514
			case 'c': do_current = 1; break;
453
			case 'g': do_time = 1; average = 0; break;
515
			case 'g': do_time = 1; average = 0; break;
454
			case 'H': do_human_readable = 1; break;
516
			case 'H': do_human_readable = 1; break;
455
			case 'f':
517
			case 'f':
456
				if (opt_logfile) err("Only use -f once");
518
				if (opt_logfile) err("Only use -f once");
457
				opt_logfile = xstrdup(optarg);
519
				opt_logfile = xstrdup(optarg);
458
				break;
520
				break;
459
		}
521
		}
460
	}
522
	}
461
	if (!do_list && !do_unlist && !do_time && !do_sync && !do_current)
523
	if (!do_list && !do_unlist && !do_time && !do_sync && !do_current)
462
		qlop_usage(EXIT_FAILURE);
524
		qlop_usage(EXIT_FAILURE);
463
	if (opt_logfile != NULL)
525
	if (opt_logfile != NULL)
464
		logfile = opt_logfile;
526
		logfile = opt_logfile;
465
527
466
	argc -= optind;
528
	argc -= optind;
467
	argv += optind;
529
	argv += optind;
468
530
469
	if (do_list && do_unlist)
531
	if (do_list && do_unlist)
470
		show_emerge_history(QLOP_LIST | QLOP_UNLIST, argc, argv, logfile);
532
		show_emerge_history(QLOP_LIST | QLOP_UNLIST, argc, argv, logfile);
471
	else if (do_list)
533
	else if (do_list)
472
		show_emerge_history(QLOP_LIST, argc, argv, logfile);
534
		show_emerge_history(QLOP_LIST, argc, argv, logfile);
473
	else if (do_unlist)
535
	else if (do_unlist)
474
		show_emerge_history(QLOP_UNLIST, argc, argv, logfile);
536
		show_emerge_history(QLOP_UNLIST, argc, argv, logfile);
475
	if (do_current)
537
	if (do_current)
476
		show_current_emerge();
538
		show_current_emerge(logfile);
477
	if (do_sync)
539
	if (do_sync)
478
		show_sync_history(logfile);
540
		show_sync_history(logfile);
479
541
480
	if (do_time) {
542
	if (do_time) {
481
		for (i = 0; i < argc; ++i)
543
		for (i = 0; i < argc; ++i)
482
			show_merge_times(argv[i], logfile, average, do_human_readable);
544
			show_merge_times(argv[i], logfile, average, do_human_readable);
483
	}
545
	}
484
546
485
	if (opt_logfile) free(opt_logfile);
547
	if (opt_logfile) free(opt_logfile);
486
548
487
	return EXIT_SUCCESS;
549
	return EXIT_SUCCESS;
488
}
550
}
489
551
490
#else
552
#else
491
DEFINE_APPLET_STUB(qlop)
553
DEFINE_APPLET_STUB(qlop)
492
#endif
554
#endif

Return to bug 161244