1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * wracct - write system accounting records
31 */
32
33#include <sys/types.h>
34#include <sys/procset.h>
35#include <exacct.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <libintl.h>
39#include <strings.h>
40#include <errno.h>
41
42#define	CMDNAME "wracct"
43#define	USAGE \
44    gettext("Usage: wracct -i id_list [-t partial | interval ] " \
45	"{process | task}\n")
46#define	OPTIONS_STRING "i:t:"
47
48static void
49usage(void)
50{
51	(void) fprintf(stderr, USAGE);
52	exit(2);
53}
54
55static long
56Atol(char *p)
57{
58	long l;
59	char *q;
60	errno = 0;
61	l = strtol(p, &q, 10);
62	if (errno != 0 || q == p || l < 0 || *q != '\0') {
63		(void) fprintf(stderr, gettext("%s: illegal argument -- %s\n"),
64		    CMDNAME, p);
65		exit(2);
66		/*NOTREACHED*/
67	} else {
68		return (l);
69	}
70}
71
72int
73main(int argc, char *argv[])
74{
75	idtype_t ent_flag = -1;
76	int rec_flag = EW_PARTIAL;
77	id_t id = -1;
78	char *id_sequence = NULL;
79	char *idlp = NULL;
80	int c, r;
81
82	while ((c = getopt(argc, argv, OPTIONS_STRING)) != EOF) {
83		switch (c) {
84			case 't':
85				if (strcmp(optarg, "partial") == 0) {
86					rec_flag = EW_PARTIAL;
87				} else if (strcmp(optarg, "interval") == 0) {
88					rec_flag = EW_INTERVAL;
89				} else {
90					(void) fprintf(stderr,
91					    gettext("%s: wrong record type\n"),
92					    CMDNAME);
93					usage();
94				}
95				break;
96			case 'i':
97				id_sequence = strdup(optarg);
98				break;
99			case '?':
100			default:
101				usage();
102				break;
103		}
104	}
105
106	if (optind >= argc) {
107		usage();
108	}
109
110	if (strcmp(argv[optind], "task") == 0) {
111		ent_flag = P_TASKID;
112	} else if (strcmp(argv[optind], "process") == 0 ||
113	    strcmp(argv[optind], "proc") == 0) {
114		ent_flag = P_PID;
115	} else {
116		usage();
117	}
118
119	if (ent_flag == P_PID && rec_flag == EW_INTERVAL) {
120		(void) fprintf(stderr,
121		    gettext("%s: interval process records not supported\n"),
122		    CMDNAME);
123		exit(2);
124	}
125
126	if (id_sequence == NULL) {
127		(void) fprintf(stderr,
128		    gettext("%s: please use -i option to specify ids\n"),
129		    CMDNAME);
130		exit(2);
131	}
132
133	for (idlp = strtok(id_sequence, ", \t\n"); idlp != NULL;
134	    idlp = strtok(NULL, ", \t\n")) {
135		id = Atol(idlp);
136		if (wracct(ent_flag, id, rec_flag) < 0) {
137			r = errno;
138			(void) fprintf(stderr,
139			    "%s: operation failed on %s %d: %s\n",
140			    CMDNAME, (ent_flag == P_TASKID) ? "taskid" : "pid",
141			    (int)id, strerror(r));
142			exit(1);
143		}
144	}
145
146	return (0);
147}
148