1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.15.1.2 */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * logins.c 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * This file contains the source for the administrative command 36*7c478bd9Sstevel@tonic-gate * "logins" (available to the administrator) that produces a report 37*7c478bd9Sstevel@tonic-gate * containing login-IDs and other requested information. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate /* 41*7c478bd9Sstevel@tonic-gate * Header files referenced: 42*7c478bd9Sstevel@tonic-gate * sys/types.h System data types 43*7c478bd9Sstevel@tonic-gate * stdio.h Definitions for standard I/O functions and constants 44*7c478bd9Sstevel@tonic-gate * unistd.h Standard UNIX definitions 45*7c478bd9Sstevel@tonic-gate * string.h Definitions for string-handling functions 46*7c478bd9Sstevel@tonic-gate * ctype.h Character-type definitions 47*7c478bd9Sstevel@tonic-gate * grp.h Definitions for referencing the /etc/group file 48*7c478bd9Sstevel@tonic-gate * pwd.h Definitions for referencing the /etc/passwd file 49*7c478bd9Sstevel@tonic-gate * shadow.h Definitions for the shadow password file /etc/shadow 50*7c478bd9Sstevel@tonic-gate * time.h Time definitions (ctime(), asctime(), etc.) 51*7c478bd9Sstevel@tonic-gate * stdarg.h Definitions for using a variable argument list 52*7c478bd9Sstevel@tonic-gate * fmtmsg.h Definitions for using the standard message generator 53*7c478bd9Sstevel@tonic-gate */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 56*7c478bd9Sstevel@tonic-gate #include <stdio.h> 57*7c478bd9Sstevel@tonic-gate #include <unistd.h> 58*7c478bd9Sstevel@tonic-gate #include <string.h> 59*7c478bd9Sstevel@tonic-gate #include <ctype.h> 60*7c478bd9Sstevel@tonic-gate #include <grp.h> 61*7c478bd9Sstevel@tonic-gate #include <pwd.h> 62*7c478bd9Sstevel@tonic-gate #include <shadow.h> 63*7c478bd9Sstevel@tonic-gate #include <time.h> 64*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 65*7c478bd9Sstevel@tonic-gate #include <fmtmsg.h> 66*7c478bd9Sstevel@tonic-gate #include <locale.h> 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * Externals referenced (and not defined by a header file): 70*7c478bd9Sstevel@tonic-gate * malloc Allocate memory from main memory 71*7c478bd9Sstevel@tonic-gate * getopt Extract the next option from the command line 72*7c478bd9Sstevel@tonic-gate * optind The argument count of the next option to extract 73*7c478bd9Sstevel@tonic-gate * from the command line 74*7c478bd9Sstevel@tonic-gate * optarg A pointer to the argument of the option just extracted 75*7c478bd9Sstevel@tonic-gate * from the command line 76*7c478bd9Sstevel@tonic-gate * opterr FLAG: !0 tells getopt() to write an error message if 77*7c478bd9Sstevel@tonic-gate * it detects an error 78*7c478bd9Sstevel@tonic-gate * getpwent Get next entry from the /etc/passwd file 79*7c478bd9Sstevel@tonic-gate * getpwuid Get next entry from the /etc/passwd file that has a 80*7c478bd9Sstevel@tonic-gate * specific user-ID 81*7c478bd9Sstevel@tonic-gate * fgetpwent Get next entry from an /etc/passwd-like file 82*7c478bd9Sstevel@tonic-gate * setpwent Rewind the /etc/passwd file 83*7c478bd9Sstevel@tonic-gate * endpwent Quit using the /etc/passwd file 84*7c478bd9Sstevel@tonic-gate * getgrent Get next entry from the /etc/group file 85*7c478bd9Sstevel@tonic-gate * setgrent Rewind the /etc/group file 86*7c478bd9Sstevel@tonic-gate * endgrent Quit using the /etc/passwd file 87*7c478bd9Sstevel@tonic-gate * getspnam Get the next entry for a specific login-ID from the 88*7c478bd9Sstevel@tonic-gate * /etc/shadow file 89*7c478bd9Sstevel@tonic-gate * setspent Rewind the /etc/shadow file 90*7c478bd9Sstevel@tonic-gate * endspent Quit using the /etc/shadow file 91*7c478bd9Sstevel@tonic-gate * fmtmsg Interface to the standard message generation facility 92*7c478bd9Sstevel@tonic-gate * putenv Modify the environment 93*7c478bd9Sstevel@tonic-gate * exit Exit the program 94*7c478bd9Sstevel@tonic-gate */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate extern void *malloc(); 97*7c478bd9Sstevel@tonic-gate extern int getopt(); 98*7c478bd9Sstevel@tonic-gate extern char *optarg; 99*7c478bd9Sstevel@tonic-gate extern int optind; 100*7c478bd9Sstevel@tonic-gate extern int opterr; 101*7c478bd9Sstevel@tonic-gate extern struct passwd *getpwent(); 102*7c478bd9Sstevel@tonic-gate extern struct passwd *getpwuid(); 103*7c478bd9Sstevel@tonic-gate extern struct passwd *fgetpwent(); 104*7c478bd9Sstevel@tonic-gate extern void setpwent(); 105*7c478bd9Sstevel@tonic-gate extern void endpwent(); 106*7c478bd9Sstevel@tonic-gate extern struct group *getgrent(); 107*7c478bd9Sstevel@tonic-gate extern void setgrent(); 108*7c478bd9Sstevel@tonic-gate extern void endgrent(); 109*7c478bd9Sstevel@tonic-gate extern struct spwd *getspnam(); 110*7c478bd9Sstevel@tonic-gate extern void setspent(); 111*7c478bd9Sstevel@tonic-gate extern void endspent(); 112*7c478bd9Sstevel@tonic-gate extern int fmtmsg(); 113*7c478bd9Sstevel@tonic-gate extern int putenv(); 114*7c478bd9Sstevel@tonic-gate extern void exit(); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* 117*7c478bd9Sstevel@tonic-gate * Local constant definitions 118*7c478bd9Sstevel@tonic-gate * TRUE Boolean constant 119*7c478bd9Sstevel@tonic-gate * FALSE Boolean constant 120*7c478bd9Sstevel@tonic-gate * USAGE_MSG Message used to display a usage error 121*7c478bd9Sstevel@tonic-gate * MAXLOGINSIZE Maximum length of a valid login-ID 122*7c478bd9Sstevel@tonic-gate * MAXSYSTEMLOGIN Maximum value of a system user-ID. 123*7c478bd9Sstevel@tonic-gate * OPTSTR Options to this command 124*7c478bd9Sstevel@tonic-gate * ROOT_ID The user-ID of an administrator 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate #ifndef FALSE 128*7c478bd9Sstevel@tonic-gate #define FALSE 0 129*7c478bd9Sstevel@tonic-gate #endif 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate #ifndef TRUE 132*7c478bd9Sstevel@tonic-gate #define TRUE ((int) 't') 133*7c478bd9Sstevel@tonic-gate #endif 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate #define USAGE_MSG "usage: logins [-admopstux] [-g groups] [-l logins]" 136*7c478bd9Sstevel@tonic-gate #define MAXLOGINSIZE 14 137*7c478bd9Sstevel@tonic-gate #define MAXSYSTEMLOGIN 99 138*7c478bd9Sstevel@tonic-gate #define OPTSTR "adg:l:mopstux" 139*7c478bd9Sstevel@tonic-gate #define ROOT_ID 0 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * The following macros do their function for now but will probably have 143*7c478bd9Sstevel@tonic-gate * to be replaced by functions sometime in the near future. The maximum 144*7c478bd9Sstevel@tonic-gate * system login value may someday be administerable, in which case these 145*7c478bd9Sstevel@tonic-gate * will have to be changed to become functions 146*7c478bd9Sstevel@tonic-gate * 147*7c478bd9Sstevel@tonic-gate * isasystemlogin Returns TRUE if the user-ID in the "struct passwd" 148*7c478bd9Sstevel@tonic-gate * structure referenced by the function's argument is 149*7c478bd9Sstevel@tonic-gate * less than or equal to the maximum value for a system 150*7c478bd9Sstevel@tonic-gate * user-ID, FALSE otherwise. 151*7c478bd9Sstevel@tonic-gate * isauserlogin Returns TRUE if the user-ID in the "struct passwd" 152*7c478bd9Sstevel@tonic-gate * structure referenced by the function's argument is 153*7c478bd9Sstevel@tonic-gate * greater than the maximum value for a system user-ID, 154*7c478bd9Sstevel@tonic-gate * FALSE otherwise. 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate #define isauserlogin(pw) (pw->pw_uid > MAXSYSTEMLOGIN) 158*7c478bd9Sstevel@tonic-gate #define isasystemlogin(pw) (pw->pw_uid <= MAXSYSTEMLOGIN) 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * Local datatype definitions 163*7c478bd9Sstevel@tonic-gate * struct reqgrp Describes a group as requested through the 164*7c478bd9Sstevel@tonic-gate * -g option 165*7c478bd9Sstevel@tonic-gate * struct reqlogin Describes a login-ID as requested through 166*7c478bd9Sstevel@tonic-gate * the -l option 167*7c478bd9Sstevel@tonic-gate * struct pwdinfo Describes a password's aging information, 168*7c478bd9Sstevel@tonic-gate * as extracted from /etc/shadow 169*7c478bd9Sstevel@tonic-gate * struct secgrp Describes a login-ID's secondary group 170*7c478bd9Sstevel@tonic-gate */ 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* Describes a specified group name (from the -g groups option) */ 173*7c478bd9Sstevel@tonic-gate struct reqgrp { 174*7c478bd9Sstevel@tonic-gate char *groupname; /* Requested group name */ 175*7c478bd9Sstevel@tonic-gate struct reqgrp *next; /* Next item in the list */ 176*7c478bd9Sstevel@tonic-gate int found; /* TRUE if group in /etc/group */ 177*7c478bd9Sstevel@tonic-gate gid_t groupID; /* Group's ID */ 178*7c478bd9Sstevel@tonic-gate }; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* Describes a specified login name (from the -l logins option) */ 181*7c478bd9Sstevel@tonic-gate struct reqlogin { 182*7c478bd9Sstevel@tonic-gate char *loginname; /* Requested login name */ 183*7c478bd9Sstevel@tonic-gate struct reqlogin *next; /* Next item in the list */ 184*7c478bd9Sstevel@tonic-gate int found; /* TRUE if login in /etc/passwd */ 185*7c478bd9Sstevel@tonic-gate }; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * This structure describes a password's information 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate struct pwdinfo { 192*7c478bd9Sstevel@tonic-gate long datechg; /* Date the password was changed (mmddyy) */ 193*7c478bd9Sstevel@tonic-gate char *passwdstatus; /* Password status */ 194*7c478bd9Sstevel@tonic-gate long mindaystilchg; /* Min days b4 pwd can change again */ 195*7c478bd9Sstevel@tonic-gate long maxdaystilchg; /* Max days b4 pwd can change again */ 196*7c478bd9Sstevel@tonic-gate long warninterval; /* Days before expire to warn user */ 197*7c478bd9Sstevel@tonic-gate long inactive; /* Lapsed days of inactivity before lock */ 198*7c478bd9Sstevel@tonic-gate long expdate; /* Date of expiration (mmddyy) */ 199*7c478bd9Sstevel@tonic-gate }; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* This structure describes secondary groups that a user belongs to */ 202*7c478bd9Sstevel@tonic-gate struct secgrp { 203*7c478bd9Sstevel@tonic-gate char *groupname; /* Name of the group */ 204*7c478bd9Sstevel@tonic-gate struct secgrp *next; /* Next item in the list */ 205*7c478bd9Sstevel@tonic-gate gid_t groupID; /* Group-ID */ 206*7c478bd9Sstevel@tonic-gate }; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * These functions handle error and warning message writing. 210*7c478bd9Sstevel@tonic-gate * (This deals with UNIX(r) standard message generation, so 211*7c478bd9Sstevel@tonic-gate * the rest of the code doesn't have to.) 212*7c478bd9Sstevel@tonic-gate * 213*7c478bd9Sstevel@tonic-gate * Functions included: 214*7c478bd9Sstevel@tonic-gate * initmsg Initialize the message handling functions. 215*7c478bd9Sstevel@tonic-gate * wrtmsg Write the message using fmtmsg(). 216*7c478bd9Sstevel@tonic-gate * 217*7c478bd9Sstevel@tonic-gate * Static data included: 218*7c478bd9Sstevel@tonic-gate * fcnlbl The label for standard messages 219*7c478bd9Sstevel@tonic-gate * msgbuf A buffer to contain the edited message 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate static char fcnlbl[MM_MXLABELLN+1]; /* Buffer for message label */ 223*7c478bd9Sstevel@tonic-gate static char msgbuf[MM_MXTXTLN+1]; /* Buffer for message text */ 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * void initmsg(p) 227*7c478bd9Sstevel@tonic-gate * 228*7c478bd9Sstevel@tonic-gate * This function initializes the message handling functions. 229*7c478bd9Sstevel@tonic-gate * 230*7c478bd9Sstevel@tonic-gate * Arguments: 231*7c478bd9Sstevel@tonic-gate * p A pointer to a character string that is the name of the 232*7c478bd9Sstevel@tonic-gate * function, used to generate the label on messages. If this 233*7c478bd9Sstevel@tonic-gate * string contains a slash ('/'), it only uses the characters 234*7c478bd9Sstevel@tonic-gate * beyond the last slash in the string (this permits argv[0] 235*7c478bd9Sstevel@tonic-gate * to be used). 236*7c478bd9Sstevel@tonic-gate * 237*7c478bd9Sstevel@tonic-gate * Returns: Void 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate static void 241*7c478bd9Sstevel@tonic-gate initmsg(p) 242*7c478bd9Sstevel@tonic-gate char *p; /* Command name (as invoked) */ 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate /* Automatic data */ 245*7c478bd9Sstevel@tonic-gate char *q; /* Local multi-use pointer */ 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* Use only the simple filename if there is a slash in the name */ 248*7c478bd9Sstevel@tonic-gate if (!(q = strrchr(p, '/'))) q = p; 249*7c478bd9Sstevel@tonic-gate else q++; 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* Build the label for messages */ 252*7c478bd9Sstevel@tonic-gate (void) sprintf(fcnlbl, "UX:%s", q); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* Restrict messages to the text-component */ 255*7c478bd9Sstevel@tonic-gate (void) putenv("MSGVERB=text"); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate /* 259*7c478bd9Sstevel@tonic-gate * void wrtmsg(severity, action, tag, text[, txtarg1[, txtarg2[, ...]]]) 260*7c478bd9Sstevel@tonic-gate * 261*7c478bd9Sstevel@tonic-gate * This function writes a message using fmtmsg() 262*7c478bd9Sstevel@tonic-gate * 263*7c478bd9Sstevel@tonic-gate * Arguments: 264*7c478bd9Sstevel@tonic-gate * severity The severity-component of the message 265*7c478bd9Sstevel@tonic-gate * action The action-string used to generate the 266*7c478bd9Sstevel@tonic-gate * action-component of the message 267*7c478bd9Sstevel@tonic-gate * tag Tag-component of the message 268*7c478bd9Sstevel@tonic-gate * text The text-string used to generate the text- 269*7c478bd9Sstevel@tonic-gate * component of the message 270*7c478bd9Sstevel@tonic-gate * txtarg Arguments to be inserted into the "text" 271*7c478bd9Sstevel@tonic-gate * string using vsprintf() 272*7c478bd9Sstevel@tonic-gate * 273*7c478bd9Sstevel@tonic-gate * Returns: Void 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate /*VARARGS4*/ 276*7c478bd9Sstevel@tonic-gate static void 277*7c478bd9Sstevel@tonic-gate wrtmsg(int severity, char *action, char *tag, char *text, ...) 278*7c478bd9Sstevel@tonic-gate { 279*7c478bd9Sstevel@tonic-gate /* Automatic data */ 280*7c478bd9Sstevel@tonic-gate int errorflg; /* TRUE if problem generating message */ 281*7c478bd9Sstevel@tonic-gate va_list argp; /* Pointer into vararg list */ 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate /* No problems yet */ 285*7c478bd9Sstevel@tonic-gate errorflg = FALSE; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* Generate the error message */ 288*7c478bd9Sstevel@tonic-gate va_start(argp, text); 289*7c478bd9Sstevel@tonic-gate if (text != MM_NULLTXT) errorflg = vsprintf(msgbuf, text, argp) > MM_MXTXTLN; 290*7c478bd9Sstevel@tonic-gate (void) fmtmsg(MM_PRINT, fcnlbl, severity, 291*7c478bd9Sstevel@tonic-gate (text == MM_NULLTXT) ? MM_NULLTXT : msgbuf, 292*7c478bd9Sstevel@tonic-gate action, tag); 293*7c478bd9Sstevel@tonic-gate va_end(argp); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * If there was a buffer overflow generating the error message, 297*7c478bd9Sstevel@tonic-gate * write a message and quit (things are probably corrupt in the 298*7c478bd9Sstevel@tonic-gate * static data space now 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate if (errorflg) { 301*7c478bd9Sstevel@tonic-gate (void) fmtmsg(MM_PRINT, fcnlbl, MM_WARNING, 302*7c478bd9Sstevel@tonic-gate gettext("Internal message buffer overflow"), 303*7c478bd9Sstevel@tonic-gate MM_NULLACT, MM_NULLTAG); 304*7c478bd9Sstevel@tonic-gate exit(100); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * These functions allocate space for the information we gather. 311*7c478bd9Sstevel@tonic-gate * It works by having a memory heap with strings allocated from 312*7c478bd9Sstevel@tonic-gate * the end of the heap and structures (aligned data) allocated 313*7c478bd9Sstevel@tonic-gate * from the beginning of the heap. It begins with a 4k block of 314*7c478bd9Sstevel@tonic-gate * memory then allocates memory in 4k chunks. These functions 315*7c478bd9Sstevel@tonic-gate * should never fail. If they do, they report the problem and 316*7c478bd9Sstevel@tonic-gate * exit with an exit code of 101. 317*7c478bd9Sstevel@tonic-gate * 318*7c478bd9Sstevel@tonic-gate * Functions contained: 319*7c478bd9Sstevel@tonic-gate * allocblk Allocates a block of memory, aligned on a 320*7c478bd9Sstevel@tonic-gate * 4-byte (double-word) boundary. 321*7c478bd9Sstevel@tonic-gate * allocstr Allocates a block of memory with no 322*7c478bd9Sstevel@tonic-gate * particular alignment 323*7c478bd9Sstevel@tonic-gate * 324*7c478bd9Sstevel@tonic-gate * Constant definitions: 325*7c478bd9Sstevel@tonic-gate * ALLOCBLKSZ Size of a chunk of main memory allocated 326*7c478bd9Sstevel@tonic-gate * using malloc() 327*7c478bd9Sstevel@tonic-gate * 328*7c478bd9Sstevel@tonic-gate * Static data: 329*7c478bd9Sstevel@tonic-gate * nextblkaddr Address of the next available chunk of 330*7c478bd9Sstevel@tonic-gate * aligned space in the heap 331*7c478bd9Sstevel@tonic-gate * laststraddr Address of the last chunk of unaligned space 332*7c478bd9Sstevel@tonic-gate * allocated from the heap 333*7c478bd9Sstevel@tonic-gate * toomuchspace Message to write if someone attempts to allocate 334*7c478bd9Sstevel@tonic-gate * too much space (>ALLOCBLKSZ bytes) 335*7c478bd9Sstevel@tonic-gate * memallocdif Message to write if there is a problem 336*7c478bd9Sstevel@tonic-gate * allocating main menory. 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate #define ALLOCBLKSZ 4096 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate static char *nextblkaddr = (char *) NULL; 342*7c478bd9Sstevel@tonic-gate static char *laststraddr = (char *) NULL; 343*7c478bd9Sstevel@tonic-gate #define MEMALLOCDIF "Memory allocation difficulty. Command terminates" 344*7c478bd9Sstevel@tonic-gate #define TOOMUCHSPACE "Internal space allocation error. Command terminates" 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate /* 347*7c478bd9Sstevel@tonic-gate * void *allocblk(size) 348*7c478bd9Sstevel@tonic-gate * unsigned int size 349*7c478bd9Sstevel@tonic-gate * 350*7c478bd9Sstevel@tonic-gate * This function allocates a block of aligned (4-byte or 351*7c478bd9Sstevel@tonic-gate * double-word boundary) memory from the program's heap. 352*7c478bd9Sstevel@tonic-gate * It returns a pointer to that block of allocated memory. 353*7c478bd9Sstevel@tonic-gate * 354*7c478bd9Sstevel@tonic-gate * Arguments: 355*7c478bd9Sstevel@tonic-gate * size Minimum number of bytes to allocate (will 356*7c478bd9Sstevel@tonic-gate * round up to multiple of 4) 357*7c478bd9Sstevel@tonic-gate * 358*7c478bd9Sstevel@tonic-gate * Returns: void * 359*7c478bd9Sstevel@tonic-gate * Pointer to the allocated block of memory 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate static void * 363*7c478bd9Sstevel@tonic-gate allocblk(size) 364*7c478bd9Sstevel@tonic-gate unsigned int size; 365*7c478bd9Sstevel@tonic-gate { 366*7c478bd9Sstevel@tonic-gate /* Automatic data */ 367*7c478bd9Sstevel@tonic-gate char *rtnval; 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate /* Make sure the sizes are aligned correctly */ 371*7c478bd9Sstevel@tonic-gate if ((size = size + (4 - (size % 4))) > ALLOCBLKSZ) { 372*7c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(TOOMUCHSPACE)); 373*7c478bd9Sstevel@tonic-gate exit(101); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* Set up the value we're going to return */ 377*7c478bd9Sstevel@tonic-gate rtnval = nextblkaddr; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* Get the space we need off of the heap */ 380*7c478bd9Sstevel@tonic-gate if ((nextblkaddr += size) >= laststraddr) { 381*7c478bd9Sstevel@tonic-gate if (!(rtnval = (char *) malloc(ALLOCBLKSZ))) { 382*7c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(MEMALLOCDIF)); 383*7c478bd9Sstevel@tonic-gate exit(101); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate laststraddr = rtnval + ALLOCBLKSZ; 386*7c478bd9Sstevel@tonic-gate nextblkaddr = rtnval + size; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* We're through */ 390*7c478bd9Sstevel@tonic-gate return((void *) rtnval); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * char *allocstr(nbytes) 395*7c478bd9Sstevel@tonic-gate * unsigned int nbytes 396*7c478bd9Sstevel@tonic-gate * 397*7c478bd9Sstevel@tonic-gate * This function allocates a block of unaligned memory from the 398*7c478bd9Sstevel@tonic-gate * program's heap. It returns a pointer to that block of allocated 399*7c478bd9Sstevel@tonic-gate * memory. 400*7c478bd9Sstevel@tonic-gate * 401*7c478bd9Sstevel@tonic-gate * Arguments: 402*7c478bd9Sstevel@tonic-gate * nbytes Number of bytes to allocate 403*7c478bd9Sstevel@tonic-gate * 404*7c478bd9Sstevel@tonic-gate * Returns: char * 405*7c478bd9Sstevel@tonic-gate * Pointer to the allocated block of memory 406*7c478bd9Sstevel@tonic-gate */ 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate static char * 409*7c478bd9Sstevel@tonic-gate allocstr(nchars) 410*7c478bd9Sstevel@tonic-gate unsigned int nchars; 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate if (nchars > ALLOCBLKSZ) { 413*7c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(TOOMUCHSPACE)); 414*7c478bd9Sstevel@tonic-gate exit(101); 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate if (laststraddr == NULL || 417*7c478bd9Sstevel@tonic-gate (laststraddr -= nchars) < nextblkaddr) { 418*7c478bd9Sstevel@tonic-gate if (!(nextblkaddr = (char *) malloc(ALLOCBLKSZ))) { 419*7c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(MEMALLOCDIF)); 420*7c478bd9Sstevel@tonic-gate exit(101); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate laststraddr = nextblkaddr + ALLOCBLKSZ - nchars; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate return(laststraddr); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * These functions control the group membership list, as found in 429*7c478bd9Sstevel@tonic-gate * the /etc/group file. 430*7c478bd9Sstevel@tonic-gate * 431*7c478bd9Sstevel@tonic-gate * Functions included: 432*7c478bd9Sstevel@tonic-gate * initmembers Initialize the membership list (to NULL) 433*7c478bd9Sstevel@tonic-gate * addmember Adds a member to the membership list 434*7c478bd9Sstevel@tonic-gate * isamember Looks for a particular login-ID in the 435*7c478bd9Sstevel@tonic-gate * list of members 436*7c478bd9Sstevel@tonic-gate * 437*7c478bd9Sstevel@tonic-gate * Datatype Definitions: 438*7c478bd9Sstevel@tonic-gate * struct grpmember Describes a group member 439*7c478bd9Sstevel@tonic-gate * 440*7c478bd9Sstevel@tonic-gate * Static Data: 441*7c478bd9Sstevel@tonic-gate * membershead Pointer to the head of the list of 442*7c478bd9Sstevel@tonic-gate * group members 443*7c478bd9Sstevel@tonic-gate */ 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate struct grpmember { 446*7c478bd9Sstevel@tonic-gate char *membername; 447*7c478bd9Sstevel@tonic-gate struct grpmember *next; 448*7c478bd9Sstevel@tonic-gate }; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate static struct grpmember *membershead; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* 453*7c478bd9Sstevel@tonic-gate * void initmembers() 454*7c478bd9Sstevel@tonic-gate * 455*7c478bd9Sstevel@tonic-gate * This function initializes the list of members of specified groups. 456*7c478bd9Sstevel@tonic-gate * 457*7c478bd9Sstevel@tonic-gate * Arguments: None 458*7c478bd9Sstevel@tonic-gate * 459*7c478bd9Sstevel@tonic-gate * Returns: Void 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate static void 463*7c478bd9Sstevel@tonic-gate initmembers() 464*7c478bd9Sstevel@tonic-gate { 465*7c478bd9Sstevel@tonic-gate /* Set up the members list to be a null member's list */ 466*7c478bd9Sstevel@tonic-gate membershead = (struct grpmember *) NULL; 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* 470*7c478bd9Sstevel@tonic-gate * void addmember(p) 471*7c478bd9Sstevel@tonic-gate * char *p 472*7c478bd9Sstevel@tonic-gate * 473*7c478bd9Sstevel@tonic-gate * This function adds a member to the group member's list. The 474*7c478bd9Sstevel@tonic-gate * group members list is a list of structures containing a pointer 475*7c478bd9Sstevel@tonic-gate * to the member-name and a pointer to the next item in the 476*7c478bd9Sstevel@tonic-gate * structure. The structure is not ordered in any particular way. 477*7c478bd9Sstevel@tonic-gate * 478*7c478bd9Sstevel@tonic-gate * Arguments: 479*7c478bd9Sstevel@tonic-gate * p Pointer to the member name 480*7c478bd9Sstevel@tonic-gate * 481*7c478bd9Sstevel@tonic-gate * Returns: Void 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate static void 485*7c478bd9Sstevel@tonic-gate addmember(p) 486*7c478bd9Sstevel@tonic-gate char *p; 487*7c478bd9Sstevel@tonic-gate { 488*7c478bd9Sstevel@tonic-gate /* Automatic data */ 489*7c478bd9Sstevel@tonic-gate struct grpmember *new; /* Member being added */ 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate new = (struct grpmember *) allocblk(sizeof(struct grpmember)); 492*7c478bd9Sstevel@tonic-gate new->membername = strcpy(allocstr((unsigned int) strlen(p)+1), p); 493*7c478bd9Sstevel@tonic-gate new->next = membershead; 494*7c478bd9Sstevel@tonic-gate membershead = new; 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate /* 498*7c478bd9Sstevel@tonic-gate * init isamember(p) 499*7c478bd9Sstevel@tonic-gate * char *p 500*7c478bd9Sstevel@tonic-gate * 501*7c478bd9Sstevel@tonic-gate * This function examines the list of group-members for the string 502*7c478bd9Sstevel@tonic-gate * referenced by 'p'. If 'p' is a member of the members list, the 503*7c478bd9Sstevel@tonic-gate * function returns TRUE. Otherwise it returns FALSE. 504*7c478bd9Sstevel@tonic-gate * 505*7c478bd9Sstevel@tonic-gate * Arguments: 506*7c478bd9Sstevel@tonic-gate * p Pointer to the name to search for. 507*7c478bd9Sstevel@tonic-gate * 508*7c478bd9Sstevel@tonic-gate * Returns: int 509*7c478bd9Sstevel@tonic-gate * TRUE If 'p' is found in the members list, 510*7c478bd9Sstevel@tonic-gate * FALSE otherwise 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate static int 514*7c478bd9Sstevel@tonic-gate isamember(p) 515*7c478bd9Sstevel@tonic-gate char *p; 516*7c478bd9Sstevel@tonic-gate { 517*7c478bd9Sstevel@tonic-gate /* Automatic Data */ 518*7c478bd9Sstevel@tonic-gate int found; /* TRUE if login found in list */ 519*7c478bd9Sstevel@tonic-gate struct grpmember *pmem; /* Group member being examined */ 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate /* Search the membership list for 'p' */ 523*7c478bd9Sstevel@tonic-gate found = FALSE; 524*7c478bd9Sstevel@tonic-gate for (pmem = membershead ; !found && pmem ; pmem = pmem->next) { 525*7c478bd9Sstevel@tonic-gate if (strcmp(p, pmem->membername) == 0) found = TRUE; 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate return (found); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate /* 532*7c478bd9Sstevel@tonic-gate * These functions handle the display list. The display list contains 533*7c478bd9Sstevel@tonic-gate * all of the information we're to display. The list contains a pointer 534*7c478bd9Sstevel@tonic-gate * to the login-name, a pointer to the free-field (comment), and a 535*7c478bd9Sstevel@tonic-gate * pointer to the next item in the list. The list is ordered alpha- 536*7c478bd9Sstevel@tonic-gate * betically (ascending) on the login-name field. The list initially 537*7c478bd9Sstevel@tonic-gate * contains a dummy field (to make insertion easier) that contains a 538*7c478bd9Sstevel@tonic-gate * login-name of "". 539*7c478bd9Sstevel@tonic-gate * 540*7c478bd9Sstevel@tonic-gate * Functions included: 541*7c478bd9Sstevel@tonic-gate * initdisp Initializes the display list 542*7c478bd9Sstevel@tonic-gate * adddisp Adds information to the display list 543*7c478bd9Sstevel@tonic-gate * isuidindisp Looks to see if a particular user-ID is in the 544*7c478bd9Sstevel@tonic-gate * display list 545*7c478bd9Sstevel@tonic-gate * genreport Generates a report from the items in the display 546*7c478bd9Sstevel@tonic-gate * list 547*7c478bd9Sstevel@tonic-gate * applygroup Add group information to the items in the display 548*7c478bd9Sstevel@tonic-gate * list 549*7c478bd9Sstevel@tonic-gate * applypasswd Add extended password information to the items 550*7c478bd9Sstevel@tonic-gate * in the display list 551*7c478bd9Sstevel@tonic-gate * 552*7c478bd9Sstevel@tonic-gate * Datatypes Defined: 553*7c478bd9Sstevel@tonic-gate * struct display Describes the structure that contains the information 554*7c478bd9Sstevel@tonic-gate * to be displayed. Includes pointers to the login-ID, 555*7c478bd9Sstevel@tonic-gate * free-field (comment), and the next structure in the 556*7c478bd9Sstevel@tonic-gate * list. 557*7c478bd9Sstevel@tonic-gate * 558*7c478bd9Sstevel@tonic-gate * Static Data: 559*7c478bd9Sstevel@tonic-gate * displayhead Pointer to the head of the display list. Initially 560*7c478bd9Sstevel@tonic-gate * references the null-item on the head of the list. 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate struct display { 564*7c478bd9Sstevel@tonic-gate char *loginID; /* Login name */ 565*7c478bd9Sstevel@tonic-gate char *freefield; /* Free (comment) field */ 566*7c478bd9Sstevel@tonic-gate char *groupname; /* Name of the primary group */ 567*7c478bd9Sstevel@tonic-gate char *iwd; /* Initial working directory */ 568*7c478bd9Sstevel@tonic-gate char *shell; /* Shell after login (may be null) */ 569*7c478bd9Sstevel@tonic-gate struct pwdinfo *passwdinfo; /* Password information structure */ 570*7c478bd9Sstevel@tonic-gate struct secgrp *secgrplist; /* Head of the secondary group list */ 571*7c478bd9Sstevel@tonic-gate uid_t userID; /* User ID */ 572*7c478bd9Sstevel@tonic-gate gid_t groupID; /* Group ID of primary group */ 573*7c478bd9Sstevel@tonic-gate struct display *nextlogin; /* Next login in the list */ 574*7c478bd9Sstevel@tonic-gate struct display *nextuid; /* Next user-ID in the list */ 575*7c478bd9Sstevel@tonic-gate }; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate static struct display *displayhead; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate /* 580*7c478bd9Sstevel@tonic-gate * void initdisp() 581*7c478bd9Sstevel@tonic-gate * 582*7c478bd9Sstevel@tonic-gate * Initializes the display list. An empty display list contains 583*7c478bd9Sstevel@tonic-gate * a single element, the dummy element. 584*7c478bd9Sstevel@tonic-gate * 585*7c478bd9Sstevel@tonic-gate * Arguments: None 586*7c478bd9Sstevel@tonic-gate * 587*7c478bd9Sstevel@tonic-gate * Returns: Void 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate static void 591*7c478bd9Sstevel@tonic-gate initdisp() 592*7c478bd9Sstevel@tonic-gate { 593*7c478bd9Sstevel@tonic-gate displayhead = (struct display *) allocblk(sizeof(struct display)); 594*7c478bd9Sstevel@tonic-gate displayhead->nextlogin = (struct display *) NULL; 595*7c478bd9Sstevel@tonic-gate displayhead->nextuid = (struct display *) NULL; 596*7c478bd9Sstevel@tonic-gate displayhead->loginID = ""; 597*7c478bd9Sstevel@tonic-gate displayhead->freefield = ""; 598*7c478bd9Sstevel@tonic-gate displayhead->userID = -1; 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate /* 602*7c478bd9Sstevel@tonic-gate * void adddisp(pwent) 603*7c478bd9Sstevel@tonic-gate * struct passwd *pwent 604*7c478bd9Sstevel@tonic-gate * 605*7c478bd9Sstevel@tonic-gate * This function adds the appropriate information from the login 606*7c478bd9Sstevel@tonic-gate * description referenced by 'pwent' to the list if information 607*7c478bd9Sstevel@tonic-gate * to be displayed. It only adds the information if the login-ID 608*7c478bd9Sstevel@tonic-gate * (user-name) is unique. It inserts the information in the list 609*7c478bd9Sstevel@tonic-gate * in such a way that the list remains ordered alphabetically 610*7c478bd9Sstevel@tonic-gate * (ascending) according to the login-ID (user-name). 611*7c478bd9Sstevel@tonic-gate * 612*7c478bd9Sstevel@tonic-gate * Arguments: 613*7c478bd9Sstevel@tonic-gate * pwent Structure that contains all of the login information 614*7c478bd9Sstevel@tonic-gate * of the login being added to the list. The only 615*7c478bd9Sstevel@tonic-gate * information that this function uses is the login-ID 616*7c478bd9Sstevel@tonic-gate * (user-name) and the free-field (comment field). 617*7c478bd9Sstevel@tonic-gate * 618*7c478bd9Sstevel@tonic-gate * Returns: Void 619*7c478bd9Sstevel@tonic-gate */ 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate static void 622*7c478bd9Sstevel@tonic-gate adddisp(pwent) 623*7c478bd9Sstevel@tonic-gate struct passwd *pwent; 624*7c478bd9Sstevel@tonic-gate { 625*7c478bd9Sstevel@tonic-gate /* Automatic data */ 626*7c478bd9Sstevel@tonic-gate struct display *new; /* Item being added to the list */ 627*7c478bd9Sstevel@tonic-gate struct display *prev; /* Previous item in the list */ 628*7c478bd9Sstevel@tonic-gate struct display *current; /* Next item in the list */ 629*7c478bd9Sstevel@tonic-gate int found; /* FLAG, insertion point found */ 630*7c478bd9Sstevel@tonic-gate int compare = 1; /* strcmp() compare value */ 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate /* Find where this value belongs in the list */ 634*7c478bd9Sstevel@tonic-gate prev = displayhead; 635*7c478bd9Sstevel@tonic-gate found = FALSE; 636*7c478bd9Sstevel@tonic-gate while (!found && (current = prev->nextlogin)) 637*7c478bd9Sstevel@tonic-gate if ((compare = strcmp(current->loginID, pwent->pw_name)) >= 0) found = TRUE; 638*7c478bd9Sstevel@tonic-gate else prev = current; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* Insert this value in the list, only if it is unique though */ 641*7c478bd9Sstevel@tonic-gate if (compare != 0) { 642*7c478bd9Sstevel@tonic-gate new = (struct display *) allocblk(sizeof(struct display)); 643*7c478bd9Sstevel@tonic-gate new->loginID = strcpy(allocstr((unsigned int) strlen(pwent->pw_name)+1), pwent->pw_name); 644*7c478bd9Sstevel@tonic-gate if (pwent->pw_comment && pwent->pw_comment[0] != '\0') 645*7c478bd9Sstevel@tonic-gate new->freefield = 646*7c478bd9Sstevel@tonic-gate strcpy(allocstr((unsigned int) 647*7c478bd9Sstevel@tonic-gate strlen(pwent->pw_comment)+1), 648*7c478bd9Sstevel@tonic-gate pwent->pw_comment); 649*7c478bd9Sstevel@tonic-gate else 650*7c478bd9Sstevel@tonic-gate new->freefield = 651*7c478bd9Sstevel@tonic-gate strcpy(allocstr((unsigned int) 652*7c478bd9Sstevel@tonic-gate strlen(pwent->pw_gecos)+1), 653*7c478bd9Sstevel@tonic-gate pwent->pw_gecos); 654*7c478bd9Sstevel@tonic-gate if (!pwent->pw_shell || !(*pwent->pw_shell)) new->shell = "/sbin/sh"; 655*7c478bd9Sstevel@tonic-gate else new->shell = strcpy(allocstr((unsigned int) strlen(pwent->pw_shell)+1), pwent->pw_shell); 656*7c478bd9Sstevel@tonic-gate new->iwd = strcpy(allocstr((unsigned int) strlen(pwent->pw_dir)+1), pwent->pw_dir); 657*7c478bd9Sstevel@tonic-gate new->userID = pwent->pw_uid; 658*7c478bd9Sstevel@tonic-gate new->groupID = pwent->pw_gid; 659*7c478bd9Sstevel@tonic-gate new->secgrplist = (struct secgrp *) NULL; 660*7c478bd9Sstevel@tonic-gate new->passwdinfo = (struct pwdinfo *) NULL; 661*7c478bd9Sstevel@tonic-gate new->groupname = (char *) NULL; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* Add new display item to the list ordered by login-ID */ 664*7c478bd9Sstevel@tonic-gate new->nextlogin = current; 665*7c478bd9Sstevel@tonic-gate prev->nextlogin = new; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* Find the appropriate place for the new item in the list 668*7c478bd9Sstevel@tonic-gate * ordered by userID */ 669*7c478bd9Sstevel@tonic-gate prev = displayhead; 670*7c478bd9Sstevel@tonic-gate found = FALSE; 671*7c478bd9Sstevel@tonic-gate while (!found && (current = prev->nextuid)) 672*7c478bd9Sstevel@tonic-gate if (current->userID > pwent->pw_uid) found = TRUE; 673*7c478bd9Sstevel@tonic-gate else prev = current; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate /* Add the item into the list that is ordered by user-ID */ 676*7c478bd9Sstevel@tonic-gate new->nextuid = current; 677*7c478bd9Sstevel@tonic-gate prev->nextuid = new; 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate /* 682*7c478bd9Sstevel@tonic-gate * int isuidindisp(pwent) 683*7c478bd9Sstevel@tonic-gate * struct passwd *pwent 684*7c478bd9Sstevel@tonic-gate * 685*7c478bd9Sstevel@tonic-gate * This function examines the display list to see if the uid in 686*7c478bd9Sstevel@tonic-gate * the (struct passwd) referenced by "pwent" is already in the 687*7c478bd9Sstevel@tonic-gate * display list. It returns TRUE if it is in the list, FALSE 688*7c478bd9Sstevel@tonic-gate * otherwise. 689*7c478bd9Sstevel@tonic-gate * 690*7c478bd9Sstevel@tonic-gate * Since the display list is ordered by user-ID, the search continues 691*7c478bd9Sstevel@tonic-gate * until a match is found or a user-ID is found that is larger than 692*7c478bd9Sstevel@tonic-gate * the one we're searching for. 693*7c478bd9Sstevel@tonic-gate * 694*7c478bd9Sstevel@tonic-gate * Arguments: 695*7c478bd9Sstevel@tonic-gate * pwent Structure that contains the user-ID we're to 696*7c478bd9Sstevel@tonic-gate * look for 697*7c478bd9Sstevel@tonic-gate * 698*7c478bd9Sstevel@tonic-gate * Returns: int 699*7c478bd9Sstevel@tonic-gate * TRUE if the user-ID was found, FALSE otherwise. 700*7c478bd9Sstevel@tonic-gate */ 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate static int 703*7c478bd9Sstevel@tonic-gate isuidindisp(pwent) 704*7c478bd9Sstevel@tonic-gate struct passwd *pwent; /* Struct of user to look for */ 705*7c478bd9Sstevel@tonic-gate { 706*7c478bd9Sstevel@tonic-gate /* Automatic data */ 707*7c478bd9Sstevel@tonic-gate struct display *dp; 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate /* 711*7c478bd9Sstevel@tonic-gate * Search the list, beginning at the beginning (where else?) 712*7c478bd9Sstevel@tonic-gate * and stopping when the user-ID is found or one is found that 713*7c478bd9Sstevel@tonic-gate * is greater than the user-ID we're searching for. Recall 714*7c478bd9Sstevel@tonic-gate * that this list is ordered by user-ID 715*7c478bd9Sstevel@tonic-gate */ 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate for (dp = displayhead->nextuid ; dp && (dp->userID < pwent->pw_uid) ; dp = dp->nextuid) ; 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate /* If the pointer "dp" points to a structure that has a 720*7c478bd9Sstevel@tonic-gate * matching user-ID, return TRUE. Otherwise FALSE */ 721*7c478bd9Sstevel@tonic-gate return (dp && (dp->userID == pwent->pw_uid)); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate /* 725*7c478bd9Sstevel@tonic-gate * void applygroup(allgroups) 726*7c478bd9Sstevel@tonic-gate * int allgroups 727*7c478bd9Sstevel@tonic-gate * 728*7c478bd9Sstevel@tonic-gate * This function applies group information to the login-IDs in the 729*7c478bd9Sstevel@tonic-gate * display list. It always applies the primary group information. 730*7c478bd9Sstevel@tonic-gate * If "allgroups" is TRUE, it applies secondary information as well. 731*7c478bd9Sstevel@tonic-gate * 732*7c478bd9Sstevel@tonic-gate * Arguments: 733*7c478bd9Sstevel@tonic-gate * allgroups FLAG. TRUE if secondary group info is to be 734*7c478bd9Sstevel@tonic-gate * applied -- FALSE otherwise. 735*7c478bd9Sstevel@tonic-gate * 736*7c478bd9Sstevel@tonic-gate * Returns: void 737*7c478bd9Sstevel@tonic-gate */ 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate static void 740*7c478bd9Sstevel@tonic-gate applygroup(allgroups) 741*7c478bd9Sstevel@tonic-gate int allgroups; /* TRUE if applying secondary groups */ 742*7c478bd9Sstevel@tonic-gate { 743*7c478bd9Sstevel@tonic-gate /* Automatic Data */ 744*7c478bd9Sstevel@tonic-gate struct display *dp; /* Display list running ptr */ 745*7c478bd9Sstevel@tonic-gate struct group *grent; /* Group info, from getgrent() */ 746*7c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */ 747*7c478bd9Sstevel@tonic-gate char **pp; /* Temp char * pointer */ 748*7c478bd9Sstevel@tonic-gate int compare; /* Value from strcmp() */ 749*7c478bd9Sstevel@tonic-gate int done; /* TRUE if finished, FALSE otherwise */ 750*7c478bd9Sstevel@tonic-gate struct secgrp *psecgrp; /* Block allocated for this info */ 751*7c478bd9Sstevel@tonic-gate struct secgrp *psrch; /* Secondary group -- for searching */ 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate /* For each group-ID in the /etc/group file ... */ 755*7c478bd9Sstevel@tonic-gate while (grent = getgrent()) { 756*7c478bd9Sstevel@tonic-gate /* 757*7c478bd9Sstevel@tonic-gate * Set the primary group for the login-IDs in the display 758*7c478bd9Sstevel@tonic-gate * list. For each group-ID we get, leaf through the display 759*7c478bd9Sstevel@tonic-gate * list and set the group-name if the group-IDs match 760*7c478bd9Sstevel@tonic-gate */ 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate p = (char *) NULL; 763*7c478bd9Sstevel@tonic-gate for (dp = displayhead->nextuid ; dp ; dp = dp->nextuid) 764*7c478bd9Sstevel@tonic-gate if ((dp->groupID == grent->gr_gid) && !dp->groupname) { 765*7c478bd9Sstevel@tonic-gate if (!p) p = strcpy(allocstr((unsigned int) strlen(grent->gr_name)+1), grent->gr_name); 766*7c478bd9Sstevel@tonic-gate dp->groupname = p; 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate /* 770*7c478bd9Sstevel@tonic-gate * If we're to be displaying secondary group membership, 771*7c478bd9Sstevel@tonic-gate * leaf through the list of group members. Then, attempt 772*7c478bd9Sstevel@tonic-gate * to find that member in the display list. When found, 773*7c478bd9Sstevel@tonic-gate * attach secondary group info to the user. 774*7c478bd9Sstevel@tonic-gate */ 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate if (allgroups) for (pp = grent->gr_mem ; *pp ; pp++) { 777*7c478bd9Sstevel@tonic-gate done = FALSE; 778*7c478bd9Sstevel@tonic-gate for (dp = displayhead->nextlogin ; !done && dp ; dp = dp->nextlogin) { 779*7c478bd9Sstevel@tonic-gate if (((compare = strcmp(dp->loginID, *pp)) == 0) && !(grent->gr_gid == dp->groupID)) { 780*7c478bd9Sstevel@tonic-gate if (!p) p = strcpy(allocstr((unsigned int) strlen(grent->gr_name)+1), grent->gr_name); 781*7c478bd9Sstevel@tonic-gate psecgrp = (struct secgrp *) allocblk(sizeof(struct secgrp)); 782*7c478bd9Sstevel@tonic-gate psecgrp->groupID = grent->gr_gid; 783*7c478bd9Sstevel@tonic-gate psecgrp->groupname = p; 784*7c478bd9Sstevel@tonic-gate psecgrp->next = (struct secgrp *) NULL; 785*7c478bd9Sstevel@tonic-gate if (!dp->secgrplist) dp->secgrplist = psecgrp; 786*7c478bd9Sstevel@tonic-gate else { 787*7c478bd9Sstevel@tonic-gate for (psrch = dp->secgrplist ; psrch->next ; psrch = psrch->next) ; 788*7c478bd9Sstevel@tonic-gate psrch->next = psecgrp; 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate done = TRUE; 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate else if (compare > 0) done = TRUE; 793*7c478bd9Sstevel@tonic-gate } 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate } 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate /* Close the /etc/group file */ 798*7c478bd9Sstevel@tonic-gate endgrent(); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate /* 802*7c478bd9Sstevel@tonic-gate * void applypasswd() 803*7c478bd9Sstevel@tonic-gate * 804*7c478bd9Sstevel@tonic-gate * This function applies extended password information to an item 805*7c478bd9Sstevel@tonic-gate * to be displayed. It allocates space for a structure describing 806*7c478bd9Sstevel@tonic-gate * the password, then fills in that structure from the information 807*7c478bd9Sstevel@tonic-gate * in the /etc/shadow file. 808*7c478bd9Sstevel@tonic-gate * 809*7c478bd9Sstevel@tonic-gate * Arguments: None 810*7c478bd9Sstevel@tonic-gate * 811*7c478bd9Sstevel@tonic-gate * Returns: Void 812*7c478bd9Sstevel@tonic-gate */ 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate static void 815*7c478bd9Sstevel@tonic-gate applypasswd() 816*7c478bd9Sstevel@tonic-gate { 817*7c478bd9Sstevel@tonic-gate /* 818*7c478bd9Sstevel@tonic-gate * Local declarations 819*7c478bd9Sstevel@tonic-gate */ 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate struct pwdinfo *ppasswd; /* Ptr to pwd desc in current element */ 822*7c478bd9Sstevel@tonic-gate struct display *dp; /* Ptr to current element */ 823*7c478bd9Sstevel@tonic-gate struct spwd *psp; /* Pointer to a shadow-file entry */ 824*7c478bd9Sstevel@tonic-gate struct tm *ptm; /* Pointer to a time-of-day structure */ 825*7c478bd9Sstevel@tonic-gate char *p; /* Running character pointer */ 826*7c478bd9Sstevel@tonic-gate time_t pwchg; /* System-time of last pwd chg */ 827*7c478bd9Sstevel@tonic-gate time_t pwexp; /* System-time of password expiration */ 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* Make sure the shadow file is rewound */ 831*7c478bd9Sstevel@tonic-gate setspent(); 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * For each item in the display list... 836*7c478bd9Sstevel@tonic-gate */ 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate for (dp = displayhead->nextuid ; dp ; dp = dp->nextuid) { 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* Allocate structure space for the password description */ 841*7c478bd9Sstevel@tonic-gate ppasswd = (struct pwdinfo *) allocblk(sizeof(struct pwdinfo)); 842*7c478bd9Sstevel@tonic-gate dp->passwdinfo = ppasswd; 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate /* 845*7c478bd9Sstevel@tonic-gate * If there's no entry in the /etc/shadow file, assume 846*7c478bd9Sstevel@tonic-gate * that the login is locked 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate if (!(psp = getspnam(dp->loginID))) { 850*7c478bd9Sstevel@tonic-gate pwchg = 0L; /* Epoch */ 851*7c478bd9Sstevel@tonic-gate ppasswd->passwdstatus = "LK"; /* LK, Locked */ 852*7c478bd9Sstevel@tonic-gate ppasswd->mindaystilchg = 0L; 853*7c478bd9Sstevel@tonic-gate ppasswd->maxdaystilchg = 0L; 854*7c478bd9Sstevel@tonic-gate ppasswd->warninterval = 0L; 855*7c478bd9Sstevel@tonic-gate ppasswd->inactive = 0L; 856*7c478bd9Sstevel@tonic-gate pwexp = 0L; 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate /* 860*7c478bd9Sstevel@tonic-gate * Otherwise, fill in the password information from the 861*7c478bd9Sstevel@tonic-gate * info in the shadow file entry 862*7c478bd9Sstevel@tonic-gate */ 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate else { 865*7c478bd9Sstevel@tonic-gate /* See if the login has no password */ 866*7c478bd9Sstevel@tonic-gate if (!psp->sp_pwdp || !(*psp->sp_pwdp)) ppasswd->passwdstatus = "NP"; 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate /* 869*7c478bd9Sstevel@tonic-gate * See if the login is explicitly locked (encrypted 870*7c478bd9Sstevel@tonic-gate * password is <13 characters) 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate else if (strlen(psp->sp_pwdp) != 13) ppasswd->passwdstatus = "LK"; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * If it's a valid encrypted password, the login is 877*7c478bd9Sstevel@tonic-gate * password protected 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate else { 880*7c478bd9Sstevel@tonic-gate ppasswd->passwdstatus = "PS"; 881*7c478bd9Sstevel@tonic-gate for (p = psp->sp_pwdp ; *p ; p++) { 882*7c478bd9Sstevel@tonic-gate if (!isalnum(*p) && (*p != '.') && (*p != '/')) { 883*7c478bd9Sstevel@tonic-gate ppasswd->passwdstatus = "LK"; 884*7c478bd9Sstevel@tonic-gate break; 885*7c478bd9Sstevel@tonic-gate } 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate /* 890*7c478bd9Sstevel@tonic-gate * Set up the last-changed date, the minimum days between 891*7c478bd9Sstevel@tonic-gate * changes, the maximum life of a password, the interval 892*7c478bd9Sstevel@tonic-gate * before expiration that the user is warned, the number of 893*7c478bd9Sstevel@tonic-gate * days a login can be inactive before it expires, and the 894*7c478bd9Sstevel@tonic-gate * login expiration date 895*7c478bd9Sstevel@tonic-gate */ 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate pwchg = psp->sp_lstchg; 898*7c478bd9Sstevel@tonic-gate ppasswd->mindaystilchg = psp->sp_min; 899*7c478bd9Sstevel@tonic-gate ppasswd->maxdaystilchg = psp->sp_max; 900*7c478bd9Sstevel@tonic-gate ppasswd->warninterval = psp->sp_warn; 901*7c478bd9Sstevel@tonic-gate ppasswd->inactive = psp->sp_inact; 902*7c478bd9Sstevel@tonic-gate pwexp = psp->sp_expire; 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * Convert the date of the last password change from days- 907*7c478bd9Sstevel@tonic-gate * since-epoch to mmddyy (integer) form. Involves the 908*7c478bd9Sstevel@tonic-gate * intermediate step of converting the date from days- 909*7c478bd9Sstevel@tonic-gate * since-epoch to seconds-since-epoch. We'll set this to 910*7c478bd9Sstevel@tonic-gate * somewhere near the middle of the day, since there are not 911*7c478bd9Sstevel@tonic-gate * always 24*60*60 seconds in a year. (Yeech) 912*7c478bd9Sstevel@tonic-gate * 913*7c478bd9Sstevel@tonic-gate * Note: The form mmddyy should probably be subject to 914*7c478bd9Sstevel@tonic-gate * internationalization -- Non-Americans will think that 915*7c478bd9Sstevel@tonic-gate * 070888 is 07 August 88 when the software is trying to say 916*7c478bd9Sstevel@tonic-gate * 08 July 88. Systems Engineers seem to think that this isn't 917*7c478bd9Sstevel@tonic-gate * a problem though... 918*7c478bd9Sstevel@tonic-gate */ 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (pwchg != -1L) { 921*7c478bd9Sstevel@tonic-gate pwchg = (pwchg * DAY) + (DAY/2); 922*7c478bd9Sstevel@tonic-gate ptm = localtime(&pwchg); 923*7c478bd9Sstevel@tonic-gate ppasswd->datechg = ((long) (ptm->tm_mon+1) * 10000L) + 924*7c478bd9Sstevel@tonic-gate (long) ((ptm->tm_mday * 100) + 925*7c478bd9Sstevel@tonic-gate (ptm->tm_year % 100)); 926*7c478bd9Sstevel@tonic-gate } else ppasswd->datechg = 0L; 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate /* 929*7c478bd9Sstevel@tonic-gate * Convert the passwd expiration date from days-since-epoch 930*7c478bd9Sstevel@tonic-gate * to mmddyy (long integer) form using the same algorithm and 931*7c478bd9Sstevel@tonic-gate * comments as above. 932*7c478bd9Sstevel@tonic-gate */ 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate if (pwexp != -1L) { 935*7c478bd9Sstevel@tonic-gate pwexp = (pwexp * DAY) + (DAY/2); 936*7c478bd9Sstevel@tonic-gate ptm = localtime(&pwexp); 937*7c478bd9Sstevel@tonic-gate ppasswd->expdate = ((long) (ptm->tm_mon+1) * 10000L) + 938*7c478bd9Sstevel@tonic-gate (long) ((ptm->tm_mday * 100) + 939*7c478bd9Sstevel@tonic-gate (ptm->tm_year % 100)); 940*7c478bd9Sstevel@tonic-gate } else ppasswd->expdate = 0L; 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* Close the shadow password file */ 944*7c478bd9Sstevel@tonic-gate endspent(); 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate /* 948*7c478bd9Sstevel@tonic-gate * int hasnopasswd(pwent) 949*7c478bd9Sstevel@tonic-gate * struct passwd *pwent 950*7c478bd9Sstevel@tonic-gate * 951*7c478bd9Sstevel@tonic-gate * This function examines a login's password-file entry 952*7c478bd9Sstevel@tonic-gate * and, if necessary, its shadow password-file entry and 953*7c478bd9Sstevel@tonic-gate * returns TRUE if that user-ID has no password, meaning 954*7c478bd9Sstevel@tonic-gate * that the user-ID can be used to log into the system 955*7c478bd9Sstevel@tonic-gate * without giving a password. The function returns FALSE 956*7c478bd9Sstevel@tonic-gate * otherwise. 957*7c478bd9Sstevel@tonic-gate * 958*7c478bd9Sstevel@tonic-gate * Arguments: 959*7c478bd9Sstevel@tonic-gate * pwent Login to examine. 960*7c478bd9Sstevel@tonic-gate * 961*7c478bd9Sstevel@tonic-gate * Returns: int 962*7c478bd9Sstevel@tonic-gate * TRUE if the login can be used without a password, FALSE 963*7c478bd9Sstevel@tonic-gate * otherwise. 964*7c478bd9Sstevel@tonic-gate */ 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate static int 967*7c478bd9Sstevel@tonic-gate hasnopasswd(pwent) 968*7c478bd9Sstevel@tonic-gate struct passwd *pwent; /* /etc/passwd entry of login to check */ 969*7c478bd9Sstevel@tonic-gate { 970*7c478bd9Sstevel@tonic-gate /* Local definitions */ 971*7c478bd9Sstevel@tonic-gate struct spwd *psp; /* /etc/shadow file struct */ 972*7c478bd9Sstevel@tonic-gate int nopwflag; /* TRUE if login has no passwd */ 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate /* 975*7c478bd9Sstevel@tonic-gate * A login has no password if: 976*7c478bd9Sstevel@tonic-gate * 1. There exists an entry for that login in the 977*7c478bd9Sstevel@tonic-gate * shadow password-file (/etc/passwd), and 978*7c478bd9Sstevel@tonic-gate * 2. The encrypted password in the structure describing 979*7c478bd9Sstevel@tonic-gate * that entry is either: 980*7c478bd9Sstevel@tonic-gate * a. (char *) NULL 981*7c478bd9Sstevel@tonic-gate * b. A null string ("") 982*7c478bd9Sstevel@tonic-gate */ 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate /* Get the login's entry in the shadow password file */ 985*7c478bd9Sstevel@tonic-gate if (psp = getspnam(pwent->pw_name)) { 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate /* Look at the encrypted password in that entry */ 988*7c478bd9Sstevel@tonic-gate if (psp->sp_pwdp == (char *)0 || 989*7c478bd9Sstevel@tonic-gate *psp->sp_pwdp == '\0') 990*7c478bd9Sstevel@tonic-gate nopwflag = TRUE; 991*7c478bd9Sstevel@tonic-gate else 992*7c478bd9Sstevel@tonic-gate nopwflag = FALSE; 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate else 995*7c478bd9Sstevel@tonic-gate nopwflag = FALSE; 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* Done ... */ 998*7c478bd9Sstevel@tonic-gate return(nopwflag); 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate /* 1002*7c478bd9Sstevel@tonic-gate * void writeunformatted(current, xtndflag, expflag) 1003*7c478bd9Sstevel@tonic-gate * struct display *current 1004*7c478bd9Sstevel@tonic-gate * int xtndflag 1005*7c478bd9Sstevel@tonic-gate * int expflag 1006*7c478bd9Sstevel@tonic-gate * 1007*7c478bd9Sstevel@tonic-gate * This function writes the data in the display structure "current" 1008*7c478bd9Sstevel@tonic-gate * to the standard output file. It writes the information in the 1009*7c478bd9Sstevel@tonic-gate * form of a colon-list. It writes secondary group information if 1010*7c478bd9Sstevel@tonic-gate * that information is in the structure, it writes extended 1011*7c478bd9Sstevel@tonic-gate * (initial working directory, shell, and password-aging) info 1012*7c478bd9Sstevel@tonic-gate * if the "xtndflag" is TRUE, and it writes password expiration 1013*7c478bd9Sstevel@tonic-gate * information if "expflag" is TRUE. 1014*7c478bd9Sstevel@tonic-gate * 1015*7c478bd9Sstevel@tonic-gate * Arguments: 1016*7c478bd9Sstevel@tonic-gate * current Structure containing information to write. 1017*7c478bd9Sstevel@tonic-gate * xtndflag TRUE if extended information is to be written, 1018*7c478bd9Sstevel@tonic-gate * FALSE otherwise 1019*7c478bd9Sstevel@tonic-gate * expflag TRUE if password expiration information is to 1020*7c478bd9Sstevel@tonic-gate * be written, FALSE otherwise 1021*7c478bd9Sstevel@tonic-gate * 1022*7c478bd9Sstevel@tonic-gate * Returns: void 1023*7c478bd9Sstevel@tonic-gate */ 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate static void 1026*7c478bd9Sstevel@tonic-gate writeunformatted(current, xtndflag, expflag) 1027*7c478bd9Sstevel@tonic-gate struct display *current; /* Struct with info to write */ 1028*7c478bd9Sstevel@tonic-gate int xtndflag; /* Write extended output flag */ 1029*7c478bd9Sstevel@tonic-gate int expflag; /* Write password expiration info flag */ 1030*7c478bd9Sstevel@tonic-gate { 1031*7c478bd9Sstevel@tonic-gate /* Automatic data */ 1032*7c478bd9Sstevel@tonic-gate struct secgrp *psecgrp; /* Secondary group info */ 1033*7c478bd9Sstevel@tonic-gate struct pwdinfo *pwdinfo; /* Password aging info */ 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate /* Write the general information */ 1036*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s:%ld:%s:%ld:%s", 1037*7c478bd9Sstevel@tonic-gate current->loginID, 1038*7c478bd9Sstevel@tonic-gate current->userID, 1039*7c478bd9Sstevel@tonic-gate current->groupname == (char *) NULL ? "" : current->groupname, 1040*7c478bd9Sstevel@tonic-gate current->groupID, 1041*7c478bd9Sstevel@tonic-gate current->freefield); 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate /* 1044*7c478bd9Sstevel@tonic-gate * If the group information is there, write it (it's only 1045*7c478bd9Sstevel@tonic-gate * there if it's supposed to be written) 1046*7c478bd9Sstevel@tonic-gate */ 1047*7c478bd9Sstevel@tonic-gate for (psecgrp = current->secgrplist ; psecgrp ; psecgrp = psecgrp->next) 1048*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, ":%s:%ld", psecgrp->groupname, psecgrp->groupID); 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate /* If the extended info flag is TRUE, write the extended information */ 1051*7c478bd9Sstevel@tonic-gate if (xtndflag) { 1052*7c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 1053*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, ":%s:%s:%s:%6.6ld:%ld:%ld:%ld", 1054*7c478bd9Sstevel@tonic-gate current->iwd, current->shell, 1055*7c478bd9Sstevel@tonic-gate pwdinfo->passwdstatus, 1056*7c478bd9Sstevel@tonic-gate pwdinfo->datechg, 1057*7c478bd9Sstevel@tonic-gate pwdinfo->mindaystilchg, pwdinfo->maxdaystilchg, 1058*7c478bd9Sstevel@tonic-gate pwdinfo->warninterval); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate /* If the password expiration information is requested, write it. */ 1062*7c478bd9Sstevel@tonic-gate if (expflag) { 1063*7c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 1064*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, ":%ld:%ld", pwdinfo->inactive, pwdinfo->expdate); 1065*7c478bd9Sstevel@tonic-gate } 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate /* Terminate the information with a new-line */ 1068*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate /* 1072*7c478bd9Sstevel@tonic-gate * void writeformatted(current, xtndflag, expflag) 1073*7c478bd9Sstevel@tonic-gate * struct display *current 1074*7c478bd9Sstevel@tonic-gate * int xtndflag 1075*7c478bd9Sstevel@tonic-gate * int expflag 1076*7c478bd9Sstevel@tonic-gate * 1077*7c478bd9Sstevel@tonic-gate * This function writes the data in the display structure "current" 1078*7c478bd9Sstevel@tonic-gate * to the standard output file. It writes the information in an 1079*7c478bd9Sstevel@tonic-gate * easily readable format. It writes secondary group information 1080*7c478bd9Sstevel@tonic-gate * if that information is in the structure, it writes extended 1081*7c478bd9Sstevel@tonic-gate * (initial working directory, shell, and password-aging) info if 1082*7c478bd9Sstevel@tonic-gate * "xtndflag" is TRUE, and it write password expiration information 1083*7c478bd9Sstevel@tonic-gate * if "expflag" is TRUE. 1084*7c478bd9Sstevel@tonic-gate * 1085*7c478bd9Sstevel@tonic-gate * Arguments: 1086*7c478bd9Sstevel@tonic-gate * current Structure containing info to write. 1087*7c478bd9Sstevel@tonic-gate * xtndflag TRUE if extended information is to be written, 1088*7c478bd9Sstevel@tonic-gate * FALSE otherwise 1089*7c478bd9Sstevel@tonic-gate * expflag TRUE if password expiration information is to be written, 1090*7c478bd9Sstevel@tonic-gate * FALSE otherwise 1091*7c478bd9Sstevel@tonic-gate * 1092*7c478bd9Sstevel@tonic-gate * Returns: void 1093*7c478bd9Sstevel@tonic-gate */ 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate static void 1096*7c478bd9Sstevel@tonic-gate writeformatted(current, xtndflag, expflag) 1097*7c478bd9Sstevel@tonic-gate struct display *current; /* Struct with info to write */ 1098*7c478bd9Sstevel@tonic-gate int xtndflag; /* Write extended output flag */ 1099*7c478bd9Sstevel@tonic-gate int expflag; /* Write password expiration info flag */ 1100*7c478bd9Sstevel@tonic-gate { 1101*7c478bd9Sstevel@tonic-gate /* Automatic data */ 1102*7c478bd9Sstevel@tonic-gate struct secgrp *psecgrp; /* Secondary group info */ 1103*7c478bd9Sstevel@tonic-gate struct pwdinfo *pwdinfo; /* Password aging info */ 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate /* Write general information */ 1106*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%-14s %-6ld %-14s %-6ld %s\n", 1107*7c478bd9Sstevel@tonic-gate current->loginID, current->userID, 1108*7c478bd9Sstevel@tonic-gate current->groupname == (char *) NULL ? "" : current->groupname, 1109*7c478bd9Sstevel@tonic-gate current->groupID, current->freefield); 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate /* 1112*7c478bd9Sstevel@tonic-gate * Write information about secondary groups if the info exists 1113*7c478bd9Sstevel@tonic-gate * (it only exists if it is to be written) 1114*7c478bd9Sstevel@tonic-gate */ 1115*7c478bd9Sstevel@tonic-gate for (psecgrp = current->secgrplist ; psecgrp ; psecgrp = psecgrp->next) 1116*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %-14s %-6ld\n", 1117*7c478bd9Sstevel@tonic-gate psecgrp->groupname, psecgrp->groupID); 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate /* If the extended information flag is TRUE, write the extended information */ 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate if (xtndflag) { 1122*7c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 1123*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %s\n", current->iwd); 1124*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %s\n", current->shell); 1125*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %s %6.6ld %ld %ld %ld\n", 1126*7c478bd9Sstevel@tonic-gate pwdinfo->passwdstatus, 1127*7c478bd9Sstevel@tonic-gate pwdinfo->datechg, pwdinfo->mindaystilchg, 1128*7c478bd9Sstevel@tonic-gate pwdinfo->maxdaystilchg, 1129*7c478bd9Sstevel@tonic-gate pwdinfo->warninterval); 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate /* If the password expiration info flag is TRUE, write that information */ 1133*7c478bd9Sstevel@tonic-gate if (expflag) { 1134*7c478bd9Sstevel@tonic-gate pwdinfo = current->passwdinfo; 1135*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %ld %6.6ld\n", 1136*7c478bd9Sstevel@tonic-gate pwdinfo->inactive, pwdinfo->expdate); 1137*7c478bd9Sstevel@tonic-gate } 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate /* 1141*7c478bd9Sstevel@tonic-gate * void genuidreport(pipeflag, xtndflag, expflag) 1142*7c478bd9Sstevel@tonic-gate * int pipeflag 1143*7c478bd9Sstevel@tonic-gate * int xtndflag 1144*7c478bd9Sstevel@tonic-gate * int expflag 1145*7c478bd9Sstevel@tonic-gate * 1146*7c478bd9Sstevel@tonic-gate * This function generates a report on the standard output 1147*7c478bd9Sstevel@tonic-gate * stream (stdout) containing the login-IDs in the list of 1148*7c478bd9Sstevel@tonic-gate * logins built by this command. The list is ordered based 1149*7c478bd9Sstevel@tonic-gate * on user-ID. If the <pipeflag> variable is not zero, it 1150*7c478bd9Sstevel@tonic-gate * will generate a report containing parsable records. 1151*7c478bd9Sstevel@tonic-gate * Otherwise, it will generate a columnarized report. If 1152*7c478bd9Sstevel@tonic-gate * the <xtndflag> variable is not zero, it will include the 1153*7c478bd9Sstevel@tonic-gate * extended set of information (password aging info, home 1154*7c478bd9Sstevel@tonic-gate * directory, shell process, etc.). If <expflag> is not 1155*7c478bd9Sstevel@tonic-gate * zero, it will display password expiration information. 1156*7c478bd9Sstevel@tonic-gate * 1157*7c478bd9Sstevel@tonic-gate * Arguments: 1158*7c478bd9Sstevel@tonic-gate * pipeflag int 1159*7c478bd9Sstevel@tonic-gate * TRUE if a parsable report is needed, 1160*7c478bd9Sstevel@tonic-gate * FALSE if a columnar report is needed 1161*7c478bd9Sstevel@tonic-gate * xtndflag int 1162*7c478bd9Sstevel@tonic-gate * TRUE if extended set of info is to be displayed, 1163*7c478bd9Sstevel@tonic-gate * FALSE otherwise 1164*7c478bd9Sstevel@tonic-gate * expflag int 1165*7c478bd9Sstevel@tonic-gate * TRUE if password expiration information is to be 1166*7c478bd9Sstevel@tonic-gate * displayed, FALSE otherwise 1167*7c478bd9Sstevel@tonic-gate * 1168*7c478bd9Sstevel@tonic-gate * Returns: void 1169*7c478bd9Sstevel@tonic-gate */ 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate static void 1172*7c478bd9Sstevel@tonic-gate genuidreport(pipeflag, xtndflag, expflag) 1173*7c478bd9Sstevel@tonic-gate int pipeflag; /* Parsible output flag */ 1174*7c478bd9Sstevel@tonic-gate int xtndflag; /* Extended info flag */ 1175*7c478bd9Sstevel@tonic-gate int expflag; /* Password expiration info flag */ 1176*7c478bd9Sstevel@tonic-gate { 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate /* Automatic data */ 1179*7c478bd9Sstevel@tonic-gate struct display *current; /* Data being displayed */ 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate /* 1183*7c478bd9Sstevel@tonic-gate * Initialization for loop. 1184*7c478bd9Sstevel@tonic-gate * (NOTE: The first element in the list of logins to 1185*7c478bd9Sstevel@tonic-gate * display is a dummy element.) 1186*7c478bd9Sstevel@tonic-gate */ 1187*7c478bd9Sstevel@tonic-gate current = displayhead; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate /* 1190*7c478bd9Sstevel@tonic-gate * Display elements in the list 1191*7c478bd9Sstevel@tonic-gate */ 1192*7c478bd9Sstevel@tonic-gate if (pipeflag) 1193*7c478bd9Sstevel@tonic-gate for (current = displayhead->nextuid ; current ; current = current->nextuid) 1194*7c478bd9Sstevel@tonic-gate writeunformatted(current, xtndflag, expflag); 1195*7c478bd9Sstevel@tonic-gate else 1196*7c478bd9Sstevel@tonic-gate for (current = displayhead->nextuid ; current ; current = current->nextuid) 1197*7c478bd9Sstevel@tonic-gate writeformatted(current, xtndflag, expflag); 1198*7c478bd9Sstevel@tonic-gate } 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate /* 1201*7c478bd9Sstevel@tonic-gate * void genlogreport(pipeflag, xtndflag, expflag) 1202*7c478bd9Sstevel@tonic-gate * int pipeflag 1203*7c478bd9Sstevel@tonic-gate * int xtndflag 1204*7c478bd9Sstevel@tonic-gate * int expflag 1205*7c478bd9Sstevel@tonic-gate * 1206*7c478bd9Sstevel@tonic-gate * This function generates a report on the standard output 1207*7c478bd9Sstevel@tonic-gate * stream (stdout) containing the login-IDs in the list of 1208*7c478bd9Sstevel@tonic-gate * logins built by this command. The list is ordered based 1209*7c478bd9Sstevel@tonic-gate * on user name. If the <pipeflag> variable is not zero, it 1210*7c478bd9Sstevel@tonic-gate * will generate a report containing parsable records. 1211*7c478bd9Sstevel@tonic-gate * Otherwise, it will generate a columnarized report. If 1212*7c478bd9Sstevel@tonic-gate * the <xtndflag> variable is not zero, it will include the 1213*7c478bd9Sstevel@tonic-gate * extended set of information (password aging info, home 1214*7c478bd9Sstevel@tonic-gate * directory, shell process, etc.). If <expflag> is not 1215*7c478bd9Sstevel@tonic-gate * zero, it will include password expiration information. 1216*7c478bd9Sstevel@tonic-gate * 1217*7c478bd9Sstevel@tonic-gate * Arguments: 1218*7c478bd9Sstevel@tonic-gate * pipeflag int 1219*7c478bd9Sstevel@tonic-gate * TRUE if a parsable report is needed, 1220*7c478bd9Sstevel@tonic-gate * FALSE if a columnar report is needed 1221*7c478bd9Sstevel@tonic-gate * xtndflag int 1222*7c478bd9Sstevel@tonic-gate * TRUE if extended set of info is to be displayed, 1223*7c478bd9Sstevel@tonic-gate * FALSE otherwise 1224*7c478bd9Sstevel@tonic-gate * expflag int 1225*7c478bd9Sstevel@tonic-gate * TRUE if password expiration information is to 1226*7c478bd9Sstevel@tonic-gate * be displayed, FALSE otherwise 1227*7c478bd9Sstevel@tonic-gate * 1228*7c478bd9Sstevel@tonic-gate * Returns: void 1229*7c478bd9Sstevel@tonic-gate */ 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate static void 1232*7c478bd9Sstevel@tonic-gate genlogreport(pipeflag, xtndflag, expflag) 1233*7c478bd9Sstevel@tonic-gate int pipeflag; /* Parsable output flag */ 1234*7c478bd9Sstevel@tonic-gate int xtndflag; /* Extended info flag */ 1235*7c478bd9Sstevel@tonic-gate int expflag; /* Password expiration info flag */ 1236*7c478bd9Sstevel@tonic-gate { 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate /* Automatic data */ 1239*7c478bd9Sstevel@tonic-gate struct display *p; /* Value being displayed */ 1240*7c478bd9Sstevel@tonic-gate 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate /* 1243*7c478bd9Sstevel@tonic-gate * Initialization for loop. 1244*7c478bd9Sstevel@tonic-gate * (NOTE: The first element in the list of logins to 1245*7c478bd9Sstevel@tonic-gate * display is a dummy element.) 1246*7c478bd9Sstevel@tonic-gate */ 1247*7c478bd9Sstevel@tonic-gate p = displayhead; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate /* 1250*7c478bd9Sstevel@tonic-gate * Display elements in the list 1251*7c478bd9Sstevel@tonic-gate */ 1252*7c478bd9Sstevel@tonic-gate if (pipeflag) 1253*7c478bd9Sstevel@tonic-gate for (p = displayhead->nextlogin ; p ; p = p->nextlogin) 1254*7c478bd9Sstevel@tonic-gate writeunformatted(p, xtndflag, expflag); 1255*7c478bd9Sstevel@tonic-gate else 1256*7c478bd9Sstevel@tonic-gate for (p = displayhead->nextlogin ; p ; p = p->nextlogin) 1257*7c478bd9Sstevel@tonic-gate writeformatted(p, xtndflag, expflag); 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate char * 1261*7c478bd9Sstevel@tonic-gate strcpmalloc(str) 1262*7c478bd9Sstevel@tonic-gate char *str; 1263*7c478bd9Sstevel@tonic-gate { 1264*7c478bd9Sstevel@tonic-gate char *cp; 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate if (str == NULL) 1267*7c478bd9Sstevel@tonic-gate return NULL; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate return (strcpy(allocstr((unsigned int)strlen(str)+1), str)); 1270*7c478bd9Sstevel@tonic-gate } 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate struct localpw { 1273*7c478bd9Sstevel@tonic-gate struct localpw *next; 1274*7c478bd9Sstevel@tonic-gate struct passwd pw; 1275*7c478bd9Sstevel@tonic-gate }; 1276*7c478bd9Sstevel@tonic-gate 1277*7c478bd9Sstevel@tonic-gate struct localpw *pwtable = NULL; 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate struct localpw *pwptr; /* Local passwd pointer for getpwent() 1280*7c478bd9Sstevel@tonic-gate * -- -1 means not in use, NULL for EOF */ 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate int in_localgetpwent = 0; /* Set if in local_getpwent */ 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate void 1285*7c478bd9Sstevel@tonic-gate build_localpw() 1286*7c478bd9Sstevel@tonic-gate { 1287*7c478bd9Sstevel@tonic-gate struct localpw *next, *cur; 1288*7c478bd9Sstevel@tonic-gate struct passwd *pw; 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate next = (struct localpw *) allocblk(sizeof (struct localpw)); 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate pwtable = next; 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate while ((pw = getpwent()) != NULL) { 1295*7c478bd9Sstevel@tonic-gate /* 1296*7c478bd9Sstevel@tonic-gate * Copy the data -- we have to alloc areas for it all 1297*7c478bd9Sstevel@tonic-gate */ 1298*7c478bd9Sstevel@tonic-gate next->pw.pw_name = strcpmalloc(pw->pw_name); 1299*7c478bd9Sstevel@tonic-gate next->pw.pw_passwd = strcpmalloc(pw->pw_passwd); 1300*7c478bd9Sstevel@tonic-gate next->pw.pw_uid = pw->pw_uid; 1301*7c478bd9Sstevel@tonic-gate next->pw.pw_gid = pw->pw_gid; 1302*7c478bd9Sstevel@tonic-gate next->pw.pw_age = strcpmalloc(pw->pw_age); 1303*7c478bd9Sstevel@tonic-gate next->pw.pw_comment = strcpmalloc(pw->pw_comment); 1304*7c478bd9Sstevel@tonic-gate next->pw.pw_gecos = strcpmalloc(pw->pw_gecos); 1305*7c478bd9Sstevel@tonic-gate next->pw.pw_dir = strcpmalloc(pw->pw_dir); 1306*7c478bd9Sstevel@tonic-gate next->pw.pw_shell = strcpmalloc(pw->pw_shell); 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate next->next = (struct localpw *) allocblk(sizeof (struct localpw)); 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate cur = next; 1311*7c478bd9Sstevel@tonic-gate next = next->next; 1312*7c478bd9Sstevel@tonic-gate } 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate /* 1315*7c478bd9Sstevel@tonic-gate * At this point we have one extra (struct localpw) allocated; 1316*7c478bd9Sstevel@tonic-gate * sine alloclbk doesn't have a freeblk, we just leave it unreferenced. 1317*7c478bd9Sstevel@tonic-gate */ 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate if (pwtable == next) 1320*7c478bd9Sstevel@tonic-gate pwtable = NULL; 1321*7c478bd9Sstevel@tonic-gate else 1322*7c478bd9Sstevel@tonic-gate cur->next = NULL; 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate endpwent(); 1325*7c478bd9Sstevel@tonic-gate } 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate struct passwd * 1328*7c478bd9Sstevel@tonic-gate local_getpwent() 1329*7c478bd9Sstevel@tonic-gate { 1330*7c478bd9Sstevel@tonic-gate if (!in_localgetpwent) { 1331*7c478bd9Sstevel@tonic-gate in_localgetpwent = 1; 1332*7c478bd9Sstevel@tonic-gate pwptr = pwtable; 1333*7c478bd9Sstevel@tonic-gate } else if ( pwptr != NULL) 1334*7c478bd9Sstevel@tonic-gate pwptr = pwptr->next; 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate if (pwptr != NULL) 1337*7c478bd9Sstevel@tonic-gate return &(pwptr->pw); 1338*7c478bd9Sstevel@tonic-gate else 1339*7c478bd9Sstevel@tonic-gate return NULL; 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate void 1343*7c478bd9Sstevel@tonic-gate local_endpwent() 1344*7c478bd9Sstevel@tonic-gate { 1345*7c478bd9Sstevel@tonic-gate in_localgetpwent = 0; 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate long 1349*7c478bd9Sstevel@tonic-gate local_pwtell() 1350*7c478bd9Sstevel@tonic-gate { 1351*7c478bd9Sstevel@tonic-gate return (long)pwptr; 1352*7c478bd9Sstevel@tonic-gate } 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate void 1355*7c478bd9Sstevel@tonic-gate local_pwseek(ptr) 1356*7c478bd9Sstevel@tonic-gate long ptr; 1357*7c478bd9Sstevel@tonic-gate { 1358*7c478bd9Sstevel@tonic-gate pwptr = (struct localpw *)ptr; 1359*7c478bd9Sstevel@tonic-gate } 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate /* 1362*7c478bd9Sstevel@tonic-gate * logins [-admopstux] [-l logins] [-g groups] 1363*7c478bd9Sstevel@tonic-gate * 1364*7c478bd9Sstevel@tonic-gate * This command generates a report of logins administered on 1365*7c478bd9Sstevel@tonic-gate * the system. The list will contain logins that meet criteria 1366*7c478bd9Sstevel@tonic-gate * described by the options in the list. If there are no options, 1367*7c478bd9Sstevel@tonic-gate * it will list all logins administered. It is intended to be used 1368*7c478bd9Sstevel@tonic-gate * only by administrators. 1369*7c478bd9Sstevel@tonic-gate * 1370*7c478bd9Sstevel@tonic-gate * Options: 1371*7c478bd9Sstevel@tonic-gate * -a Display password expiration information. 1372*7c478bd9Sstevel@tonic-gate * -d list all logins that share user-IDs with another 1373*7c478bd9Sstevel@tonic-gate * login. 1374*7c478bd9Sstevel@tonic-gate * -g groups specifies the names of the groups to which a login 1375*7c478bd9Sstevel@tonic-gate * must belong before it is included in the generated 1376*7c478bd9Sstevel@tonic-gate * list. "groups" is a comma-list of group names. 1377*7c478bd9Sstevel@tonic-gate * -l logins specifies the logins to display. "logins" is a 1378*7c478bd9Sstevel@tonic-gate * comma-list of login names. 1379*7c478bd9Sstevel@tonic-gate * -m in addition to the usual information, for each 1380*7c478bd9Sstevel@tonic-gate * login displayed, list all groups to which that 1381*7c478bd9Sstevel@tonic-gate * login is member. 1382*7c478bd9Sstevel@tonic-gate * -o generate a report as a colon-list instead of in a 1383*7c478bd9Sstevel@tonic-gate * columnar format 1384*7c478bd9Sstevel@tonic-gate * -p list all logins that have no password. 1385*7c478bd9Sstevel@tonic-gate * -s list all system logins 1386*7c478bd9Sstevel@tonic-gate * -t sort the report lexicographically by login name 1387*7c478bd9Sstevel@tonic-gate * instead of by user-ID 1388*7c478bd9Sstevel@tonic-gate * -u list all user logins 1389*7c478bd9Sstevel@tonic-gate * -x in addition to the usual information, display an 1390*7c478bd9Sstevel@tonic-gate * extended set of information that includes the home 1391*7c478bd9Sstevel@tonic-gate * directory, initial process, and password status and 1392*7c478bd9Sstevel@tonic-gate * aging information 1393*7c478bd9Sstevel@tonic-gate * 1394*7c478bd9Sstevel@tonic-gate * Exit Codes: 1395*7c478bd9Sstevel@tonic-gate * 0 All's well that ends well 1396*7c478bd9Sstevel@tonic-gate * 1 Usage error 1397*7c478bd9Sstevel@tonic-gate */ 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate main(argc, argv) 1400*7c478bd9Sstevel@tonic-gate int argc; /* Number of args on the command line */ 1401*7c478bd9Sstevel@tonic-gate char *argv[]; /* Pointers pointing to the arguments */ 1402*7c478bd9Sstevel@tonic-gate { 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate /* Automatic data */ 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate struct passwd *plookpwd; /* Ptr to searcher pw (-d) */ 1407*7c478bd9Sstevel@tonic-gate struct reqgrp *reqgrphead; /* Head of the req'd group list */ 1408*7c478bd9Sstevel@tonic-gate struct reqgrp *pgrp; /* Current item in req'd group list */ 1409*7c478bd9Sstevel@tonic-gate struct reqgrp *qgrp; /* Prev item in the req'd group list */ 1410*7c478bd9Sstevel@tonic-gate struct reqlogin *reqloginhead; /* Head of req'd login list */ 1411*7c478bd9Sstevel@tonic-gate struct reqlogin *plogin; /* Current item in the req'd login list */ 1412*7c478bd9Sstevel@tonic-gate struct reqlogin *qlogin; /* Prev item in the req'd login list */ 1413*7c478bd9Sstevel@tonic-gate struct passwd *pwent; /* /etc/passwd entry */ 1414*7c478bd9Sstevel@tonic-gate struct group *grent; /* /etc/group entry */ 1415*7c478bd9Sstevel@tonic-gate char *token; /* Token extracted by strtok() */ 1416*7c478bd9Sstevel@tonic-gate char **pp; /* Group member */ 1417*7c478bd9Sstevel@tonic-gate char *g_arg; /* -g option's argument */ 1418*7c478bd9Sstevel@tonic-gate char *l_arg; /* -l option's argument */ 1419*7c478bd9Sstevel@tonic-gate long lookpos; /* File pos'n, rec we're looking for */ 1420*7c478bd9Sstevel@tonic-gate int a_seen; /* Is -a requested? */ 1421*7c478bd9Sstevel@tonic-gate int d_seen; /* Is -d requested? */ 1422*7c478bd9Sstevel@tonic-gate int g_seen; /* Is -g requested? */ 1423*7c478bd9Sstevel@tonic-gate int l_seen; /* Is -l requested? */ 1424*7c478bd9Sstevel@tonic-gate int m_seen; /* Is -m requested? */ 1425*7c478bd9Sstevel@tonic-gate int o_seen; /* Is -o requested? */ 1426*7c478bd9Sstevel@tonic-gate int p_seen; /* Is -p requested? */ 1427*7c478bd9Sstevel@tonic-gate int s_seen; /* Is -s requested? */ 1428*7c478bd9Sstevel@tonic-gate int t_seen; /* Is -t requested? */ 1429*7c478bd9Sstevel@tonic-gate int u_seen; /* Is -u requested? */ 1430*7c478bd9Sstevel@tonic-gate int x_seen; /* Is -x requested? */ 1431*7c478bd9Sstevel@tonic-gate int errflg; /* Is there a command-line problem */ 1432*7c478bd9Sstevel@tonic-gate int done; /* Is the process (?) is complete */ 1433*7c478bd9Sstevel@tonic-gate int groupcount; /* Number of groups specified by the user */ 1434*7c478bd9Sstevel@tonic-gate int doall; /* Are all logins to be reported */ 1435*7c478bd9Sstevel@tonic-gate int c; /* Character returned from getopt() */ 1436*7c478bd9Sstevel@tonic-gate 1437*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 1440*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1441*7c478bd9Sstevel@tonic-gate #endif 1442*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1443*7c478bd9Sstevel@tonic-gate 1444*7c478bd9Sstevel@tonic-gate /* Initializations */ 1445*7c478bd9Sstevel@tonic-gate initmsg(argv[0]); 1446*7c478bd9Sstevel@tonic-gate 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate /* 1450*7c478bd9Sstevel@tonic-gate * Command-line processing 1451*7c478bd9Sstevel@tonic-gate */ 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate /* Initializations */ 1454*7c478bd9Sstevel@tonic-gate a_seen = FALSE; 1455*7c478bd9Sstevel@tonic-gate d_seen = FALSE; 1456*7c478bd9Sstevel@tonic-gate g_seen = FALSE; 1457*7c478bd9Sstevel@tonic-gate l_seen = FALSE; 1458*7c478bd9Sstevel@tonic-gate m_seen = FALSE; 1459*7c478bd9Sstevel@tonic-gate o_seen = FALSE; 1460*7c478bd9Sstevel@tonic-gate p_seen = FALSE; 1461*7c478bd9Sstevel@tonic-gate s_seen = FALSE; 1462*7c478bd9Sstevel@tonic-gate t_seen = FALSE; 1463*7c478bd9Sstevel@tonic-gate u_seen = FALSE; 1464*7c478bd9Sstevel@tonic-gate x_seen = FALSE; 1465*7c478bd9Sstevel@tonic-gate errflg = FALSE; 1466*7c478bd9Sstevel@tonic-gate opterr = 0; 1467*7c478bd9Sstevel@tonic-gate while (!errflg && ((c = getopt(argc, argv, OPTSTR)) != EOF)) { 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate /* Case on the option character */ 1470*7c478bd9Sstevel@tonic-gate switch(c) { 1471*7c478bd9Sstevel@tonic-gate 1472*7c478bd9Sstevel@tonic-gate /* 1473*7c478bd9Sstevel@tonic-gate * -a option: 1474*7c478bd9Sstevel@tonic-gate * Display password expiration information 1475*7c478bd9Sstevel@tonic-gate */ 1476*7c478bd9Sstevel@tonic-gate 1477*7c478bd9Sstevel@tonic-gate case 'a': 1478*7c478bd9Sstevel@tonic-gate if (a_seen) errflg = TRUE; 1479*7c478bd9Sstevel@tonic-gate else a_seen = TRUE; 1480*7c478bd9Sstevel@tonic-gate break; 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate /* 1483*7c478bd9Sstevel@tonic-gate * -d option: 1484*7c478bd9Sstevel@tonic-gate * Display logins which share user-IDs with other logins 1485*7c478bd9Sstevel@tonic-gate */ 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate case 'd': 1488*7c478bd9Sstevel@tonic-gate if (d_seen) errflg = TRUE; 1489*7c478bd9Sstevel@tonic-gate else d_seen = TRUE; 1490*7c478bd9Sstevel@tonic-gate break; 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate /* 1493*7c478bd9Sstevel@tonic-gate * -g <groups> option: 1494*7c478bd9Sstevel@tonic-gate * Display the specified groups 1495*7c478bd9Sstevel@tonic-gate */ 1496*7c478bd9Sstevel@tonic-gate 1497*7c478bd9Sstevel@tonic-gate case 'g': 1498*7c478bd9Sstevel@tonic-gate if (g_seen) errflg = TRUE; 1499*7c478bd9Sstevel@tonic-gate else { 1500*7c478bd9Sstevel@tonic-gate g_seen = TRUE; 1501*7c478bd9Sstevel@tonic-gate g_arg = optarg; 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate break; 1504*7c478bd9Sstevel@tonic-gate 1505*7c478bd9Sstevel@tonic-gate /* 1506*7c478bd9Sstevel@tonic-gate * -l <logins> option: 1507*7c478bd9Sstevel@tonic-gate * Display the specified logins 1508*7c478bd9Sstevel@tonic-gate */ 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate case 'l': 1511*7c478bd9Sstevel@tonic-gate if (l_seen) errflg = TRUE; 1512*7c478bd9Sstevel@tonic-gate else { 1513*7c478bd9Sstevel@tonic-gate l_seen = TRUE; 1514*7c478bd9Sstevel@tonic-gate l_arg = optarg; 1515*7c478bd9Sstevel@tonic-gate } 1516*7c478bd9Sstevel@tonic-gate break; 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate /* 1519*7c478bd9Sstevel@tonic-gate * -m option: 1520*7c478bd9Sstevel@tonic-gate * Display multiple group information 1521*7c478bd9Sstevel@tonic-gate */ 1522*7c478bd9Sstevel@tonic-gate 1523*7c478bd9Sstevel@tonic-gate case 'm': 1524*7c478bd9Sstevel@tonic-gate if (m_seen) errflg = TRUE; 1525*7c478bd9Sstevel@tonic-gate else m_seen = TRUE; 1526*7c478bd9Sstevel@tonic-gate break; 1527*7c478bd9Sstevel@tonic-gate 1528*7c478bd9Sstevel@tonic-gate /* 1529*7c478bd9Sstevel@tonic-gate * -o option: 1530*7c478bd9Sstevel@tonic-gate * Display information as a colon-list 1531*7c478bd9Sstevel@tonic-gate */ 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate case 'o': 1534*7c478bd9Sstevel@tonic-gate if (o_seen) errflg = TRUE; 1535*7c478bd9Sstevel@tonic-gate else o_seen = TRUE; 1536*7c478bd9Sstevel@tonic-gate break; 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate /* 1539*7c478bd9Sstevel@tonic-gate * -p option: 1540*7c478bd9Sstevel@tonic-gate * Select logins that have no password 1541*7c478bd9Sstevel@tonic-gate */ 1542*7c478bd9Sstevel@tonic-gate 1543*7c478bd9Sstevel@tonic-gate case 'p': 1544*7c478bd9Sstevel@tonic-gate if (p_seen) errflg = TRUE; 1545*7c478bd9Sstevel@tonic-gate else p_seen = TRUE; 1546*7c478bd9Sstevel@tonic-gate break; 1547*7c478bd9Sstevel@tonic-gate 1548*7c478bd9Sstevel@tonic-gate /* 1549*7c478bd9Sstevel@tonic-gate * -s option: 1550*7c478bd9Sstevel@tonic-gate * Select system logins 1551*7c478bd9Sstevel@tonic-gate */ 1552*7c478bd9Sstevel@tonic-gate 1553*7c478bd9Sstevel@tonic-gate case 's': 1554*7c478bd9Sstevel@tonic-gate if (s_seen) errflg = TRUE; 1555*7c478bd9Sstevel@tonic-gate else s_seen = TRUE; 1556*7c478bd9Sstevel@tonic-gate break; 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate /* 1559*7c478bd9Sstevel@tonic-gate * -t option: 1560*7c478bd9Sstevel@tonic-gate * Sort alphabetically by login-ID instead of numerically 1561*7c478bd9Sstevel@tonic-gate * by user-ID 1562*7c478bd9Sstevel@tonic-gate */ 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate case 't': 1565*7c478bd9Sstevel@tonic-gate if (t_seen) errflg = TRUE; 1566*7c478bd9Sstevel@tonic-gate else t_seen = TRUE; 1567*7c478bd9Sstevel@tonic-gate break; 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate /* 1570*7c478bd9Sstevel@tonic-gate * -u option: 1571*7c478bd9Sstevel@tonic-gate * Select user logins 1572*7c478bd9Sstevel@tonic-gate */ 1573*7c478bd9Sstevel@tonic-gate 1574*7c478bd9Sstevel@tonic-gate case 'u': 1575*7c478bd9Sstevel@tonic-gate if (u_seen) errflg = TRUE; 1576*7c478bd9Sstevel@tonic-gate else u_seen = TRUE; 1577*7c478bd9Sstevel@tonic-gate break; 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate /* 1580*7c478bd9Sstevel@tonic-gate * -x option: 1581*7c478bd9Sstevel@tonic-gate * Display extended info (init working dir, shell, pwd info) 1582*7c478bd9Sstevel@tonic-gate */ 1583*7c478bd9Sstevel@tonic-gate 1584*7c478bd9Sstevel@tonic-gate case 'x': 1585*7c478bd9Sstevel@tonic-gate if (x_seen) errflg = TRUE; 1586*7c478bd9Sstevel@tonic-gate else x_seen = TRUE; 1587*7c478bd9Sstevel@tonic-gate break; 1588*7c478bd9Sstevel@tonic-gate 1589*7c478bd9Sstevel@tonic-gate default: /* Oops.... */ 1590*7c478bd9Sstevel@tonic-gate errflg = TRUE; 1591*7c478bd9Sstevel@tonic-gate } 1592*7c478bd9Sstevel@tonic-gate } 1593*7c478bd9Sstevel@tonic-gate 1594*7c478bd9Sstevel@tonic-gate /* Write out a usage message if necessary and quit */ 1595*7c478bd9Sstevel@tonic-gate if (errflg || (optind != argc)) { 1596*7c478bd9Sstevel@tonic-gate wrtmsg(MM_ERROR, MM_NULLACT, MM_NULLTAG, gettext(USAGE_MSG)); 1597*7c478bd9Sstevel@tonic-gate exit(1); 1598*7c478bd9Sstevel@tonic-gate } 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate /* 1603*7c478bd9Sstevel@tonic-gate * The following section does preparation work, setting up for 1604*7c478bd9Sstevel@tonic-gate * building the list of logins to display 1605*7c478bd9Sstevel@tonic-gate */ 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate /* 1608*7c478bd9Sstevel@tonic-gate * Very first thing, build an in-core structure of passwd file entries. 1609*7c478bd9Sstevel@tonic-gate * This is important since we have to assume that getpwent() is going 1610*7c478bd9Sstevel@tonic-gate * out to one or more network name services that could be changing 1611*7c478bd9Sstevel@tonic-gate * on the fly. This will limit us to one pass through the network data. 1612*7c478bd9Sstevel@tonic-gate */ 1613*7c478bd9Sstevel@tonic-gate build_localpw(); 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate /* 1617*7c478bd9Sstevel@tonic-gate * If the -g groups option was on the command line, build a 1618*7c478bd9Sstevel@tonic-gate * list containing groups we're to list logins for. 1619*7c478bd9Sstevel@tonic-gate */ 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate if (g_seen) { 1622*7c478bd9Sstevel@tonic-gate groupcount = 0; 1623*7c478bd9Sstevel@tonic-gate reqgrphead = (struct reqgrp *) NULL; 1624*7c478bd9Sstevel@tonic-gate if (token = strtok(g_arg, ",")) { 1625*7c478bd9Sstevel@tonic-gate pgrp = (struct reqgrp *) allocblk(sizeof(struct reqgrp)); 1626*7c478bd9Sstevel@tonic-gate pgrp->groupname = token; 1627*7c478bd9Sstevel@tonic-gate pgrp->found = FALSE; 1628*7c478bd9Sstevel@tonic-gate pgrp->next = (struct reqgrp *) NULL; 1629*7c478bd9Sstevel@tonic-gate groupcount++; 1630*7c478bd9Sstevel@tonic-gate reqgrphead = pgrp; 1631*7c478bd9Sstevel@tonic-gate qgrp = pgrp; 1632*7c478bd9Sstevel@tonic-gate while (token = strtok(NULL, ",")) { 1633*7c478bd9Sstevel@tonic-gate pgrp = (struct reqgrp *) allocblk(sizeof(struct reqgrp)); 1634*7c478bd9Sstevel@tonic-gate pgrp->groupname = token; 1635*7c478bd9Sstevel@tonic-gate pgrp->found = FALSE; 1636*7c478bd9Sstevel@tonic-gate pgrp->next = (struct reqgrp *) NULL; 1637*7c478bd9Sstevel@tonic-gate groupcount++; 1638*7c478bd9Sstevel@tonic-gate qgrp->next = pgrp; 1639*7c478bd9Sstevel@tonic-gate qgrp = pgrp; 1640*7c478bd9Sstevel@tonic-gate } 1641*7c478bd9Sstevel@tonic-gate } 1642*7c478bd9Sstevel@tonic-gate } 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate 1645*7c478bd9Sstevel@tonic-gate /* 1646*7c478bd9Sstevel@tonic-gate * If -l logins is on the command line, build a list of 1647*7c478bd9Sstevel@tonic-gate * logins we're to generate reports for. 1648*7c478bd9Sstevel@tonic-gate */ 1649*7c478bd9Sstevel@tonic-gate 1650*7c478bd9Sstevel@tonic-gate if (l_seen) { 1651*7c478bd9Sstevel@tonic-gate reqloginhead = (struct reqlogin *) NULL; 1652*7c478bd9Sstevel@tonic-gate if (token = strtok(l_arg, ",")) { 1653*7c478bd9Sstevel@tonic-gate plogin = (struct reqlogin *) allocblk(sizeof(struct reqlogin)); 1654*7c478bd9Sstevel@tonic-gate plogin->loginname = token; 1655*7c478bd9Sstevel@tonic-gate plogin->found = FALSE; 1656*7c478bd9Sstevel@tonic-gate plogin->next = (struct reqlogin *) NULL; 1657*7c478bd9Sstevel@tonic-gate reqloginhead = plogin; 1658*7c478bd9Sstevel@tonic-gate qlogin = plogin; 1659*7c478bd9Sstevel@tonic-gate while (token = strtok(NULL, ",")) { 1660*7c478bd9Sstevel@tonic-gate plogin = (struct reqlogin *) allocblk(sizeof(struct reqlogin)); 1661*7c478bd9Sstevel@tonic-gate plogin->loginname = token; 1662*7c478bd9Sstevel@tonic-gate plogin->found = FALSE; 1663*7c478bd9Sstevel@tonic-gate plogin->next = (struct reqlogin *) NULL; 1664*7c478bd9Sstevel@tonic-gate qlogin->next = plogin; 1665*7c478bd9Sstevel@tonic-gate qlogin = plogin; 1666*7c478bd9Sstevel@tonic-gate } 1667*7c478bd9Sstevel@tonic-gate } 1668*7c478bd9Sstevel@tonic-gate } 1669*7c478bd9Sstevel@tonic-gate 1670*7c478bd9Sstevel@tonic-gate if (l_seen) { 1671*7c478bd9Sstevel@tonic-gate while(pwent = local_getpwent()) { 1672*7c478bd9Sstevel@tonic-gate done = FALSE; 1673*7c478bd9Sstevel@tonic-gate for (plogin = reqloginhead ; !done && plogin ; 1674*7c478bd9Sstevel@tonic-gate plogin = plogin->next) { 1675*7c478bd9Sstevel@tonic-gate if (strcmp(pwent->pw_name, 1676*7c478bd9Sstevel@tonic-gate plogin->loginname) == 0) { 1677*7c478bd9Sstevel@tonic-gate plogin->found = TRUE; 1678*7c478bd9Sstevel@tonic-gate done = TRUE; 1679*7c478bd9Sstevel@tonic-gate } 1680*7c478bd9Sstevel@tonic-gate } 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate local_endpwent(); 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate 1685*7c478bd9Sstevel@tonic-gate /* 1686*7c478bd9Sstevel@tonic-gate * Generate the list of login information to display 1687*7c478bd9Sstevel@tonic-gate */ 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate /* Initialize the login list */ 1690*7c478bd9Sstevel@tonic-gate initmembers(); 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate /* 1694*7c478bd9Sstevel@tonic-gate * If -g groups was specified, generate a list of members 1695*7c478bd9Sstevel@tonic-gate * of the specified groups 1696*7c478bd9Sstevel@tonic-gate */ 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate if (g_seen) { 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate /* For each group in the /etc/group file ... */ 1701*7c478bd9Sstevel@tonic-gate while (grent = getgrent()) { 1702*7c478bd9Sstevel@tonic-gate 1703*7c478bd9Sstevel@tonic-gate /* For each group mentioned with the -g option ... */ 1704*7c478bd9Sstevel@tonic-gate for (pgrp = reqgrphead ; (groupcount > 0) && pgrp ; pgrp = pgrp->next) { 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate if (!pgrp->found) { 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate /* 1709*7c478bd9Sstevel@tonic-gate * If the mentioned group is found in the 1710*7c478bd9Sstevel@tonic-gate * /etc/group file ... 1711*7c478bd9Sstevel@tonic-gate */ 1712*7c478bd9Sstevel@tonic-gate if (strcmp(grent->gr_name, pgrp->groupname) == 0) { 1713*7c478bd9Sstevel@tonic-gate 1714*7c478bd9Sstevel@tonic-gate /* 1715*7c478bd9Sstevel@tonic-gate * Mark the entry is found, remembering the 1716*7c478bd9Sstevel@tonic-gate * group-ID for later 1717*7c478bd9Sstevel@tonic-gate */ 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate pgrp->found = TRUE; 1720*7c478bd9Sstevel@tonic-gate groupcount--; 1721*7c478bd9Sstevel@tonic-gate pgrp->groupID = grent->gr_gid; 1722*7c478bd9Sstevel@tonic-gate for (pp = grent->gr_mem ; *pp ; pp++) addmember(*pp); 1723*7c478bd9Sstevel@tonic-gate } 1724*7c478bd9Sstevel@tonic-gate } 1725*7c478bd9Sstevel@tonic-gate } 1726*7c478bd9Sstevel@tonic-gate } 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate 1729*7c478bd9Sstevel@tonic-gate /* 1730*7c478bd9Sstevel@tonic-gate * If any groups weren't found, write a message indicating 1731*7c478bd9Sstevel@tonic-gate * such, then continue 1732*7c478bd9Sstevel@tonic-gate */ 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate qgrp = (struct reqgrp *) NULL; 1735*7c478bd9Sstevel@tonic-gate for (pgrp = reqgrphead ; pgrp ; pgrp = pgrp->next) { 1736*7c478bd9Sstevel@tonic-gate if (!pgrp->found) { 1737*7c478bd9Sstevel@tonic-gate wrtmsg(MM_WARNING, MM_NULLACT, MM_NULLTAG, gettext("%s was not found"), pgrp->groupname); 1738*7c478bd9Sstevel@tonic-gate if (!qgrp) reqgrphead = pgrp->next; 1739*7c478bd9Sstevel@tonic-gate else qgrp->next = pgrp->next; 1740*7c478bd9Sstevel@tonic-gate } 1741*7c478bd9Sstevel@tonic-gate else qgrp = pgrp; 1742*7c478bd9Sstevel@tonic-gate } 1743*7c478bd9Sstevel@tonic-gate endgrent(); 1744*7c478bd9Sstevel@tonic-gate } 1745*7c478bd9Sstevel@tonic-gate 1746*7c478bd9Sstevel@tonic-gate 1747*7c478bd9Sstevel@tonic-gate /* Initialize the list of logins to display */ 1748*7c478bd9Sstevel@tonic-gate initdisp(); 1749*7c478bd9Sstevel@tonic-gate 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate /* 1752*7c478bd9Sstevel@tonic-gate * Add logins that have user-IDs that are used more than once, 1753*7c478bd9Sstevel@tonic-gate * if requested. This command is pretty slow, since the algorithm 1754*7c478bd9Sstevel@tonic-gate * reads from the /etc/passwd file 1+2+3+...+n times where n is the 1755*7c478bd9Sstevel@tonic-gate * number of login-IDs in the /etc/passwd file. (Actually, this 1756*7c478bd9Sstevel@tonic-gate * can be optimized so it's not quite that bad, but the order or 1757*7c478bd9Sstevel@tonic-gate * magnitude stays the same.) 1758*7c478bd9Sstevel@tonic-gate * 1759*7c478bd9Sstevel@tonic-gate * Note: This processing needs to be done before any other options 1760*7c478bd9Sstevel@tonic-gate * are processed -- the algorithm contains an optimization 1761*7c478bd9Sstevel@tonic-gate * that insists on the display list being empty before this 1762*7c478bd9Sstevel@tonic-gate * option is processed. 1763*7c478bd9Sstevel@tonic-gate */ 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate if (d_seen) { 1766*7c478bd9Sstevel@tonic-gate 1767*7c478bd9Sstevel@tonic-gate /* 1768*7c478bd9Sstevel@tonic-gate * The following code is a quick&dirty reimplementation of the 1769*7c478bd9Sstevel@tonic-gate * original algorithm, which opened the password file twice (to 1770*7c478bd9Sstevel@tonic-gate * get two file pointer into the data) and then used fgetpwent() 1771*7c478bd9Sstevel@tonic-gate * in undocumented ways to scan through the file, checking for 1772*7c478bd9Sstevel@tonic-gate * duplicates. This does not work when getpwent() is used to 1773*7c478bd9Sstevel@tonic-gate * go out over the network, since there is not file pointer. 1774*7c478bd9Sstevel@tonic-gate * 1775*7c478bd9Sstevel@tonic-gate * Instead an in-memory list of passwd structures is built, and then 1776*7c478bd9Sstevel@tonic-gate * this list is scanned. The routines Local_getpwent(), etc., 1777*7c478bd9Sstevel@tonic-gate * are designed to mimic the standard library routines, so this code 1778*7c478bd9Sstevel@tonic-gate * does not have to be extensively modified. 1779*7c478bd9Sstevel@tonic-gate */ 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate /* 1782*7c478bd9Sstevel@tonic-gate * For reference, here is the original comment about the next 1783*7c478bd9Sstevel@tonic-gate * section of code. Some of the code has changed, but the algorithm 1784*7c478bd9Sstevel@tonic-gate * is the same: 1785*7c478bd9Sstevel@tonic-gate * 1786*7c478bd9Sstevel@tonic-gate * Open the system password file once. This instance will be 1787*7c478bd9Sstevel@tonic-gate * used to leaf through the file once, reading each entry once, 1788*7c478bd9Sstevel@tonic-gate * and searching the remainder of the file for another login-ID 1789*7c478bd9Sstevel@tonic-gate * that has the same user-ID. Note that there are lots of 1790*7c478bd9Sstevel@tonic-gate * contortions one has to go through when reading two instances 1791*7c478bd9Sstevel@tonic-gate * of the /etc/passwd file. That's why there's some seeking, 1792*7c478bd9Sstevel@tonic-gate * re-reading of the same record, and other junk. Luckily, this 1793*7c478bd9Sstevel@tonic-gate * feature won't be requested very often, and still isn't too 1794*7c478bd9Sstevel@tonic-gate * slow... 1795*7c478bd9Sstevel@tonic-gate */ 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate /* For each entry in the passwd database ... */ 1798*7c478bd9Sstevel@tonic-gate while (plookpwd = local_getpwent()) { 1799*7c478bd9Sstevel@tonic-gate /* 1800*7c478bd9Sstevel@tonic-gate * Optimization -- If the login's user-ID is already in 1801*7c478bd9Sstevel@tonic-gate * the display list, there's no reason to process this 1802*7c478bd9Sstevel@tonic-gate * entry -- it's already there. 1803*7c478bd9Sstevel@tonic-gate */ 1804*7c478bd9Sstevel@tonic-gate if (!isuidindisp(plookpwd)) { 1805*7c478bd9Sstevel@tonic-gate 1806*7c478bd9Sstevel@tonic-gate /* 1807*7c478bd9Sstevel@tonic-gate * Rememeber the current entry's position, so when we finish 1808*7c478bd9Sstevel@tonic-gate * scanning through the database looking for duplicates 1809*7c478bd9Sstevel@tonic-gate * we can return to the current place, so that the enclosing 1810*7c478bd9Sstevel@tonic-gate * loop will march in an orderly fashion through the passwd 1811*7c478bd9Sstevel@tonic-gate * database. 1812*7c478bd9Sstevel@tonic-gate */ 1813*7c478bd9Sstevel@tonic-gate done = FALSE; 1814*7c478bd9Sstevel@tonic-gate lookpos = local_pwtell(); 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate /* 1817*7c478bd9Sstevel@tonic-gate * For each record in the passwd database beyond 1818*7c478bd9Sstevel@tonic-gate * the searching record ... 1819*7c478bd9Sstevel@tonic-gate */ 1820*7c478bd9Sstevel@tonic-gate while (pwent = local_getpwent()) { 1821*7c478bd9Sstevel@tonic-gate 1822*7c478bd9Sstevel@tonic-gate /* 1823*7c478bd9Sstevel@tonic-gate * If there's a match between the searcher's user- 1824*7c478bd9Sstevel@tonic-gate * ID and the searchee's user-ID ... 1825*7c478bd9Sstevel@tonic-gate */ 1826*7c478bd9Sstevel@tonic-gate if (pwent->pw_uid == plookpwd->pw_uid) { 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate /* 1829*7c478bd9Sstevel@tonic-gate * If this is the first duplicate of this searcher 1830*7c478bd9Sstevel@tonic-gate * that we find, 1831*7c478bd9Sstevel@tonic-gate * add the searcher's record to the display list 1832*7c478bd9Sstevel@tonic-gate * (It wants to be on the list first 1833*7c478bd9Sstevel@tonic-gate * to avoid ordering "flakeyness") 1834*7c478bd9Sstevel@tonic-gate */ 1835*7c478bd9Sstevel@tonic-gate if (done == FALSE) { 1836*7c478bd9Sstevel@tonic-gate adddisp(plookpwd); 1837*7c478bd9Sstevel@tonic-gate done == TRUE; 1838*7c478bd9Sstevel@tonic-gate } 1839*7c478bd9Sstevel@tonic-gate 1840*7c478bd9Sstevel@tonic-gate /* 1841*7c478bd9Sstevel@tonic-gate * Now add the searchee's record 1842*7c478bd9Sstevel@tonic-gate */ 1843*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1844*7c478bd9Sstevel@tonic-gate 1845*7c478bd9Sstevel@tonic-gate } 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate /* Reposition to searcher record */ 1848*7c478bd9Sstevel@tonic-gate local_pwseek(lookpos); 1849*7c478bd9Sstevel@tonic-gate } 1850*7c478bd9Sstevel@tonic-gate } 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate local_endpwent(); 1853*7c478bd9Sstevel@tonic-gate } 1854*7c478bd9Sstevel@tonic-gate 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate /* 1857*7c478bd9Sstevel@tonic-gate * Loop through the passwd database squirelling away the 1858*7c478bd9Sstevel@tonic-gate * information we need for the display. 1859*7c478bd9Sstevel@tonic-gate * 1860*7c478bd9Sstevel@tonic-gate * NOTE: Once a login is added to the list, the rest of the 1861*7c478bd9Sstevel@tonic-gate * body of the loop is bypassed (via a continue statement). 1862*7c478bd9Sstevel@tonic-gate */ 1863*7c478bd9Sstevel@tonic-gate 1864*7c478bd9Sstevel@tonic-gate doall = !(s_seen || u_seen || p_seen || d_seen || l_seen || g_seen); 1865*7c478bd9Sstevel@tonic-gate 1866*7c478bd9Sstevel@tonic-gate if (doall || s_seen || u_seen || p_seen || l_seen || g_seen) { 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate while (pwent = local_getpwent()) { 1869*7c478bd9Sstevel@tonic-gate done = FALSE; 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate /* If no user-specific options were specified, 1872*7c478bd9Sstevel@tonic-gate * include this login-ID */ 1873*7c478bd9Sstevel@tonic-gate if (doall) { 1874*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1875*7c478bd9Sstevel@tonic-gate continue; 1876*7c478bd9Sstevel@tonic-gate } 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate /* If the user specified system login-IDs, 1879*7c478bd9Sstevel@tonic-gate * and this is a system ID, include it */ 1880*7c478bd9Sstevel@tonic-gate if (s_seen) if (isasystemlogin(pwent)) { 1881*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1882*7c478bd9Sstevel@tonic-gate continue; 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate 1885*7c478bd9Sstevel@tonic-gate /* If the user specified user login-IDs, 1886*7c478bd9Sstevel@tonic-gate * and this is a user ID, include it */ 1887*7c478bd9Sstevel@tonic-gate if (u_seen) if (isauserlogin(pwent)) { 1888*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1889*7c478bd9Sstevel@tonic-gate continue; 1890*7c478bd9Sstevel@tonic-gate } 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate /* If the user is asking for login-IDs that have 1893*7c478bd9Sstevel@tonic-gate * no password, and this one has no password, 1894*7c478bd9Sstevel@tonic-gate * include it */ 1895*7c478bd9Sstevel@tonic-gate if (p_seen) if (hasnopasswd(pwent)) { 1896*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1897*7c478bd9Sstevel@tonic-gate continue; 1898*7c478bd9Sstevel@tonic-gate } 1899*7c478bd9Sstevel@tonic-gate 1900*7c478bd9Sstevel@tonic-gate /* 1901*7c478bd9Sstevel@tonic-gate * If specific logins were requested, leaf through 1902*7c478bd9Sstevel@tonic-gate * the list of logins they requested. If this login 1903*7c478bd9Sstevel@tonic-gate * is on the list, include it. 1904*7c478bd9Sstevel@tonic-gate */ 1905*7c478bd9Sstevel@tonic-gate if (l_seen) { 1906*7c478bd9Sstevel@tonic-gate for (plogin = reqloginhead ; !done && plogin ; plogin = plogin->next) { 1907*7c478bd9Sstevel@tonic-gate if (strcmp(pwent->pw_name, plogin->loginname) == 0) { 1908*7c478bd9Sstevel@tonic-gate plogin->found = TRUE; 1909*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1910*7c478bd9Sstevel@tonic-gate done = TRUE; 1911*7c478bd9Sstevel@tonic-gate } 1912*7c478bd9Sstevel@tonic-gate } 1913*7c478bd9Sstevel@tonic-gate if (done) continue; 1914*7c478bd9Sstevel@tonic-gate } 1915*7c478bd9Sstevel@tonic-gate 1916*7c478bd9Sstevel@tonic-gate /* 1917*7c478bd9Sstevel@tonic-gate * If specific groups were requested, leaf through the 1918*7c478bd9Sstevel@tonic-gate * list of login-IDs that belong to those groups. If this 1919*7c478bd9Sstevel@tonic-gate * login-ID is in that list, or its primary group is one 1920*7c478bd9Sstevel@tonic-gate * of those requested, include it. 1921*7c478bd9Sstevel@tonic-gate */ 1922*7c478bd9Sstevel@tonic-gate 1923*7c478bd9Sstevel@tonic-gate if (g_seen) { 1924*7c478bd9Sstevel@tonic-gate for (pgrp = reqgrphead ; !done && pgrp ; pgrp = pgrp->next) 1925*7c478bd9Sstevel@tonic-gate if (pwent->pw_gid == pgrp->groupID) { 1926*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1927*7c478bd9Sstevel@tonic-gate done = TRUE; 1928*7c478bd9Sstevel@tonic-gate } 1929*7c478bd9Sstevel@tonic-gate if (!done && isamember(pwent->pw_name)) { 1930*7c478bd9Sstevel@tonic-gate adddisp(pwent); 1931*7c478bd9Sstevel@tonic-gate done = TRUE; 1932*7c478bd9Sstevel@tonic-gate } 1933*7c478bd9Sstevel@tonic-gate } 1934*7c478bd9Sstevel@tonic-gate if (done) continue; 1935*7c478bd9Sstevel@tonic-gate } 1936*7c478bd9Sstevel@tonic-gate local_endpwent(); 1937*7c478bd9Sstevel@tonic-gate } 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate /* Let the user know about logins they requested that 1940*7c478bd9Sstevel@tonic-gate * don't exist */ 1941*7c478bd9Sstevel@tonic-gate if (l_seen) for (plogin = reqloginhead ; plogin ; plogin = plogin->next) 1942*7c478bd9Sstevel@tonic-gate if (!plogin->found) 1943*7c478bd9Sstevel@tonic-gate wrtmsg(MM_WARNING, MM_NULLACT, MM_NULLTAG, gettext("%s was not found"), plogin->loginname); 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate /* 1946*7c478bd9Sstevel@tonic-gate * Apply group information 1947*7c478bd9Sstevel@tonic-gate */ 1948*7c478bd9Sstevel@tonic-gate applygroup(m_seen); 1949*7c478bd9Sstevel@tonic-gate 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate /* 1952*7c478bd9Sstevel@tonic-gate * Apply password information (only needed if the extended 1953*7c478bd9Sstevel@tonic-gate * set of information has been requested) 1954*7c478bd9Sstevel@tonic-gate */ 1955*7c478bd9Sstevel@tonic-gate if (x_seen || a_seen) applypasswd(); 1956*7c478bd9Sstevel@tonic-gate 1957*7c478bd9Sstevel@tonic-gate 1958*7c478bd9Sstevel@tonic-gate /* 1959*7c478bd9Sstevel@tonic-gate * Generate a report from this display items we've squirreled 1960*7c478bd9Sstevel@tonic-gate * away 1961*7c478bd9Sstevel@tonic-gate */ 1962*7c478bd9Sstevel@tonic-gate 1963*7c478bd9Sstevel@tonic-gate if (t_seen) genlogreport(o_seen, x_seen, a_seen); 1964*7c478bd9Sstevel@tonic-gate else genuidreport(o_seen, x_seen, a_seen); 1965*7c478bd9Sstevel@tonic-gate 1966*7c478bd9Sstevel@tonic-gate /* 1967*7c478bd9Sstevel@tonic-gate * We're through! 1968*7c478bd9Sstevel@tonic-gate */ 1969*7c478bd9Sstevel@tonic-gate exit(0); 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate #ifdef lint 1972*7c478bd9Sstevel@tonic-gate return(0); 1973*7c478bd9Sstevel@tonic-gate #endif 1974*7c478bd9Sstevel@tonic-gate } 1975