From: lezz@merlin.dev.cdx.mot.com (Lezz Giles)
Subject: Re: Filename expansion ("~user")
Keywords: ~user filename expansion
Reply-To: lezz@merlin.dev.cdx.mot.com (Lezz Giles)
Organization: Motorola Codex, Canton, MA
Distribution: usa
Date: Fri, 21 Aug 1992 18:33:18 GMT

In article <1992Aug20.153727.167@cbnews.cb.att.com>, daleske@cbnews.cb.att.com (John D. Daleske) writes:
|>I'm relatively new to Perl and love it.  I've read the recent notes in this
|>notes group and have not found how do one capability that I am trying to
|>use in a Perl script which is the ~user filename expansion.  Following is a test
|>script:
|>
|>$tst1="~daleske";
|>die "${tst1} not a directory" if !(-d ${tst1});
|>opendir(DH, ${tst1});
|>@allfiles = readdir(DH);
|>closedir(DH);
|>print "@allfiles\n";
|>
|>If I set $tst1 to the full pathname it works fine.  I'd like to use the common
|>facility of ~user to avoid needing to know the full path name.  (User home
|>directories do get moved around.)

You'll certainly get the standard response about "~ is only a shell construct
and so you'll need to use a shell to expand it", which is valid enough and
leads to various solutions.  However, some time ago I was working in an
environment where we wanted to write /bin/sh scripts which could access
people's home directories - so we had a semi-standard tool called 'logdir'
which takes a username and returns the home directory, e.g.

$ logdir lezz
/usr/u/a1/lezz

Once you've written this tool, you can add lines like these to your perl prog:

($homedir = `logdir lezz`) || die "Can't find home dir for lezz\n";

$homebin = `logdir lezz` . "/bin";

The source for logdir is:

=================CUT HERE================
/*
 * Program:
 *  logdir
 *
 * Function:
 *  returns the HOME directory of the specified user.
 *
 * Author:
 *  Lezz Giles
 *
 * History:
 *  0.1   4/30  First release.
 */

/*
 * First of all, define all the constants
 */
#define OPTSTRING "HV"
#define HELPSTRING "logdir will return the HOME directory of the given user,\n\
default is your own HOME directory.\n\
Usage: where [-H|V] [user]\n\
\n\
\tOptions:\n\
\t\t-H\tPrint this message\n\
\t\t-V\tPrint version number\n\
\n\
Examples:\n\
\tlogdir jdoe\n\
\t\treturns the HOME directory of jdoe\n\
\n\
\tlogdir\n\
\t\treturns your HOME directory\n"
#define USAGE "[-H|V] [user]"
#define VERSID "0.1"
#define STRLEN 100

/*
 * Next all the include files
 */
#include <errno.h>
#include <stdio.h>
#include <pwd.h>
#include <string.h>

/*
 * Any extern declarations needed...
 */
extern char *getlogin();

/*
 * Now any typedefs
 */
typedef enum {
  FALSE=0,
  TRUE=1
} boolean;

/*
 * Then any global variables
 */
char  *cmd_name;

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

{
  char *path=NULL;
  char option;
  extern int optind, opterr;
  extern char *optarg;
  struct passwd *pwd_entry;

  /*
   * Remember the command name for error messages
   */
  cmd_name = argv[0];

  /*
   * Parse the options...
   */
  while ((option = getopt(argc, argv, OPTSTRING)) != EOF)
    switch (option) {
    case 'H':
      printf("%s\n",HELPSTRING);
      exit(0);
    case 'V':
      printf("%s: Version %s\n",cmd_name, VERSID);
      exit(0);
    }

  /*
   * Now if there is one parameter...
   */
  if (optind == argc-1) {
    if ((pwd_entry = getpwnam(argv[optind])) == NULL) {
      fprintf(stderr,"%s: Cannot find entry for %s\n",cmd_name,argv[optind]);
      exit(1);
    }
  } else if (optind == argc) {
  /*
   * else if there is no parameter...
   */
    char *username;
    if ((username = getlogin()) != NULL) {
      if ((pwd_entry = getpwnam(username)) == NULL) {
	fprintf(stderr,"%s: Cannot find entry for %s\n",cmd_name,username);
	exit(1);
      }
    } else {
      if ((pwd_entry = getpwent(getuid())) == NULL) {
	fprintf(stderr,"%s: Cannot find entry for you\n",cmd_name);
	exit(1);
      }
    }
  } else {
  /*
   * Error condition if there is more than one parameter...
   */
    fprintf(stderr,"%s: Only one username please!\n",cmd_name);
    exit(1);
  }
  printf("%s\n",pwd_entry->pw_dir);
  exit(0);
}






Newsgroups: comp.lang.perl