17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate * 22*49e7ca49Speteh * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 267c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 297c478bd9Sstevel@tonic-gate * The Regents of the University of California 307c478bd9Sstevel@tonic-gate * All Rights Reserved 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 337c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 347c478bd9Sstevel@tonic-gate * contributors. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include <stdio.h> 407c478bd9Sstevel@tonic-gate #include <signal.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 437c478bd9Sstevel@tonic-gate #include <memory.h> 447c478bd9Sstevel@tonic-gate #include <netconfig.h> 457c478bd9Sstevel@tonic-gate #include <stropts.h> 467c478bd9Sstevel@tonic-gate #include <syslog.h> 477c478bd9Sstevel@tonic-gate #include <utmpx.h> 487c478bd9Sstevel@tonic-gate #include <rpcsvc/rusers.h> 497c478bd9Sstevel@tonic-gate #include <sys/resource.h> 507c478bd9Sstevel@tonic-gate #include <limits.h> 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #ifdef DEBUG 537c478bd9Sstevel@tonic-gate #define RPC_SVC_FG 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define _RPCSVC_CLOSEDOWN 120 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate static void rusers_service(); 597c478bd9Sstevel@tonic-gate static void closedown(); 607c478bd9Sstevel@tonic-gate static void msgout(); 617c478bd9Sstevel@tonic-gate static unsigned min(); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static int _rpcpmstart; /* Started by a port monitor ? */ 647c478bd9Sstevel@tonic-gate static int _rpcfdtype; /* Whether Stream or Datagram ? */ 657c478bd9Sstevel@tonic-gate static int _rpcsvcdirty; /* Still serving ? */ 667c478bd9Sstevel@tonic-gate static int _rpcsvcrecent; /* set when we serivce a request; tested */ 677c478bd9Sstevel@tonic-gate /* and cleared by closedown() routine */ 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #define DIV60(t) ((t+30)/60) /* x/60 rounded */ 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #define ALL_ENTRIES 1 727c478bd9Sstevel@tonic-gate #define REAL_USERS 0 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate utmp_array utmp_array_res; 757c478bd9Sstevel@tonic-gate int used_array_len = 0; 767c478bd9Sstevel@tonic-gate struct utmpidlearr utmpidlearr; 777c478bd9Sstevel@tonic-gate 78*49e7ca49Speteh static void free_ua_entry(rusers_utmp *uap); 79*49e7ca49Speteh static int findidle(char *name, int ln, time_t now); 80*49e7ca49Speteh static void usys5to_ru(struct utmpx *s5, struct ru_utmp *bss); 81*49e7ca49Speteh 82*49e7ca49Speteh int 83*49e7ca49Speteh main(int argc, char *argv[]) 847c478bd9Sstevel@tonic-gate { 857c478bd9Sstevel@tonic-gate pid_t pid; 867c478bd9Sstevel@tonic-gate int i; 877c478bd9Sstevel@tonic-gate int connmaxrec = RPC_MAXDATASIZE; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * Set non-blocking mode and maximum record size for 917c478bd9Sstevel@tonic-gate * connection oriented RPC transports. 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) { 947c478bd9Sstevel@tonic-gate msgout("unable to set maximum RPC record size"); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * If stdin looks like a TLI endpoint, we assume 997c478bd9Sstevel@tonic-gate * that we were started by a port monitor. If 1007c478bd9Sstevel@tonic-gate * t_getstate fails with TBADF, this is not a 1017c478bd9Sstevel@tonic-gate * TLI endpoint. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate if (t_getstate(0) != -1 || t_errno != TBADF) { 1047c478bd9Sstevel@tonic-gate char *netid; 1057c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL; 1067c478bd9Sstevel@tonic-gate SVCXPRT *transp; 1077c478bd9Sstevel@tonic-gate int pmclose; 1087c478bd9Sstevel@tonic-gate extern char *getenv(); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate _rpcpmstart = 1; 1117c478bd9Sstevel@tonic-gate openlog("rusers", LOG_PID, LOG_DAEMON); 1127c478bd9Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 1137c478bd9Sstevel@tonic-gate #ifdef DEBUG 1147c478bd9Sstevel@tonic-gate msgout("cannot get transport name"); 1157c478bd9Sstevel@tonic-gate #endif 1167c478bd9Sstevel@tonic-gate } else if ((nconf = getnetconfigent(netid)) == NULL) { 1177c478bd9Sstevel@tonic-gate #ifdef DEBUG 1187c478bd9Sstevel@tonic-gate msgout("cannot get transport info"); 1197c478bd9Sstevel@tonic-gate #endif 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 1227c478bd9Sstevel@tonic-gate msgout("cannot create server handle"); 1237c478bd9Sstevel@tonic-gate exit(1); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate if (nconf) 1267c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 1277c478bd9Sstevel@tonic-gate if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_3, rusers_service, 1287c478bd9Sstevel@tonic-gate 0)) { 1297c478bd9Sstevel@tonic-gate msgout("unable to register (RUSERSPROG, RUSERSVERS_3)."); 1307c478bd9Sstevel@tonic-gate exit(1); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE, 1337c478bd9Sstevel@tonic-gate rusers_service, 0)) { 1347c478bd9Sstevel@tonic-gate msgout("unable to register (RUSERSPROG, RUSERSVERS_IDLE)."); 1357c478bd9Sstevel@tonic-gate exit(1); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, closedown); 1387c478bd9Sstevel@tonic-gate (void) alarm(_RPCSVC_CLOSEDOWN); 1397c478bd9Sstevel@tonic-gate svc_run(); 1407c478bd9Sstevel@tonic-gate msgout("svc_run returned"); 1417c478bd9Sstevel@tonic-gate exit(1); 1427c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate #ifndef RPC_SVC_FG 1457c478bd9Sstevel@tonic-gate pid = fork(); 1467c478bd9Sstevel@tonic-gate if (pid < 0) { 1477c478bd9Sstevel@tonic-gate perror("rpc.rusersd: cannot fork"); 1487c478bd9Sstevel@tonic-gate exit(1); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate if (pid) 1517c478bd9Sstevel@tonic-gate exit(0); 1527c478bd9Sstevel@tonic-gate for (i = 0; i < 20; i++) 1537c478bd9Sstevel@tonic-gate (void) close(i); 1547c478bd9Sstevel@tonic-gate setsid(); 1557c478bd9Sstevel@tonic-gate openlog("rusers", LOG_PID, LOG_DAEMON); 1567c478bd9Sstevel@tonic-gate #endif 1577c478bd9Sstevel@tonic-gate if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_3, "netpath")) { 1587c478bd9Sstevel@tonic-gate msgout("unable to create (RUSERSPROG, RUSERSVERS_3) for netpath"); 1597c478bd9Sstevel@tonic-gate exit(1); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE, 1627c478bd9Sstevel@tonic-gate "netpath")) { 1637c478bd9Sstevel@tonic-gate msgout( 1647c478bd9Sstevel@tonic-gate "unable to create (RUSERSPROG, RUSERSVERS_IDLE) for netpath"); 1657c478bd9Sstevel@tonic-gate exit(1); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate svc_run(); 1697c478bd9Sstevel@tonic-gate msgout("svc_run returned"); 170*49e7ca49Speteh return (1); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * This routine gets the user information. 1767c478bd9Sstevel@tonic-gate * "all" specifies whether all listings should be counted, or only those of 1777c478bd9Sstevel@tonic-gate * type "USER_PROCESS". 1787c478bd9Sstevel@tonic-gate * "version" is either RUSERSVERS_IDLE or RUSERSVERS_3. If anything else, 1797c478bd9Sstevel@tonic-gate * just a count is returned. 1807c478bd9Sstevel@tonic-gate * "limit" specifies the maximum number of entries to be processed. 1817c478bd9Sstevel@tonic-gate * 1827c478bd9Sstevel@tonic-gate * For both versions, the results are placed into an external variable. 1837c478bd9Sstevel@tonic-gate * For RUSERSVERS_IDLE, this routine mallocs entries in a vector as it 1847c478bd9Sstevel@tonic-gate * processed each utmpx entry. These malloc'd entries must be freed after the 1857c478bd9Sstevel@tonic-gate * results are returned. 1867c478bd9Sstevel@tonic-gate * For RUSERSVERS_3, this routine uses array entries that are malloc'd prior 1877c478bd9Sstevel@tonic-gate * to this routine being called. "limit" is the number of elements available. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate int 1907c478bd9Sstevel@tonic-gate getutmpx_3(all, version, limit) 1917c478bd9Sstevel@tonic-gate int all; /* give all listings? */ 1927c478bd9Sstevel@tonic-gate int version; /* version 2 or 3 */ 1937c478bd9Sstevel@tonic-gate int limit; /* limits users returned, 0 means no limit */ 1947c478bd9Sstevel@tonic-gate { 1957c478bd9Sstevel@tonic-gate struct utmpx *utent; 1967c478bd9Sstevel@tonic-gate struct utmpidle **q = utmpidlearr.uia_arr; 1977c478bd9Sstevel@tonic-gate int minidle; 1987c478bd9Sstevel@tonic-gate int cnt = 0; 1997c478bd9Sstevel@tonic-gate time_t now; 2007c478bd9Sstevel@tonic-gate extern char *s_malodup(); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate time(&now); /* only one call to time() for this rpc call */ 2037c478bd9Sstevel@tonic-gate setutxent(); /* reset the utmpx file */ 2047c478bd9Sstevel@tonic-gate while ((utent = getutxent()) != NULL && (limit == 0 || cnt < limit)) { 2057c478bd9Sstevel@tonic-gate if (utent->ut_line[0] == '\0' || utent->ut_user[0] == '\0') 2067c478bd9Sstevel@tonic-gate continue; 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * List only user processes. 2097c478bd9Sstevel@tonic-gate * XXX modified to exclude cmdtool style window entries. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate if ((all == REAL_USERS) && ((utent->ut_type != USER_PROCESS) || 2127c478bd9Sstevel@tonic-gate nonuserx(*utent))) 2137c478bd9Sstevel@tonic-gate continue; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if (version == RUSERSVERS_IDLE) { 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * need to free this; done after svc_sendreply. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate *q = (struct utmpidle *) 2207c478bd9Sstevel@tonic-gate malloc(sizeof (struct utmpidle)); 2217c478bd9Sstevel@tonic-gate (*q)->ui_idle = findidle(utent->ut_line, 2227c478bd9Sstevel@tonic-gate sizeof (utent->ut_line), now); 2237c478bd9Sstevel@tonic-gate if (strncmp(utent->ut_line, "console", 2247c478bd9Sstevel@tonic-gate strlen("console")) == 0) { 2257c478bd9Sstevel@tonic-gate (*q)->ui_idle = min((*q)->ui_idle, 2267c478bd9Sstevel@tonic-gate console_idle(now)); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate usys5to_ru(utent, &((*q)->ui_utmp)); 2297c478bd9Sstevel@tonic-gate #ifdef DEBUG 2307c478bd9Sstevel@tonic-gate printf("%-*s %-*s %s; idle %d", 2317c478bd9Sstevel@tonic-gate sizeof (utent->ut_line), 2327c478bd9Sstevel@tonic-gate utent->ut_line, 2337c478bd9Sstevel@tonic-gate sizeof (utent->ut_name), 2347c478bd9Sstevel@tonic-gate utent->ut_name, 2357c478bd9Sstevel@tonic-gate ctime(&utent->ut_xtime), 2367c478bd9Sstevel@tonic-gate (*q)->ui_idle); 2377c478bd9Sstevel@tonic-gate #endif 2387c478bd9Sstevel@tonic-gate q++; 2397c478bd9Sstevel@tonic-gate } else if (version == RUSERSVERS_3) { 2407c478bd9Sstevel@tonic-gate #define uav utmp_array_res.utmp_array_val 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate uav[cnt].ut_host = 2437c478bd9Sstevel@tonic-gate s_malodup(utent->ut_host, utent->ut_syslen); 2447c478bd9Sstevel@tonic-gate uav[cnt].ut_user = s_malodup(utent->ut_user, 2457c478bd9Sstevel@tonic-gate sizeof (utent->ut_user)); 2467c478bd9Sstevel@tonic-gate uav[cnt].ut_line = s_malodup(utent->ut_line, 2477c478bd9Sstevel@tonic-gate sizeof (utent->ut_line)); 2487c478bd9Sstevel@tonic-gate uav[cnt].ut_type = utent->ut_type; 2497c478bd9Sstevel@tonic-gate uav[cnt].ut_time = utent->ut_xtime; 2507c478bd9Sstevel@tonic-gate uav[cnt].ut_idle = findidle(utent->ut_line, 2517c478bd9Sstevel@tonic-gate sizeof (utent->ut_line), now); 2527c478bd9Sstevel@tonic-gate if (strncmp(utent->ut_line, "console", 2537c478bd9Sstevel@tonic-gate strlen("console")) == 0) { 2547c478bd9Sstevel@tonic-gate uav[cnt].ut_idle = 2557c478bd9Sstevel@tonic-gate min(uav[cnt].ut_idle, 2567c478bd9Sstevel@tonic-gate console_idle(now)); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate #ifdef DEBUG 2597c478bd9Sstevel@tonic-gate printf("user: %-10s line: %-10s %s; idle %d (%s)\n", 2607c478bd9Sstevel@tonic-gate uav[cnt].ut_line, uav[cnt].ut_user, 2617c478bd9Sstevel@tonic-gate ctime((time_t *)&uav[cnt].ut_time), 2627c478bd9Sstevel@tonic-gate uav[cnt].ut_idle, uav[cnt].ut_host); 2637c478bd9Sstevel@tonic-gate #endif 2647c478bd9Sstevel@tonic-gate #undef uav 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate cnt++; 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate return (cnt); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * "string" is a character array with maximum size "size". Return a 2737c478bd9Sstevel@tonic-gate * malloc'd string that's a duplicate of the string. 2747c478bd9Sstevel@tonic-gate */ 2757c478bd9Sstevel@tonic-gate char * 2767c478bd9Sstevel@tonic-gate s_malodup(string, size) 2777c478bd9Sstevel@tonic-gate char *string; 2787c478bd9Sstevel@tonic-gate int size; 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate char *tmp; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate tmp = (char *)malloc(size+1); 2837c478bd9Sstevel@tonic-gate if (tmp == NULL) { 2847c478bd9Sstevel@tonic-gate msgout("rpc.rusersd: malloc failed (2)"); 2857c478bd9Sstevel@tonic-gate return (NULL); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate strncpy(tmp, string, size); 2887c478bd9Sstevel@tonic-gate tmp[size] = '\0'; 2897c478bd9Sstevel@tonic-gate return (tmp); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate int 2947c478bd9Sstevel@tonic-gate console_idle(now) 2957c478bd9Sstevel@tonic-gate time_t now; 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * On the console, the user may be running a window system; if so, 2997c478bd9Sstevel@tonic-gate * their activity will show up in the last-access times of 3007c478bd9Sstevel@tonic-gate * "/dev/kbd" and "/dev/mouse", so take the minimum of the idle 3017c478bd9Sstevel@tonic-gate * times on those two devices and "/dev/console" and treat that as 3027c478bd9Sstevel@tonic-gate * the idle time. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate return (min((unsigned)findidle("kbd", strlen("kbd"), now), 3057c478bd9Sstevel@tonic-gate (unsigned)findidle("mouse", strlen("mouse"), now))); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate static void 3097c478bd9Sstevel@tonic-gate rusers_service(rqstp, transp) 3107c478bd9Sstevel@tonic-gate register struct svc_req *rqstp; 3117c478bd9Sstevel@tonic-gate register SVCXPRT *transp; 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate int i; 3147c478bd9Sstevel@tonic-gate int cnt; 3157c478bd9Sstevel@tonic-gate char *replyerr = "rpc.rusersd: error replying to request"; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate _rpcsvcrecent = _rpcsvcdirty = 1; 3187c478bd9Sstevel@tonic-gate switch (rqstp->rq_proc) { 3197c478bd9Sstevel@tonic-gate case 0: 3207c478bd9Sstevel@tonic-gate if (svc_sendreply(transp, xdr_void, 0) == FALSE) { 3217c478bd9Sstevel@tonic-gate msgout(replyerr); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate break; 3247c478bd9Sstevel@tonic-gate case RUSERSPROC_NUM: 3257c478bd9Sstevel@tonic-gate cnt = getutmpx_3(REAL_USERS, 0, 0); 3267c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_u_long, (caddr_t)&cnt)) 3277c478bd9Sstevel@tonic-gate msgout(replyerr); 3287c478bd9Sstevel@tonic-gate break; 3297c478bd9Sstevel@tonic-gate case RUSERSPROC_NAMES: 3307c478bd9Sstevel@tonic-gate case RUSERSPROC_ALLNAMES: 3317c478bd9Sstevel@tonic-gate if (rqstp->rq_vers == RUSERSVERS_IDLE) { 3327c478bd9Sstevel@tonic-gate utmpidlearr.uia_arr = (struct utmpidle **) 3337c478bd9Sstevel@tonic-gate malloc(MAXUSERS*sizeof (struct utmpidle *)); 3347c478bd9Sstevel@tonic-gate utmpidlearr.uia_cnt = getutmpx_3(rqstp->rq_proc == 3357c478bd9Sstevel@tonic-gate RUSERSPROC_ALLNAMES, 3367c478bd9Sstevel@tonic-gate RUSERSVERS_IDLE, MAXUSERS); 3377c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_utmpidlearr, 3387c478bd9Sstevel@tonic-gate (caddr_t)&utmpidlearr)) 3397c478bd9Sstevel@tonic-gate msgout(replyerr); 3407c478bd9Sstevel@tonic-gate for (i = 0; i < utmpidlearr.uia_cnt; i++) { 3417c478bd9Sstevel@tonic-gate free(utmpidlearr.uia_arr[i]); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate free(utmpidlearr.uia_arr); 3447c478bd9Sstevel@tonic-gate } else if (rqstp->rq_vers == RUSERSVERS_3) { 3457c478bd9Sstevel@tonic-gate int entries, alloc_array_len; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * Always free strings from previous results array 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate for (i = 0; i < used_array_len; i++) { 3517c478bd9Sstevel@tonic-gate free_ua_entry(&utmp_array_res.utmp_array_val[i]); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate entries = (rqstp->rq_proc == RUSERSPROC_ALLNAMES); 3547c478bd9Sstevel@tonic-gate cnt = getutmpx_3(entries, 0, 0); /* get cnt */ 3557c478bd9Sstevel@tonic-gate if (cnt > utmp_array_res.utmp_array_len) { 3567c478bd9Sstevel@tonic-gate free(utmp_array_res.utmp_array_val); 3577c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_len = 0; 3587c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_val = (rusers_utmp *) 3597c478bd9Sstevel@tonic-gate malloc(cnt * sizeof (rusers_utmp)); 3607c478bd9Sstevel@tonic-gate if (utmp_array_res.utmp_array_val == NULL) { 3617c478bd9Sstevel@tonic-gate msgout("rpc.rusersd: malloc failed (1)"); 3627c478bd9Sstevel@tonic-gate break; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate alloc_array_len = cnt; 3657c478bd9Sstevel@tonic-gate } else { 3667c478bd9Sstevel@tonic-gate alloc_array_len = utmp_array_res.utmp_array_len; 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate cnt = getutmpx_3(entries, RUSERSVERS_3, cnt); 3697c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_len = used_array_len = cnt; 3707c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_utmp_array, 3717c478bd9Sstevel@tonic-gate (caddr_t)&utmp_array_res)) 3727c478bd9Sstevel@tonic-gate msgout(replyerr); 3737c478bd9Sstevel@tonic-gate utmp_array_res.utmp_array_len = alloc_array_len; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate default: 3777c478bd9Sstevel@tonic-gate svcerr_noproc(transp); 3787c478bd9Sstevel@tonic-gate break; 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate _rpcsvcdirty = 0; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 384*49e7ca49Speteh static void 385*49e7ca49Speteh free_ua_entry(rusers_utmp *uap) 3867c478bd9Sstevel@tonic-gate { 3877c478bd9Sstevel@tonic-gate if (uap == NULL) 3887c478bd9Sstevel@tonic-gate return; 3897c478bd9Sstevel@tonic-gate if (uap->ut_user) 3907c478bd9Sstevel@tonic-gate free(uap->ut_user); 3917c478bd9Sstevel@tonic-gate if (uap->ut_line) 3927c478bd9Sstevel@tonic-gate free(uap->ut_line); 3937c478bd9Sstevel@tonic-gate if (uap->ut_host) 3947c478bd9Sstevel@tonic-gate free(uap->ut_host); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* find & return number of minutes current tty has been idle */ 400*49e7ca49Speteh static int 401*49e7ca49Speteh findidle(char *name, int ln, time_t now) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate struct stat stbuf; 4047c478bd9Sstevel@tonic-gate long lastaction, diff; 4057c478bd9Sstevel@tonic-gate char ttyname[32]; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate strcpy(ttyname, "/dev/"); 4087c478bd9Sstevel@tonic-gate strncat(ttyname, name, ln); 4097c478bd9Sstevel@tonic-gate if (stat(ttyname, &stbuf) < 0) 4107c478bd9Sstevel@tonic-gate return (INT_MAX); 4117c478bd9Sstevel@tonic-gate lastaction = stbuf.st_atime; 4127c478bd9Sstevel@tonic-gate diff = now - lastaction; 4137c478bd9Sstevel@tonic-gate diff = DIV60(diff); 4147c478bd9Sstevel@tonic-gate if (diff < 0) diff = 0; 4157c478bd9Sstevel@tonic-gate return (diff); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 418*49e7ca49Speteh static void 419*49e7ca49Speteh usys5to_ru(struct utmpx *s5, struct ru_utmp *bss) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate int i; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate #ifdef DEBUG 4247c478bd9Sstevel@tonic-gate printf("sizeof (bss->ut_host) == %d\n", sizeof (bss->ut_host)); 4257c478bd9Sstevel@tonic-gate #endif 4267c478bd9Sstevel@tonic-gate strncpy(bss->ut_name, s5->ut_name, sizeof (bss->ut_name)); 4277c478bd9Sstevel@tonic-gate strncpy(bss->ut_line, s5->ut_line, sizeof (bss->ut_line)); 4287c478bd9Sstevel@tonic-gate strncpy(bss->ut_host, s5->ut_host, sizeof (bss->ut_host)); 4297c478bd9Sstevel@tonic-gate bss->ut_time = s5->ut_xtime; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate static void 4337c478bd9Sstevel@tonic-gate msgout(msg) 4347c478bd9Sstevel@tonic-gate char *msg; 4357c478bd9Sstevel@tonic-gate { 4367c478bd9Sstevel@tonic-gate #ifdef RPC_SVC_FG 4377c478bd9Sstevel@tonic-gate if (_rpcpmstart) 4387c478bd9Sstevel@tonic-gate syslog(LOG_ERR, msg); 4397c478bd9Sstevel@tonic-gate else 4407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", msg); 4417c478bd9Sstevel@tonic-gate #else 4427c478bd9Sstevel@tonic-gate syslog(LOG_ERR, msg); 4437c478bd9Sstevel@tonic-gate #endif 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate static void 4477c478bd9Sstevel@tonic-gate closedown(sig) 4487c478bd9Sstevel@tonic-gate int sig; 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate if (_rpcsvcrecent) { 4517c478bd9Sstevel@tonic-gate _rpcsvcrecent = 0; 4527c478bd9Sstevel@tonic-gate } else { 4537c478bd9Sstevel@tonic-gate if (_rpcsvcdirty == 0) { 4547c478bd9Sstevel@tonic-gate int i, openfd; 4557c478bd9Sstevel@tonic-gate struct t_info tinfo; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (t_getinfo(0, &tinfo) || (tinfo.servtype == T_CLTS)) 4587c478bd9Sstevel@tonic-gate exit(0); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate for (i = 0, openfd = 0; 4617c478bd9Sstevel@tonic-gate i < svc_max_pollfd && openfd < 2; 4627c478bd9Sstevel@tonic-gate i++) { 4637c478bd9Sstevel@tonic-gate if (svc_pollfd[i].fd >= 0) 4647c478bd9Sstevel@tonic-gate openfd++; 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (openfd <= 1) 4687c478bd9Sstevel@tonic-gate exit(0); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, closedown); 4727c478bd9Sstevel@tonic-gate (void) alarm(_RPCSVC_CLOSEDOWN); 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate unsigned 4767c478bd9Sstevel@tonic-gate min(a, b) 4777c478bd9Sstevel@tonic-gate unsigned a; 4787c478bd9Sstevel@tonic-gate unsigned b; 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate if (a < b) 4817c478bd9Sstevel@tonic-gate return (a); 4827c478bd9Sstevel@tonic-gate else 4837c478bd9Sstevel@tonic-gate return (b); 4847c478bd9Sstevel@tonic-gate } 485