10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*4845Svikram * Common Development and Distribution License (the "License").
6*4845Svikram * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*4845Svikram * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <sys/ctfs.h>
290Sstevel@tonic-gate #include <unistd.h>
300Sstevel@tonic-gate #include <fcntl.h>
310Sstevel@tonic-gate #include <errno.h>
320Sstevel@tonic-gate #include <limits.h>
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <assert.h>
350Sstevel@tonic-gate #include <libuutil.h>
36*4845Svikram #include <libintl.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <procfs.h>
390Sstevel@tonic-gate #include <libcontract.h>
400Sstevel@tonic-gate #include <libcontract_priv.h>
410Sstevel@tonic-gate #include "libcontract_impl.h"
420Sstevel@tonic-gate #include "process_dump.h"
43*4845Svikram #include "device_dump.h"
440Sstevel@tonic-gate
450Sstevel@tonic-gate
460Sstevel@tonic-gate contract_type_t types[CTT_MAXTYPE] = {
47*4845Svikram { "process", event_process },
48*4845Svikram { "device", event_device }
490Sstevel@tonic-gate };
500Sstevel@tonic-gate
510Sstevel@tonic-gate static int
close_on_exec(int fd)520Sstevel@tonic-gate close_on_exec(int fd)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate int flags = fcntl(fd, F_GETFD, 0);
550Sstevel@tonic-gate if ((flags != -1) && (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1))
560Sstevel@tonic-gate return (0);
570Sstevel@tonic-gate return (-1);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate
600Sstevel@tonic-gate int
contract_latest(ctid_t * id)610Sstevel@tonic-gate contract_latest(ctid_t *id)
620Sstevel@tonic-gate {
630Sstevel@tonic-gate int cfd, r;
640Sstevel@tonic-gate ct_stathdl_t st;
650Sstevel@tonic-gate ctid_t result;
660Sstevel@tonic-gate
670Sstevel@tonic-gate if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1)
680Sstevel@tonic-gate return (errno);
690Sstevel@tonic-gate
700Sstevel@tonic-gate if ((r = ct_status_read(cfd, CTD_COMMON, &st)) != 0) {
710Sstevel@tonic-gate (void) close(cfd);
720Sstevel@tonic-gate return (r);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate
750Sstevel@tonic-gate result = ct_status_get_id(st);
760Sstevel@tonic-gate ct_status_free(st);
770Sstevel@tonic-gate (void) close(cfd);
780Sstevel@tonic-gate
790Sstevel@tonic-gate *id = result;
800Sstevel@tonic-gate return (0);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate int
contract_open(ctid_t ctid,const char * type,const char * file,int oflag)840Sstevel@tonic-gate contract_open(ctid_t ctid, const char *type, const char *file, int oflag)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate char path[PATH_MAX];
870Sstevel@tonic-gate int n, fd;
880Sstevel@tonic-gate
890Sstevel@tonic-gate assert((oflag & O_CREAT) == 0);
900Sstevel@tonic-gate
910Sstevel@tonic-gate if (type == NULL)
920Sstevel@tonic-gate type = "all";
930Sstevel@tonic-gate
940Sstevel@tonic-gate n = snprintf(path, PATH_MAX, CTFS_ROOT "/%s/%ld/%s", type, ctid, file);
950Sstevel@tonic-gate if (n >= PATH_MAX) {
960Sstevel@tonic-gate errno = ENAMETOOLONG;
970Sstevel@tonic-gate return (-1);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate
1000Sstevel@tonic-gate fd = open64(path, oflag);
1010Sstevel@tonic-gate if (fd != -1) {
1020Sstevel@tonic-gate if (close_on_exec(fd) == -1) {
1030Sstevel@tonic-gate int err = errno;
1040Sstevel@tonic-gate (void) close(fd);
1050Sstevel@tonic-gate errno = err;
1060Sstevel@tonic-gate return (-1);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate return (fd);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate int
contract_abandon_id(ctid_t ctid)1130Sstevel@tonic-gate contract_abandon_id(ctid_t ctid)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate int fd, err;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate fd = contract_open(ctid, "all", "ctl", O_WRONLY);
1180Sstevel@tonic-gate if (fd == -1)
1190Sstevel@tonic-gate return (errno);
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate err = ct_ctl_abandon(fd);
1220Sstevel@tonic-gate (void) close(fd);
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate return (err);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate ctid_t
getctid(void)1280Sstevel@tonic-gate getctid(void)
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate int fd;
1310Sstevel@tonic-gate psinfo_t ps;
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
1340Sstevel@tonic-gate return (-1);
1350Sstevel@tonic-gate if (read(fd, &ps, sizeof (ps)) != sizeof (ps)) {
1360Sstevel@tonic-gate (void) close(fd);
1370Sstevel@tonic-gate return (-1);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate (void) close(fd);
1400Sstevel@tonic-gate return (ps.pr_contract);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate void
contract_event_dump(FILE * file,ct_evthdl_t hdl,int verbose)1440Sstevel@tonic-gate contract_event_dump(FILE *file, ct_evthdl_t hdl, int verbose)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate ct_typeid_t type;
1470Sstevel@tonic-gate struct ctlib_event_info *info = hdl;
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate type = info->event.ctev_cttype;
1500Sstevel@tonic-gate types[type].type_event(file, hdl, verbose);
1510Sstevel@tonic-gate }
152*4845Svikram
153*4845Svikram void
contract_negend_dump(FILE * file,ct_evthdl_t ev)154*4845Svikram contract_negend_dump(FILE *file, ct_evthdl_t ev)
155*4845Svikram {
156*4845Svikram ctevid_t nevid = 0;
157*4845Svikram ctid_t my_ctid = ct_event_get_ctid(ev);
158*4845Svikram ctid_t new_ctid = 0;
159*4845Svikram char *s;
160*4845Svikram
161*4845Svikram (void) ct_event_get_nevid(ev, &nevid);
162*4845Svikram (void) ct_event_get_newct(ev, &new_ctid);
163*4845Svikram
164*4845Svikram if (new_ctid != my_ctid) {
165*4845Svikram s = dgettext(TEXT_DOMAIN, "negotiation %llu succeeded\n");
166*4845Svikram } else {
167*4845Svikram s = dgettext(TEXT_DOMAIN, "negotiation %llu failed\n");
168*4845Svikram }
169*4845Svikram /*LINTED*/
170*4845Svikram (void) fprintf(file, s, (unsigned long long)nevid);
171*4845Svikram }
172