Index: Makefile
===================================================================
RCS file: /net/cy/repository/net/netatalk/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -c -r1.1.1.1 -r1.4
*** Makefile	1997/08/10 21:44:32	1.1.1.1
--- Makefile	1997/08/13 01:16:42	1.4
***************
*** 26,31 ****
--- 26,36 ----
  #INCDIR=/usr/include
  #MANDIR=/usr/man
  
+ # Location of the DES library and include files.  Uncomment and edit
+ # this if you want to support Randnum Exchange as a UAM for afpd.  We
+ # expect libdes.a in $DESDIR/lib and des.h in $DESDIR/include.
+ # DESDIR=/usr
+ 
  # Location of the AFS and Kerberos libraries and include files.  Uncomment
  # and edit these if you want to include AFS or Kerberos support in afpd
  # or Kerberos support in papd.
***************
*** 54,60 ****
  	    SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}"\
  	    ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
  	    DESTDIR="${DESTDIR}" MANDIR="${MANDIR}" \
! 	    AFSDIR="${AFSDIR}" KRBDIR="${KRBDIR}" $@
  
  FRC:
  
--- 59,65 ----
  	    SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}"\
  	    ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
  	    DESTDIR="${DESTDIR}" MANDIR="${MANDIR}" \
! 	    AFSDIR="${AFSDIR}" KRBDIR="${KRBDIR}" DESDIR="${DESDIR}" $@
  
  FRC:
  
Index: etc/Makefile
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** Makefile	1997/08/10 21:44:32	1.1.1.1
--- Makefile	1997/08/10 21:53:03	1.2
***************
*** 10,16 ****
  	    ADDLIBS="${ADDLIBS}" DEFS="${DEFS}" OPTOPTS="${OPTOPTS}" \
  	    SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
  	    ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
! 	    DESTDIR="${DESTDIR}" AFSDIR="${AFSDIR}" KRBDIR="${KRBDIR}"
  
  FRC:
  
--- 10,17 ----
  	    ADDLIBS="${ADDLIBS}" DEFS="${DEFS}" OPTOPTS="${OPTOPTS}" \
  	    SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
  	    ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
! 	    DESTDIR="${DESTDIR}" AFSDIR="${AFSDIR}" KRBDIR="${KRBDIR}" \
! 	    DESDIR="${DESDIR}"
  
  FRC:
  
***************
*** 28,34 ****
  	        SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
  	        ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
  		DESTDIR="${DESTDIR}" AFSDIR="${AFSDIR}" KRBDIR="${KRBDIR}" \
! 		INSTALL="${INSTALL}" install); \
  	done
  
  clean:
--- 29,35 ----
  	        SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
  	        ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
  		DESTDIR="${DESTDIR}" AFSDIR="${AFSDIR}" KRBDIR="${KRBDIR}" \
! 		INSTALL="${INSTALL}" DESDIR="${DESDIR}" install); \
  	done
  
  clean:
Index: etc/afpd/Makefile
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** Makefile	1997/08/10 21:44:32	1.1.1.1
--- Makefile	1997/08/12 01:12:18	1.3
***************
*** 8,18 ****
  	main.o switch.o auth.o volume.o directory.o file.o \
  	enumerate.o desktop.o filedir.o fork.o appl.o gettok.o bprint.o
  
! INCPATH=	-I../../include ${AFSINCPATH} ${KRBINCPATH}
! CFLAGS=	${DEFS} ${AFSDEFS} ${KRBDEFS} ${OPTOPTS} ${INCPATH} \
! 	-DAPPLCNAME -DCRLF # -DDOWNCASE
! LIBS=	-latalk ${AFSLIBS} ${KRBLIBS} ${ADDLIBS}
! LIBDIRS=	-L../../libatalk ${AFSLIBDIRS} ${KRBLIBDIRS}
  TAGSFILE=	tags
  CC=	cc
  INSTALL=	install
--- 8,19 ----
  	main.o switch.o auth.o volume.o directory.o file.o \
  	enumerate.o desktop.o filedir.o fork.o appl.o gettok.o bprint.o
  
! INCPATH=	-I../../include ${AFSINCPATH} ${KRBINCPATH} ${DESINCPATH}
! CFLAGS=	${DEFS} ${AFSDEFS} ${KRBDEFS} ${DESDEFS} ${OPTOPTS} ${INCPATH} \
! 	-DAPPLCNAME
! # -DCRLF -DDOWNCASE
! LIBS=	-latalk ${AFSLIBS} ${KRBLIBS} ${DESLIBS} ${ADDLIBS}
! LIBDIRS=	-L../../libatalk ${AFSLIBDIRS} ${KRBLIBDIRS} ${DESLIBDIRS}
  TAGSFILE=	tags
  CC=	cc
  INSTALL=	install
***************
*** 31,44 ****
  	    AFSINCPATH="-I${AFSDIR}/include"; \
  	    AFSDEFS="-DAFS"; \
  	fi; \
  	${MAKE} ${MFLAGS} CC="${CC}" ADDLIBS="${ADDLIBS}" DEFS="${DEFS}" \
! 	    OPTOPTS="${OPTOPTS}" DESTDIR="${DESTDIR}" \
  	    SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
  	    ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
  	    KRBLIBS="$${KRBLIBS}" KRBLIBDIRS="$${KRBLIBDIRS}" \
  	    KRBINCPATH="$${KRBINCPATH}" KRBDEFS="$${KRBDEFS}" \
  	    AFSLIBS="$${AFSLIBS}" AFSLIBDIRS="$${AFSLIBDIRS}" \
  	    AFSINCPATH="$${AFSINCPATH}" AFSDEFS="$${AFSDEFS}" \
  	    afpd
  
  afpd : ${OBJ} ../../libatalk/libatalk.a
--- 32,53 ----
  	    AFSINCPATH="-I${AFSDIR}/include"; \
  	    AFSDEFS="-DAFS"; \
  	fi; \
+ 	if [ x"${DESDIR}" != x ]; then \
+ 	    DESLIBS="-ldes"; \
+ 	    DESLIBDIRS="-L${DESDIR}/lib"; \
+ 	    DESINCPATH="-I${DESDIR}/include"; \
+ 	    DESDEFS="-DUAM_RNDNUM"; \
+ 	fi; \
  	${MAKE} ${MFLAGS} CC="${CC}" ADDLIBS="${ADDLIBS}" DEFS="${DEFS}" \
! 	    OPTOPTS="${OPTOPTS}" DESTDIR="${DESTDIR}" DESDIR="${DESDIR}" \
  	    SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
  	    ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
  	    KRBLIBS="$${KRBLIBS}" KRBLIBDIRS="$${KRBLIBDIRS}" \
  	    KRBINCPATH="$${KRBINCPATH}" KRBDEFS="$${KRBDEFS}" \
  	    AFSLIBS="$${AFSLIBS}" AFSLIBDIRS="$${AFSLIBDIRS}" \
  	    AFSINCPATH="$${AFSINCPATH}" AFSDEFS="$${AFSDEFS}" \
+ 	    DESLIBS="$${DESLIBS}" DESLIBDIRS="$${DESLIBDIRS}" \
+ 	    DESINCPATH="$${DESINCPATH}" DESDEFS="$${DESDEFS}" \
  	    afpd
  
  afpd : ${OBJ} ../../libatalk/libatalk.a
***************
*** 48,53 ****
--- 57,63 ----
  	${CC} ${CFLAGS} \
  	    -D_PATH_AFPDDEFVOL=\"${ETCDIR}/AppleVolumes.default\" \
  	    -D_PATH_AFPDSYSVOL=\"${ETCDIR}/AppleVolumes.system\" \
+ 	    -D_NAME_AFPDPWFILE=\".randpw\" \
  	    -DVERSION=\"`cat ../../VERSION`\" \
  	    ${CPPFLAGS} -c main.c
  
Index: etc/afpd/auth.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/auth.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -c -r1.1.1.1 -r1.4
*** auth.c	1997/08/10 21:44:32	1.1.1.1
--- auth.c	1997/08/13 00:12:45	1.4
***************
*** 20,25 ****
--- 20,30 ----
  #include <ctype.h>
  #include <pwd.h>
  
+ #ifdef UAM_RNDNUM
+ #include <sys/stat.h>
+ #include <sys/fcntl.h>
+ #endif UAM_RNDNUM
+ 
  #ifdef SOLARIS
  #define SHADOWPW
  #endif SOLARIS
***************
*** 36,48 ****
  #include <netinet/in.h>
  #endif KRB AFS UAM_AFSKRB
  
! #if defined( KRB ) || defined( UAM_AFSKRB )
! #include <krb.h>
  #include <des.h>
- #include <prot.h>
  
  C_Block			seskey;
  Key_schedule		seskeysched;
  static char		realm[ REALM_SZ ];
  #endif KRB UAM_AFSKRB
  
--- 41,57 ----
  #include <netinet/in.h>
  #endif KRB AFS UAM_AFSKRB
  
! #if defined( KRB ) || defined( UAM_AFSKRB ) || defined( UAM_RNDNUM )
  #include <des.h>
  
  C_Block			seskey;
  Key_schedule		seskeysched;
+ #endif KRB UAM_AFSKRB UAM_RNDNUM
+ 
+ #if defined( KRB ) || defined( UAM_AFSKRB )
+ #include <krb.h>
+ #include <prot.h>
+ 
  static char		realm[ REALM_SZ ];
  #endif KRB UAM_AFSKRB
  
***************
*** 106,112 ****
--- 115,125 ----
      { "AFS Kerberos",		afskrb_login,	afskrb_logincont,	0 },
  #endif UAM_AFSKRB
      { "No User Authent",	noauth_login,	NULL,			0 },
+ #ifdef UAM_RNDNUM
+     { "Randnum exchange",       randnum_login,  randnum_logincont,      0 },
+ #endif UAM_RNDNUM
  };
+ 
  struct afp_uams		*afp_uam = NULL;
  
  /*
***************
*** 255,260 ****
--- 268,274 ----
      }
  
      uuid = pwent->pw_uid;
+     username = strdup( pwent->pw_name );
      ngroups = 0;
  
  #ifdef AFS
***************
*** 315,320 ****
--- 329,501 ----
      }
      return;
  }
+ 
+ #ifdef UAM_RNDNUM
+ 
+ #define RND_SESS_ID 511
+ static u_char target[8];
+ static struct passwd	*pwd;
+ static char randname[ 32 ];
+ 
+ randnum_login( ibuf, ibuflen, rbuf, rbuflen )
+     char	*ibuf, *rbuf;
+     int		ibuflen, *rbuflen;
+ {
+     union 
+     {
+       u_int random[2];
+       u_char randnum[8];
+     }
+     randbuf;
+ 
+     time_t seed;
+ 
+     u_short             ashort;
+     int                 i;
+     int			len;
+ 
+     char		*p, *getusershell();
+ 
+     char                *src, *dst;
+     int                 pwfd;
+     struct stat         pwstat;
+     char                pwfile[64];
+     char                userpw[8];
+ 
+     /* Just in case we bail! */
+     *rbuflen = 0;
+ 
+     /* Read login name */
+     len = *ibuf++;
+     if ( len > 31 ) {
+ 	return( AFPERR_PARAM );
+     }
+     bcopy( ibuf, randname, len );
+     randname[ len ] = '\0';
+     username = randname;
+ 
+     syslog( LOG_INFO, "randnum login: %s", username );
+ 
+     /* Do some checks against passwd database */
+     if (( pwd = getpwnam( username )) == NULL ) {
+       return( AFPERR_NOTAUTH );
+     }
+     
+     if ( pwd->pw_shell != NULL && pwd->pw_shell[ 0 ] != '\0' ) {
+       while (( p = getusershell()) != NULL ) {
+ 	if ( strcmp( p, pwd->pw_shell ) == 0 ) {
+ 	  break;
+ 	}
+       }
+       endusershell();
+       if ( p == NULL ) {
+ 	syslog( LOG_INFO, "illegal shell %s for %s",
+ 		pwd->pw_shell, username );
+ 	return( AFPERR_NOTAUTH );
+       }
+     }
+ 
+     /* Build pathname to user's '.randpw' file */
+     if ( (strlen(pwd->pw_dir) + strlen(randpwfile) + 1) > 64 )
+       return( AFPERR_PARAM );
+ 
+     strcpy( pwfile, pwd->pw_dir );
+     strcat( pwfile, "/" );
+     strcat( pwfile, randpwfile );
+ 
+     if ( (pwfd = open(pwfile, O_RDONLY)) < 0 ) {
+ 	syslog( LOG_ERR, "Failed to open %s", pwfile );
+ 	return( AFPERR_NOTAUTH );
+     }
+     
+     if ( fstat( pwfd, &pwstat ) < 0 )
+       return( AFPERR_NOTAUTH );
+ 
+     /* If any of these are true, disallow login: 
+        - not a regular file
+        - gid or uid don't match user
+        - anyone else has permissions of any sort
+        */
+     if ( !S_ISREG(pwstat.st_mode) ||
+ 	 (pwd->pw_uid != pwstat.st_uid) ||
+ 	 (pwd->pw_gid != pwstat.st_gid) ||
+ 	 (pwstat.st_mode & ( S_IRWXG | S_IRWXO )) ) {
+       syslog( LOG_INFO, "Insecure permissions found for %s", pwfile );
+       return( AFPERR_NOTAUTH );
+     }
+     
+     /* Read cleartext password from file and build the key */
+     memset( userpw, 0, DES_KEY_SZ );
+     if ( read( pwfd, userpw, DES_KEY_SZ ) < 0 ) {
+ 	syslog( LOG_ERR, "Failed to read from %s", pwfile );
+ 	return( AFPERR_NOTAUTH );
+     }
+     close( pwfd );
+ 
+     memset( seskey, 0, DES_KEY_SZ );
+     src = userpw;
+     dst = seskey;
+     i = 0;
+     while ( isgraph(*src) && (i < DES_KEY_SZ) ) {
+ 	*dst++ = *src++;
+ 	i++;
+     }
+     
+     /* Generate a 64-bit random number and encrypt using the
+        password as a key. */
+     time( &seed );
+     srand( (int)seed );
+     randbuf.random[0] = rand();
+ 
+     time( &seed );
+     srand( (int)seed );
+     randbuf.random[1] = rand();
+ 
+     key_sched( (des_cblock *)seskey, seskeysched );
+ 
+     ecb_encrypt( (C_Block *)&randbuf, 
+ 		 (C_Block *)target, 
+ 		 seskeysched,
+ 		 DES_ENCRYPT );
+ 
+     /* We don't use a session ID, but client expects something.. */
+     ashort = htons( RND_SESS_ID );
+     bcopy( &ashort, rbuf, sizeof( u_short ) );
+ 
+     rbuf += sizeof( u_short );
+     *rbuflen += sizeof( u_short );
+ 
+     /* Send client the random number also */
+     bcopy( &randbuf, rbuf, sizeof( randbuf ) );
+ 
+     *rbuflen += sizeof( randbuf );
+ 
+     return( AFPERR_AUTHCONT );
+ }
+ 
+ 
+ 
+ randnum_logincont( ibuf, ibuflen, rbuf, rbuflen )
+     char	*ibuf, *rbuf;
+     int		ibuflen, *rbuflen;
+ {
+     u_char              response[8];
+ 
+     /* Skip over header and session ID */
+     ibuf += 4;
+ 
+     /* Grab encrypted response and test it against our copy. */
+     bcopy( ibuf, response, 8 * sizeof( u_char ));
+     
+     *rbuflen = 0;
+     if ( memcmp( target, response, 8 ) == 0 )
+       return( login( pwd->pw_name, pwd->pw_uid, pwd->pw_gid ));
+     else
+       return( AFPERR_NOTAUTH );
+ }
+ 
+ #endif UAM_RNDNUM
+ 
  
  #ifdef KRB
  
Index: etc/afpd/auth.h
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/auth.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** auth.h	1997/08/10 21:44:32	1.1.1.1
--- auth.h	1997/08/10 21:53:04	1.2
***************
*** 16,21 ****
--- 16,24 ----
  };
  #define AU_OFF	(1<<0)
  
+ extern int      randnum_login();
+ extern int      randnum_logincont();
+ 
  extern int	noauth_login();
  #ifdef KRB
  extern int	krb4_login();
Index: etc/afpd/desktop.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/desktop.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** desktop.c	1997/08/10 21:44:32	1.1.1.1
--- desktop.c	1997/08/13 01:16:53	1.3
***************
*** 450,458 ****
  #define hextoint( c )	( isdigit( c ) ? c - '0' : c + 10 - 'a' )
  #define islxdigit(x)	(!isupper(x)&&isxdigit(x))
  
  char *
! utompath( upath )
      char	*upath;
  {
      static char	mpath[ MAXNAMLEN ];
      char	*m, *u;
--- 450,463 ----
  #define hextoint( c )	( isdigit( c ) ? c - '0' : c + 10 - 'a' )
  #define islxdigit(x)	(!isupper(x)&&isxdigit(x))
  
+ /* ProDOS-8 doesn't know about lower case, so if ucflag is set, force
+    alpha chars in file name to upper. If clear, leave them as found.
+    In either case, convert strings of the form ":xy" (xy are valid hex
+    digits), to a single literal character. <shirsch@ibm.net> */
  char *
! utompath( upath, ucflag )
      char	*upath;
+     int         ucflag;
  {
      static char	mpath[ MAXNAMLEN ];
      char	*m, *u;
***************
*** 469,475 ****
  	    h |= hextoint( *u );
  	    *m++ = h;
  	} else {
! 	    *m++ = *u;
  	}
  	u++;
      }
--- 474,483 ----
  	    h |= hextoint( *u );
  	    *m++ = h;
  	} else {
! 	    if ( ucflag )
! 	      *m++ = ( !isupper( *u )) ? toupper( *u ) : *u;
! 	    else
! 	      *m++ = *u;
  	}
  	u++;
      }
Index: etc/afpd/directory.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/directory.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -c -r1.1.1.1 -r1.4
*** directory.c	1997/08/10 21:44:32	1.1.1.1
--- directory.c	1997/08/13 01:16:53	1.4
***************
*** 284,289 ****
--- 284,291 ----
      struct dirent	*de;
      int			bit = 0, aint, isad = 1;
      u_short		ashort;
+     u_char              achar;
+     u_long              along;
  
      if ( ad_open( upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY, 0777, &ad ) < 0 ) {
  	isad = 0;
***************
*** 413,418 ****
--- 415,441 ----
  	    data += sizeof( int );
  	    break;
  
+ 	    /* Client has requested the ProDOS information block.
+ 	       Just pass back the same basic block for all
+ 	       directories. <shirsch@ibm.net> */
+ 	case DIRPBIT_PDINFO :			  /* ProDOS Info Block */
+ 	    achar = 0x0f;
+ 	    bcopy( &achar, data, sizeof( u_char ));
+ 	    data += sizeof( u_char );
+ 
+ 	    achar = 0x0;
+ 	    bcopy( &achar, data, sizeof( u_char ));
+ 	    data += sizeof( u_char );
+ 
+ 	    ashort = htons( 0x0200 );
+ 	    bcopy( &ashort, data, sizeof( u_short ));
+ 	    data += sizeof( u_short );
+ 
+ 	    ashort = htons( 0x0000 );
+ 	    bcopy( &ashort, data, sizeof( u_short ));
+ 	    data += sizeof( u_short );
+ 	    break;
+ 
  	default :
  	    if ( isad ) {
  		ad_close( &ad, ADFLAGS_HF );
***************
*** 619,624 ****
--- 642,654 ----
  		    return( AFPERR_PARAM );
  		}
  	    }
+ 	    break;
+ 	    
+ 	    /* Ignore what the client thinks we should do to the
+ 	       ProDOS information block.  Skip over the data and
+ 	       report nothing amiss. <shirsch@ibm.net> */
+ 	case DIRPBIT_PDINFO :
+ 	    buf += 6;
  	    break;
  
  	default :
Index: etc/afpd/directory.h
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/directory.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** directory.h	1997/08/10 21:44:32	1.1.1.1
--- directory.h	1997/08/10 22:03:01	1.2
***************
*** 49,54 ****
--- 49,55 ----
  #define DIRPBIT_UID	10
  #define DIRPBIT_GID	11
  #define DIRPBIT_ACCESS	12
+ #define DIRPBIT_PDINFO  13			  /* ProDOS Info */
  
  struct maccess {
      u_char	ma_user;
Index: etc/afpd/enumerate.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/enumerate.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** enumerate.c	1997/08/10 21:44:32	1.1.1.1
--- enumerate.c	1997/08/13 01:16:54	1.3
***************
*** 82,87 ****
--- 82,88 ----
      char			*path, *data, *end, *start, dbuf[ MAXPATHLEN ];
      u_short			vid, fbitmap, dbitmap, reqcnt, actcnt = 0;
      u_short			sindex, maxsz, sz = 0;
+     int                         ucflag;
  
      if ( sd.sd_buflen == 0 ) {
  	if (( sd.sd_buf = (char *)malloc( SDBUFBRK )) == NULL ) {
***************
*** 102,107 ****
--- 103,113 ----
  	return( AFPERR_PARAM );
      }
  
+     /* If this volume is to be used by a ProDOS-8 client, the
+        designated bit in the volume flags will be
+        set. <shirsch@ibm.net> */
+     ucflag = vol->v_flags & AFPVOL_TOUPPER;
+ 
      bcopy( ibuf, &did, sizeof( int ));
      ibuf += sizeof( int );
      ibuflen -= sizeof( int );
***************
*** 239,245 ****
  		sd.sd_last += len + 1;
  		continue;
  	    }
! 	    path = utompath( sd.sd_last );
  
  	    for ( dir = curdir->d_child; dir; dir = dir->d_next ) {
  		if ( strcmp( dir->d_name, path ) == 0 ) {
--- 245,251 ----
  		sd.sd_last += len + 1;
  		continue;
  	    }
! 	    path = utompath( sd.sd_last, ucflag );
  
  	    for ( dir = curdir->d_child; dir; dir = dir->d_next ) {
  		if ( strcmp( dir->d_name, path ) == 0 ) {
***************
*** 261,267 ****
  		sd.sd_last += len + 1;
  		continue;
  	    }
! 	    if (( ret = getfilparams( fbitmap, utompath( sd.sd_last ),
  		    curdir, &st, data + 2 * sizeof( u_char ), &esz )) !=
  		    AFP_OK ) {
  		*rbuflen = 0;
--- 267,273 ----
  		sd.sd_last += len + 1;
  		continue;
  	    }
! 	    if (( ret = getfilparams( fbitmap, utompath( sd.sd_last, ucflag ),
  		    curdir, &st, data + 2 * sizeof( u_char ), &esz )) !=
  		    AFP_OK ) {
  		*rbuflen = 0;
Index: etc/afpd/file.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/file.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -c -r1.1.1.1 -r1.4
*** file.c	1997/08/10 21:44:32	1.1.1.1
--- file.c	1997/08/13 01:16:54	1.4
***************
*** 52,57 ****
--- 52,60 ----
      char		*data, *nameoff = 0;
      int			bit = 0, isad = 1, aint;
      u_short		ashort;
+     u_char              achar;
+     u_char              fdType[4];
+     char                test[5];
  
      if ( ad_open( mtoupath( path ), ADFLAGS_HF, O_RDONLY, 0, &ad ) < 0 ) {
  	isad = 0;
***************
*** 187,192 ****
--- 190,250 ----
  	    data += sizeof( int );
  	    break;
  
+ 	    /* Current client needs ProDOS info block for this file.
+ 	       Use simple heuristic and let the Mac "type" string tell
+ 	       us what the PD file code should be.  Everything gets a
+ 	       subtype of 0x0000 unless the original value was hashed
+ 	       to "pXYZ" when we created it.  See IA, Ver 2.
+ 	       <shirsch@ibm.net> */
+ 	case FILPBIT_PDINFO :
+ 	    if ( isad ) {
+ 	      bcopy( ad_entry( &ad, ADEID_FINDERI ), fdType, 4 );
+ 	      
+ 	      if ( bcmp( fdType, "TEXT", 4 ) == 0 ) {
+ 		achar = '\x04';
+ 		ashort = 0x0000;
+ 	      }
+ 	      else if ( bcmp( fdType, "PSYS", 4 ) == 0 ) {
+ 		achar = '\xff';
+ 		ashort = 0x0000;
+ 	      }
+ 	      else if ( bcmp( fdType, "PS16", 4 ) == 0 ) {
+ 		achar = '\xb3';
+ 		ashort = 0x0000;
+ 	      }
+ 	      else if ( bcmp( fdType, "BINA", 4 ) == 0 ) {
+ 		achar = '\x00';
+ 		ashort = 0x0000;
+ 	      }
+ 	      else if ( fdType[0] == 'p' ) {
+ 		achar = fdType[1];
+ 		ashort = (fdType[2] * 256) + fdType[3];
+ 	      } 
+ 	      else {
+ 		achar = '\x00';
+ 		ashort = 0x0000;
+ 	      }
+ 	    } 
+ 	    else {
+ 	      achar = '\x00';
+ 	      ashort = 0x0000;
+ 	    }
+ 	    
+ 	    bcopy( &achar, data, sizeof( u_char ));
+ 	    data += sizeof( u_char );
+ 
+ 	    achar = 0x00;
+ 	    bcopy( &achar, data, sizeof( u_char ));
+ 	    data += sizeof( u_char );
+ 
+ 	    bcopy( &ashort, data, sizeof( u_short ));
+ 	    data += sizeof( u_short );
+ 
+ 	    ashort = 0x0000;
+ 	    bcopy( &ashort, data, sizeof( u_short ));
+ 	    data += sizeof( u_short );
+ 	    break;
+ 
  	default :
  	    if ( isad ) {
  		ad_close( &ad, ADFLAGS_HF );
***************
*** 339,344 ****
--- 397,405 ----
      u_long		along;
      time_t		atime;
      struct utimbuf	ut;
+     u_char              achar;
+     u_char              *fdType;
+     u_char              xyy[4];
  
      if ( ad_open( mtoupath( path ), ADFLAGS_HF, O_RDWR|O_CREAT,
  	    0666, &ad ) < 0 ) {
***************
*** 409,414 ****
--- 470,518 ----
  	    }
  	    bcopy( buf, ad_entry( &ad, ADEID_FINDERI ), 32 );
  	    buf += 32;
+ 	    break;
+ 
+ 	    /* Client needs to set the ProDOS file info for this file.
+ 	       Use defined strings for the simple cases, and convert
+ 	       all else into pXYY per Inside Appletalk.  Always set
+ 	       the creator as "pdos". <shirsch@ibm.net> */
+ 	case FILPBIT_PDINFO :
+ 	    bcopy( buf, &achar, sizeof( u_char ));
+ 	    buf += 2 * sizeof( u_char );
+ 	  
+ 	    bcopy( buf, &ashort, sizeof( u_short ));
+ 	    ashort = ntohs( ashort );
+ 	    buf += 2 * sizeof( u_char );
+ 
+ 	    switch ( (unsigned int) achar )
+ 	      {
+ 	      case 0x04 :
+ 		fdType = ( u_char *) "TEXT";
+ 		break;
+ 		
+ 	      case 0xff :
+ 		fdType = ( u_char *) "PSYS";
+ 		break;
+ 
+ 	      case 0xb3 :
+ 		fdType = ( u_char *) "PS16";
+ 		break;
+ 
+ 	      case 0x00 :
+ 		fdType = ( u_char *) "BINA";
+ 		break;
+ 
+ 	      default :
+ 		xyy[0] = ( u_char ) 'p';
+ 		xyy[1] = achar;
+ 		xyy[2] = ( u_char ) ( ashort >> 8 ) & 0xff;
+ 		xyy[3] = ( u_char ) ashort & 0xff;
+ 		fdType = xyy;
+ 		break;
+ 	      }
+ 	    
+ 	    bcopy( fdType, ad_entry( &ad, ADEID_FINDERI ), 4 );
+ 	    bcopy( "pdos", ad_entry( &ad, ADEID_FINDERI ) + 4, 4 );
  	    break;
  
  	default :
Index: etc/afpd/file.h
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/file.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** file.h	1997/08/10 21:44:32	1.1.1.1
--- file.h	1997/08/11 00:55:01	1.3
***************
*** 34,39 ****
--- 34,40 ----
  #define FILPBIT_FNUM	8
  #define FILPBIT_DFLEN	9
  #define FILPBIT_RFLEN	10
+ #define FILPBIT_PDINFO  13			  /* ProDOS Info */
  
  #define ATTRBIT_SETCLR	(1<<15)
  #define FILEIOFF_CREATE	0
Index: etc/afpd/globals.h
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/globals.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** globals.h	1997/08/10 21:44:32	1.1.1.1
--- globals.h	1997/08/11 00:55:03	1.3
***************
*** 10,15 ****
--- 10,16 ----
  extern char		*username;
  extern char		*defaultvol;
  extern char		*systemvol;
+ extern char             *randpwfile;
  extern struct vol	*volumes;
  extern struct dir	*curdir;
  extern char		getwdbuf[];
Index: etc/afpd/main.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/main.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** main.c	1997/08/10 21:44:32	1.1.1.1
--- main.c	1997/08/11 00:55:04	1.3
***************
*** 49,54 ****
--- 49,55 ----
  int	connections = 5;
  char	*defaultvol = _PATH_AFPDDEFVOL;
  char	*systemvol = _PATH_AFPDSYSVOL;
+ char    *randpwfile = _NAME_AFPDPWFILE;
  char	*guest = "nobody";
  char	*Obj, *Type = "AFPServer", *Zone = "*";
  char	*version = VERSION;
Index: etc/afpd/volume.c
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/volume.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** volume.c	1997/08/10 21:44:32	1.1.1.1
--- volume.c	1997/08/13 01:16:55	1.3
***************
*** 81,88 ****
  	if (( st.st_mode & S_IFDIR ) == 0 ) {
  	    continue;		/* not a dir */
  	}
! 
! 	*data++ = 0;
  	len = strlen( volume->v_name );
  	*data++ = len;
  	bcopy( volume->v_name, data, len );
--- 81,97 ----
  	if (( st.st_mode & S_IFDIR ) == 0 ) {
  	    continue;		/* not a dir */
  	}
! 	
! 	/* Apple 2 clients running ProDOS-8 expect one volume to have
! 	   bit 0 of this byte set.  They will not recognize anything
! 	   on the server unless this is the case.  I have not
! 	   completely worked this out, but it's related to booting
! 	   from the server.  Support for that function is a ways
! 	   off.. <shirsch@ibm.net> */
! 	if ( volume->v_flags & AFPVOL_A2VOL )
! 	  *data++ = (u_char) 1;
! 	else
! 	  *data++ = 0;
  	len = strlen( volume->v_name );
  	*data++ = len;
  	bcopy( volume->v_name, data, len );
***************
*** 103,110 ****
      return( AFP_OK );
  }
  
! creatvol( path, name )
      char	*path, *name;
  {
      struct vol	*volume;
      int		vlen;
--- 112,123 ----
      return( AFP_OK );
  }
  
! /* Allow volume-specific flag setting to be passed in on mount. Not
!    specific to P8; this will be needed for parameter support from the
!    Applevolumes file. */
! creatvol( path, name, flags )
      char	*path, *name;
+     int         flags;
  {
      struct vol	*volume;
      int		vlen;
***************
*** 148,154 ****
  
      volume->v_dir = NULL;
      volume->v_did = NULL;
!     volume->v_flags = 0;
  #ifdef __svr4__
      volume->v_qfd = -1;
  #else __svr4__
--- 161,169 ----
  
      volume->v_dir = NULL;
      volume->v_did = NULL;
! 
!     /* Start with flag settings parsed from AppleVolumes */
!     volume->v_flags = flags;
  #ifdef __svr4__
      volume->v_qfd = -1;
  #else __svr4__
***************
*** 210,215 ****
--- 225,231 ----
      char		*u, *p;
      int			quoted = 0;
      struct passwd	*pw;
+     int                 flags;
  
      strcpy( path, p1 );
      if ( p2 != NULL ) {
***************
*** 251,257 ****
  
  	case '/' :
  	    parseline( sizeof( volname ) - 1, volname );
! 	    creatvol( path, volname );
  	    break;
  
  	case '.' :
--- 267,280 ----
  
  	case '/' :
  	    parseline( sizeof( volname ) - 1, volname );
! 
! 	    /* FIXME!! Real crude and quick way to grab a
! 	       user-supplied integer in [0..3] and shift it into the
! 	       ProDOS bits of the volume flag.  Obviously some room
! 	       for improvement here.  <shirsch@ibm.net> */
! 	    parseline( sizeof( tmp ) - 1, tmp );
! 	    flags = ( atoi ( tmp ) & 3 ) << 5;
! 	    creatvol( path, volname, flags );
  	    break;
  
  	case '.' :
***************
*** 543,550 ****
      }
  #endif linux
  
!     *bfree = min( *bfree, 0x7fffffff );
!     *btotal = min( *btotal, 0x7fffffff );
      vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_USTATFS;
      return( AFP_OK );
  }
--- 566,584 ----
      }
  #endif linux
  
!     /* If this is designated as a ProDOS-8 volume, make sure to avoid
!        wrap-around by capping reported free space under 64k blocks. */
!     if ( vol->v_flags & AFPVOL_A2VOL )
!         {
! 	  *bfree = min( *bfree, 0x01fffe00 );
! 	  *btotal = min( *btotal, 0x01fffe00 );
! 	} 
!     else 
!         {
! 	  *bfree = min( *bfree, 0x7fffffff );
! 	  *btotal = min( *btotal, 0x7fffffff );
! 	}
!     
      vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_USTATFS;
      return( AFP_OK );
  }
Index: etc/afpd/volume.h
===================================================================
RCS file: /net/cy/repository/net/netatalk/etc/afpd/volume.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** volume.h	1997/08/10 21:44:32	1.1.1.1
--- volume.h	1997/08/13 01:16:55	1.3
***************
*** 30,35 ****
--- 30,53 ----
  #define AFPVOL_USTATFS	(2<<2)
  #define AFPVOL_UQUOTA	(4<<2)
  
+ /* If I may be so bold...  Grab some unused flag bits to control
+    behavior towards Apple 2 clients.  These are configured by placing
+    a digit in [0..3] after the exported Apple name in AppleVolumes -
+    delimited with whitespace.
+ 
+    0 or none = Normal netatalk defaults
+    1         = This volume to be compatible with ProDOS-8
+    2         = Force all file and directory names to uppercase
+                from clients point of view.  Note that this
+ 	       only really makes sense when the volume will
+ 	       not be shared with GSOS or Mac.
+    3         = Both of the above..
+ 
+    <shirsch@ibm.net> */
+ #define AFPVOL_A2MASK   (3<<5)
+ #define AFPVOL_A2VOL    (1<<5)
+ #define AFPVOL_TOUPPER  (2<<5)
+ 
  #define AFPVOLSIG_FIX	2
  
  #define VOLPBIT_ATTR	0
