1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 23*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 29*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 30*7c478bd9Sstevel@tonic-gate * All Rights Reserved 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 33*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 34*7c478bd9Sstevel@tonic-gate * contributors. 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <stdio.h> 40*7c478bd9Sstevel@tonic-gate #include <signal.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 42*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 43*7c478bd9Sstevel@tonic-gate #include <memory.h> 44*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 45*7c478bd9Sstevel@tonic-gate #include <stropts.h> 46*7c478bd9Sstevel@tonic-gate #include <syslog.h> 47*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 48*7c478bd9Sstevel@tonic-gate #include <rpcsvc/rusers.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 50*7c478bd9Sstevel@tonic-gate #include <limits.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 53*7c478bd9Sstevel@tonic-gate #define RPC_SVC_FG 54*7c478bd9Sstevel@tonic-gate #endif 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #define _RPCSVC_CLOSEDOWN 120 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate static void rusers_service(); 59*7c478bd9Sstevel@tonic-gate static void closedown(); 60*7c478bd9Sstevel@tonic-gate static void msgout(); 61*7c478bd9Sstevel@tonic-gate static unsigned min(); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate static int _rpcpmstart; /* Started by a port monitor ? */ 64*7c478bd9Sstevel@tonic-gate static int _rpcfdtype; /* Whether Stream or Datagram ? */ 65*7c478bd9Sstevel@tonic-gate static int _rpcsvcdirty; /* Still serving ? */ 66*7c478bd9Sstevel@tonic-gate static int _rpcsvcrecent; /* set when we serivce a request; tested */ 67*7c478bd9Sstevel@tonic-gate /* and cleared by closedown() routine */ 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define DIV60(t) ((t+30)/60) /* x/60 rounded */ 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #define ALL_ENTRIES 1 72*7c478bd9Sstevel@tonic-gate #define REAL_USERS 0 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate utmp_array utmp_array_res; 75*7c478bd9Sstevel@tonic-gate int used_array_len = 0; 76*7c478bd9Sstevel@tonic-gate struct utmpidlearr utmpidlearr; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate main() 79*7c478bd9Sstevel@tonic-gate { 80*7c478bd9Sstevel@tonic-gate pid_t pid; 81*7c478bd9Sstevel@tonic-gate int i; 82*7c478bd9Sstevel@tonic-gate int connmaxrec = RPC_MAXDATASIZE; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * Set non-blocking mode and maximum record size for 86*7c478bd9Sstevel@tonic-gate * connection oriented RPC transports. 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) { 89*7c478bd9Sstevel@tonic-gate msgout("unable to set maximum RPC record size"); 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* 93*7c478bd9Sstevel@tonic-gate * If stdin looks like a TLI endpoint, we assume 94*7c478bd9Sstevel@tonic-gate * that we were started by a port monitor. If 95*7c478bd9Sstevel@tonic-gate * t_getstate fails with TBADF, this is not a 96*7c478bd9Sstevel@tonic-gate * TLI endpoint. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate if (t_getstate(0) != -1 || t_errno != TBADF) { 99*7c478bd9Sstevel@tonic-gate char *netid; 100*7c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL; 101*7c478bd9Sstevel@tonic-gate SVCXPRT *transp; 102*7c478bd9Sstevel@tonic-gate int pmclose; 103*7c478bd9Sstevel@tonic-gate extern char *getenv(); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate _rpcpmstart = 1; 106*7c478bd9Sstevel@tonic-gate openlog("rusers", LOG_PID, LOG_DAEMON); 107*7c478bd9Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 108*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 109*7c478bd9Sstevel@tonic-gate msgout("cannot get transport name"); 110*7c478bd9Sstevel@tonic-gate #endif 111*7c478bd9Sstevel@tonic-gate } else if ((nconf = getnetconfigent(netid)) == NULL) { 112*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 113*7c478bd9Sstevel@tonic-gate msgout("cannot get transport info"); 114*7c478bd9Sstevel@tonic-gate #endif 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 117*7c478bd9Sstevel@tonic-gate msgout("cannot create server handle"); 118*7c478bd9Sstevel@tonic-gate exit(1); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate if (nconf) 121*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 122*7c478bd9Sstevel@tonic-gate if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_3, rusers_service, 123*7c478bd9Sstevel@tonic-gate 0)) { 124*7c478bd9Sstevel@tonic-gate msgout("unable to register (RUSERSPROG, RUSERSVERS_3)."); 125*7c478bd9Sstevel@tonic-gate exit(1); 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE, 128*7c478bd9Sstevel@tonic-gate rusers_service, 0)) { 129*7c478bd9Sstevel@tonic-gate msgout("unable to register (RUSERSPROG, RUSERSVERS_IDLE)."); 130*7c478bd9Sstevel@tonic-gate exit(1); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, closedown); 133*7c478bd9Sstevel@tonic-gate (void) alarm(_RPCSVC_CLOSEDOWN); 134*7c478bd9Sstevel@tonic-gate svc_run(); 135*7c478bd9Sstevel@tonic-gate msgout("svc_run returned"); 136*7c478bd9Sstevel@tonic-gate exit(1); 137*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate #ifndef RPC_SVC_FG 140*7c478bd9Sstevel@tonic-gate pid = fork(); 141*7c478bd9Sstevel@tonic-gate if (pid < 0) { 142*7c478bd9Sstevel@tonic-gate perror("rpc.rusersd: cannot fork"); 143*7c478bd9Sstevel@tonic-gate exit(1); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate if (pid) 146*7c478bd9Sstevel@tonic-gate exit(0); 147*7c478bd9Sstevel@tonic-gate for (i = 0; i < 20; i++) 148*7c478bd9Sstevel@tonic-gate (void) close(i); 149*7c478bd9Sstevel@tonic-gate setsid(); 150*7c478bd9Sstevel@tonic-gate openlog("rusers", LOG_PID, LOG_DAEMON); 151*7c478bd9Sstevel@tonic-gate #endif 152*7c478bd9Sstevel@tonic-gate if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_3, "netpath")) { 153*7c478bd9Sstevel@tonic-gate msgout("unable to create (RUSERSPROG, RUSERSVERS_3) for netpath"); 154*7c478bd9Sstevel@tonic-gate exit(1); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE, 157*7c478bd9Sstevel@tonic-gate "netpath")) { 158*7c478bd9Sstevel@tonic-gate msgout( 159*7c478bd9Sstevel@tonic-gate "unable to create (RUSERSPROG, RUSERSVERS_IDLE) for netpath"); 160*7c478bd9Sstevel@tonic-gate exit(1); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate svc_run(); 164*7c478bd9Sstevel@tonic-gate msgout("svc_run returned"); 165*7c478bd9Sstevel@tonic-gate exit(1); 166*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * This routine gets the user information. 172*7c478bd9Sstevel@tonic-gate * "all" specifies whether all listings should be counted, or only those of 173*7c478bd9Sstevel@tonic-gate * type "USER_PROCESS". 174*7c478bd9Sstevel@tonic-gate * "version" is either RUSERSVERS_IDLE or RUSERSVERS_3. If anything else, 175*7c478bd9Sstevel@tonic-gate * just a count is returned. 176*7c478bd9Sstevel@tonic-gate * "limit" specifies the maximum number of entries to be processed. 177*7c478bd9Sstevel@tonic-gate * 178*7c478bd9Sstevel@tonic-gate * For both versions, the results are placed into an external variable. 179*7c478bd9Sstevel@tonic-gate * For RUSERSVERS_IDLE, this routine mallocs entries in a vector as it 180*7c478bd9Sstevel@tonic-gate * processed each utmpx entry. These malloc'd entries must be freed after the 181*7c478bd9Sstevel@tonic-gate * results are returned. 182*7c478bd9Sstevel@tonic-gate * For RUSERSVERS_3, this routine uses array entries that are malloc'd prior 183*7c478bd9Sstevel@tonic-gate * to this routine being called. "limit" is the number of elements available. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate int 186*7c478bd9Sstevel@tonic-gate getutmpx_3(all, version, limit) 187*7c478bd9Sstevel@tonic-gate int all; /* give all listings? */ 188*7c478bd9Sstevel@tonic-gate int version; /* version 2 or 3 */ 189*7c478bd9Sstevel@tonic-gate int limit; /* limits users returned, 0 means no limit */ 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate struct utmpx *utent; 192*7c478bd9Sstevel@tonic-gate struct utmpidle **q = utmpidlearr.uia_arr; 193*7c478bd9Sstevel@tonic-gate int minidle; 194*7c478bd9Sstevel@tonic-gate int cnt = 0; 195*7c478bd9Sstevel@tonic-gate time_t now; 196*7c478bd9Sstevel@tonic-gate extern char *s_malodup(); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate time(&now); /* only one call to time() for this rpc call */ 199*7c478bd9Sstevel@tonic-gate setutxent(); /* reset the utmpx file */ 200*7c478bd9Sstevel@tonic-gate while ((utent = getutxent()) != NULL && (limit == 0 || cnt < limit)) { 201*7c478bd9Sstevel@tonic-gate if (utent->ut_line[0] == '\0' || utent->ut_user[0] == '\0') 202*7c478bd9Sstevel@tonic-gate continue; 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * List only user processes. 205*7c478bd9Sstevel@tonic-gate * XXX modified to exclude cmdtool style window entries. 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate if ((all == REAL_USERS) && ((utent->ut_type != USER_PROCESS) || 208*7c478bd9Sstevel@tonic-gate nonuserx(*utent))) 209*7c478bd9Sstevel@tonic-gate continue; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if (version == RUSERSVERS_IDLE) { 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * need to free this; done after svc_sendreply. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate *q = (struct utmpidle *) 216*7c478bd9Sstevel@tonic-gate malloc(sizeof (struct utmpidle)); 217*7c478bd9Sstevel@tonic-gate (*q)->ui_idle = findidle(utent->ut_line, 218*7c478bd9Sstevel@tonic-gate sizeof (utent->ut_line), now); 219*7c478bd9Sstevel@tonic-gate if (strncmp(utent->ut_line, "console", 220*7c478bd9Sstevel@tonic-gate strlen("console")) == 0) { 221*7c478bd9Sstevel@tonic-gate (*q)->ui_idle = min((*q)->ui_idle, 222*7c478bd9Sstevel@tonic-gate console_idle(now)); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate usys5to_ru(utent, &((*q)->ui_utmp)); 225*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 226*7c478bd9Sstevel@tonic-gate printf("%-*s %-*s %s; idle %d", 227*7c478bd9Sstevel@tonic-gate sizeof (utent->ut_line), 228*7c478bd9Sstevel@tonic-gate utent->ut_line, 229*7c478bd9Sstevel@tonic-gate sizeof (utent->ut_name), 230*7c478bd9Sstevel@tonic-gate utent->ut_name, 231*7c478bd9Sstevel@tonic-gate ctime(&utent->ut_xtime), 232*7c478bd9Sstevel@tonic-gate (*q)->ui_idle); 233*7c478bd9Sstevel@tonic-gate #endif 234*7c478bd9Sstevel@tonic-gate q++; 235*7c478bd9Sstevel@tonic-gate } else if (version == RUSERSVERS_3) { 236*7c478bd9Sstevel@tonic-gate #define uav utmp_array_res.utmp_array_val 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate uav[cnt].ut_host = 239*7c478bd9Sstevel@tonic-gate s_malodup(utent->ut_host, utent->ut_syslen); 240*7c478bd9Sstevel@tonic-gate uav[cnt].ut_user = s_malodup(utent->ut_user, 241*7c478bd9Sstevel@tonic-gate sizeof (utent->ut_user)); 242*7c478bd9Sstevel@tonic-gate uav[cnt].ut_line = s_malodup(utent->ut_line, 243*7c478bd9Sstevel@tonic-gate sizeof (utent->ut_line)); 244*7c478bd9Sstevel@tonic-gate uav[cnt].ut_type = utent->ut_type; 245*7c478bd9Sstevel@tonic-gate uav[cnt].ut_time = utent->ut_xtime; 246*7c478bd9Sstevel@tonic-gate uav[cnt].ut_idle = findidle(utent->ut_line, 247*7c478bd9Sstevel@tonic-gate sizeof (utent->ut_line), now); 248*7c478bd9Sstevel@tonic-gate if (strncmp(utent->ut_line, "console", 249*7c478bd9Sstevel@tonic-gate strlen("console")) == 0) { 250*7c478bd9Sstevel@tonic-gate uav[cnt].ut_idle = 251*7c478bd9Sstevel@tonic-gate min(uav[cnt].ut_idle, 252*7c478bd9Sstevel@tonic-gate console_idle(now)); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 255*7c478bd9Sstevel@tonic-gate printf("user: %-10s line: %-10s %s; idle %d (%s)\n", 256*7c478bd9Sstevel@tonic-gate uav[cnt].ut_line, uav[cnt].ut_user, 257*7c478bd9Sstevel@tonic-gate ctime((time_t *)&uav[cnt].ut_time), 258*7c478bd9Sstevel@tonic-gate uav[cnt].ut_idle, uav[cnt].ut_host); 259*7c478bd9Sstevel@tonic-gate #endif 260*7c478bd9Sstevel@tonic-gate #undef uav 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate cnt++; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate return (cnt); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* 268*7c478bd9Sstevel@tonic-gate * "string" is a character array with maximum size "size". Return a 269*7c478bd9Sstevel@tonic-gate * malloc'd string that's a duplicate of the string. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate char * 272*7c478bd9Sstevel@tonic-gate s_malodup(string, size) 273*7c478bd9Sstevel@tonic-gate char *string; 274*7c478bd9Sstevel@tonic-gate int size; 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate char *tmp; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate tmp = (char *)malloc(size+1); 279*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 280*7c478bd9Sstevel@tonic-gate msgout("rpc.rusersd: malloc failed (2)"); 281*7c478bd9Sstevel@tonic-gate return (NULL); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate strncpy(tmp, string, size); 284*7c478bd9Sstevel@tonic-gate tmp[size] = '\0'; 285*7c478bd9Sstevel@tonic-gate return (tmp); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate int 290*7c478bd9Sstevel@tonic-gate console_idle(now) 291*7c478bd9Sstevel@tonic-gate time_t now; 292*7c478bd9Sstevel@tonic-gate { 293*7c478bd9Sstevel@tonic-gate /* 294*7c478bd9Sstevel@tonic-gate * On the console, the user may be running a window system; if so, 295*7c478bd9Sstevel@tonic-gate * their activity will show up in the last-access times of 296*7c478bd9Sstevel@tonic-gate * "/dev/kbd" and "/dev/mouse", so take the minimum of the idle 297*7c478bd9Sstevel@tonic-gate * times on those two devices and "/dev/console" and treat that as 298*7c478bd9Sstevel@tonic-gate * the idle time. 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate return (min((unsigned)findidle("kbd", strlen("kbd"), now), 301*7c478bd9Sstevel@tonic-gate (unsigned)findidle("mouse", strlen("mouse"), now))); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate static void 305*7c478bd9Sstevel@tonic-gate rusers_service(rqstp, transp) 306*7c478bd9Sstevel@tonic-gate register struct svc_req *rqstp; 307*7c478bd9Sstevel@tonic-gate register SVCXPRT *transp; 308*7c478bd9Sstevel@tonic-gate { 309*7c478bd9Sstevel@tonic-gate int i; 310*7c478bd9Sstevel@tonic-gate int cnt; 311*7c478bd9Sstevel@tonic-gate char *replyerr = "rpc.rusersd: error replying to request"; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate _rpcsvcrecent = _rpcsvcdirty = 1; 314*7c478bd9Sstevel@tonic-gate switch (rqstp->rq_proc) { 315*7c478bd9Sstevel@tonic-gate case 0: 316*7c478bd9Sstevel@tonic-gate if (svc_sendreply(transp, xdr_void, 0) == FALSE) { 317*7c478bd9Sstevel@tonic-gate msgout(replyerr); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate case RUSERSPROC_NUM: 321*7c478bd9Sstevel@tonic-gate cnt = getutmpx_3(REAL_USERS, 0, 0); 322*7c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_u_long, (caddr_t)&cnt)) 323*7c478bd9Sstevel@tonic-gate msgout(replyerr); 324*7c478bd9Sstevel@tonic-gate break; 325*7c478bd9Sstevel@tonic-gate case RUSERSPROC_NAMES: 326*7c478bd9Sstevel@tonic-gate case RUSERSPROC_ALLNAMES: 327*7c478bd9Sstevel@tonic-gate if (rqstp->rq_vers == RUSERSVERS_IDLE) { 328*7c478bd9Sstevel@tonic-gate utmpidlearr.uia_arr = (struct utmpidle **) 329*7c478bd9Sstevel@tonic-gate malloc(MAXUSERS*sizeof (struct utmpidle *)); 330*7c478bd9Sstevel@tonic-gate utmpidlearr.uia_cnt = getutmpx_3(rqstp->rq_proc == 331*7c478bd9Sstevel@tonic-gate RUSERSPROC_ALLNAMES, 332*7c478bd9Sstevel@tonic-gate RUSERSVERS_IDLE, MAXUSERS); 333*7c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_utmpidlearr, 334*7c478bd9Sstevel@tonic-gate (caddr_t)&utmpidlearr)) 335*7c478bd9Sstevel@tonic-gate msgout(replyerr); 336*7c478bd9Sstevel@tonic-gate for (i = 0; i < utmpidlearr.uia_cnt; i++) { 337*7c478bd9Sstevel@tonic-gate free(utmpidlearr.uia_arr[i]); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate free(utmpidlearr.uia_arr); 340*7c478bd9Sstevel@tonic-gate } else if (rqstp->rq_vers == RUSERSVERS_3) { 341*7c478bd9Sstevel@tonic-gate int entries, alloc_array_len; 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * Always free strings from previous results array 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate for (i = 0; i < used_array_len; i++) { 347*7c478bd9Sstevel@tonic-gate free_ua_entry(&utmp_array_res.utmp_array_val[i]); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate entries = (rqstp->rq_proc == RUSERSPROC_ALLNAMES); 350*7c478bd9Sstevel@tonic-gate cnt = getutmpx_3(entries, 0, 0); /* get cnt */ 351*7c478bd9Sstevel@tonic-gate if (cnt > utmp_array_res.utmp_array_len) { 352*7c478bd9Sstevel@tonic-gate free(utmp_array_res.utmp_array_val); 353*7c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_len = 0; 354*7c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_val = (rusers_utmp *) 355*7c478bd9Sstevel@tonic-gate malloc(cnt * sizeof (rusers_utmp)); 356*7c478bd9Sstevel@tonic-gate if (utmp_array_res.utmp_array_val == NULL) { 357*7c478bd9Sstevel@tonic-gate msgout("rpc.rusersd: malloc failed (1)"); 358*7c478bd9Sstevel@tonic-gate break; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate alloc_array_len = cnt; 361*7c478bd9Sstevel@tonic-gate } else { 362*7c478bd9Sstevel@tonic-gate alloc_array_len = utmp_array_res.utmp_array_len; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate cnt = getutmpx_3(entries, RUSERSVERS_3, cnt); 365*7c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_len = used_array_len = cnt; 366*7c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_utmp_array, 367*7c478bd9Sstevel@tonic-gate (caddr_t)&utmp_array_res)) 368*7c478bd9Sstevel@tonic-gate msgout(replyerr); 369*7c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_len = alloc_array_len; 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate break; 372*7c478bd9Sstevel@tonic-gate default: 373*7c478bd9Sstevel@tonic-gate svcerr_noproc(transp); 374*7c478bd9Sstevel@tonic-gate break; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate _rpcsvcdirty = 0; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate free_ua_entry(uap) 381*7c478bd9Sstevel@tonic-gate rusers_utmp *uap; 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate if (uap == NULL) 384*7c478bd9Sstevel@tonic-gate return; 385*7c478bd9Sstevel@tonic-gate if (uap->ut_user) 386*7c478bd9Sstevel@tonic-gate free(uap->ut_user); 387*7c478bd9Sstevel@tonic-gate if (uap->ut_line) 388*7c478bd9Sstevel@tonic-gate free(uap->ut_line); 389*7c478bd9Sstevel@tonic-gate if (uap->ut_host) 390*7c478bd9Sstevel@tonic-gate free(uap->ut_host); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /* find & return number of minutes current tty has been idle */ 396*7c478bd9Sstevel@tonic-gate findidle(name, ln, now) 397*7c478bd9Sstevel@tonic-gate char *name; 398*7c478bd9Sstevel@tonic-gate int ln; 399*7c478bd9Sstevel@tonic-gate time_t now; 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate struct stat stbuf; 402*7c478bd9Sstevel@tonic-gate long lastaction, diff; 403*7c478bd9Sstevel@tonic-gate char ttyname[32]; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate strcpy(ttyname, "/dev/"); 406*7c478bd9Sstevel@tonic-gate strncat(ttyname, name, ln); 407*7c478bd9Sstevel@tonic-gate if (stat(ttyname, &stbuf) < 0) 408*7c478bd9Sstevel@tonic-gate return (INT_MAX); 409*7c478bd9Sstevel@tonic-gate lastaction = stbuf.st_atime; 410*7c478bd9Sstevel@tonic-gate diff = now - lastaction; 411*7c478bd9Sstevel@tonic-gate diff = DIV60(diff); 412*7c478bd9Sstevel@tonic-gate if (diff < 0) diff = 0; 413*7c478bd9Sstevel@tonic-gate return (diff); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate static 417*7c478bd9Sstevel@tonic-gate usys5to_ru(s5, bss) 418*7c478bd9Sstevel@tonic-gate struct utmpx *s5; 419*7c478bd9Sstevel@tonic-gate struct ru_utmp *bss; 420*7c478bd9Sstevel@tonic-gate { 421*7c478bd9Sstevel@tonic-gate int i; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 424*7c478bd9Sstevel@tonic-gate printf("sizeof (bss->ut_host) == %d\n", sizeof (bss->ut_host)); 425*7c478bd9Sstevel@tonic-gate #endif 426*7c478bd9Sstevel@tonic-gate strncpy(bss->ut_name, s5->ut_name, sizeof (bss->ut_name)); 427*7c478bd9Sstevel@tonic-gate strncpy(bss->ut_line, s5->ut_line, sizeof (bss->ut_line)); 428*7c478bd9Sstevel@tonic-gate strncpy(bss->ut_host, s5->ut_host, sizeof (bss->ut_host)); 429*7c478bd9Sstevel@tonic-gate bss->ut_time = s5->ut_xtime; 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate static void 433*7c478bd9Sstevel@tonic-gate msgout(msg) 434*7c478bd9Sstevel@tonic-gate char *msg; 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate #ifdef RPC_SVC_FG 437*7c478bd9Sstevel@tonic-gate if (_rpcpmstart) 438*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, msg); 439*7c478bd9Sstevel@tonic-gate else 440*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", msg); 441*7c478bd9Sstevel@tonic-gate #else 442*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, msg); 443*7c478bd9Sstevel@tonic-gate #endif 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate static void 447*7c478bd9Sstevel@tonic-gate closedown(sig) 448*7c478bd9Sstevel@tonic-gate int sig; 449*7c478bd9Sstevel@tonic-gate { 450*7c478bd9Sstevel@tonic-gate if (_rpcsvcrecent) { 451*7c478bd9Sstevel@tonic-gate _rpcsvcrecent = 0; 452*7c478bd9Sstevel@tonic-gate } else { 453*7c478bd9Sstevel@tonic-gate if (_rpcsvcdirty == 0) { 454*7c478bd9Sstevel@tonic-gate int i, openfd; 455*7c478bd9Sstevel@tonic-gate struct t_info tinfo; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (t_getinfo(0, &tinfo) || (tinfo.servtype == T_CLTS)) 458*7c478bd9Sstevel@tonic-gate exit(0); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate for (i = 0, openfd = 0; 461*7c478bd9Sstevel@tonic-gate i < svc_max_pollfd && openfd < 2; 462*7c478bd9Sstevel@tonic-gate i++) { 463*7c478bd9Sstevel@tonic-gate if (svc_pollfd[i].fd >= 0) 464*7c478bd9Sstevel@tonic-gate openfd++; 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate if (openfd <= 1) 468*7c478bd9Sstevel@tonic-gate exit(0); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, closedown); 472*7c478bd9Sstevel@tonic-gate (void) alarm(_RPCSVC_CLOSEDOWN); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate unsigned 476*7c478bd9Sstevel@tonic-gate min(a, b) 477*7c478bd9Sstevel@tonic-gate unsigned a; 478*7c478bd9Sstevel@tonic-gate unsigned b; 479*7c478bd9Sstevel@tonic-gate { 480*7c478bd9Sstevel@tonic-gate if (a < b) 481*7c478bd9Sstevel@tonic-gate return (a); 482*7c478bd9Sstevel@tonic-gate else 483*7c478bd9Sstevel@tonic-gate return (b); 484*7c478bd9Sstevel@tonic-gate } 485