/**
   @file      passwdshadow.c
   @author    Mitch Richling <http://www.mitchr.me/>
   @Copyright Copyright 1996 by Mitch Richling.  All rights reserved.
   @brief     UNIX password and shadow password degrees@EOL
   @Keywords  UNIX password shadow passwd getpwuid
   @Std       ISOC POSIX UNIX98 BSD4.3 SYSV3

              This is an example program intended to illustrate how to
              query most UNIX versions for password and shadow
              password information.  This has been tested on Solaris
              and Linux.

   @Tested    
              - Solaris 2.8
              - BROKEN: MacOS X.2 (no shadow API)
              - Linux (RH 7.3)
*/

#include <pwd.h>                /* UNIX passwd     POSIX */
#include <sys/types.h>          /* UNIX types      POSIX */
#include <stdlib.h>             /* Standard Lib    ISOC  */
#include <shadow.h>             /* UNIX shadow DB  SYSV  */
#include <unistd.h>             /* UNIX std stf    POSIX */
#include <stdio.h>              /* I/O lib         ISOC  */

int main(int argc, char *argv[]);

int main(int argc, char *argv[]) {
  struct passwd *pwEnt;
  struct spwd *spEnt;
  char pwSalt[3];
  uid_t theUid, theEuid;

  /* Figure out who the user is running this thing. */
  theUid = getuid();
  theEuid = geteuid();
  printf("uid: %ld  euid: %ld\n", (long)theUid, (long)theEuid);

  /* Get the password record for the user. */
  pwEnt = getpwuid(theUid);
  if(pwEnt == NULL) {
    printf("ERROR: getpwuid.\n");
    exit(1);
  } /* end if */
  printf("pw_name:   %s\n", pwEnt->pw_name);
  printf("pw_passwd: %s\n", pwEnt->pw_passwd);
  printf("pw_uid:    %ld\n", (long)pwEnt->pw_uid);
  printf("pw_gid:    %ld\n", (long)pwEnt->pw_gid);
  printf("pw_gecos:  %s\n", pwEnt->pw_gecos);
  printf("pw_dir:    %s\n", pwEnt->pw_dir);
  printf("pw_shell:  %s\n", pwEnt->pw_shell);

  /* Get the shadow information for this user. */
  spEnt = getspnam(pwEnt->pw_name);
  if(spEnt == NULL) {
    printf("ERROR: getspnam.\n");
    exit(1);
  } /* end if */
  printf("sp_namp:    %s\n", spEnt->sp_namp);
  printf("sp_pwdp:    %s\n", spEnt->sp_pwdp);
  printf("sp_lastchg: %ld\n", (long)spEnt->sp_lstchg);
  printf("sp_min:     %ld\n", (long)spEnt->sp_min);
  printf("sp_max:     %ld\n", (long)spEnt->sp_max);
  printf("sp_warn:    %ld\n", (long)spEnt->sp_warn);
  printf("sp_intact:  %ld\n", (long)spEnt->sp_inact);
  printf("sp_expire:  %ld\n", (long)spEnt->sp_expire);
  printf("sp_flag:    %ld\n", (long)spEnt->sp_flag);

  /* Extract the salt from the encrypted password. */
  pwSalt[0] = (spEnt->sp_pwdp)[0];
  pwSalt[1] = (spEnt->sp_pwdp)[1];
  pwSalt[2] = '\0';
  printf("Salt: %s\n", pwSalt);

  return 0;
} /* end func main */

