--- src/bin/pg_passwd/pg_passwd.c.orig	Sat Mar 24 01:54:55 2001
+++ src/bin/pg_passwd/pg_passwd.c	Wed Apr 18 04:54:14 2001
@@ -7,6 +7,12 @@
 #include <errno.h>
 #include <time.h>
 #include <ctype.h>
+
+#if defined(__FreeBSD__)
+#include <pwd.h>  /* defines _PASSWORD_LEN, max # of characters in a password */
+#include <sys/time.h> /* gettimeofday for password salt */
+#endif
+
 #define issaltchar(c)	(isalnum((unsigned char) (c)) || (c) == '.' || (c) == '/')
 
 #ifdef HAVE_TERMIOS_H
@@ -23,18 +29,31 @@
  * We assume that the output of crypt(3) is always 13 characters,
  * and that at most 8 characters can usefully be sent to it.
  *
+ * For FreeBSD, take these values from /usr/include/pwd.h
  * Postgres usernames are assumed to be less than NAMEDATALEN chars long.
  */
+#if defined(__FreeBSD__)
+#define CLEAR_PASSWD_LEN   _PASSWORD_LEN
+#define CRYPTED_PASSWD_LEN _PASSWORD_LEN /* max length, not containing NULL */
+#define SALT_LEN 10
+#else
 #define CLEAR_PASSWD_LEN 8		/* not including null */
 #define CRYPTED_PASSWD_LEN 13	/* not including null */
+#define SALT_LEN 3
+#endif
+
+static unsigned char itoa64[] =		/* 0 ... 63 => ascii - 64 */
+	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
 
 const char *progname;
 
 static void usage(void);
+static void to64(char *s, long v, int n);
 static void read_pwd_file(char *filename);
 static void write_pwd_file(char *filename, char *bkname);
 static void encrypt_pwd(char key[CLEAR_PASSWD_LEN + 1],
-			char salt[3],
+			char salt[SALT_LEN],
 			char passwd[CRYPTED_PASSWD_LEN + 1]);
 static void prompt_for_username(char *username);
 static void prompt_for_password(char *prompt, char *password);
@@ -47,6 +66,15 @@
 	printf("Report bugs to <pgsql-bugs@postgresql.org>.\n");
 }
 
+static void
+to64(char *s, long v, int n)
+{
+	while (--n >= 0) {
+		*s++ = itoa64[v&0x3f];
+		v >>= 6;
+	}
+}
+
 typedef struct
 {
 	char	   *uname;
@@ -154,7 +182,7 @@
 			if (q != NULL)
 				*(q++) = '\0';
 
-			if (strlen(p) != CRYPTED_PASSWD_LEN && strcmp(p, "+") != 0)
+			if (strlen(p) > CRYPTED_PASSWD_LEN && strcmp(p, "+") != 0)
 			{
 				fprintf(stderr, "%s:%d: warning: invalid password length\n",
 						filename, npwds + 1);
@@ -221,15 +249,25 @@
 
 static void
 encrypt_pwd(char key[CLEAR_PASSWD_LEN + 1],
-			char salt[3],
+			char salt[SALT_LEN],
 			char passwd[CRYPTED_PASSWD_LEN + 1])
 {
+#if !defined(__FreeBSD__)
 	int			n;
-
+#endif
 	/* select a salt, if not already given */
 	if (salt[0] == '\0')
 	{
+#if defined(__FreeBSD__)
+		struct timeval tv;
+		srandomdev();
+		gettimeofday(&tv,0);
+		to64(&salt[0], random(), 3);
+		to64(&salt[3], tv.tv_usec, 3);
+		to64(&salt[6], tv.tv_sec, 2);
+		salt[8] = '\0';
 		srand(time(NULL));
+#else
 		do
 		{
 			n = rand() % 256;
@@ -241,6 +279,7 @@
 		} while (!issaltchar(n));
 		salt[1] = n;
 		salt[2] = '\0';
+#endif
 	}
 
 	/* get encrypted password */
@@ -335,7 +374,7 @@
 	char	   *filename;
 	char		bkname[MAXPGPATH];
 	char		username[NAMEDATALEN];
-	char		salt[3];
+	char		salt[SALT_LEN];
 	char		key[CLEAR_PASSWD_LEN + 1],
 				key2[CLEAR_PASSWD_LEN + 1];
 	char		e_passwd[CRYPTED_PASSWD_LEN + 1];
