/*************************************************
*    The PMW Music Typesetter - 3rd incarnation  *
*************************************************/

/* Copyright (c) Philip Hazel, 1991 - 2009 */

/* Written by Philip Hazel, starting November 1991 */
/* This file last modified: April 2009 */


/* This file contains initializing and other housekeeping functions. */


#include "rdargs.h"
#include "pmwhdr.h"
#include "outhdr.h"

/* NO_PMWRC is set when --disable-pmwrc is given to "configure". */

#ifndef NO_PMWRC
#include <pwd.h>
#include <unistd.h>
#endif



/*************************************************
*         Read a MIDI translation file           *
*************************************************/

/* These files are short: reading them twice in order to get the correct size
doesn't take much time and saves much hassle. The files contain translation
between names and MIDI voice numbers or names and MIDI "pitches" for untuned
percussion.

Arguments:
  anchor     where to build 
  filename   the file name
  
Returns:     nothing; if the file fails to open, no action is taken  
*/

void 
read_midi_translation(uschar **anchor, uschar *filename)
{
FILE *f = Ufopen(filename, "r");
int length = 0;
uschar *p;
uschar line[60];

if (f == NULL) return;

while (Ufgets(line, 60, f) != NULL)
  {
  line[Ustrlen(line)-1] = 0;
  if (!isdigit(line[0])) continue;  /* Ignore line not starting with a digit */
  length += Ustrlen(line+4) + 2;
  }

if (length == 0) return;            /* No usable text in the file */

/* We store the file in one long byte string. Each name is followed by a zero 
byte and then a binary byte containing its number. */

*anchor = malloc(length+1);
p = *anchor;

rewind(f);
while (Ufgets(line, 60, f) != NULL)
  {
  line[Ustrlen(line)-1] = 0;
  if (!isdigit(line[0])) continue;
  Ustrcpy(p, line+4);
  p += Ustrlen(p) + 1;
  *p++ = Uatoi(line);   
  }
  
/* An empty name marks the end of the list */
 
*p = 0;
fclose(f);
}


/*************************************************
*              Local initialization              *
*************************************************/

/* This is called before argument decoding is done. It is passed the argument 
list, and it has the opportunity of modifying that list. Unless configured not 
to include this code, we search for a .pmwrc file and stuff it on the front of
the arguments. 

Arguments:
  argc          argc from main()
  argv          argv from main()
  newargvptr    where to return the possibly modified argv
  arg_pattern   the argument decoding pattern, to check for validity
  
Returns:        new argc value  
*/

int 
init_command(int argc, char **argv, char ***newargvptr, char *arg_pattern)
{
char **nargv;
int ap = 0;
int nargc = 0;

*newargvptr = nargv = malloc(100 * sizeof(char *));
nargv[nargc++] = argv[ap++];    /* Program name */

/* This will need to be cut out on non-Unix-like systems */

#ifndef NO_PMWRC
if (argv[1] != NULL && strcmp(argv[1], "-norc") == 0)
  {
  ap++;   /* Just skip over -norc if it's first; don't read the file */
  } 
  
else
  {
  struct passwd *pw = getpwuid(geteuid());
  if (pw != NULL)
    { 
    uschar buff[256];
    struct stat statbuf;
  
    Ustrcpy(buff, pw->pw_dir);
    Ustrcat(buff, "/.pmwrc");
    
    if (stat(CS buff, &statbuf) == 0) 
      { 
      arg_result results[64];
      FILE *f = Ufopen(buff, "r");
      
      /* Failure to open a file that statted OK is a hard error */
       
      if (f == NULL) error_moan(41, buff, strerror(errno));
      
      /* Add items from the file */
      
      while (fgets(CS buff, sizeof(buff), f) != NULL)
        {
        uschar *p = buff;
        while (isspace(*p)) p++;
        while (*p != 0)
          {
          uschar *pp = p;
          while (*p != 0 && !isspace(*p)) p++;
          nargv[nargc] = malloc(p - pp + 1);
          Ustrncpy(nargv[nargc], pp, p - pp);
          nargv[nargc++][p-pp] = 0; 
          while (isspace(*p)) p++;    
          }   
        } 
      fclose(f);
      
      /* Check that what we have obtained from the .pmwrc file is a complete
      set of options; we don't want to end up with one that expects a data 
      value, because that would subvert the argument on the real command line, 
      possibly doing damage. */
      
      if (rdargs(nargc, nargv, arg_pattern, results) != 0)
        error_moan(124, results[0].text, results[1].text);  /* Hard */
      }
      
    /* stat() problem other than file not found is serious */
     
    else if (errno != ENOENT) error_moan(41, buff, strerror(errno));  /* Hard */
    } 
  }
#endif   

/* Copy the remaining stuff from the original command line */

while (argv[ap] != NULL) nargv[nargc++] = argv[ap++];
nargv[nargc] = NULL;

return nargc;
}



/*************************************************
*            Relativize a file name              *
*************************************************/

/* The name must be in a buffer that is long enough to take the additional path 
if necessary, because it is modified in place. If the name does not start with
'/', we make it relative to the main input file name.

Argument:    the name under consideration
Returns:     nothing
*/

void 
sys_relativize(uschar *name)
{
uschar temp[256];
int i;
DEBUG(("sys_relativize(%s) entered\n", name));
if (name[0] == '/' || main_filename == NULL) return;
i = Ustrlen(main_filename);
Ustrcpy(temp, name);
while (i > 0 && main_filename[--i] != '/');
if (i != 0) i++;
Ustrncpy(name, main_filename, i);
Ustrcpy(name+i, temp);
DEBUG(("relativized to %s\n", name));
}


/* End of init.c */
