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 */ 227c478bd9Sstevel@tonic-gate /* 23*20d7339fSgww * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.15.1.2 */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * logins.c 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * This file contains the source for the administrative command 367c478bd9Sstevel@tonic-gate * "logins" (available to the administrator) that produces a report 377c478bd9Sstevel@tonic-gate * containing login-IDs and other requested information. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <stdio.h> 42*20d7339fSgww #include <stdlib.h> 437c478bd9Sstevel@tonic-gate #include <unistd.h> 447c478bd9Sstevel@tonic-gate #include <string.h> 457c478bd9Sstevel@tonic-gate #include <ctype.h> 467c478bd9Sstevel@tonic-gate #include <grp.h> 477c478bd9Sstevel@tonic-gate #include <pwd.h> 487c478bd9Sstevel@tonic-gate #include <shadow.h> 497c478bd9Sstevel@tonic-gate #include <time.h> 507c478bd9Sstevel@tonic-gate #include <stdarg.h> 517c478bd9Sstevel@tonic-gate #include <fmtmsg.h> 527c478bd9Sstevel@tonic-gate #include <locale.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * Local constant definitions 567c478bd9Sstevel@tonic-gate * TRUE Boolean constant 577c478bd9Sstevel@tonic-gate * FALSE Boolean constant 587c478bd9Sstevel@tonic-gate * USAGE_MSG Message used to display a usage error 597c478bd9Sstevel@tonic-gate * MAXLOGINSIZE Maximum length of a valid login-ID 607c478bd9Sstevel@tonic-gate * MAXSYSTEMLOGIN Maximum value of a system user-ID. 617c478bd9Sstevel@tonic-gate * OPTSTR Options to this command 627c478bd9Sstevel@tonic-gate * ROOT_ID The user-ID of an administrator 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #ifndef FALSE 667c478bd9Sstevel@tonic-gate #define FALSE 0 677c478bd9Sstevel@tonic-gate #endif 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #ifndef TRUE 707c478bd9Sstevel@tonic-gate #define TRUE ((int)'t') 717c478bd9Sstevel@tonic-gate #endif 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #define USAGE_MSG "usage: logins [-admopstux] [-g groups] [-l logins]" 747c478bd9Sstevel@tonic-gate #define MAXLOGINSIZE 14 757c478bd9Sstevel@tonic-gate #define MAXSYSTEMLOGIN 99 767c478bd9Sstevel@tonic-gate #define OPTSTR "adg:l:mopstux" 777c478bd9Sstevel@tonic-gate #define ROOT_ID 0 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * The following macros do their function for now but will probably have 817c478bd9Sstevel@tonic-gate * to be replaced by functions sometime in the near future. The maximum 827c478bd9Sstevel@tonic-gate * system login value may someday be administerable, in which case these 837c478bd9Sstevel@tonic-gate * will have to be changed to become functions 847c478bd9Sstevel@tonic-gate * 857c478bd9Sstevel@tonic-gate * isasystemlogin Returns TRUE if the user-ID in the "struct passwd" 867c478bd9Sstevel@tonic-gate * structure referenced by the function's argument is 877c478bd9Sstevel@tonic-gate * less than or equal to the maximum value for a system 887c478bd9Sstevel@tonic-gate * user-ID, FALSE otherwise. 897c478bd9Sstevel@tonic-gate * isauserlogin Returns TRUE if the user-ID in the "struct passwd" 907c478bd9Sstevel@tonic-gate * structure referenced by the function's argument is 917c478bd9Sstevel@tonic-gate * greater than the maximum value for a system user-ID, 927c478bd9Sstevel@tonic-gate * FALSE otherwise. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #define isauserlogin(pw) (pw->pw_uid > MAXSYSTEMLOGIN) 967c478bd9Sstevel@tonic-gate #define isasystemlogin(pw) (pw->pw_uid <= MAXSYSTEMLOGIN) 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * Local datatype definitions 1017c478bd9Sstevel@tonic-gate * struct reqgrp Describes a group as requested through the 1027c478bd9Sstevel@tonic-gate * -g option 1037c478bd9Sstevel@tonic-gate * struct reqlogin Describes a login-ID as requested through 1047c478bd9Sstevel@tonic-gate * the -l option 1057c478bd9Sstevel@tonic-gate * struct pwdinfo Describes a password's aging information, 1067c478bd9Sstevel@tonic-gate * as extracted from /etc/shadow 1077c478bd9Sstevel@tonic-gate * struct secgrp Describes a login-ID's secondary group 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* Describes a specified group name (from the -g groups option) */ 1117c478bd9Sstevel@tonic-gate struct reqgrp { 1127c478bd9Sstevel@tonic-gate char *groupname; /* Requested group name */ 1137c478bd9Sstevel@tonic-gate struct reqgrp *next; /* Next item in the list */ 1147c478bd9Sstevel@tonic-gate int found; /* TRUE if group in /etc/group */ 1157c478bd9Sstevel@tonic-gate gid_t groupID; /* Group's ID */ 1167c478bd9Sstevel@tonic-gate }; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* Describes a specified login name (from the -l logins option) */ 1197c478bd9Sstevel@tonic-gate struct reqlogin { 1207c478bd9Sstevel@tonic-gate char *loginname; /* Requested login name */ 1217c478bd9Sstevel@tonic-gate struct reqlogin *next; /* Next item in the list */ 1227c478bd9Sstevel@tonic-gate int found; /* TRUE if login in /etc/passwd */ 1237c478bd9Sstevel@tonic-gate }; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * This structure describes a password's information 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate struct pwdinfo { 1307c478bd9Sstevel@tonic-gate long datechg; /* Date the password was changed (mmddyy) */ 1317c478bd9Sstevel@tonic-gate char *passwdstatus; /* Password status */ 1327c478bd9Sstevel@tonic-gate long mindaystilchg; /* Min days b4 pwd can change again */ 1337c478bd9Sstevel@tonic-gate long maxdaystilchg; /* Max days b4 pwd can change again */ 1347c478bd9Sstevel@tonic-gate long warninterval; /* Days before expire to warn user */ 1357c478bd9Sstevel@tonic-gate long inactive; /* Lapsed days of inactivity before lock */ 1367c478bd9Sstevel@tonic-gate long expdate; /* Date of expiration (mmddyy) */ 1377c478bd9Sstevel@tonic-gate }; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* This structure describes secondary groups that a user belongs to */ 1407c478bd9Sstevel@tonic-gate struct secgrp { 1417c478bd9Sstevel@tonic-gate char *groupname; /* Name of the group */ 1427c478bd9Sstevel@tonic-gate struct secgrp *next; /* Next item in the list */ 1437c478bd9Sstevel@tonic-gate gid_t groupID; /* Group-ID */ 1447c478bd9Sstevel@tonic-gate }; 145*20d7339fSgww 146*20d7339fSgww 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * These functions handle error and warning message writing. 1497c478bd9Sstevel@tonic-gate * (This deals with UNIX(r) standard message generation, so 1507c478bd9Sstevel@tonic-gate * the rest of the code doesn't have to.) 1517c478bd9Sstevel@tonic-gate * 1527c478bd9Sstevel@tonic-gate * Functions included: 1537c478bd9Sstevel@tonic-gate * initmsg Initialize the message handling functions. 1547c478bd9Sstevel@tonic-gate * wrtmsg Write the message using fmtmsg(). 1557c478bd9Sstevel@tonic-gate * 1567c478bd9Sstevel@tonic-gate * Static data included: 1577c478bd9Sstevel@tonic-gate * fcnlbl The label for standard messages 1587c478bd9Sstevel@tonic-gate * msgbuf A buffer to contain the edited message 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate static char fcnlbl[MM_MXLABELLN+1]; /* Buffer for message label */ 1627c478bd9Sstevel@tonic-gate static char msgbuf[MM_MXTXTLN+1]; /* Buffer for message text */ 163*20d7339fSgww 164*20d7339fSgww 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * void initmsg(p) 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * This function initializes the message handling functions. 1697c478bd9Sstevel@tonic-gate * 1707c478bd9Sstevel@tonic-gate * Arguments: 1717c478bd9Sstevel@tonic-gate * p A pointer to a character string that is the name of the 1727c478bd9Sstevel@tonic-gate * function, used to generate the label on messages. If this 1737c478bd9Sstevel@tonic-gate * string contains a slash ('/'), it only uses the characters 1747c478bd9Sstevel@tonic-gate * beyond the last slash in the string (this permits argv[0] 1757c478bd9Sstevel@tonic-gate * to be used). 1767c478bd9Sstevel@tonic-gate * 1777c478bd9Sstevel@tonic-gate * Returns: Void 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate static void 181*20d7339fSgww initmsg(char *p) 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate char *q; /* Local multi-use pointer */ 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* Use only the simple filename if there is a slash in the name */ 186*20d7339fSgww if (!(q = strrchr(p, '/'))) { 187*20d7339fSgww q = p; 188*20d7339fSgww } else { 189*20d7339fSgww q++; 190*20d7339fSgww } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* Build the label for messages */ 193*20d7339fSgww (void) snprintf(fcnlbl, MM_MXLABELLN, "UX:%s", q); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* Restrict messages to the text-component */ 1967c478bd9Sstevel@tonic-gate (void) putenv("MSGVERB=text"); 1977c478bd9Sstevel@tonic-gate } 198*20d7339fSgww 199*20d7339fSgww 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * void wrtmsg(severity, action, tag, text[, txtarg1[, txtarg2[, ...]]]) 2027c478bd9Sstevel@tonic-gate * 2037c478bd9Sstevel@tonic-gate * This function writes a message using fmtmsg() 2047c478bd9Sstevel@tonic-gate * 2057c478bd9Sstevel@tonic-gate * Arguments: 2067c478bd9Sstevel@tonic-gate * severity The severity-component of the message 2077c478bd9Sstevel@tonic-gate * action The action-string used to generate the 2087c478bd9Sstevel@tonic-gate * action-component of the message 2097c478bd9Sstevel@tonic-gate * tag Tag-component of the message 2107c478bd9Sstevel@tonic-gate * text The text-string used to generate the text- 2117c478bd9Sstevel@tonic-gate * component of the message 2127c478bd9Sstevel@tonic-gate * txtarg Arguments to be inserted into the "text" 2137c478bd9Sstevel@tonic-gate * string using vsprintf() 2147c478bd9Sstevel@tonic-gate * 2157c478bd9Sstevel@tonic-gate * Returns: Void 2167c478bd9Sstevel@tonic-gate */ 217*20d7339fSgww /*PRINTFLIKE4*/ 2187c478bd9Sstevel@tonic-gate static void 2197c478bd9Sstevel@tonic-gate wrtmsg(int severity, char *action, char *tag, char *text, ...) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate int errorflg; /* TRUE if problem generating message */ 2227c478bd9Sstevel@tonic-gate va_list argp; /* Pointer into vararg list */ 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* No problems yet */ 2267c478bd9Sstevel@tonic-gate errorflg = FALSE; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* Generate the error message */ 2297c478bd9Sstevel@tonic-gate va_start(argp, text); 230*20d7339fSgww if (text != MM_NULLTXT) { 231*20d7339fSgww errorflg = vsnprintf(msgbuf, 232*20d7339fSgww MM_MXTXTLN, text, argp) > MM_MXTXTLN; 233*20d7339fSgww } 2347c478bd9Sstevel@tonic-gate (void) fmtmsg(MM_PRINT, fcnlbl, severity, 235*20d7339fSgww (text == MM_NULLTXT) ? MM_NULLTXT : msgbuf, action, tag); 2367c478bd9Sstevel@tonic-gate va_end(argp); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * If there was a buffer overflow generating the error message, 2407c478bd9Sstevel@tonic-gate * write a message and quit (things are probably corrupt in the 2417c478bd9Sstevel@tonic-gate * static data space now 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate if (errorflg) { 2447c478bd9Sstevel@tonic-gate (void) fmtmsg(MM_PRINT, fcnlbl, MM_WARNING, 2457c478bd9Sstevel@tonic-gate gettext("Internal message buffer overflow"), 2467c478bd9Sstevel@tonic-gate MM_NULLACT, MM_NULLTAG); 2477c478bd9Sstevel@tonic-gate exit(100); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate } 250*20d7339fSgww 251*20d7339fSgww 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * These functions allocate space for the information we gather. 2547c478bd9Sstevel@tonic-gate * It works by having a memory heap with strings allocated from 2557c478bd9Sstevel@tonic-gate * the end of the heap and structures (aligned data) allocated 2567c478bd9Sstevel@tonic-gate * from the beginning of the heap. It begins with a 4k block of 2577c478bd9Sstevel@tonic-gate * memory then allocates memory in 4k chunks. These functions 2587c478bd9Sstevel@tonic-gate * should never fail. If they do, they report the problem and 2597c478bd9Sstevel@tonic-gate * exit with an exit code of 101. 2607c478bd9Sstevel@tonic-gate * 2617c478bd9Sstevel@tonic-gate * Functions contained: 2627c478bd9Sstevel@tonic-gate * allocblk Allocates a block of memory, aligned on a 2637c478bd9Sstevel@tonic-gate * 4-byte (double-word) boundary. 2647c478bd9Sstevel@tonic-gate * allocstr Allocates a block of memory with no 2657c478bd9Sstevel@tonic-gate * particular alignment 2667c478bd9Sstevel@tonic-gate * 2677c478bd9Sstevel@tonic-gate * Constant definitions: 2687c478bd9Sstevel@tonic-gate * ALLOCBLKSZ Size of a chunk of main memory allocated 2697c478bd9Sstevel@tonic-gate * using malloc() 2707c478bd9Sstevel@tonic-gate * 2717c478bd9Sstevel@tonic-gate * Static data: 2727c478bd9Sstevel@tonic-gate * nextblkaddr Address of the next available chunk of 2737c478bd9Sstevel@tonic-gate * aligned space in the heap 2747c478bd9Sstevel@tonic-gate * laststraddr Address of the last chunk of unaligned space 2757c478bd9Sstevel@tonic-gate * allocated from the heap 2767c478bd9Sstevel@tonic-gate * toomuchspace Message to write if someone attempts to allocate 2777c478bd9Sstevel@tonic-gate * too much space (>ALLOCBLKSZ bytes) 2787c478bd9Sstevel@tonic-gate * memallocdif Message to write if there is a problem 2797c478bd9Sstevel@tonic-gate * allocating main menory. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate #define ALLOCBLKSZ 4096 2837c478bd9Sstevel@tonic-gate 284*20d7339fSgww static char *nextblkaddr = NULL; 285*20d7339fSgww static char *laststraddr = NULL; 2867c478bd9Sstevel@tonic-gate #define MEMALLOCDIF "Memory allocation difficulty. Command terminates" 2877c478bd9Sstevel@tonic-gate #define TOOMUCHSPACE "Internal space allocation error. Command terminates" 288*20d7339fSgww 289*20d7339fSgww 2907c478bd9Sstevel@tonic-gate /* 2917c478bd9Sstevel@tonic-gate * void *allocblk(size) 2927c478bd9Sstevel@tonic-gate * unsigned int size 2937c478bd9Sstevel@tonic-gate * 2947c478bd9Sstevel@tonic-gate * This function allocates a block of aligned (4-byte or 2957c478bd9Sstevel@tonic-gate * double-word boundary) memory from the program's heap. 2967c478bd9Sstevel@tonic-gate * It returns a pointer to that block of allocated memory. 2977c478bd9Sstevel@tonic-gate * 2987c478bd9Sstevel@tonic-gate * Arguments: 2997c478bd9Sstevel@tonic-gate * size Minimum number of bytes to allocate (will 3007c478bd9Sstevel@tonic-gate * round up to multiple of 4) 3017c478bd9Sstevel@tonic-gate * 3027c478bd9Sstevel@tonic-gate * Returns: void * 3037c478bd9Sstevel@tonic-gate * Pointer to the allocated block of memory 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate static void * 307*20d7339fSgww allocblk(unsigned int size) 3087c478bd9Sstevel@tonic-gate { 3097c478bd9Sstevel@tonic-gate char *rtnval; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* Make sure the sizes are aligned correctly */ 3127c478bd9Sstevel@tonic-gate if ((size = size + (4 - (size % 4))) > ALLOCBLKSZ) { 3137c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(TOOMUCHSPACE)); 3147c478bd9Sstevel@tonic-gate exit(101); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* Set up the value we're going to return */ 3187c478bd9Sstevel@tonic-gate rtnval = nextblkaddr; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* Get the space we need off of the heap */ 3217c478bd9Sstevel@tonic-gate if ((nextblkaddr += size) >= laststraddr) { 3227c478bd9Sstevel@tonic-gate if (!(rtnval = (char *)malloc(ALLOCBLKSZ))) { 323*20d7339fSgww wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, 324*20d7339fSgww gettext(MEMALLOCDIF)); 3257c478bd9Sstevel@tonic-gate exit(101); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate laststraddr = rtnval + ALLOCBLKSZ; 3287c478bd9Sstevel@tonic-gate nextblkaddr = rtnval + size; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* We're through */ 3327c478bd9Sstevel@tonic-gate return ((void *)rtnval); 3337c478bd9Sstevel@tonic-gate } 334*20d7339fSgww 335*20d7339fSgww 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * char *allocstr(nbytes) 3387c478bd9Sstevel@tonic-gate * unsigned int nbytes 3397c478bd9Sstevel@tonic-gate * 3407c478bd9Sstevel@tonic-gate * This function allocates a block of unaligned memory from the 3417c478bd9Sstevel@tonic-gate * program's heap. It returns a pointer to that block of allocated 3427c478bd9Sstevel@tonic-gate * memory. 3437c478bd9Sstevel@tonic-gate * 3447c478bd9Sstevel@tonic-gate * Arguments: 3457c478bd9Sstevel@tonic-gate * nbytes Number of bytes to allocate 3467c478bd9Sstevel@tonic-gate * 3477c478bd9Sstevel@tonic-gate * Returns: char * 3487c478bd9Sstevel@tonic-gate * Pointer to the allocated block of memory 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate static char * 352*20d7339fSgww allocstr(unsigned int nchars) 3537c478bd9Sstevel@tonic-gate { 3547c478bd9Sstevel@tonic-gate if (nchars > ALLOCBLKSZ) { 3557c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(TOOMUCHSPACE)); 3567c478bd9Sstevel@tonic-gate exit(101); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate if (laststraddr == NULL || 3597c478bd9Sstevel@tonic-gate (laststraddr -= nchars) < nextblkaddr) { 3607c478bd9Sstevel@tonic-gate if (!(nextblkaddr = (char *)malloc(ALLOCBLKSZ))) { 361*20d7339fSgww wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, 362*20d7339fSgww gettext(MEMALLOCDIF)); 3637c478bd9Sstevel@tonic-gate exit(101); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate laststraddr = nextblkaddr + ALLOCBLKSZ - nchars; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate return (laststraddr); 3687c478bd9Sstevel@tonic-gate } 369*20d7339fSgww 370*20d7339fSgww 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * These functions control the group membership list, as found in 3737c478bd9Sstevel@tonic-gate * the /etc/group file. 3747c478bd9Sstevel@tonic-gate * 3757c478bd9Sstevel@tonic-gate * Functions included: 3767c478bd9Sstevel@tonic-gate * initmembers Initialize the membership list (to NULL) 3777c478bd9Sstevel@tonic-gate * addmember Adds a member to the membership list 3787c478bd9Sstevel@tonic-gate * isamember Looks for a particular login-ID in the 3797c478bd9Sstevel@tonic-gate * list of members 3807c478bd9Sstevel@tonic-gate * 3817c478bd9Sstevel@tonic-gate * Datatype Definitions: 3827c478bd9Sstevel@tonic-gate * struct grpmember Describes a group member 3837c478bd9Sstevel@tonic-gate * 3847c478bd9Sstevel@tonic-gate * Static Data: 3857c478bd9Sstevel@tonic-gate * membershead Pointer to the head of the list of 3867c478bd9Sstevel@tonic-gate * group members 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate struct grpmember { 3907c478bd9Sstevel@tonic-gate char *membername; 3917c478bd9Sstevel@tonic-gate struct grpmember *next; 3927c478bd9Sstevel@tonic-gate }; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate static struct grpmember *membershead; 395*20d7339fSgww 396*20d7339fSgww 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * void initmembers() 3997c478bd9Sstevel@tonic-gate * 4007c478bd9Sstevel@tonic-gate * This function initializes the list of members of specified groups. 4017c478bd9Sstevel@tonic-gate * 4027c478bd9Sstevel@tonic-gate * Arguments: None 4037c478bd9Sstevel@tonic-gate * 4047c478bd9Sstevel@tonic-gate * Returns: Void 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate static void 408*20d7339fSgww initmembers(void) 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate /* Set up the members list to be a null member's list */ 411*20d7339fSgww membershead = NULL; 4127c478bd9Sstevel@tonic-gate } 413*20d7339fSgww 414*20d7339fSgww 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * void addmember(p) 4177c478bd9Sstevel@tonic-gate * char *p 4187c478bd9Sstevel@tonic-gate * 4197c478bd9Sstevel@tonic-gate * This function adds a member to the group member's list. The 4207c478bd9Sstevel@tonic-gate * group members list is a list of structures containing a pointer 4217c478bd9Sstevel@tonic-gate * to the member-name and a pointer to the next item in the 4227c478bd9Sstevel@tonic-gate * structure. The structure is not ordered in any particular way. 4237c478bd9Sstevel@tonic-gate * 4247c478bd9Sstevel@tonic-gate * Arguments: 4257c478bd9Sstevel@tonic-gate * p Pointer to the member name 4267c478bd9Sstevel@tonic-gate * 4277c478bd9Sstevel@tonic-gate * Returns: Void 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate static void 431*20d7339fSgww addmember(char *p) 4327c478bd9Sstevel@tonic-gate { 4337c478bd9Sstevel@tonic-gate struct grpmember *new; /* Member being added */ 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate new = (struct grpmember *)allocblk(sizeof (struct grpmember)); 4367c478bd9Sstevel@tonic-gate new->membername = strcpy(allocstr((unsigned int)strlen(p)+1), p); 4377c478bd9Sstevel@tonic-gate new->next = membershead; 4387c478bd9Sstevel@tonic-gate membershead = new; 4397c478bd9Sstevel@tonic-gate } 440*20d7339fSgww 441*20d7339fSgww 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * init isamember(p) 4447c478bd9Sstevel@tonic-gate * char *p 4457c478bd9Sstevel@tonic-gate * 4467c478bd9Sstevel@tonic-gate * This function examines the list of group-members for the string 4477c478bd9Sstevel@tonic-gate * referenced by 'p'. If 'p' is a member of the members list, the 4487c478bd9Sstevel@tonic-gate * function returns TRUE. Otherwise it returns FALSE. 4497c478bd9Sstevel@tonic-gate * 4507c478bd9Sstevel@tonic-gate * Arguments: 4517c478bd9Sstevel@tonic-gate * p Pointer to the name to search for. 4527c478bd9Sstevel@tonic-gate * 4537c478bd9Sstevel@tonic-gate * Returns: int 4547c478bd9Sstevel@tonic-gate * TRUE If 'p' is found in the members list, 4557c478bd9Sstevel@tonic-gate * FALSE otherwise 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate static int 459*20d7339fSgww isamember(char *p) 4607c478bd9Sstevel@tonic-gate { 4617c478bd9Sstevel@tonic-gate int found; /* TRUE if login found in list */ 4627c478bd9Sstevel@tonic-gate struct grpmember *pmem; /* Group member being examined */ 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* Search the membership list for 'p' */ 4667c478bd9Sstevel@tonic-gate found = FALSE; 4677c478bd9Sstevel@tonic-gate for (pmem = membershead; !found && pmem; pmem = pmem->next) { 468*20d7339fSgww if (strcmp(p, pmem->membername) == 0) 469*20d7339fSgww found = TRUE; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate return (found); 4737c478bd9Sstevel@tonic-gate } 474*20d7339fSgww 475*20d7339fSgww 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * These functions handle the display list. The display list contains 4787c478bd9Sstevel@tonic-gate * all of the information we're to display. The list contains a pointer 4797c478bd9Sstevel@tonic-gate * to the login-name, a pointer to the free-field (comment), and a 4807c478bd9Sstevel@tonic-gate * pointer to the next item in the list. The list is ordered alpha- 4817c478bd9Sstevel@tonic-gate * betically (ascending) on the login-name field. The list initially 4827c478bd9Sstevel@tonic-gate * contains a dummy field (to make insertion easier) that contains a 4837c478bd9Sstevel@tonic-gate * login-name of "". 4847c478bd9Sstevel@tonic-gate * 4857c478bd9Sstevel@tonic-gate * Functions included: 4867c478bd9Sstevel@tonic-gate * initdisp Initializes the display list 4877c478bd9Sstevel@tonic-gate * adddisp Adds information to the display list 4887c478bd9Sstevel@tonic-gate * isuidindisp Looks to see if a particular user-ID is in the 4897c478bd9Sstevel@tonic-gate * display list 4907c478bd9Sstevel@tonic-gate * genreport Generates a report from the items in the display 4917c478bd9Sstevel@tonic-gate * list 4927c478bd9Sstevel@tonic-gate * applygroup Add group information to the items in the display 4937c478bd9Sstevel@tonic-gate * list 4947c478bd9Sstevel@tonic-gate * applypasswd Add extended password information to the items 4957c478bd9Sstevel@tonic-gate * in the display list 4967c478bd9Sstevel@tonic-gate * 4977c478bd9Sstevel@tonic-gate * Datatypes Defined: 4987c478bd9Sstevel@tonic-gate * struct display Describes the structure that contains the information 4997c478bd9Sstevel@tonic-gate * to be displayed. Includes pointers to the login-ID, 5007c478bd9Sstevel@tonic-gate * free-field (comment), and the next structure in the 5017c478bd9Sstevel@tonic-gate * list. 5027c478bd9Sstevel@tonic-gate * 5037c478bd9Sstevel@tonic-gate * Static Data: 5047c478bd9Sstevel@tonic-gate * displayhead Pointer to the head of the display list. Initially 5057c478bd9Sstevel@tonic-gate * references the null-item on the head of the list. 5067c478bd9Sstevel@tonic-gate */ 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate struct display { 5097c478bd9Sstevel@tonic-gate char *loginID; /* Login name */ 5107c478bd9Sstevel@tonic-gate char *freefield; /* Free (comment) field */ 5117c478bd9Sstevel@tonic-gate char *groupname; /* Name of the primary group */ 5127c478bd9Sstevel@tonic-gate char *iwd; /* Initial working directory */ 5137c478bd9Sstevel@tonic-gate char *shell; /* Shell after login (may be null) */ 5147c478bd9Sstevel@tonic-gate struct pwdinfo *passwdinfo; /* Password information structure */ 5157c478bd9Sstevel@tonic-gate struct secgrp *secgrplist; /* Head of the secondary group list */ 5167c478bd9Sstevel@tonic-gate uid_t userID; /* User ID */ 5177c478bd9Sstevel@tonic-gate gid_t groupID; /* Group ID of primary group */ 5187c478bd9Sstevel@tonic-gate struct display *nextlogin; /* Next login in the list */ 5197c478bd9Sstevel@tonic-gate struct display *nextuid; /* Next user-ID in the list */ 5207c478bd9Sstevel@tonic-gate }; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate static struct display *displayhead; 523*20d7339fSgww 524*20d7339fSgww 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * void initdisp() 5277c478bd9Sstevel@tonic-gate * 5287c478bd9Sstevel@tonic-gate * Initializes the display list. An empty display list contains 5297c478bd9Sstevel@tonic-gate * a single element, the dummy element. 5307c478bd9Sstevel@tonic-gate * 5317c478bd9Sstevel@tonic-gate * Arguments: None 5327c478bd9Sstevel@tonic-gate * 5337c478bd9Sstevel@tonic-gate * Returns: Void 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate static void 537*20d7339fSgww initdisp(void) 5387c478bd9Sstevel@tonic-gate { 5397c478bd9Sstevel@tonic-gate displayhead = (struct display *)allocblk(sizeof (struct display)); 540*20d7339fSgww displayhead->nextlogin = NULL; 541*20d7339fSgww displayhead->nextuid = NULL; 5427c478bd9Sstevel@tonic-gate displayhead->loginID = ""; 5437c478bd9Sstevel@tonic-gate displayhead->freefield = ""; 5447c478bd9Sstevel@tonic-gate displayhead->userID = -1; 5457c478bd9Sstevel@tonic-gate } 546*20d7339fSgww 547*20d7339fSgww 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * void adddisp(pwent) 5507c478bd9Sstevel@tonic-gate * struct passwd *pwent 5517c478bd9Sstevel@tonic-gate * 5527c478bd9Sstevel@tonic-gate * This function adds the appropriate information from the login 5537c478bd9Sstevel@tonic-gate * description referenced by 'pwent' to the list if information 5547c478bd9Sstevel@tonic-gate * to be displayed. It only adds the information if the login-ID 5557c478bd9Sstevel@tonic-gate * (user-name) is unique. It inserts the information in the list 5567c478bd9Sstevel@tonic-gate * in such a way that the list remains ordered alphabetically 5577c478bd9Sstevel@tonic-gate * (ascending) according to the login-ID (user-name). 5587c478bd9Sstevel@tonic-gate * 5597c478bd9Sstevel@tonic-gate * Arguments: 5607c478bd9Sstevel@tonic-gate * pwent Structure that contains all of the login information 5617c478bd9Sstevel@tonic-gate * of the login being added to the list. The only 5627c478bd9Sstevel@tonic-gate * information that this function uses is the login-ID 5637c478bd9Sstevel@tonic-gate * (user-name) and the free-field (comment field). 5647c478bd9Sstevel@tonic-gate * 5657c478bd9Sstevel@tonic-gate * Returns: Void 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate static void 569*20d7339fSgww adddisp(struct passwd *pwent) 5707c478bd9Sstevel@tonic-gate { 5717c478bd9Sstevel@tonic-gate struct display *new; /* Item being added to the list */ 5727c478bd9Sstevel@tonic-gate struct display *prev; /* Previous item in the list */ 5737c478bd9Sstevel@tonic-gate struct display *current; /* Next item in the list */ 5747c478bd9Sstevel@tonic-gate int found; /* FLAG, insertion point found */ 5757c478bd9Sstevel@tonic-gate int compare = 1; /* strcmp() compare value */ 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* Find where this value belongs in the list */ 5797c478bd9Sstevel@tonic-gate prev = displayhead; 5807c478bd9Sstevel@tonic-gate found = FALSE; 581*20d7339fSgww while (!found && (current = prev->nextlogin)) { 582*20d7339fSgww if ((compare = strcmp(current->loginID, pwent->pw_name)) >= 0) { 583*20d7339fSgww found = TRUE; 584*20d7339fSgww } else { 585*20d7339fSgww prev = current; 586*20d7339fSgww } 5877c478bd9Sstevel@tonic-gate 588*20d7339fSgww } 5897c478bd9Sstevel@tonic-gate /* Insert this value in the list, only if it is unique though */ 5907c478bd9Sstevel@tonic-gate if (compare != 0) { 5917c478bd9Sstevel@tonic-gate new = (struct display *)allocblk(sizeof (struct display)); 592*20d7339fSgww new->loginID = strcpy(allocstr( 593*20d7339fSgww (unsigned int)strlen(pwent->pw_name)+1), pwent->pw_name); 594*20d7339fSgww if (pwent->pw_comment && pwent->pw_comment[0] != '\0') { 595*20d7339fSgww new->freefield = strcpy(allocstr( 596*20d7339fSgww (unsigned int)strlen(pwent->pw_comment)+1), 5977c478bd9Sstevel@tonic-gate pwent->pw_comment); 598*20d7339fSgww } else { 599*20d7339fSgww new->freefield = strcpy(allocstr( 600*20d7339fSgww (unsigned int)strlen(pwent->pw_gecos)+1), 6017c478bd9Sstevel@tonic-gate pwent->pw_gecos); 602*20d7339fSgww } 603*20d7339fSgww if (!pwent->pw_shell || !(*pwent->pw_shell)) { 604*20d7339fSgww new->shell = "/sbin/sh"; 605*20d7339fSgww } else { 606*20d7339fSgww new->shell = strcpy(allocstr( 607*20d7339fSgww (unsigned int)strlen(pwent->pw_shell)+1), 608*20d7339fSgww pwent->pw_shell); 609*20d7339fSgww } 610*20d7339fSgww new->iwd = strcpy(allocstr( 611*20d7339fSgww (unsigned int)strlen(pwent->pw_dir)+1), pwent->pw_dir); 6127c478bd9Sstevel@tonic-gate new->userID = pwent->pw_uid; 6137c478bd9Sstevel@tonic-gate new->groupID = pwent->pw_gid; 614*20d7339fSgww new->secgrplist = NULL; 615*20d7339fSgww new->passwdinfo = NULL; 616*20d7339fSgww new->groupname = NULL; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* Add new display item to the list ordered by login-ID */ 6197c478bd9Sstevel@tonic-gate new->nextlogin = current; 6207c478bd9Sstevel@tonic-gate prev->nextlogin = new; 6217c478bd9Sstevel@tonic-gate 622*20d7339fSgww /* 623*20d7339fSgww * Find the appropriate place for the new item in the list 624*20d7339fSgww * ordered by userID 625*20d7339fSgww */ 6267c478bd9Sstevel@tonic-gate prev = displayhead; 6277c478bd9Sstevel@tonic-gate found = FALSE; 628*20d7339fSgww while (!found && (current = prev->nextuid)) { 629*20d7339fSgww if (current->userID > pwent->pw_uid) { 630*20d7339fSgww found = TRUE; 631*20d7339fSgww } else { 632*20d7339fSgww prev = current; 633*20d7339fSgww } 634*20d7339fSgww } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* Add the item into the list that is ordered by user-ID */ 6377c478bd9Sstevel@tonic-gate new->nextuid = current; 6387c478bd9Sstevel@tonic-gate prev->nextuid = new; 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate } 641*20d7339fSgww 642*20d7339fSgww 6437c478bd9Sstevel@tonic-gate /* 6447c478bd9Sstevel@tonic-gate * int isuidindisp(pwent) 6457c478bd9Sstevel@tonic-gate * struct passwd *pwent 6467c478bd9Sstevel@tonic-gate * 6477c478bd9Sstevel@tonic-gate * This function examines the display list to see if the uid in 6487c478bd9Sstevel@tonic-gate * the (struct passwd) referenced by "pwent" is already in the 6497c478bd9Sstevel@tonic-gate * display list. It returns TRUE if it is in the list, FALSE 6507c478bd9Sstevel@tonic-gate * otherwise. 6517c478bd9Sstevel@tonic-gate * 6527c478bd9Sstevel@tonic-gate * Since the display list is ordered by user-ID, the search continues 6537c478bd9Sstevel@tonic-gate * until a match is found or a user-ID is found that is larger than 6547c478bd9Sstevel@tonic-gate * the one we're searching for. 6557c478bd9Sstevel@tonic-gate * 6567c478bd9Sstevel@tonic-gate * Arguments: 6577c478bd9Sstevel@tonic-gate * pwent Structure that contains the user-ID we're to 6587c478bd9Sstevel@tonic-gate * look for 6597c478bd9Sstevel@tonic-gate * 6607c478bd9Sstevel@tonic-gate * Returns: int 6617c478bd9Sstevel@tonic-gate * TRUE if the user-ID was found, FALSE otherwise. 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate static int 665*20d7339fSgww isuidindisp(struct passwd *pwent) 6667c478bd9Sstevel@tonic-gate { 6677c478bd9Sstevel@tonic-gate struct display *dp; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate * Search the list, beginning at the beginning (where else?) 6727c478bd9Sstevel@tonic-gate * and stopping when the user-ID is found or one is found that 6737c478bd9Sstevel@tonic-gate * is greater than the user-ID we're searching for. Recall 6747c478bd9Sstevel@tonic-gate * that this list is ordered by user-ID 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate 677*20d7339fSgww for (dp = displayhead->nextuid; dp && (dp->userID < pwent->pw_uid); 678*20d7339fSgww dp = dp->nextuid) { 679*20d7339fSgww continue; 680*20d7339fSgww } 6817c478bd9Sstevel@tonic-gate 682*20d7339fSgww /* 683*20d7339fSgww * If the pointer "dp" points to a structure that has a 684*20d7339fSgww * matching user-ID, return TRUE. Otherwise FALSE 685*20d7339fSgww */ 6867c478bd9Sstevel@tonic-gate return (dp && (dp->userID == pwent->pw_uid)); 6877c478bd9Sstevel@tonic-gate } 688*20d7339fSgww 689*20d7339fSgww 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * void applygroup(allgroups) 6927c478bd9Sstevel@tonic-gate * int allgroups 6937c478bd9Sstevel@tonic-gate * 6947c478bd9Sstevel@tonic-gate * This function applies group information to the login-IDs in the 6957c478bd9Sstevel@tonic-gate * display list. It always applies the primary group information. 6967c478bd9Sstevel@tonic-gate * If "allgroups" is TRUE, it applies secondary information as well. 6977c478bd9Sstevel@tonic-gate * 6987c478bd9Sstevel@tonic-gate * Arguments: 6997c478bd9Sstevel@tonic-gate * allgroups FLAG. TRUE if secondary group info is to be 7007c478bd9Sstevel@tonic-gate * applied -- FALSE otherwise. 7017c478bd9Sstevel@tonic-gate * 7027c478bd9Sstevel@tonic-gate * Returns: void 7037c478bd9Sstevel@tonic-gate */ 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate static void 706*20d7339fSgww applygroup(int allgroups) 7077c478bd9Sstevel@tonic-gate { 7087c478bd9Sstevel@tonic-gate struct display *dp; /* Display list running ptr */ 7097c478bd9Sstevel@tonic-gate struct group *grent; /* Group info, from getgrent() */ 7107c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */ 7117c478bd9Sstevel@tonic-gate char **pp; /* Temp char * pointer */ 7127c478bd9Sstevel@tonic-gate int compare; /* Value from strcmp() */ 7137c478bd9Sstevel@tonic-gate int done; /* TRUE if finished, FALSE otherwise */ 7147c478bd9Sstevel@tonic-gate struct secgrp *psecgrp; /* Block allocated for this info */ 7157c478bd9Sstevel@tonic-gate struct secgrp *psrch; /* Secondary group -- for searching */ 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate /* For each group-ID in the /etc/group file ... */ 7197c478bd9Sstevel@tonic-gate while (grent = getgrent()) { 7207c478bd9Sstevel@tonic-gate /* 7217c478bd9Sstevel@tonic-gate * Set the primary group for the login-IDs in the display 7227c478bd9Sstevel@tonic-gate * list. For each group-ID we get, leaf through the display 7237c478bd9Sstevel@tonic-gate * list and set the group-name if the group-IDs match 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate 726*20d7339fSgww p = NULL; 727*20d7339fSgww for (dp = displayhead->nextuid; dp; dp = dp->nextuid) { 7287c478bd9Sstevel@tonic-gate if ((dp->groupID == grent->gr_gid) && !dp->groupname) { 729*20d7339fSgww if (!p) { 730*20d7339fSgww p = strcpy(allocstr( 731*20d7339fSgww (unsigned int)strlen( 732*20d7339fSgww grent->gr_name)+1), grent->gr_name); 733*20d7339fSgww } 7347c478bd9Sstevel@tonic-gate dp->groupname = p; 7357c478bd9Sstevel@tonic-gate } 736*20d7339fSgww } 7377c478bd9Sstevel@tonic-gate 738*20d7339fSgww if (!allgroups) { 739*20d7339fSgww continue; 740*20d7339fSgww } 7417c478bd9Sstevel@tonic-gate /* 7427c478bd9Sstevel@tonic-gate * If we're to be displaying secondary group membership, 7437c478bd9Sstevel@tonic-gate * leaf through the list of group members. Then, attempt 7447c478bd9Sstevel@tonic-gate * to find that member in the display list. When found, 7457c478bd9Sstevel@tonic-gate * attach secondary group info to the user. 7467c478bd9Sstevel@tonic-gate */ 7477c478bd9Sstevel@tonic-gate 748*20d7339fSgww for (pp = grent->gr_mem; *pp; pp++) { 7497c478bd9Sstevel@tonic-gate done = FALSE; 750*20d7339fSgww for (dp = displayhead->nextlogin; !done && dp; 751*20d7339fSgww dp = dp->nextlogin) { 752*20d7339fSgww if (((compare = strcmp(dp->loginID, 753*20d7339fSgww *pp)) == 0) && 754*20d7339fSgww !(grent->gr_gid == dp->groupID)) { 755*20d7339fSgww if (!p) { 756*20d7339fSgww p = strcpy(allocstr( 757*20d7339fSgww (unsigned int)strlen( 758*20d7339fSgww grent->gr_name)+1), 759*20d7339fSgww grent->gr_name); 760*20d7339fSgww } 761*20d7339fSgww psecgrp = (struct secgrp *)allocblk( 762*20d7339fSgww sizeof (struct secgrp)); 7637c478bd9Sstevel@tonic-gate psecgrp->groupID = grent->gr_gid; 7647c478bd9Sstevel@tonic-gate psecgrp->groupname = p; 765*20d7339fSgww psecgrp->next = NULL; 766*20d7339fSgww if (!dp->secgrplist) { 767*20d7339fSgww dp->secgrplist = psecgrp; 768*20d7339fSgww } else { 769*20d7339fSgww for (psrch = dp->secgrplist; 770*20d7339fSgww psrch->next; 771*20d7339fSgww psrch = psrch->next) { 772*20d7339fSgww continue; 773*20d7339fSgww } 7747c478bd9Sstevel@tonic-gate psrch->next = psecgrp; 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate done = TRUE; 777*20d7339fSgww } else if (compare > 0) { 778*20d7339fSgww done = TRUE; 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* Close the /etc/group file */ 7857c478bd9Sstevel@tonic-gate endgrent(); 7867c478bd9Sstevel@tonic-gate } 787*20d7339fSgww 788*20d7339fSgww 7897c478bd9Sstevel@tonic-gate /* 7907c478bd9Sstevel@tonic-gate * void applypasswd() 7917c478bd9Sstevel@tonic-gate * 7927c478bd9Sstevel@tonic-gate * This function applies extended password information to an item 7937c478bd9Sstevel@tonic-gate * to be displayed. It allocates space for a structure describing 7947c478bd9Sstevel@tonic-gate * the password, then fills in that structure from the information 7957c478bd9Sstevel@tonic-gate * in the /etc/shadow file. 7967c478bd9Sstevel@tonic-gate * 7977c478bd9Sstevel@tonic-gate * Arguments: None 7987c478bd9Sstevel@tonic-gate * 7997c478bd9Sstevel@tonic-gate * Returns: Void 8007c478bd9Sstevel@tonic-gate */ 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate static void 803*20d7339fSgww applypasswd(void) 8047c478bd9Sstevel@tonic-gate { 8057c478bd9Sstevel@tonic-gate struct pwdinfo *ppasswd; /* Ptr to pwd desc in current element */ 8067c478bd9Sstevel@tonic-gate struct display *dp; /* Ptr to current element */ 8077c478bd9Sstevel@tonic-gate struct spwd *psp; /* Pointer to a shadow-file entry */ 8087c478bd9Sstevel@tonic-gate struct tm *ptm; /* Pointer to a time-of-day structure */ 8097c478bd9Sstevel@tonic-gate char *p; /* Running character pointer */ 8107c478bd9Sstevel@tonic-gate time_t pwchg; /* System-time of last pwd chg */ 8117c478bd9Sstevel@tonic-gate time_t pwexp; /* System-time of password expiration */ 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* Make sure the shadow file is rewound */ 8157c478bd9Sstevel@tonic-gate setspent(); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate /* 8197c478bd9Sstevel@tonic-gate * For each item in the display list... 8207c478bd9Sstevel@tonic-gate */ 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate for (dp = displayhead->nextuid; dp; dp = dp->nextuid) { 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* Allocate structure space for the password description */ 8257c478bd9Sstevel@tonic-gate ppasswd = (struct pwdinfo *)allocblk(sizeof (struct pwdinfo)); 8267c478bd9Sstevel@tonic-gate dp->passwdinfo = ppasswd; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate /* 8297c478bd9Sstevel@tonic-gate * If there's no entry in the /etc/shadow file, assume 8307c478bd9Sstevel@tonic-gate * that the login is locked 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if (!(psp = getspnam(dp->loginID))) { 8347c478bd9Sstevel@tonic-gate pwchg = 0L; /* Epoch */ 8357c478bd9Sstevel@tonic-gate ppasswd->passwdstatus = "LK"; /* LK, Locked */ 8367c478bd9Sstevel@tonic-gate ppasswd->mindaystilchg = 0L; 8377c478bd9Sstevel@tonic-gate ppasswd->maxdaystilchg = 0L; 8387c478bd9Sstevel@tonic-gate ppasswd->warninterval = 0L; 8397c478bd9Sstevel@tonic-gate ppasswd->inactive = 0L; 8407c478bd9Sstevel@tonic-gate pwexp = 0L; 841*20d7339fSgww } else { 8427c478bd9Sstevel@tonic-gate /* 8437c478bd9Sstevel@tonic-gate * Otherwise, fill in the password information from the 8447c478bd9Sstevel@tonic-gate * info in the shadow file entry 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate /* See if the login has no password */ 847*20d7339fSgww if (!psp->sp_pwdp || !(*psp->sp_pwdp)) { 848*20d7339fSgww ppasswd->passwdstatus = "NP"; 849*20d7339fSgww } else if (strlen(psp->sp_pwdp) != 13) { 8507c478bd9Sstevel@tonic-gate /* 851*20d7339fSgww * See if the login is explicitly locked 852*20d7339fSgww * (encrypted password is <13 characters) 8537c478bd9Sstevel@tonic-gate */ 854*20d7339fSgww ppasswd->passwdstatus = "LK"; 855*20d7339fSgww } else { 8567c478bd9Sstevel@tonic-gate /* 857*20d7339fSgww * If it's a valid encrypted password, 858*20d7339fSgww * the login is password protected 8597c478bd9Sstevel@tonic-gate */ 8607c478bd9Sstevel@tonic-gate ppasswd->passwdstatus = "PS"; 8617c478bd9Sstevel@tonic-gate for (p = psp->sp_pwdp; *p; p++) { 862*20d7339fSgww if (!isalnum(*p) && 863*20d7339fSgww (*p != '.') && 864*20d7339fSgww (*p != '/')) { 8657c478bd9Sstevel@tonic-gate ppasswd->passwdstatus = "LK"; 8667c478bd9Sstevel@tonic-gate break; 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 872*20d7339fSgww * Set up the last-changed date, 873*20d7339fSgww * the minimum days between changes, 874*20d7339fSgww * the maximum life of a password, 875*20d7339fSgww * the interval before expiration that the user 876*20d7339fSgww * is warned, 877*20d7339fSgww * the number of days a login can be inactive before 878*20d7339fSgww * it expires, and the login expiration date 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate pwchg = psp->sp_lstchg; 8827c478bd9Sstevel@tonic-gate ppasswd->mindaystilchg = psp->sp_min; 8837c478bd9Sstevel@tonic-gate ppasswd->maxdaystilchg = psp->sp_max; 8847c478bd9Sstevel@tonic-gate ppasswd->warninterval = psp->sp_warn; 8857c478bd9Sstevel@tonic-gate ppasswd->inactive = psp->sp_inact; 8867c478bd9Sstevel@tonic-gate pwexp = psp->sp_expire; 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate /* 8907c478bd9Sstevel@tonic-gate * Convert the date of the last password change from days- 8917c478bd9Sstevel@tonic-gate * since-epoch to mmddyy (integer) form. Involves the 8927c478bd9Sstevel@tonic-gate * intermediate step of converting the date from days- 8937c478bd9Sstevel@tonic-gate * since-epoch to seconds-since-epoch. We'll set this to 8947c478bd9Sstevel@tonic-gate * somewhere near the middle of the day, since there are not 8957c478bd9Sstevel@tonic-gate * always 24*60*60 seconds in a year. (Yeech) 8967c478bd9Sstevel@tonic-gate * 8977c478bd9Sstevel@tonic-gate * Note: The form mmddyy should probably be subject to 8987c478bd9Sstevel@tonic-gate * internationalization -- Non-Americans will think that 8997c478bd9Sstevel@tonic-gate * 070888 is 07 August 88 when the software is trying to say 9007c478bd9Sstevel@tonic-gate * 08 July 88. Systems Engineers seem to think that this isn't 9017c478bd9Sstevel@tonic-gate * a problem though... 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if (pwchg != -1L) { 9057c478bd9Sstevel@tonic-gate pwchg = (pwchg * DAY) + (DAY/2); 9067c478bd9Sstevel@tonic-gate ptm = localtime(&pwchg); 9077c478bd9Sstevel@tonic-gate ppasswd->datechg = ((long)(ptm->tm_mon+1) * 10000L) + 9087c478bd9Sstevel@tonic-gate (long)((ptm->tm_mday * 100) + 9097c478bd9Sstevel@tonic-gate (ptm->tm_year % 100)); 910*20d7339fSgww } else { 911*20d7339fSgww ppasswd->datechg = 0L; 912*20d7339fSgww } 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate /* 9157c478bd9Sstevel@tonic-gate * Convert the passwd expiration date from days-since-epoch 9167c478bd9Sstevel@tonic-gate * to mmddyy (long integer) form using the same algorithm and 9177c478bd9Sstevel@tonic-gate * comments as above. 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate if (pwexp != -1L) { 9217c478bd9Sstevel@tonic-gate pwexp = (pwexp * DAY) + (DAY/2); 9227c478bd9Sstevel@tonic-gate ptm = localtime(&pwexp); 9237c478bd9Sstevel@tonic-gate ppasswd->expdate = ((long)(ptm->tm_mon+1) * 10000L) + 9247c478bd9Sstevel@tonic-gate (long)((ptm->tm_mday * 100) + 9257c478bd9Sstevel@tonic-gate (ptm->tm_year % 100)); 926*20d7339fSgww } else { 927*20d7339fSgww ppasswd->expdate = 0L; 928*20d7339fSgww } 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate /* Close the shadow password file */ 9327c478bd9Sstevel@tonic-gate endspent(); 9337c478bd9Sstevel@tonic-gate } 934*20d7339fSgww 935*20d7339fSgww 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate * int hasnopasswd(pwent) 9387c478bd9Sstevel@tonic-gate * struct passwd *pwent 9397c478bd9Sstevel@tonic-gate * 9407c478bd9Sstevel@tonic-gate * This function examines a login's password-file entry 9417c478bd9Sstevel@tonic-gate * and, if necessary, its shadow password-file entry and 9427c478bd9Sstevel@tonic-gate * returns TRUE if that user-ID has no password, meaning 9437c478bd9Sstevel@tonic-gate * that the user-ID can be used to log into the system 9447c478bd9Sstevel@tonic-gate * without giving a password. The function returns FALSE 9457c478bd9Sstevel@tonic-gate * otherwise. 9467c478bd9Sstevel@tonic-gate * 9477c478bd9Sstevel@tonic-gate * Arguments: 9487c478bd9Sstevel@tonic-gate * pwent Login to examine. 9497c478bd9Sstevel@tonic-gate * 9507c478bd9Sstevel@tonic-gate * Returns: int 9517c478bd9Sstevel@tonic-gate * TRUE if the login can be used without a password, FALSE 9527c478bd9Sstevel@tonic-gate * otherwise. 9537c478bd9Sstevel@tonic-gate */ 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate static int 956*20d7339fSgww hasnopasswd(struct passwd *pwent) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate struct spwd *psp; /* /etc/shadow file struct */ 9597c478bd9Sstevel@tonic-gate int nopwflag; /* TRUE if login has no passwd */ 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * A login has no password if: 9637c478bd9Sstevel@tonic-gate * 1. There exists an entry for that login in the 9647c478bd9Sstevel@tonic-gate * shadow password-file (/etc/passwd), and 9657c478bd9Sstevel@tonic-gate * 2. The encrypted password in the structure describing 966*20d7339fSgww * that entry is either: NULL or a null string ("") 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* Get the login's entry in the shadow password file */ 9707c478bd9Sstevel@tonic-gate if (psp = getspnam(pwent->pw_name)) { 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* Look at the encrypted password in that entry */ 9737c478bd9Sstevel@tonic-gate if (psp->sp_pwdp == (char *)0 || 974*20d7339fSgww *psp->sp_pwdp == '\0') { 9757c478bd9Sstevel@tonic-gate nopwflag = TRUE; 976*20d7339fSgww } else { 9777c478bd9Sstevel@tonic-gate nopwflag = FALSE; 9787c478bd9Sstevel@tonic-gate } 979*20d7339fSgww } else { 9807c478bd9Sstevel@tonic-gate nopwflag = FALSE; 981*20d7339fSgww } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate /* Done ... */ 9847c478bd9Sstevel@tonic-gate return (nopwflag); 9857c478bd9Sstevel@tonic-gate } 986*20d7339fSgww 987*20d7339fSgww 9887c478bd9Sstevel@tonic-gate /* 9897c478bd9Sstevel@tonic-gate * void writeunformatted(current, xtndflag, expflag) 9907c478bd9Sstevel@tonic-gate * struct display *current 9917c478bd9Sstevel@tonic-gate * int xtndflag 9927c478bd9Sstevel@tonic-gate * int expflag 9937c478bd9Sstevel@tonic-gate * 9947c478bd9Sstevel@tonic-gate * This function writes the data in the display structure "current" 9957c478bd9Sstevel@tonic-gate * to the standard output file. It writes the information in the 9967c478bd9Sstevel@tonic-gate * form of a colon-list. It writes secondary group information if 9977c478bd9Sstevel@tonic-gate * that information is in the structure, it writes extended 9987c478bd9Sstevel@tonic-gate * (initial working directory, shell, and password-aging) info 9997c478bd9Sstevel@tonic-gate * if the "xtndflag" is TRUE, and it writes password expiration 10007c478bd9Sstevel@tonic-gate * information if "expflag" is TRUE. 10017c478bd9Sstevel@tonic-gate * 10027c478bd9Sstevel@tonic-gate * Arguments: 10037c478bd9Sstevel@tonic-gate * current Structure containing information to write. 10047c478bd9Sstevel@tonic-gate * xtndflag TRUE if extended information is to be written, 10057c478bd9Sstevel@tonic-gate * FALSE otherwise 10067c478bd9Sstevel@tonic-gate * expflag TRUE if password expiration information is to 10077c478bd9Sstevel@tonic-gate * be written, FALSE otherwise 10087c478bd9Sstevel@tonic-gate * 10097c478bd9Sstevel@tonic-gate * Returns: void 10107c478bd9Sstevel@tonic-gate */ 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate static void 1013*20d7339fSgww writeunformatted(struct display *current, int xtndflag, int expflag) 10147c478bd9Sstevel@tonic-gate { 10157c478bd9Sstevel@tonic-gate struct secgrp *psecgrp; /* Secondary group info */ 10167c478bd9Sstevel@tonic-gate struct pwdinfo *pwdinfo; /* Password aging info */ 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate /* Write the general information */ 10197c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s:%ld:%s:%ld:%s", 10207c478bd9Sstevel@tonic-gate current->loginID, 10217c478bd9Sstevel@tonic-gate current->userID, 1022*20d7339fSgww current->groupname == NULL ? "" : current->groupname, 10237c478bd9Sstevel@tonic-gate current->groupID, 10247c478bd9Sstevel@tonic-gate current->freefield); 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* 10277c478bd9Sstevel@tonic-gate * If the group information is there, write it (it's only 10287c478bd9Sstevel@tonic-gate * there if it's supposed to be written) 10297c478bd9Sstevel@tonic-gate */ 1030*20d7339fSgww for (psecgrp = current->secgrplist; psecgrp; psecgrp = psecgrp->next) { 1031*20d7339fSgww (void) fprintf(stdout, ":%s:%ld", 1032*20d7339fSgww psecgrp->groupname, psecgrp->groupID); 1033*20d7339fSgww } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate /* If the extended info flag is TRUE, write the extended information */ 10367c478bd9Sstevel@tonic-gate if (xtndflag) { 10377c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 10387c478bd9Sstevel@tonic-gate (void) fprintf(stdout, ":%s:%s:%s:%6.6ld:%ld:%ld:%ld", 10397c478bd9Sstevel@tonic-gate current->iwd, current->shell, 10407c478bd9Sstevel@tonic-gate pwdinfo->passwdstatus, 10417c478bd9Sstevel@tonic-gate pwdinfo->datechg, 10427c478bd9Sstevel@tonic-gate pwdinfo->mindaystilchg, pwdinfo->maxdaystilchg, 10437c478bd9Sstevel@tonic-gate pwdinfo->warninterval); 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate /* If the password expiration information is requested, write it. */ 10477c478bd9Sstevel@tonic-gate if (expflag) { 10487c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 1049*20d7339fSgww (void) fprintf(stdout, ":%ld:%ld", 1050*20d7339fSgww pwdinfo->inactive, pwdinfo->expdate); 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* Terminate the information with a new-line */ 10547c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 10557c478bd9Sstevel@tonic-gate } 1056*20d7339fSgww 1057*20d7339fSgww 10587c478bd9Sstevel@tonic-gate /* 10597c478bd9Sstevel@tonic-gate * void writeformatted(current, xtndflag, expflag) 10607c478bd9Sstevel@tonic-gate * struct display *current 10617c478bd9Sstevel@tonic-gate * int xtndflag 10627c478bd9Sstevel@tonic-gate * int expflag 10637c478bd9Sstevel@tonic-gate * 10647c478bd9Sstevel@tonic-gate * This function writes the data in the display structure "current" 10657c478bd9Sstevel@tonic-gate * to the standard output file. It writes the information in an 10667c478bd9Sstevel@tonic-gate * easily readable format. It writes secondary group information 10677c478bd9Sstevel@tonic-gate * if that information is in the structure, it writes extended 10687c478bd9Sstevel@tonic-gate * (initial working directory, shell, and password-aging) info if 10697c478bd9Sstevel@tonic-gate * "xtndflag" is TRUE, and it write password expiration information 10707c478bd9Sstevel@tonic-gate * if "expflag" is TRUE. 10717c478bd9Sstevel@tonic-gate * 10727c478bd9Sstevel@tonic-gate * Arguments: 10737c478bd9Sstevel@tonic-gate * current Structure containing info to write. 1074*20d7339fSgww * xtndflag TRUE if extended information to be written, 10757c478bd9Sstevel@tonic-gate * FALSE otherwise 1076*20d7339fSgww * expflag TRUE if password expiration information to be written, 10777c478bd9Sstevel@tonic-gate * FALSE otherwise 10787c478bd9Sstevel@tonic-gate * 10797c478bd9Sstevel@tonic-gate * Returns: void 10807c478bd9Sstevel@tonic-gate */ 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate static void 1083*20d7339fSgww writeformatted(struct display *current, int xtndflag, int expflag) 10847c478bd9Sstevel@tonic-gate { 10857c478bd9Sstevel@tonic-gate struct secgrp *psecgrp; /* Secondary group info */ 10867c478bd9Sstevel@tonic-gate struct pwdinfo *pwdinfo; /* Password aging info */ 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate /* Write general information */ 10897c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%-14s %-6ld %-14s %-6ld %s\n", 10907c478bd9Sstevel@tonic-gate current->loginID, current->userID, 1091*20d7339fSgww current->groupname == NULL ? "" : current->groupname, 10927c478bd9Sstevel@tonic-gate current->groupID, current->freefield); 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate /* 10957c478bd9Sstevel@tonic-gate * Write information about secondary groups if the info exists 10967c478bd9Sstevel@tonic-gate * (it only exists if it is to be written) 10977c478bd9Sstevel@tonic-gate */ 1098*20d7339fSgww for (psecgrp = current->secgrplist; psecgrp; psecgrp = psecgrp->next) { 10997c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %-14s %-6ld\n", 11007c478bd9Sstevel@tonic-gate psecgrp->groupname, psecgrp->groupID); 1101*20d7339fSgww } 11027c478bd9Sstevel@tonic-gate 1103*20d7339fSgww /* 1104*20d7339fSgww * If the extended information flag is TRUE, 1105*20d7339fSgww * write the extended information 1106*20d7339fSgww */ 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate if (xtndflag) { 11097c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 1110*20d7339fSgww (void) fprintf(stdout, " %s\n", 1111*20d7339fSgww current->iwd); 1112*20d7339fSgww (void) fprintf(stdout, " %s\n", 1113*20d7339fSgww current->shell); 1114*20d7339fSgww (void) fprintf(stdout, " %s " 1115*20d7339fSgww "%6.6ld %ld %ld %ld\n", 11167c478bd9Sstevel@tonic-gate pwdinfo->passwdstatus, 11177c478bd9Sstevel@tonic-gate pwdinfo->datechg, pwdinfo->mindaystilchg, 11187c478bd9Sstevel@tonic-gate pwdinfo->maxdaystilchg, 11197c478bd9Sstevel@tonic-gate pwdinfo->warninterval); 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 1122*20d7339fSgww /* 1123*20d7339fSgww * If the password expiration info flag is TRUE, 1124*20d7339fSgww * write that information 1125*20d7339fSgww */ 11267c478bd9Sstevel@tonic-gate if (expflag) { 11277c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 11287c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %ld %6.6ld\n", 11297c478bd9Sstevel@tonic-gate pwdinfo->inactive, pwdinfo->expdate); 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate } 1132*20d7339fSgww 1133*20d7339fSgww 11347c478bd9Sstevel@tonic-gate /* 11357c478bd9Sstevel@tonic-gate * void genuidreport(pipeflag, xtndflag, expflag) 11367c478bd9Sstevel@tonic-gate * int pipeflag 11377c478bd9Sstevel@tonic-gate * int xtndflag 11387c478bd9Sstevel@tonic-gate * int expflag 11397c478bd9Sstevel@tonic-gate * 11407c478bd9Sstevel@tonic-gate * This function generates a report on the standard output 11417c478bd9Sstevel@tonic-gate * stream (stdout) containing the login-IDs in the list of 11427c478bd9Sstevel@tonic-gate * logins built by this command. The list is ordered based 11437c478bd9Sstevel@tonic-gate * on user-ID. If the <pipeflag> variable is not zero, it 11447c478bd9Sstevel@tonic-gate * will generate a report containing parsable records. 11457c478bd9Sstevel@tonic-gate * Otherwise, it will generate a columnarized report. If 11467c478bd9Sstevel@tonic-gate * the <xtndflag> variable is not zero, it will include the 11477c478bd9Sstevel@tonic-gate * extended set of information (password aging info, home 11487c478bd9Sstevel@tonic-gate * directory, shell process, etc.). If <expflag> is not 11497c478bd9Sstevel@tonic-gate * zero, it will display password expiration information. 11507c478bd9Sstevel@tonic-gate * 11517c478bd9Sstevel@tonic-gate * Arguments: 11527c478bd9Sstevel@tonic-gate * pipeflag int 11537c478bd9Sstevel@tonic-gate * TRUE if a parsable report is needed, 11547c478bd9Sstevel@tonic-gate * FALSE if a columnar report is needed 11557c478bd9Sstevel@tonic-gate * xtndflag int 11567c478bd9Sstevel@tonic-gate * TRUE if extended set of info is to be displayed, 11577c478bd9Sstevel@tonic-gate * FALSE otherwise 11587c478bd9Sstevel@tonic-gate * expflag int 11597c478bd9Sstevel@tonic-gate * TRUE if password expiration information is to be 11607c478bd9Sstevel@tonic-gate * displayed, FALSE otherwise 11617c478bd9Sstevel@tonic-gate * 11627c478bd9Sstevel@tonic-gate * Returns: void 11637c478bd9Sstevel@tonic-gate */ 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate static void 1166*20d7339fSgww genuidreport(int pipeflag, int xtndflag, int expflag) 11677c478bd9Sstevel@tonic-gate { 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate struct display *current; /* Data being displayed */ 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate /* 11737c478bd9Sstevel@tonic-gate * Initialization for loop. 1174*20d7339fSgww * (NOTE: The first element in the list of logins to display is 1175*20d7339fSgww * a dummy element.) 11767c478bd9Sstevel@tonic-gate */ 11777c478bd9Sstevel@tonic-gate current = displayhead; 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate /* 11807c478bd9Sstevel@tonic-gate * Display elements in the list 11817c478bd9Sstevel@tonic-gate */ 1182*20d7339fSgww if (pipeflag) { 1183*20d7339fSgww for (current = displayhead->nextuid; current; 1184*20d7339fSgww current = current->nextuid) { 11857c478bd9Sstevel@tonic-gate writeunformatted(current, xtndflag, expflag); 1186*20d7339fSgww } 1187*20d7339fSgww } else { 1188*20d7339fSgww for (current = displayhead->nextuid; current; 1189*20d7339fSgww current = current->nextuid) { 11907c478bd9Sstevel@tonic-gate writeformatted(current, xtndflag, expflag); 11917c478bd9Sstevel@tonic-gate } 1192*20d7339fSgww } 1193*20d7339fSgww } 1194*20d7339fSgww 1195*20d7339fSgww 11967c478bd9Sstevel@tonic-gate /* 11977c478bd9Sstevel@tonic-gate * void genlogreport(pipeflag, xtndflag, expflag) 11987c478bd9Sstevel@tonic-gate * int pipeflag 11997c478bd9Sstevel@tonic-gate * int xtndflag 12007c478bd9Sstevel@tonic-gate * int expflag 12017c478bd9Sstevel@tonic-gate * 12027c478bd9Sstevel@tonic-gate * This function generates a report on the standard output 12037c478bd9Sstevel@tonic-gate * stream (stdout) containing the login-IDs in the list of 12047c478bd9Sstevel@tonic-gate * logins built by this command. The list is ordered based 12057c478bd9Sstevel@tonic-gate * on user name. If the <pipeflag> variable is not zero, it 12067c478bd9Sstevel@tonic-gate * will generate a report containing parsable records. 12077c478bd9Sstevel@tonic-gate * Otherwise, it will generate a columnarized report. If 12087c478bd9Sstevel@tonic-gate * the <xtndflag> variable is not zero, it will include the 12097c478bd9Sstevel@tonic-gate * extended set of information (password aging info, home 12107c478bd9Sstevel@tonic-gate * directory, shell process, etc.). If <expflag> is not 12117c478bd9Sstevel@tonic-gate * zero, it will include password expiration information. 12127c478bd9Sstevel@tonic-gate * 12137c478bd9Sstevel@tonic-gate * Arguments: 12147c478bd9Sstevel@tonic-gate * pipeflag int 12157c478bd9Sstevel@tonic-gate * TRUE if a parsable report is needed, 12167c478bd9Sstevel@tonic-gate * FALSE if a columnar report is needed 12177c478bd9Sstevel@tonic-gate * xtndflag int 12187c478bd9Sstevel@tonic-gate * TRUE if extended set of info is to be displayed, 12197c478bd9Sstevel@tonic-gate * FALSE otherwise 12207c478bd9Sstevel@tonic-gate * expflag int 12217c478bd9Sstevel@tonic-gate * TRUE if password expiration information is to 12227c478bd9Sstevel@tonic-gate * be displayed, FALSE otherwise 12237c478bd9Sstevel@tonic-gate * 12247c478bd9Sstevel@tonic-gate * Returns: void 12257c478bd9Sstevel@tonic-gate */ 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate static void 1228*20d7339fSgww genlogreport(int pipeflag, int xtndflag, int expflag) 12297c478bd9Sstevel@tonic-gate { 12307c478bd9Sstevel@tonic-gate struct display *p; /* Value being displayed */ 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate /* 12347c478bd9Sstevel@tonic-gate * Initialization for loop. 1235*20d7339fSgww * (NOTE: The first element in the list of logins to display is 1236*20d7339fSgww * a dummy element.) 12377c478bd9Sstevel@tonic-gate */ 12387c478bd9Sstevel@tonic-gate p = displayhead; 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate /* 12417c478bd9Sstevel@tonic-gate * Display elements in the list 12427c478bd9Sstevel@tonic-gate */ 1243*20d7339fSgww if (pipeflag) { 1244*20d7339fSgww for (p = displayhead->nextlogin; p; p = p->nextlogin) { 12457c478bd9Sstevel@tonic-gate writeunformatted(p, xtndflag, expflag); 1246*20d7339fSgww } 1247*20d7339fSgww } else { 1248*20d7339fSgww for (p = displayhead->nextlogin; p; p = p->nextlogin) { 12497c478bd9Sstevel@tonic-gate writeformatted(p, xtndflag, expflag); 12507c478bd9Sstevel@tonic-gate } 1251*20d7339fSgww } 1252*20d7339fSgww } 12537c478bd9Sstevel@tonic-gate 1254*20d7339fSgww 1255*20d7339fSgww char * 1256*20d7339fSgww strcpmalloc(char *str) 1257*20d7339fSgww { 12587c478bd9Sstevel@tonic-gate if (str == NULL) 1259*20d7339fSgww return (NULL); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate return (strcpy(allocstr((unsigned int)strlen(str)+1), str)); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate struct localpw { 12657c478bd9Sstevel@tonic-gate struct localpw *next; 12667c478bd9Sstevel@tonic-gate struct passwd pw; 12677c478bd9Sstevel@tonic-gate }; 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate struct localpw *pwtable = NULL; 12707c478bd9Sstevel@tonic-gate 1271*20d7339fSgww /* Local passwd pointer for getpwent() -- -1 means not in use, NULL for EOF */ 1272*20d7339fSgww struct localpw *pwptr; 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate int in_localgetpwent = 0; /* Set if in local_getpwent */ 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate void 1277*20d7339fSgww build_localpw(void) 12787c478bd9Sstevel@tonic-gate { 12797c478bd9Sstevel@tonic-gate struct localpw *next, *cur; 12807c478bd9Sstevel@tonic-gate struct passwd *pw; 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate next = (struct localpw *)allocblk(sizeof (struct localpw)); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate pwtable = next; 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate while ((pw = getpwent()) != NULL) { 12877c478bd9Sstevel@tonic-gate /* 12887c478bd9Sstevel@tonic-gate * Copy the data -- we have to alloc areas for it all 12897c478bd9Sstevel@tonic-gate */ 12907c478bd9Sstevel@tonic-gate next->pw.pw_name = strcpmalloc(pw->pw_name); 12917c478bd9Sstevel@tonic-gate next->pw.pw_passwd = strcpmalloc(pw->pw_passwd); 12927c478bd9Sstevel@tonic-gate next->pw.pw_uid = pw->pw_uid; 12937c478bd9Sstevel@tonic-gate next->pw.pw_gid = pw->pw_gid; 12947c478bd9Sstevel@tonic-gate next->pw.pw_age = strcpmalloc(pw->pw_age); 12957c478bd9Sstevel@tonic-gate next->pw.pw_comment = strcpmalloc(pw->pw_comment); 12967c478bd9Sstevel@tonic-gate next->pw.pw_gecos = strcpmalloc(pw->pw_gecos); 12977c478bd9Sstevel@tonic-gate next->pw.pw_dir = strcpmalloc(pw->pw_dir); 12987c478bd9Sstevel@tonic-gate next->pw.pw_shell = strcpmalloc(pw->pw_shell); 12997c478bd9Sstevel@tonic-gate 1300*20d7339fSgww next->next = (struct localpw *)allocblk( 1301*20d7339fSgww sizeof (struct localpw)); 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate cur = next; 13047c478bd9Sstevel@tonic-gate next = next->next; 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate /* 13087c478bd9Sstevel@tonic-gate * At this point we have one extra (struct localpw) allocated; 13097c478bd9Sstevel@tonic-gate * sine alloclbk doesn't have a freeblk, we just leave it unreferenced. 13107c478bd9Sstevel@tonic-gate */ 13117c478bd9Sstevel@tonic-gate 1312*20d7339fSgww if (pwtable == next) { 13137c478bd9Sstevel@tonic-gate pwtable = NULL; 1314*20d7339fSgww } else { 13157c478bd9Sstevel@tonic-gate cur->next = NULL; 1316*20d7339fSgww } 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate endpwent(); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate struct passwd * 1322*20d7339fSgww local_getpwent(void) 13237c478bd9Sstevel@tonic-gate { 13247c478bd9Sstevel@tonic-gate if (!in_localgetpwent) { 13257c478bd9Sstevel@tonic-gate in_localgetpwent = 1; 13267c478bd9Sstevel@tonic-gate pwptr = pwtable; 1327*20d7339fSgww } else if (pwptr != NULL) { 13287c478bd9Sstevel@tonic-gate pwptr = pwptr->next; 1329*20d7339fSgww } 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate if (pwptr != NULL) 1332*20d7339fSgww return (&(pwptr->pw)); 13337c478bd9Sstevel@tonic-gate else 1334*20d7339fSgww return (NULL); 13357c478bd9Sstevel@tonic-gate } 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate void 1338*20d7339fSgww local_endpwent(void) 13397c478bd9Sstevel@tonic-gate { 13407c478bd9Sstevel@tonic-gate in_localgetpwent = 0; 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate long 1344*20d7339fSgww local_pwtell(void) 13457c478bd9Sstevel@tonic-gate { 1346*20d7339fSgww return ((long)pwptr); 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate void 1350*20d7339fSgww local_pwseek(long ptr) 13517c478bd9Sstevel@tonic-gate { 13527c478bd9Sstevel@tonic-gate pwptr = (struct localpw *)ptr; 13537c478bd9Sstevel@tonic-gate } 1354*20d7339fSgww 13557c478bd9Sstevel@tonic-gate /* 13567c478bd9Sstevel@tonic-gate * logins [-admopstux] [-l logins] [-g groups] 13577c478bd9Sstevel@tonic-gate * 13587c478bd9Sstevel@tonic-gate * This command generates a report of logins administered on 13597c478bd9Sstevel@tonic-gate * the system. The list will contain logins that meet criteria 13607c478bd9Sstevel@tonic-gate * described by the options in the list. If there are no options, 13617c478bd9Sstevel@tonic-gate * it will list all logins administered. It is intended to be used 13627c478bd9Sstevel@tonic-gate * only by administrators. 13637c478bd9Sstevel@tonic-gate * 13647c478bd9Sstevel@tonic-gate * Options: 13657c478bd9Sstevel@tonic-gate * -a Display password expiration information. 13667c478bd9Sstevel@tonic-gate * -d list all logins that share user-IDs with another 13677c478bd9Sstevel@tonic-gate * login. 13687c478bd9Sstevel@tonic-gate * -g groups specifies the names of the groups to which a login 13697c478bd9Sstevel@tonic-gate * must belong before it is included in the generated 13707c478bd9Sstevel@tonic-gate * list. "groups" is a comma-list of group names. 13717c478bd9Sstevel@tonic-gate * -l logins specifies the logins to display. "logins" is a 13727c478bd9Sstevel@tonic-gate * comma-list of login names. 13737c478bd9Sstevel@tonic-gate * -m in addition to the usual information, for each 13747c478bd9Sstevel@tonic-gate * login displayed, list all groups to which that 13757c478bd9Sstevel@tonic-gate * login is member. 13767c478bd9Sstevel@tonic-gate * -o generate a report as a colon-list instead of in a 13777c478bd9Sstevel@tonic-gate * columnar format 13787c478bd9Sstevel@tonic-gate * -p list all logins that have no password. 13797c478bd9Sstevel@tonic-gate * -s list all system logins 13807c478bd9Sstevel@tonic-gate * -t sort the report lexicographically by login name 13817c478bd9Sstevel@tonic-gate * instead of by user-ID 13827c478bd9Sstevel@tonic-gate * -u list all user logins 13837c478bd9Sstevel@tonic-gate * -x in addition to the usual information, display an 13847c478bd9Sstevel@tonic-gate * extended set of information that includes the home 13857c478bd9Sstevel@tonic-gate * directory, initial process, and password status and 13867c478bd9Sstevel@tonic-gate * aging information 13877c478bd9Sstevel@tonic-gate * 13887c478bd9Sstevel@tonic-gate * Exit Codes: 13897c478bd9Sstevel@tonic-gate * 0 All's well that ends well 13907c478bd9Sstevel@tonic-gate * 1 Usage error 13917c478bd9Sstevel@tonic-gate */ 13927c478bd9Sstevel@tonic-gate 1393*20d7339fSgww int 1394*20d7339fSgww main(int argc, char *argv[]) 13957c478bd9Sstevel@tonic-gate { 13967c478bd9Sstevel@tonic-gate struct passwd *plookpwd; /* Ptr to searcher pw (-d) */ 13977c478bd9Sstevel@tonic-gate struct reqgrp *reqgrphead; /* Head of the req'd group list */ 13987c478bd9Sstevel@tonic-gate struct reqgrp *pgrp; /* Current item in req'd group list */ 13997c478bd9Sstevel@tonic-gate struct reqgrp *qgrp; /* Prev item in the req'd group list */ 14007c478bd9Sstevel@tonic-gate struct reqlogin *reqloginhead; /* Head of req'd login list */ 1401*20d7339fSgww struct reqlogin *plogin; /* Current item in req'd login list */ 1402*20d7339fSgww struct reqlogin *qlogin; /* Prev item in req'd login list */ 14037c478bd9Sstevel@tonic-gate struct passwd *pwent; /* /etc/passwd entry */ 14047c478bd9Sstevel@tonic-gate struct group *grent; /* /etc/group entry */ 14057c478bd9Sstevel@tonic-gate char *token; /* Token extracted by strtok() */ 14067c478bd9Sstevel@tonic-gate char **pp; /* Group member */ 14077c478bd9Sstevel@tonic-gate char *g_arg; /* -g option's argument */ 14087c478bd9Sstevel@tonic-gate char *l_arg; /* -l option's argument */ 14097c478bd9Sstevel@tonic-gate long lookpos; /* File pos'n, rec we're looking for */ 14107c478bd9Sstevel@tonic-gate int a_seen; /* Is -a requested? */ 14117c478bd9Sstevel@tonic-gate int d_seen; /* Is -d requested? */ 14127c478bd9Sstevel@tonic-gate int g_seen; /* Is -g requested? */ 14137c478bd9Sstevel@tonic-gate int l_seen; /* Is -l requested? */ 14147c478bd9Sstevel@tonic-gate int m_seen; /* Is -m requested? */ 14157c478bd9Sstevel@tonic-gate int o_seen; /* Is -o requested? */ 14167c478bd9Sstevel@tonic-gate int p_seen; /* Is -p requested? */ 14177c478bd9Sstevel@tonic-gate int s_seen; /* Is -s requested? */ 14187c478bd9Sstevel@tonic-gate int t_seen; /* Is -t requested? */ 14197c478bd9Sstevel@tonic-gate int u_seen; /* Is -u requested? */ 14207c478bd9Sstevel@tonic-gate int x_seen; /* Is -x requested? */ 14217c478bd9Sstevel@tonic-gate int errflg; /* Is there a command-line problem */ 14227c478bd9Sstevel@tonic-gate int done; /* Is the process (?) is complete */ 1423*20d7339fSgww int groupcount; /* Number of groups specified */ 14247c478bd9Sstevel@tonic-gate int doall; /* Are all logins to be reported */ 14257c478bd9Sstevel@tonic-gate int c; /* Character returned from getopt() */ 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 14307c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 14317c478bd9Sstevel@tonic-gate #endif 14327c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* Initializations */ 14357c478bd9Sstevel@tonic-gate initmsg(argv[0]); 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate 1439*20d7339fSgww /* Command-line processing */ 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate /* Initializations */ 14427c478bd9Sstevel@tonic-gate a_seen = FALSE; 14437c478bd9Sstevel@tonic-gate d_seen = FALSE; 14447c478bd9Sstevel@tonic-gate g_seen = FALSE; 14457c478bd9Sstevel@tonic-gate l_seen = FALSE; 14467c478bd9Sstevel@tonic-gate m_seen = FALSE; 14477c478bd9Sstevel@tonic-gate o_seen = FALSE; 14487c478bd9Sstevel@tonic-gate p_seen = FALSE; 14497c478bd9Sstevel@tonic-gate s_seen = FALSE; 14507c478bd9Sstevel@tonic-gate t_seen = FALSE; 14517c478bd9Sstevel@tonic-gate u_seen = FALSE; 14527c478bd9Sstevel@tonic-gate x_seen = FALSE; 14537c478bd9Sstevel@tonic-gate errflg = FALSE; 14547c478bd9Sstevel@tonic-gate opterr = 0; 14557c478bd9Sstevel@tonic-gate while (!errflg && ((c = getopt(argc, argv, OPTSTR)) != EOF)) { 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate /* Case on the option character */ 14587c478bd9Sstevel@tonic-gate switch (c) { 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* 14617c478bd9Sstevel@tonic-gate * -a option: 14627c478bd9Sstevel@tonic-gate * Display password expiration information 14637c478bd9Sstevel@tonic-gate */ 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate case 'a': 1466*20d7339fSgww if (a_seen) 1467*20d7339fSgww errflg = TRUE; 1468*20d7339fSgww else 1469*20d7339fSgww a_seen = TRUE; 14707c478bd9Sstevel@tonic-gate break; 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate /* 14737c478bd9Sstevel@tonic-gate * -d option: 14747c478bd9Sstevel@tonic-gate * Display logins which share user-IDs with other logins 14757c478bd9Sstevel@tonic-gate */ 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate case 'd': 1478*20d7339fSgww if (d_seen) 1479*20d7339fSgww errflg = TRUE; 1480*20d7339fSgww else 1481*20d7339fSgww d_seen = TRUE; 14827c478bd9Sstevel@tonic-gate break; 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate /* 14857c478bd9Sstevel@tonic-gate * -g <groups> option: 14867c478bd9Sstevel@tonic-gate * Display the specified groups 14877c478bd9Sstevel@tonic-gate */ 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate case 'g': 1490*20d7339fSgww if (g_seen) { 1491*20d7339fSgww errflg = TRUE; 1492*20d7339fSgww } else { 14937c478bd9Sstevel@tonic-gate g_seen = TRUE; 14947c478bd9Sstevel@tonic-gate g_arg = optarg; 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate break; 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate /* 14997c478bd9Sstevel@tonic-gate * -l <logins> option: 15007c478bd9Sstevel@tonic-gate * Display the specified logins 15017c478bd9Sstevel@tonic-gate */ 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate case 'l': 1504*20d7339fSgww if (l_seen) { 1505*20d7339fSgww errflg = TRUE; 1506*20d7339fSgww } else { 15077c478bd9Sstevel@tonic-gate l_seen = TRUE; 15087c478bd9Sstevel@tonic-gate l_arg = optarg; 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate break; 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate /* 15137c478bd9Sstevel@tonic-gate * -m option: 15147c478bd9Sstevel@tonic-gate * Display multiple group information 15157c478bd9Sstevel@tonic-gate */ 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate case 'm': 1518*20d7339fSgww if (m_seen) 1519*20d7339fSgww errflg = TRUE; 1520*20d7339fSgww else 1521*20d7339fSgww m_seen = TRUE; 15227c478bd9Sstevel@tonic-gate break; 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* 15257c478bd9Sstevel@tonic-gate * -o option: 15267c478bd9Sstevel@tonic-gate * Display information as a colon-list 15277c478bd9Sstevel@tonic-gate */ 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate case 'o': 1530*20d7339fSgww if (o_seen) 1531*20d7339fSgww errflg = TRUE; 1532*20d7339fSgww else 1533*20d7339fSgww o_seen = TRUE; 15347c478bd9Sstevel@tonic-gate break; 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate /* 15377c478bd9Sstevel@tonic-gate * -p option: 15387c478bd9Sstevel@tonic-gate * Select logins that have no password 15397c478bd9Sstevel@tonic-gate */ 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate case 'p': 1542*20d7339fSgww if (p_seen) 1543*20d7339fSgww errflg = TRUE; 1544*20d7339fSgww else 1545*20d7339fSgww p_seen = TRUE; 15467c478bd9Sstevel@tonic-gate break; 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate /* 15497c478bd9Sstevel@tonic-gate * -s option: 15507c478bd9Sstevel@tonic-gate * Select system logins 15517c478bd9Sstevel@tonic-gate */ 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate case 's': 1554*20d7339fSgww if (s_seen) 1555*20d7339fSgww errflg = TRUE; 1556*20d7339fSgww else 1557*20d7339fSgww s_seen = TRUE; 15587c478bd9Sstevel@tonic-gate break; 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate /* 15617c478bd9Sstevel@tonic-gate * -t option: 15627c478bd9Sstevel@tonic-gate * Sort alphabetically by login-ID instead of numerically 15637c478bd9Sstevel@tonic-gate * by user-ID 15647c478bd9Sstevel@tonic-gate */ 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate case 't': 1567*20d7339fSgww if (t_seen) 1568*20d7339fSgww errflg = TRUE; 1569*20d7339fSgww else 1570*20d7339fSgww t_seen = TRUE; 15717c478bd9Sstevel@tonic-gate break; 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate /* 15747c478bd9Sstevel@tonic-gate * -u option: 15757c478bd9Sstevel@tonic-gate * Select user logins 15767c478bd9Sstevel@tonic-gate */ 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate case 'u': 1579*20d7339fSgww if (u_seen) 1580*20d7339fSgww errflg = TRUE; 1581*20d7339fSgww else 1582*20d7339fSgww u_seen = TRUE; 15837c478bd9Sstevel@tonic-gate break; 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate /* 15867c478bd9Sstevel@tonic-gate * -x option: 15877c478bd9Sstevel@tonic-gate * Display extended info (init working dir, shell, pwd info) 15887c478bd9Sstevel@tonic-gate */ 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate case 'x': 1591*20d7339fSgww if (x_seen) 1592*20d7339fSgww errflg = TRUE; 1593*20d7339fSgww else 1594*20d7339fSgww x_seen = TRUE; 15957c478bd9Sstevel@tonic-gate break; 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate default: /* Oops.... */ 15987c478bd9Sstevel@tonic-gate errflg = TRUE; 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate /* Write out a usage message if necessary and quit */ 16037c478bd9Sstevel@tonic-gate if (errflg || (optind != argc)) { 16047c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(USAGE_MSG)); 16057c478bd9Sstevel@tonic-gate exit(1); 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate /* 16117c478bd9Sstevel@tonic-gate * The following section does preparation work, setting up for 16127c478bd9Sstevel@tonic-gate * building the list of logins to display 16137c478bd9Sstevel@tonic-gate */ 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate /* 16167c478bd9Sstevel@tonic-gate * Very first thing, build an in-core structure of passwd file entries. 16177c478bd9Sstevel@tonic-gate * This is important since we have to assume that getpwent() is going 16187c478bd9Sstevel@tonic-gate * out to one or more network name services that could be changing 16197c478bd9Sstevel@tonic-gate * on the fly. This will limit us to one pass through the network data. 16207c478bd9Sstevel@tonic-gate */ 16217c478bd9Sstevel@tonic-gate build_localpw(); 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate /* 16257c478bd9Sstevel@tonic-gate * If the -g groups option was on the command line, build a 16267c478bd9Sstevel@tonic-gate * list containing groups we're to list logins for. 16277c478bd9Sstevel@tonic-gate */ 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate if (g_seen) { 16307c478bd9Sstevel@tonic-gate groupcount = 0; 1631*20d7339fSgww reqgrphead = NULL; 16327c478bd9Sstevel@tonic-gate if (token = strtok(g_arg, ",")) { 1633*20d7339fSgww pgrp = (struct reqgrp *)allocblk( 1634*20d7339fSgww sizeof (struct reqgrp)); 16357c478bd9Sstevel@tonic-gate pgrp->groupname = token; 16367c478bd9Sstevel@tonic-gate pgrp->found = FALSE; 1637*20d7339fSgww pgrp->next = NULL; 16387c478bd9Sstevel@tonic-gate groupcount++; 16397c478bd9Sstevel@tonic-gate reqgrphead = pgrp; 16407c478bd9Sstevel@tonic-gate qgrp = pgrp; 16417c478bd9Sstevel@tonic-gate while (token = strtok(NULL, ",")) { 1642*20d7339fSgww pgrp = (struct reqgrp *)allocblk( 1643*20d7339fSgww sizeof (struct reqgrp)); 16447c478bd9Sstevel@tonic-gate pgrp->groupname = token; 16457c478bd9Sstevel@tonic-gate pgrp->found = FALSE; 1646*20d7339fSgww pgrp->next = NULL; 16477c478bd9Sstevel@tonic-gate groupcount++; 16487c478bd9Sstevel@tonic-gate qgrp->next = pgrp; 16497c478bd9Sstevel@tonic-gate qgrp = pgrp; 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate } 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate /* 16567c478bd9Sstevel@tonic-gate * If -l logins is on the command line, build a list of 16577c478bd9Sstevel@tonic-gate * logins we're to generate reports for. 16587c478bd9Sstevel@tonic-gate */ 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate if (l_seen) { 1661*20d7339fSgww reqloginhead = NULL; 16627c478bd9Sstevel@tonic-gate if (token = strtok(l_arg, ",")) { 1663*20d7339fSgww plogin = (struct reqlogin *)allocblk( 1664*20d7339fSgww sizeof (struct reqlogin)); 16657c478bd9Sstevel@tonic-gate plogin->loginname = token; 16667c478bd9Sstevel@tonic-gate plogin->found = FALSE; 1667*20d7339fSgww plogin->next = NULL; 16687c478bd9Sstevel@tonic-gate reqloginhead = plogin; 16697c478bd9Sstevel@tonic-gate qlogin = plogin; 16707c478bd9Sstevel@tonic-gate while (token = strtok(NULL, ",")) { 1671*20d7339fSgww plogin = (struct reqlogin *)allocblk( 1672*20d7339fSgww sizeof (struct reqlogin)); 16737c478bd9Sstevel@tonic-gate plogin->loginname = token; 16747c478bd9Sstevel@tonic-gate plogin->found = FALSE; 1675*20d7339fSgww plogin->next = NULL; 16767c478bd9Sstevel@tonic-gate qlogin->next = plogin; 16777c478bd9Sstevel@tonic-gate qlogin = plogin; 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate while (pwent = local_getpwent()) { 16817c478bd9Sstevel@tonic-gate done = FALSE; 16827c478bd9Sstevel@tonic-gate for (plogin = reqloginhead; !done && plogin; 16837c478bd9Sstevel@tonic-gate plogin = plogin->next) { 16847c478bd9Sstevel@tonic-gate if (strcmp(pwent->pw_name, 16857c478bd9Sstevel@tonic-gate plogin->loginname) == 0) { 16867c478bd9Sstevel@tonic-gate plogin->found = TRUE; 16877c478bd9Sstevel@tonic-gate done = TRUE; 16887c478bd9Sstevel@tonic-gate } 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate local_endpwent(); 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate /* 16957c478bd9Sstevel@tonic-gate * Generate the list of login information to display 16967c478bd9Sstevel@tonic-gate */ 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate /* Initialize the login list */ 16997c478bd9Sstevel@tonic-gate initmembers(); 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate /* 17037c478bd9Sstevel@tonic-gate * If -g groups was specified, generate a list of members 17047c478bd9Sstevel@tonic-gate * of the specified groups 17057c478bd9Sstevel@tonic-gate */ 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate if (g_seen) { 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate /* For each group in the /etc/group file ... */ 17107c478bd9Sstevel@tonic-gate while (grent = getgrent()) { 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate /* For each group mentioned with the -g option ... */ 1713*20d7339fSgww for (pgrp = reqgrphead; (groupcount > 0) && pgrp; 1714*20d7339fSgww pgrp = pgrp->next) { 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate if (!pgrp->found) { 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate /* 1719*20d7339fSgww * If the mentioned group is found 1720*20d7339fSgww * in the /etc/group file ... 17217c478bd9Sstevel@tonic-gate */ 1722*20d7339fSgww if (strcmp(grent->gr_name, 1723*20d7339fSgww pgrp->groupname) == 0) { 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate /* 1726*20d7339fSgww * Mark the entry is found, 1727*20d7339fSgww * remembering the group-ID 1728*20d7339fSgww * for later 17297c478bd9Sstevel@tonic-gate */ 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate pgrp->found = TRUE; 17327c478bd9Sstevel@tonic-gate groupcount--; 17337c478bd9Sstevel@tonic-gate pgrp->groupID = grent->gr_gid; 1734*20d7339fSgww for (pp = grent->gr_mem; *pp; 1735*20d7339fSgww pp++) { 1736*20d7339fSgww addmember(*pp); 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate } 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate } 1741*20d7339fSgww } 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate /* 17447c478bd9Sstevel@tonic-gate * If any groups weren't found, write a message indicating 17457c478bd9Sstevel@tonic-gate * such, then continue 17467c478bd9Sstevel@tonic-gate */ 17477c478bd9Sstevel@tonic-gate 1748*20d7339fSgww qgrp = NULL; 17497c478bd9Sstevel@tonic-gate for (pgrp = reqgrphead; pgrp; pgrp = pgrp->next) { 17507c478bd9Sstevel@tonic-gate if (!pgrp->found) { 1751*20d7339fSgww wrtmsg(MM_WARNING, MM_NULLACT, MM_NULLTAG, 1752*20d7339fSgww gettext("%s was not found"), 1753*20d7339fSgww pgrp->groupname); 1754*20d7339fSgww if (!qgrp) { 1755*20d7339fSgww reqgrphead = pgrp->next; 1756*20d7339fSgww } else { 1757*20d7339fSgww qgrp->next = pgrp->next; 17587c478bd9Sstevel@tonic-gate } 1759*20d7339fSgww } else { 1760*20d7339fSgww qgrp = pgrp; 1761*20d7339fSgww } 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate endgrent(); 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* Initialize the list of logins to display */ 17687c478bd9Sstevel@tonic-gate initdisp(); 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate /* 17727c478bd9Sstevel@tonic-gate * Add logins that have user-IDs that are used more than once, 17737c478bd9Sstevel@tonic-gate * if requested. This command is pretty slow, since the algorithm 17747c478bd9Sstevel@tonic-gate * reads from the /etc/passwd file 1+2+3+...+n times where n is the 17757c478bd9Sstevel@tonic-gate * number of login-IDs in the /etc/passwd file. (Actually, this 17767c478bd9Sstevel@tonic-gate * can be optimized so it's not quite that bad, but the order or 17777c478bd9Sstevel@tonic-gate * magnitude stays the same.) 17787c478bd9Sstevel@tonic-gate * 17797c478bd9Sstevel@tonic-gate * Note: This processing needs to be done before any other options 17807c478bd9Sstevel@tonic-gate * are processed -- the algorithm contains an optimization 17817c478bd9Sstevel@tonic-gate * that insists on the display list being empty before this 17827c478bd9Sstevel@tonic-gate * option is processed. 17837c478bd9Sstevel@tonic-gate */ 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate if (d_seen) { 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate /* 17887c478bd9Sstevel@tonic-gate * The following code is a quick&dirty reimplementation of the 17897c478bd9Sstevel@tonic-gate * original algorithm, which opened the password file twice (to 17907c478bd9Sstevel@tonic-gate * get two file pointer into the data) and then used fgetpwent() 17917c478bd9Sstevel@tonic-gate * in undocumented ways to scan through the file, checking for 17927c478bd9Sstevel@tonic-gate * duplicates. This does not work when getpwent() is used to 17937c478bd9Sstevel@tonic-gate * go out over the network, since there is not file pointer. 17947c478bd9Sstevel@tonic-gate * 1795*20d7339fSgww * Instead an in-memory list of passwd structures is built, 1796*20d7339fSgww * and then this list is scanned. The routines 1797*20d7339fSgww * Local_getpwent(), etc., are designed to mimic the standard 1798*20d7339fSgww * library routines, so this code does not have to be 1799*20d7339fSgww * extensively modified. 18007c478bd9Sstevel@tonic-gate */ 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate /* 18037c478bd9Sstevel@tonic-gate * For reference, here is the original comment about the next 1804*20d7339fSgww * section of code. Some of the code has changed, but the 1805*20d7339fSgww * algorithm is the same: 18067c478bd9Sstevel@tonic-gate * 18077c478bd9Sstevel@tonic-gate * Open the system password file once. This instance will be 18087c478bd9Sstevel@tonic-gate * used to leaf through the file once, reading each entry once, 18097c478bd9Sstevel@tonic-gate * and searching the remainder of the file for another login-ID 18107c478bd9Sstevel@tonic-gate * that has the same user-ID. Note that there are lots of 18117c478bd9Sstevel@tonic-gate * contortions one has to go through when reading two instances 18127c478bd9Sstevel@tonic-gate * of the /etc/passwd file. That's why there's some seeking, 18137c478bd9Sstevel@tonic-gate * re-reading of the same record, and other junk. Luckily, this 18147c478bd9Sstevel@tonic-gate * feature won't be requested very often, and still isn't too 18157c478bd9Sstevel@tonic-gate * slow... 18167c478bd9Sstevel@tonic-gate */ 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate /* For each entry in the passwd database ... */ 18197c478bd9Sstevel@tonic-gate while (plookpwd = local_getpwent()) { 18207c478bd9Sstevel@tonic-gate /* 1821*20d7339fSgww * Optimization -- If the login's user-ID is already 1822*20d7339fSgww * in the display list, there's no reason to process 1823*20d7339fSgww * this entry -- it's already there. 18247c478bd9Sstevel@tonic-gate */ 18257c478bd9Sstevel@tonic-gate if (!isuidindisp(plookpwd)) { 18267c478bd9Sstevel@tonic-gate /* 1827*20d7339fSgww * Rememeber the current entry's position, 1828*20d7339fSgww * so when we finish scanning through the 1829*20d7339fSgww * database looking for duplicates we can 1830*20d7339fSgww * return to the current place, so that the 1831*20d7339fSgww * enclosing loop will march in an orderly 1832*20d7339fSgww * fashion through the passwd database. 18337c478bd9Sstevel@tonic-gate */ 18347c478bd9Sstevel@tonic-gate done = FALSE; 18357c478bd9Sstevel@tonic-gate lookpos = local_pwtell(); 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate /* 1838*20d7339fSgww * For each record in the passwd database 1839*20d7339fSgww * beyond the searching record ... 18407c478bd9Sstevel@tonic-gate */ 18417c478bd9Sstevel@tonic-gate while (pwent = local_getpwent()) { 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate /* 1844*20d7339fSgww * If there's a match between the 1845*20d7339fSgww * searcher's user-ID and the 1846*20d7339fSgww * searchee's user-ID ... 18477c478bd9Sstevel@tonic-gate */ 18487c478bd9Sstevel@tonic-gate if (pwent->pw_uid == plookpwd->pw_uid) { 18497c478bd9Sstevel@tonic-gate /* 1850*20d7339fSgww * If this is the first 1851*20d7339fSgww * duplicate of this searcher 18527c478bd9Sstevel@tonic-gate * that we find, 1853*20d7339fSgww * add the searcher's 1854*20d7339fSgww * record to the display list 1855*20d7339fSgww * (It wants to be on the 1856*20d7339fSgww * list first to avoid 1857*20d7339fSgww * ordering "flakeyness") 18587c478bd9Sstevel@tonic-gate */ 18597c478bd9Sstevel@tonic-gate if (done == FALSE) { 18607c478bd9Sstevel@tonic-gate adddisp(plookpwd); 1861*20d7339fSgww done = TRUE; 18627c478bd9Sstevel@tonic-gate } 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate /* 1865*20d7339fSgww * Now add the searchee's 1866*20d7339fSgww * record 18677c478bd9Sstevel@tonic-gate */ 18687c478bd9Sstevel@tonic-gate adddisp(pwent); 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate } 18717c478bd9Sstevel@tonic-gate } 18727c478bd9Sstevel@tonic-gate /* Reposition to searcher record */ 18737c478bd9Sstevel@tonic-gate local_pwseek(lookpos); 18747c478bd9Sstevel@tonic-gate } 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate local_endpwent(); 18787c478bd9Sstevel@tonic-gate } 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate /* 18827c478bd9Sstevel@tonic-gate * Loop through the passwd database squirelling away the 18837c478bd9Sstevel@tonic-gate * information we need for the display. 18847c478bd9Sstevel@tonic-gate * 18857c478bd9Sstevel@tonic-gate * NOTE: Once a login is added to the list, the rest of the 18867c478bd9Sstevel@tonic-gate * body of the loop is bypassed (via a continue statement). 18877c478bd9Sstevel@tonic-gate */ 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate doall = !(s_seen || u_seen || p_seen || d_seen || l_seen || g_seen); 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate if (doall || s_seen || u_seen || p_seen || l_seen || g_seen) { 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate while (pwent = local_getpwent()) { 18947c478bd9Sstevel@tonic-gate done = FALSE; 18957c478bd9Sstevel@tonic-gate 1896*20d7339fSgww /* 1897*20d7339fSgww * If no user-specific options were specified, 1898*20d7339fSgww * include this login-ID 1899*20d7339fSgww */ 19007c478bd9Sstevel@tonic-gate if (doall) { 19017c478bd9Sstevel@tonic-gate adddisp(pwent); 19027c478bd9Sstevel@tonic-gate continue; 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate 1905*20d7339fSgww /* 1906*20d7339fSgww * If the user specified system login-IDs, 1907*20d7339fSgww * and this is a system ID, include it 1908*20d7339fSgww */ 1909*20d7339fSgww if (s_seen) { 1910*20d7339fSgww if (isasystemlogin(pwent)) { 19117c478bd9Sstevel@tonic-gate adddisp(pwent); 19127c478bd9Sstevel@tonic-gate continue; 19137c478bd9Sstevel@tonic-gate } 1914*20d7339fSgww } 19157c478bd9Sstevel@tonic-gate 1916*20d7339fSgww /* 1917*20d7339fSgww * If the user specified user login-IDs, 1918*20d7339fSgww * and this is a user ID, include it 1919*20d7339fSgww */ 1920*20d7339fSgww if (u_seen) { 1921*20d7339fSgww if (isauserlogin(pwent)) { 19227c478bd9Sstevel@tonic-gate adddisp(pwent); 19237c478bd9Sstevel@tonic-gate continue; 19247c478bd9Sstevel@tonic-gate } 1925*20d7339fSgww } 19267c478bd9Sstevel@tonic-gate 1927*20d7339fSgww /* 1928*20d7339fSgww * If the user is asking for login-IDs that have 1929*20d7339fSgww * no password, and this one has no password, include it 1930*20d7339fSgww */ 1931*20d7339fSgww if (p_seen) { 1932*20d7339fSgww if (hasnopasswd(pwent)) { 19337c478bd9Sstevel@tonic-gate adddisp(pwent); 19347c478bd9Sstevel@tonic-gate continue; 19357c478bd9Sstevel@tonic-gate } 1936*20d7339fSgww } 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate /* 19397c478bd9Sstevel@tonic-gate * If specific logins were requested, leaf through 19407c478bd9Sstevel@tonic-gate * the list of logins they requested. If this login 19417c478bd9Sstevel@tonic-gate * is on the list, include it. 19427c478bd9Sstevel@tonic-gate */ 19437c478bd9Sstevel@tonic-gate if (l_seen) { 1944*20d7339fSgww for (plogin = reqloginhead; !done && plogin; 1945*20d7339fSgww plogin = plogin->next) { 1946*20d7339fSgww if (strcmp(pwent->pw_name, 1947*20d7339fSgww plogin->loginname) == 0) { 19487c478bd9Sstevel@tonic-gate plogin->found = TRUE; 19497c478bd9Sstevel@tonic-gate adddisp(pwent); 19507c478bd9Sstevel@tonic-gate done = TRUE; 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate } 1953*20d7339fSgww if (done) 1954*20d7339fSgww continue; 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate /* 19587c478bd9Sstevel@tonic-gate * If specific groups were requested, leaf through the 1959*20d7339fSgww * list of login-IDs that belong to those groups. 1960*20d7339fSgww * If this login-ID is in that list, or its primary 1961*20d7339fSgww * group is one of those requested, include it. 19627c478bd9Sstevel@tonic-gate */ 19637c478bd9Sstevel@tonic-gate 19647c478bd9Sstevel@tonic-gate if (g_seen) { 1965*20d7339fSgww for (pgrp = reqgrphead; !done && pgrp; 1966*20d7339fSgww pgrp = pgrp->next) { 19677c478bd9Sstevel@tonic-gate if (pwent->pw_gid == pgrp->groupID) { 19687c478bd9Sstevel@tonic-gate adddisp(pwent); 19697c478bd9Sstevel@tonic-gate done = TRUE; 19707c478bd9Sstevel@tonic-gate } 1971*20d7339fSgww } 19727c478bd9Sstevel@tonic-gate if (!done && isamember(pwent->pw_name)) { 19737c478bd9Sstevel@tonic-gate adddisp(pwent); 19747c478bd9Sstevel@tonic-gate done = TRUE; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate } 1977*20d7339fSgww if (done) 1978*20d7339fSgww continue; 19797c478bd9Sstevel@tonic-gate } 1980*20d7339fSgww 19817c478bd9Sstevel@tonic-gate local_endpwent(); 19827c478bd9Sstevel@tonic-gate } 19837c478bd9Sstevel@tonic-gate 1984*20d7339fSgww /* Let the user know about logins they requested that don't exist */ 1985*20d7339fSgww if (l_seen) { 1986*20d7339fSgww for (plogin = reqloginhead; plogin; plogin = plogin->next) { 1987*20d7339fSgww if (!plogin->found) { 1988*20d7339fSgww wrtmsg(MM_WARNING, MM_NULLACT, MM_NULLTAG, 1989*20d7339fSgww gettext("%s was not found"), 1990*20d7339fSgww plogin->loginname); 1991*20d7339fSgww } 1992*20d7339fSgww } 1993*20d7339fSgww } 19947c478bd9Sstevel@tonic-gate 1995*20d7339fSgww /* Apply group information */ 19967c478bd9Sstevel@tonic-gate applygroup(m_seen); 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate 19997c478bd9Sstevel@tonic-gate /* 20007c478bd9Sstevel@tonic-gate * Apply password information (only needed if the extended 20017c478bd9Sstevel@tonic-gate * set of information has been requested) 20027c478bd9Sstevel@tonic-gate */ 2003*20d7339fSgww if (x_seen || a_seen) 2004*20d7339fSgww applypasswd(); 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate /* 2008*20d7339fSgww * Generate a report from this display items we've squirreled away 20097c478bd9Sstevel@tonic-gate */ 20107c478bd9Sstevel@tonic-gate 2011*20d7339fSgww if (t_seen) 2012*20d7339fSgww genlogreport(o_seen, x_seen, a_seen); 2013*20d7339fSgww else 2014*20d7339fSgww genuidreport(o_seen, x_seen, a_seen); 20157c478bd9Sstevel@tonic-gate 2016*20d7339fSgww /* We're through! */ 20177c478bd9Sstevel@tonic-gate return (0); 20187c478bd9Sstevel@tonic-gate } 2019