/* Program to generate shadow or .secure password files by using the
 * new HPUX 10 passwd database (in /tcb/files/auth)
 * K. Lemmens, 10 Dec. 1995.
 * 
 * Don't forget to link with the -lsec option, i.e.:
 * 
 *        cc -O -Ae -o mkshdpw mkshdpw.c -lsec
 */

#include <stdio.h>
#include <sys/types.h>
#include <hpsecurity.h>
#include <prot.h>
#include <string.h> /* strncpy() */
#include <stdlib.h> /* ltoa()    */

#define USE_STDOUT  1

void usage(char *argv[])
{
   fprintf(stderr,"%s <pwdfilename> <type>\n",argv[0]);
   fprintf(stderr,"   type 1 : shadow password (SUN, Linux) files\n");
   fprintf(stderr,"   type 2 : security password (HPUX 9.0) files\n");
   fprintf(stderr,"   - for pwdfilename writes to standard output\n");
   exit(1);
}

/* Next routine generates a Solaris/Linux style passwd file. */

#define SEC2DAY (24 * 60 * 60)

void doshadow(FILE *spwfd,  struct pr_passwd *pw)
{ 
   long last_chg, min_valid, max_valid, warn_exp, max_inactive, lifetime;
   
   last_chg  = pw->ufld.fd_schange / SEC2DAY;
   min_valid = pw->ufld.fd_min / SEC2DAY;

   if (pw->uflg.fg_expire)
     max_valid = pw->ufld.fd_expire / SEC2DAY;
   else if (pw->sflg.fg_expire)
     max_valid = pw->sfld.fd_expire / SEC2DAY;
   else
     max_valid = 0;

   if (pw->uflg.fg_pw_expire_warning)
     warn_exp = pw->ufld.fd_pw_expire_warning / SEC2DAY;
   else if (pw->sflg.fg_pw_expire_warning)
     warn_exp = pw->sfld.fd_pw_expire_warning / SEC2DAY;
   else
     warn_exp = 0;
   
   if (pw->uflg.fg_max_llogin)
     max_inactive = pw->ufld.fd_max_llogin / SEC2DAY;
   else if (pw->sflg.fg_max_llogin)
     max_inactive = pw->sfld.fd_max_llogin / SEC2DAY;
   else
     max_inactive = 0;
   
   if (pw->uflg.fg_lifetime)
   {
      if(pw->ufld.fd_lifetime == 0)
	lifetime = 0;
      else
	lifetime = last_chg + (pw->ufld.fd_lifetime/SEC2DAY);
   }
   else if (pw->sflg.fg_lifetime)
   { 
      if(pw->sfld.fd_lifetime == 0)
	lifetime = 0;
      else
	lifetime = last_chg + (pw->sfld.fd_lifetime/SEC2DAY);
   }
   else
     lifetime = 0;
   
   /* Warning : ltoa returns a pointer that is updated after every call.
      This implies that only the value of the LAST call will be used if you
      try to use more than one ltoa() call in one fprintf statement !!
   */
   fprintf(spwfd,"%s:%s:%d:%d:%s:%d:",
	   pw->ufld.fd_name,
	   pw->ufld.fd_encrypt,
	   last_chg, /* should be in days */
	   min_valid,
	   max_valid ? ltoa(max_valid) : "", /* 0 shouldn't be zero ... */
	   warn_exp);
	      
   fprintf(spwfd,"%s:",
	   max_inactive ? ltoa(max_inactive) : "");
   
   fprintf(spwfd,"%s:%d\n",
	   lifetime ? ltoa(lifetime) : "",0);
}

void doHPsecure(FILE *spwfd, struct pr_passwd *pw)
{
   /*	 fprintf(spwfd,"%s:%s,%s:%u:%u\n", first convert expire !! */
   fprintf(spwfd,"%s:%s:%u:%u\n",
	   pw->ufld.fd_name,
	   pw->ufld.fd_encrypt,
	   
	   /* pw->ufld.fd_expire,  should be converted first !! */
	   pw->ufld.fd_pw_audid,
	   pw->ufld.fd_pw_audflg
	   );
}

main(int argc,char *argv[])
{
   struct pr_passwd  *pw;
   FILE *spwfd;
   char mode = 0;
   
   if(argc <3) usage(argv);
   
   if(strcmp(argv[1],"-") == NULL)
   {
      spwfd = stdout;
      mode=USE_STDOUT;
   }
   else 
     if((spwfd = fopen(argv[1],"w")) == NULL)
   {
      fprintf(stderr,"Opening file %s for write failed\n",argv[1]);
      exit(1);
   }
   
   while((pw = getprpwent()) != NULL)
   {
      if(mode != USE_STDOUT)
	printf("Processing : %s\n",pw->ufld.fd_name);
      
      switch(*argv[2])
      {
       case '1':
	 doshadow(spwfd, pw);
      	 break;
       case '2':  
	 doHPsecure(spwfd, pw);
	 break;
       default: usage(argv);
      }
   }
   
   fclose(spwfd);
   exit(0);
}

