Exemple #1
0
static
void wildcard_router_receive(receiver_t* self,
			     bytecode_stream_t* message, context_t* context)
{
    router_t* router = (router_t*) self;
    bytecode_t* selector = message->pop(message);

    if(selector && selector->verb == route_atom) {
	bytecode_t* destination = message->pop(message);

	if(!destination) {
	    WARNING1("no destination provided.");
	    return;
	} else {
	    atom_t dest = destination->verb;

	    TRACE2("routing towards selector '%s' requested.", atom_get_cstring_value(dest));
	    if(dest == star_atom) {
		map_iterator_t i; 
		map_value_t pslot = NULL_MAP_VALUE;
		
		map_get_iterator(&router->children, &i);
		
		while (map_value_is_there (pslot = map_iterator_next(&i))) {
		    router_slot_t* slot = map_value_obtain (pslot);
		    // clone each message
		    bytecode_stream_t* message_copy = bytecode_stream_instantiate_toplevel(NULL);
		    message_copy->copy(message_copy, message);

		    TRACE2("sending event to slot: '%s'", 
			   atom_get_cstring_value(slot->name));
		    if(!router_route(slot, message_copy, context)) {
			WARNING2("route '%s' not defined.", 
				 atom_get_cstring_value(slot->name));
		    }
		}
		map_iterator_destroy (&i);
		map_iterator_retire (&i);

		bytecode_stream_retire (message);
	    } else {
		if(!router_route(get_slot(router, dest), message, context)) {
		    WARNING2("route '%s' not defined.", 
			     atom_get_cstring_value(dest));
		}
	    }
	}
    } else {
	message->push(message, selector);
	router->receive_backup(self, message, context);
    }
}
Exemple #2
0
static message_node_t *receiver_peek_pending(receiver_t *self, atom_t selector,
                                             context_t *context)
{
    message_fifo_t *fifo = get_fifo(self, selector);
    node_iterator_t it;
    message_node_t *head = NULL;

    if (fifo == NULL) {
        WARNING2("fifo for selector '%s' inexistant.",
                 atom_get_cstring_value(selector));
        return NULL;
    } else if (fifo->end == NULL) {
        return NULL;
    }

    if (get_node_iterator_end(fifo, &it)) {
        message_node_t *current;
        while ((current = node_iterator_prev(&it))) {
            TRACE2("ms: %f.", current->context->ms);
            if (!current->dispatched_p &&
                current->context->is_in(current->context, context)) {
                head = current;
                break;
            }
        }
    }

    return head;
}
Exemple #3
0
static void receiver_eval_pending(receiver_t *self, atom_t selector,
                                  context_t *context)
{
    message_fifo_t *fifo = get_fifo(self, selector);
    node_iterator_t it;

    if (fifo == NULL) {
        WARNING2("fifo for selector '%s' inexistant.",
                 atom_get_cstring_value(selector));
        return;
    }

    TRACE2("eval_pending for fifo: '%s'", atom_get_cstring_value(fifo->atom));
    if (fifo->end == NULL) {
        return;
    }

    if (get_node_iterator_end(fifo, &it)) {
        message_node_t *current;
        while ((current = node_iterator_prev(&it))) {
            TRACE2("current: %f", current->context->ms);
            if (!current->dispatched_p) {
                if (current->context->is_in(current->context, context)) {
                    self->eval(self, current->bytecodes, current->context);
                    current->dispatched_p = 1;
                } else {
                    break;
                }
            }
        }
    }
}
static int
write_default_config(void)
{
	int i = 0;
	int err = 0;
	FILE *f = NULL;

	create_save_dir();
	f = open_savedat("config", "wt");
	if (!f)
	{
		WARNING4("can't write defaults to file `%s/%s': %s\n",
				options.dir_savegame, "config", strerror(errno));
		return -1;
	}
	else
		NOTICE3("written defaults to file `%s/%s'",
				options.dir_savegame, "config");

	fprintf(f, "# This is template configuration file for %s\n",
		PACKAGE_STRING);
	fprintf(f, "# Comments start with '#' sign and span whole line.\n");
	fprintf(f, "# Non comment lines should look like:\n");
	fprintf(f, "# variable_name variable_value\n\n");
	fprintf(f, "# (be sure to remove the #)\n\n");
	for (i = 0; i < (int) ARRAY_LENGTH(config_strings); ++i)
		fprintf(f, "# %s\n# %s\n\n",
			config_strings[i].comment, config_strings[i].name);
	err = ferror(f);
	if (err)
		WARNING2("read error: %s", strerror(errno));
	fclose(f);
	return err;
}
Exemple #5
0
static
void router_receive(receiver_t* self,
		    bytecode_stream_t* message, context_t* context)
{
    router_t* router = (router_t*) self;
    bytecode_t* selector = message->pop(message);

    if(selector && selector->verb == route_atom) {
	bytecode_t* destination = message->pop(message);

	if(!destination) {
	    WARNING1("no destination provided.");
	    return;
	} else {
	    atom_t dest = destination->verb;
	    if(!router_route(get_slot(router, dest), message, context)) {
		WARNING2("route '%s' not defined.", 
			 atom_get_cstring_value(dest));
	    }
	}
    } else {
	message->push(message, selector);
	router->receive_backup(self, message, context);
    }
}
Exemple #6
0
string
mktex_var_expand P1C(const_string, src)
{
  const_string s;
  string ret;
  fn_type expansion;
  expansion = fn_init ();
  
  /* Copy everything but variable constructs.  */
  for (s = src; *s; s++) {
    if (IS_VAR_START (*s)) {
      s++;

      /* Three cases: `$VAR', `${VAR}', `$<anything-else>'.  */
      if (IS_VAR_CHAR (*s)) {
        /* $V: collect name constituents, then expand.  */
        const_string var_end = s;

        do {
          var_end++;
        } while (IS_VAR_CHAR (*var_end));

        var_end--; /* had to go one past */
        expand (&expansion, s, var_end);
        s = var_end;

      } else if (IS_VAR_BEGIN_DELIMITER (*s)) {
        /* ${: scan ahead for matching delimiter, then expand.  */
        const_string var_end = ++s;

        while (*var_end && !IS_VAR_END_DELIMITER (*var_end))
          var_end++;

        if (! *var_end) {
          WARNING1 ("%s: No matching } for ${", src);
          s = var_end - 1; /* will incr to null at top of loop */
        } else {
          expand (&expansion, s, var_end - 1);
          s = var_end; /* will incr past } at top of loop*/
        }

      } else {
        /* $<something-else>: error.  */
        WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s);
        /* Just ignore those chars and keep going.  */
      }
    } else
     fn_1grow (&expansion, *s);
  }
  fn_1grow (&expansion, 0);
          
  ret = FN_STRING (expansion);
  return ret;
}
Exemple #7
0
string
ps_encoding_name (charcode_type n)
{
  string ret = ENCODING_CHAR_NAME (encoding, n);
  if (ret == NULL)
    {
      WARNING2 ("%d: No such character number in encoding scheme `%s'",
                n, ENCODING_SCHEME_NAME (encoding));
      ret = ".notdef";
    }
  return ret;
}
Exemple #8
0
/** Read sequence name array from file
 *
 * \param keyname Name of the file to read from
 * \param tbl Pointer to the tblinfo to fill
 */
void
frm_read_tbl(char *keyname, struct tblinfo *tbl)
{
    FILE *fin;
    int lo, hi;
    int idx;
    char *p;
    size_t max_name_len = 8;
    char name[max_name_len + 1];

    if ((fin = sOpen(keyname, "rb", 0)) == NULL) {
        WARNING2("Unable to open file '%s'.", keyname);
        return;
    }

    /* get number of sequence keys */
    lo = getc(fin);
    hi = getc(fin);
    tbl->count = (hi << 8) | lo;

    /* alloc enough memory for all the sequence names */
    tbl->strings = (char **)xcalloc(tbl->count, sizeof * tbl->strings);

    idx = 0;

    while (fread(name, 1, max_name_len, fin) == max_name_len) {
        name[max_name_len] = '\0';

        for (p = name; *p; p++) {
            *p = tolower(*p);

            if (*p == '#') {
                *p = '_';
            }
        }

        TRACE4("Found name '%s' at position %d in file %s.", name, idx, keyname);
        tbl->strings[idx++] = xstrdup(name);
    }

    /* now idx is number of read strings */
    if (tbl->count != idx) {
        tbl->count = idx;
        tbl->strings = (char **)xrealloc(tbl->strings, sizeof * tbl->strings);
    }

    fclose(fin);
}
// Ensure that the specified music track is in memory, loading it if required
void music_load(enum music_track track)
{
	char name[80] = "";
	FILE * midi_f;
	char * midi_data = NULL;
	size_t fileLength;
	int i;
	OSStatus rv;
	
	// Don't (try to) load the track twice
	if (music_files[track].sequence_loaded || music_files[track].unplayable)
		return;
	
	// Find the name for this track
	for (i = 0; music_key[i].track != M_MAX_MUSIC; i++) {
		if (music_key[i].track == track && music_key[i].name) {
			snprintf(name, sizeof(name), "%s.MID", music_key[track].name);
			break;
		}
	}
	
	// Bail out if this track isn't known
	if (strlen(name) == 0) {
		music_files[track].unplayable = 1;
		return;		
	}
	
	// Read the MIDI file into memory
	midi_f = sOpen(name, "rb", FT_MIDI);
	if (midi_f != NULL) {
		fileLength = fread_dyn(&midi_data, &fileLength, midi_f);
		fclose(midi_f);
	}
	
	if (midi_data == NULL) {
		WARNING2("could not read MIDI file `%s'", name);
		music_files[track].unplayable = 1;
		return;
	}
	
	// Initialize the sequence
	rv = NewMusicSequence(&music_files[track].sequence);
	if (rv == 0) {
		// Try to load the sequence out of this buffer
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 /* this is deprecated, but works back to 10.3 */        
		rv = MusicSequenceLoadSMFDataWithFlags(music_files[track].sequence, CFDataCreate(NULL, (UInt8*)midi_data, fileLength), 0);
#else  /* not deprecated, but requires 10.5 or later */
        rv = MusicSequenceFileLoadData(music_files[track].sequence, CFDataCreate(NULL, (UInt8*)midi_data, fileLength), 0, 0);
#endif
	}
		
	// Regardless, free the buffer we read off disk, if any
	free(midi_data);
	
	// Did it work?
	if (rv) {
		WARNING2("could not understand MIDI file `%s'", name);
		music_files[track].unplayable = 1;		
	} else {
		music_files[track].sequence_loaded = 1;
	}
}
Exemple #10
0
static void
map_file_parse (kpathsea kpse, const_string map_filename)
{
  char *orig_l;
  unsigned map_lineno = 0;
  FILE *f = xfopen (map_filename, FOPEN_R_MODE);

  if (kpse->record_input)
    kpse->record_input (map_filename);

  while ((orig_l = read_line (f)) != NULL) {
    string filename;
    string l = orig_l; /* save for free() */
    string comment_loc = strrchr (l, '%');
    if (!comment_loc) {
      comment_loc = strstr (l, "@c");
    }

    /* Ignore anything after a % or @c.  */
    if (comment_loc)
      *comment_loc = 0;

    map_lineno++;

    /* Skip leading whitespace so we can use strlen below.  Can't use
       strtok since this routine is recursive.  */
    while (*l && ISSPACE (*l))
      l++;

    /* If we don't have any filename, that's ok, the line is blank.  */
    filename = token (l);
    if (filename) {
      string alias = token (l + strlen (filename));

      if (STREQ (filename, "include")) {
        if (alias == NULL) {
          WARNING2 ("%s:%u: Filename argument for include directive missing",
                    map_filename, map_lineno);
        } else {
          string include_fname = kpathsea_path_search (kpse,
                                   kpse->map_path, alias, false);
          if (include_fname) {
            map_file_parse (kpse, include_fname);
            if (include_fname != alias)
              free (include_fname);
          } else {
            WARNING3 ("%s:%u: Can't find fontname include file `%s'",
                      map_filename, map_lineno, alias);
          }
          free (alias);
          free (filename);
        }

      /* But if we have a filename and no alias, something's wrong.  */
      } else if (alias == NULL) {
        WARNING3 ("%s:%u: Fontname alias missing for filename `%s'",
                  map_filename, map_lineno, filename);
        free (filename);

      } else {
        /* We've got everything.  Insert the new entry.  They were
           already dynamically allocated by token(), so don't bother
           with xstrdup.  */
          hash_insert_normalized (&(kpse->map), alias, filename);
      }
    }

    free (orig_l);
  }

  xfclose (f, map_filename);
}
Exemple #11
0
string
kpathsea_var_expand (kpathsea kpse, const_string src)
{
  const_string s;
  string ret;
  fn_type expansion;
  expansion = fn_init ();

  /* Copy everything but variable constructs.  */
  for (s = src; *s; s++) {
    if (IS_VAR_START (*s)) {
      s++;

      /* Three cases: `$VAR', `${VAR}', `$<anything-else>'.  */
      if (IS_VAR_CHAR (*s)) {
        /* $V: collect name constituents, then expand.  */
        const_string var_end = s;

        do {
          var_end++;
        } while (IS_VAR_CHAR (*var_end));

        var_end--; /* had to go one past */
        if (!expand (kpse, &expansion, s, var_end)) {
          /* If no expansion, include the literal $x construct,
             so filenames containing dollar signs can be read.
             The first +1 is to get the full variable name,
             the other +1 is to get the dollar sign; we've moved past it.  */
          fn_grow (&expansion, s - 1, var_end - s + 1 + 1);
        }
        s = var_end;

      } else if (IS_VAR_BEGIN_DELIMITER (*s)) {
        /* ${: scan ahead for matching delimiter, then expand.  */
        const_string var_end = ++s;

        while (*var_end && !IS_VAR_END_DELIMITER (*var_end)) {
#if defined(WIN32)
          if (kpathsea_IS_KANJI(kpse, var_end))
            var_end++;
#endif
          var_end++;
        }

        if (! *var_end) {
          WARNING1 ("kpathsea: %s: No matching } for ${", src);
          s = var_end - 1; /* will incr to null at top of loop */
        } else {
          expand (kpse, &expansion, s, var_end - 1);
          s = var_end; /* will incr past } at top of loop*/
        }

      } else {
        /* $<something-else>: warn, but preserve characters; again, so
           filenames containing dollar signs can be read.  */
        WARNING2 ("kpathsea: %s: Unrecognized variable construct `$%c'",
                  src, *s);
        fn_grow (&expansion, s - 1, 2);  /* moved past the $  */
      }
    } else
     fn_1grow (&expansion, *s);
  }
  fn_1grow (&expansion, 0);

  ret = FN_STRING (expansion);
  return ret;
}
Exemple #12
0
ps_font_info_type
ps_init (string font_name, tfm_global_info_type tfm_info)
{
  string base_encoding, mapping;
  ps_font_info_type ret;

  libfile_start ("postscript", "map");

  while ((mapping = libfile_line ()) != NULL
         && !STREQ (font_name, strtok (mapping, " \t")))
    ;

  libfile_close ();

  if (mapping == NULL)
    {
      WARNING2 ("%s: No information for font `%s'; using defaults",
                "postscript.map", font_name);
      ret.font_name = xstrdup (font_name);
      base_encoding = "adobestd";
    }
  else
    { /* We found it; dissect the rest of the line for what we need.
         The second word is the full PostScript font name, e.g.,
         `Times-BoldItalic'.  The third word is the base filename for
         the encoding vector.  */
      ret.font_name = strtok (NULL, " \t");
      base_encoding = strtok (NULL, " \t");
    }

  /* Read the encoding file.  We don't store this in the structure we
     return, since we've never needed it.  Perhaps we should anyway.  */
  encoding = read_encoding_file (base_encoding);

  /* The family name would be `Times' for the font `Times-BoldItalic', but it's
     `Helvetica' for `Helvetica'.  (It should be `Lucida' for
     `LucidaBright-Italic', but we don't handle that case -- maybe
     optional arg in mapping file?)  */
  ret.family_name = strchr (ret.font_name, '-');
  if (ret.family_name == NULL)
    ret.family_name = ret.font_name;  /* E.g., `Helvetica'.  */
  else
    ret.family_name
      = substring (ret.font_name, 0, ret.family_name - 1- ret.font_name);

  /* If the font name contains `Bold', that's the weight.  Otherwise,
     guess `Medium'.  (I don't know of any programs that actually care
     about this.  Again, perhaps it should be an optional arg in the
     mapping file.)  */
  ret.weight = strstr (ret.font_name, "Bold") ? "Bold" : "Medium";

  /* We should be able to compute the italic angle by somehow looking at
     the characters.  bdftops.ps rotates the `I' and takes the angle
     that minimizes the width, for example.  xx */
  ret.italic_angle = 0;
  
  /* Monospaced fonts have no stretch or shrink in their interword
     space (or shouldn't), but they do have a nonzero interword space
     (math fonts sometimes have all their interword space parameters set
     to zero).  */
  ret.monospace_p
    = TFM_FONT_PARAMETER (tfm_info, TFM_STRETCH_PARAMETER) == 0.0
      && TFM_FONT_PARAMETER (tfm_info, TFM_SPACE_PARAMETER) != 0.0;

  /* What might be a good way to compute this one?  xx */
  ret.underline_position = -100;
  
  /* Here we can use the rule thickness from the TFM file, if it's set.
     Otherwise, just guess.  (A better guess would be the dominant stem
     width in the font.)  */
  ret.underline_thickness
    = TFM_FONT_PARAMETER (tfm_info, TFM_DEFAULTRULETHICKNESS_PARAMETER)
      ? : 50;

  /* What to do about the UniqueID's?  Actually, I'm not sure they
     should really be necessary.  Adobe wants people to register their
     fonts to get a UniqueID from them, which is semi-reasonable, but a
     lot of trouble.  We just omit them.  */
  ret.unique_id = 0;
  
  /* If there is no version number in the TFM file, then just say it's
     version 0.  */
  ret.version = TFM_FONT_PARAMETER (tfm_info, TFM_VERSION_PARAMETER)
                ? dtoa (TFM_FONT_PARAMETER (tfm_info, TFM_VERSION_PARAMETER))
                : "0.0";

  return ret;
}
Exemple #13
0
static int
get_packet(mm_file *mf, ogg_packet *pkt, enum stream_type type)
{
    ogg_stream_state *stream, *other;
    ogg_page pg;
    enum stream_type other_type;
    int rv = 0;

    assert(mf);
    assert(pkt);

    switch (type) {
    case MEDIA_VIDEO:
        assert(mf->video);
        stream = mf->video;
        other = mf->audio;
        other_type = MEDIA_AUDIO;
        break;

    case MEDIA_AUDIO:
        assert(mf->audio);
        stream = mf->audio;
        other = mf->video;
        other_type = MEDIA_VIDEO;
        break;

    default:
        WARNING2("bad stream type: %d", type);
        return -1;
    }

    if (mf->end_of_stream & type) {
        return 0;
    }

    while (0 == ogg_stream_packetout(stream, pkt)) {
        rv = get_page(mf, &pg);

        if (rv <= 0) {
            return rv;
        }

        if (ogg_stream_pagein(stream, &pg) < 0) {
            if (other && ogg_stream_pagein(other, &pg) == 0) {
                /*
                 * Got page from other stream. If user won't ever decode this
                 * then we need to clean up it here - otherwise read but not
                 * decoded packets would accumulate.
                 */
                if (mf->drop_packets & other_type) {
                    ogg_packet packet;

                    while (ogg_stream_packetout(other, &packet))
                        /* just drop packets */ ;
                }
            } else {
                INFO2("got page not associated with any stream, "
                      "serial 0x%x", ogg_page_serialno(&pg));
                /*
                 * drop page. Ogg source code says ogg_page member pointers are
                 * initialized to static buffers, so there is no need to free
                 * anything.
                 */
            }
        }
    }

    mf->end_of_stream |= (!!pkt->e_o_s) * type;
    return 1;
}
Exemple #14
0
static string
maketex (kpathsea kpse, kpse_file_format_type format, string* args)
{
  /* New implementation, use fork/exec pair instead of popen, since
   * the latter is virtually impossible to make safe.
   */
  unsigned len;
  string *s;
  string ret = NULL;
  string fn;
#if defined(WIN32)
  char   fullbin[256], *wrp;

  wrp = kpathsea_var_value(kpse, "SELFAUTOLOC");
  if(wrp == NULL) {
     fprintf(stderr, "I cannot get SELFAUTOLOC\n");
     exit(100);
  }

  strcpy(fullbin, wrp);
  free(wrp);
  for(wrp=fullbin; *wrp; wrp++) {
     if(*wrp == '/') *wrp = '\\';
  }
  strcat(fullbin, "\\");
  strcat(fullbin, args[0]);
#endif
  if (!kpse->make_tex_discard_errors) {
    fprintf (stderr, "\nkpathsea: Running");
    for (s = &args[0]; *s != NULL; s++)
      fprintf (stderr, " %s", *s);
    fputc('\n', stderr);
  }

#if defined (AMIGA)
  /* Amiga has a different interface. */
  {
    string cmd;
    string newcmd;
    cmd = xstrdup(args[0]);
    for (s = &args[1];  *s != NULL; s++) {
      newcmd = concat(cmd, *s);
      free (cmd);
      cmd = newcmd;
    }
    ret = system(cmd) == 0 ? getenv ("LAST_FONT_CREATED"): NULL;
    free (cmd);
  }
#elif defined (MSDOS) && !defined(__DJGPP__)
#error Implement new MSDOS mktex call interface here
#else /* WIN32 or Unix */
  {
#if defined (WIN32)
    /* spawnvp(_P_NOWAIT, ...) and pipe --ak 2002/12/15 */

    unsigned long nexitcode = STILL_ACTIVE;
    HANDLE hchild;
    int hstdout, childpipe[2];
    int hstderr = -1;
    FILE *Hnul = NULL;

    fn = NULL;

    if(_pipe(childpipe, 1024, O_TEXT | _O_NOINHERIT) == -1) {
      perror("kpathsea: pipe()");
      goto labeldone;
    }

    hstdout = _dup(fileno(stdout));
    if(_dup2(childpipe[1], fileno(stdout)) != 0) {
      close(hstdout);
      close(childpipe[0]);
      close(childpipe[1]);
      goto labeldone;
    }

    close(childpipe[1]);

    if(kpse->make_tex_discard_errors) {
      Hnul = fopen("nul", "w");
      if(!Hnul) {
        perror("kpathsea: fopen(\"nul\")");
      }
      else {
        hstderr = _dup(fileno(stderr));
        _dup2(fileno(Hnul), fileno(stderr));
      }
    }
    fprintf(stderr, "\nThe command name is %s\n", fullbin);
    hchild = (HANDLE)_spawnvp(_P_NOWAIT, fullbin, (const char * const *) args);

    _dup2(hstdout, fileno(stdout));
    close(hstdout);

    if(hchild == (HANDLE)(-1)) {
      close(childpipe[0]);
      goto labeldone;
    }

    if(hchild) {
      char buf[1024+1];
      int num;

      fn = xstrdup("");
      while(nexitcode == STILL_ACTIVE) {
        num = read(childpipe[0], buf, sizeof(buf)-1);
        if(num) {
          string newfn;
          buf[num] = '\0';
          newfn = concat(fn, buf);
          free(fn);
          fn = newfn;
        }
        if(!GetExitCodeProcess(hchild, &nexitcode)) {
          fn = NULL;
          close(childpipe[0]);
          goto labeldone;
        }
      }
      close(childpipe[0]);
    }

 labeldone:
    if(kpse->make_tex_discard_errors && Hnul) {
       _dup2(hstderr, fileno(stderr));
       close(hstderr);
       fclose(Hnul);
    }
#else /* !WIN32 */
    /* Standard input for the child.  Set to /dev/null */
    int childin;
    /* Standard output for the child, what we're interested in. */
    int childout[2];
    /* Standard error for the child, same as parent or /dev/null */
    int childerr;
    /* Child pid. */
    pid_t childpid;

    /* Open the channels that the child will use. */
    /* A fairly horrible uses of gotos for here for the error case. */
    if ((childin = open("/dev/null", O_RDONLY)) < 0) {
      perror("kpathsea: open(\"/dev/null\", O_RDONLY)");
      goto error_childin;
    }
    if (pipe(childout) < 0) {
      perror("kpathsea: pipe()");
      goto error_childout;
    }
    if ((childerr = open("/dev/null", O_WRONLY)) < 0) {
      perror("kpathsea: open(\"/dev/null\", O_WRONLY)");
      goto error_childerr;
    }
    if ((childpid = fork()) < 0) {
      perror("kpathsea: fork()");
      close(childerr);
     error_childerr:
      close(childout[0]);
      close(childout[1]);
     error_childout:
      close(childin);
     error_childin:
      fn = NULL;
    } else if (childpid == 0) {
      /* Child
       *
       * We can use vfork, provided we're careful about what we
       * do here: do not return from this function, do not modify
       * variables, call _exit if there is a problem.
       *
       * Complete setting up the file descriptors.
       * We use dup(2) so the order in which we do this matters.
       */
      close(childout[0]);
      /* stdin -- the child will not receive input from this */
      if (childin != 0) {
        close(0);
        if (dup(childin) != 0) {
          perror("kpathsea: dup(2) failed for stdin");
          close(childin);
          _exit(1);
        }
        close(childin);
      }
      /* stdout -- the output of the child's action */
      if (childout[1] != 1) {
        close(1);
        if (dup(childout[1]) != 1) {
          perror("kpathsea: dup(2) failed for stdout");
          close(childout[1]);
          _exit(1);
        }
        close(childout[1]);
      }
      /* stderr -- use /dev/null if we discard errors */
      if (childerr != 2) {
        if (kpse->make_tex_discard_errors) {
          close(2);
          if (dup(childerr) != 2) {
            perror("kpathsea: dup(2) failed for stderr");
            close(childerr);
            _exit(1);
          }
        }
        close(childerr);
      }
      /* FIXME: We could/should close all other file descriptors as well. */
      /* exec -- on failure a call of _exit(2) it is the only option */
      if (execvp(args[0], args))
        perror(args[0]);
      _exit(1);
    } else {
      /* Parent */
      char buf[1024+1];
      int num;

      /* Clean up child file descriptors that we won't use anyway. */
      close(childin);
      close(childout[1]);
      close(childerr);
      /* Get stdout of child from the pipe. */
      fn = xstrdup("");
      while ((num = read(childout[0],buf,sizeof(buf)-1)) != 0) {
        if (num == -1) {
          if (errno != EINTR) {
            perror("kpathsea: read()");
            break;
          }
        } else {
          string newfn;
          buf[num] = '\0';
          newfn = concat(fn, buf);
          free(fn);
          fn = newfn;
        }
      }
      /* End of file on pipe, child should have exited at this point. */
      close(childout[0]);
      /* We don't really care about the exit status at this point. */
      wait(NULL);
    }
#endif /* !WIN32 */

    if (fn) {
      len = strlen(fn);

      /* Remove trailing newlines and returns.  */
      while (len && (fn[len - 1] == '\n' || fn[len - 1] == '\r')) {
        fn[len - 1] = '\0';
        len--;
      }

      ret = len == 0 ? NULL : kpathsea_readable_file (kpse, fn);
      if (!ret && len > 1) {
        WARNING2 ("kpathsea: %s output `%s' instead of a filename",
                  args[0], fn);
      }

      /* Free the name if we're not returning it.  */
      if (fn != ret)
        free (fn);
    }
  }
#endif /* WIN32 or Unix */

  if (ret == NULL)
      misstex (kpse, format, args);
  else
      kpathsea_db_insert (kpse, ret);

  return ret;
}
Exemple #15
0
static string
maketex P2C(kpse_file_format_type, format, string*, args)
{
  /* New implementation, use fork/exec pair instead of popen, since
   * the latter is virtually impossible to make safe.
   */
  unsigned len;
  string *s;
  string ret;
  string fn;
  
  if (!kpse_make_tex_discard_errors) {
    fprintf (stderr, "kpathsea: Running");
    for (s = &args[0]; *s != NULL; s++)
      fprintf (stderr, " %s", *s);
    fputc('\n', stderr);
  }

#if defined (AMIGA)
  /* Amiga has a different interface. */
  {
    string cmd;
    string newcmd;
    cmd = xstrdup(args[0]);
    for (s = &args[1];  *s != NULL; s++) {
      newcmd = concat(cmd, *s);
      free (cmd);
      cmd = newcmd;
    }
    ret = system(cmd) == 0 ? getenv ("LAST_FONT_CREATED"): NULL;
    free (cmd);
  }
#elif defined (MSDOS)
#error Implement new MSDOS mktex call interface here
#elif defined (WIN32)
  /* We would vastly prefer to link directly with mktex.c here.
     Unfortunately, it is not quite possible because kpathsea
     is not reentrant. The progname is expected to be set in mktex.c
     and various initialisations occur. So to be safe, we implement
     a call sequence equivalent to the Unix one. */
  {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    HANDLE child_in, child_out, child_err;
    HANDLE father_in, father_out_dup;
    HANDLE current_pid;
    SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
    string new_cmd = NULL, app_name = NULL;

    char buf[1024+1];
    int num;
    extern char *quote_args(char **argv);

    if (look_for_cmd(args[0], &app_name) == FALSE) {
      ret = NULL;
      goto error_exit;
    }

    /* Compute the command line */
    new_cmd = quote_args(args);

    /* We need this handle to duplicate other handles */
    current_pid = GetCurrentProcess();

    ZeroMemory( &si, sizeof(STARTUPINFO) );
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW ;
    si.wShowWindow = /* 0 */ SW_HIDE ;

    /* Child stdin */
    child_in = CreateFile("nul",
                          GENERIC_READ,
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
                          &sa,  /* non inheritable */
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          NULL);
    si.hStdInput = child_in;

    if (CreatePipe(&father_in, &child_out, NULL, 0) == FALSE) {
      fprintf(stderr, "popen: error CreatePipe\n");
      goto error_exit;
    }
    if (DuplicateHandle(current_pid, child_out,
                        current_pid, &father_out_dup,
                        0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) {
      fprintf(stderr, "popen: error DuplicateHandle father_in\n");
      CloseHandle(father_in);
      CloseHandle(child_out);
      goto error_exit;
    }
    CloseHandle(child_out);
    si.hStdOutput = father_out_dup;

    /* Child stderr */
    if (kpse_make_tex_discard_errors) {
      child_err = CreateFile("nul",
                             GENERIC_WRITE,
                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                             &sa,       /* non inheritable */
                             OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL,
                             NULL);
    }
    else {
      DuplicateHandle(current_pid, GetStdHandle(STD_ERROR_HANDLE),
                      current_pid, &child_err,
                      0, TRUE,
                      DUPLICATE_SAME_ACCESS);
    }
    si.hStdError = child_err;

    /* creating child process */
    if (CreateProcess(app_name, /* pointer to name of executable module */
                      new_cmd,  /* pointer to command line string */
                      NULL,     /* pointer to process security attributes */
                      NULL,     /* pointer to thread security attributes */
                      TRUE,     /* handle inheritance flag */
                      0,                /* creation flags */
                      NULL,     /* pointer to environment */
                      NULL,     /* pointer to current directory */
                      &si,      /* pointer to STARTUPINFO */
                      &pi               /* pointer to PROCESS_INFORMATION */
                      ) == 0) {
      FATAL2("kpathsea: CreateProcess() failed for `%s' (Error %x)\n", new_cmd, GetLastError());
    }

    CloseHandle(child_in);
    CloseHandle(father_out_dup);
    CloseHandle(child_err);

    /* Only the process handle is needed */
    CloseHandle(pi.hThread);

    /* Get stdout of child from the pipe. */
    fn = xstrdup("");
    while (ReadFile(father_in,buf,sizeof(buf)-1, &num, NULL) != 0
           && num > 0) {
      if (num <= 0) {
        if (GetLastError() != ERROR_BROKEN_PIPE) {
          FATAL1("kpathsea: read() error code for `%s' (Error %d)", GetLastError());
          break;
        }
      } else {
        string newfn;
        buf[num] = '\0';
        newfn = concat(fn, buf);
        free(fn);
        fn = newfn;
      }
    }
    /* End of file on pipe, child should have exited at this point. */
    CloseHandle(father_in);

    if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) {
      WARNING2("kpathsea: failed to wait for process termination: %s (Error %d)\n",
               new_cmd, GetLastError());
    }

    CloseHandle(pi.hProcess);

    if (new_cmd) free(new_cmd);
    if (app_name) free(app_name);

    if (fn) {
      len = strlen(fn);

      /* Remove trailing newlines and returns.  */
      while (len && (fn[len - 1] == '\n' || fn[len - 1] == '\r')) {
        fn[len - 1] = '\0';
        len--;
      }

      ret = len == 0 ? NULL : kpse_readable_file (fn);
      if (!ret && len > 1) {
        WARNING1 ("kpathsea: mktexpk output `%s' instead of a filename", fn);
      }

      /* Free the name if we're not returning it.  */
      if (fn != ret)
        free (fn);
    }
  error_exit:
    ;
  }
#else
  {
    /* Standard input for the child.  Set to /dev/null */
    int childin;
    /* Standard output for the child, what we're interested in. */
    int childout[2];
    /* Standard error for the child, same as parent or /dev/null */
    int childerr;
    /* Child pid. */
    pid_t childpid;

    /* Open the channels that the child will use. */
    /* A fairly horrible uses of gotos for here for the error case. */
    if ((childin = open("/dev/null", O_RDONLY)) < 0) {
      perror("kpathsea: open(\"/dev/null\", O_RDONLY)");
      goto error_childin;
    }
    if (pipe(childout) < 0) {
      perror("kpathsea: pipe()");
      goto error_childout;
    }
    if ((childerr = open("/dev/null", O_WRONLY)) < 0) {
      perror("kpathsea: open(\"/dev/null\", O_WRONLY)");
      goto error_childerr;
    }
    if ((childpid = fork()) < 0) {
      perror("kpathsea: fork()");
      close(childerr);
     error_childerr:
      close(childout[0]);
      close(childout[1]);
     error_childout:
      close(childin);
     error_childin:
      fn = NULL;
    } else if (childpid == 0) {
      /* Child
       *
       * We can use vfork, provided we're careful about what we
       * do here: do not return from this function, do not modify
       * variables, call _exit if there is a problem.
       *
       * Complete setting up the file descriptors.
       * We use dup(2) so the order in which we do this matters.
       */
      close(childout[0]);
      /* stdin -- the child will not receive input from this */
      if (childin != 0) {
        close(0);
        dup(childin);
        close(childin);
      }
      /* stdout -- the output of the child's action */
      if (childout[1] != 1) {
        close(1);
        dup(childout[1]);
        close(childout[1]);
      }
      /* stderr -- use /dev/null if we discard errors */
      if (childerr != 2) {
        if (kpse_make_tex_discard_errors) {
          close(2);
          dup(childerr);
        }
        close(childerr);
      }
      /* FIXME: We could/should close all other file descriptors as well. */
      /* exec -- on failure a call of _exit(2) it is the only option */
      if (execvp(args[0], args))
        perror(args[0]);
      _exit(1);
    } else {
      /* Parent */
      char buf[1024+1];
      int num;
      int status;

      /* Clean up child file descriptors that we won't use anyway. */
      close(childin);
      close(childout[1]);
      close(childerr);
      /* Get stdout of child from the pipe. */
      fn = xstrdup("");
      while ((num = read(childout[0],buf,sizeof(buf)-1)) != 0) {
        if (num == -1) {
          if (errno != EINTR) {
            perror("kpathsea: read()");
            break;
          }
        } else {
          string newfn;
          buf[num] = '\0';
          newfn = concat(fn, buf);
          free(fn);
          fn = newfn;
        }
      }
      /* End of file on pipe, child should have exited at this point. */
      close(childout[0]);
      /* We don't really care about the exit status at this point. */
      wait(NULL);
    }

    if (fn) {
      len = strlen(fn);

      /* Remove trailing newlines and returns.  */
      while (len && (fn[len - 1] == '\n' || fn[len - 1] == '\r')) {
        fn[len - 1] = '\0';
        len--;
      }

      ret = len == 0 ? NULL : kpse_readable_file (fn);
      if (!ret && len > 1) {
        WARNING1 ("kpathsea: mktexpk output `%s' instead of a filename", fn);
      }

      /* Free the name if we're not returning it.  */
      if (fn != ret)
        free (fn);
    } else {
      ret = NULL;
    }
  }
#endif

  if (ret == NULL)
    misstex (format, args);
  else
    kpse_db_insert (ret);
  
  return ret;
}
// Start playing the given track
void music_start_loop(enum music_track track, int loop)
{
	OSStatus result;
	
	// Load as necessary
	music_load(track);
	
	// Ensure we can we play this
	if (!music_files[track].sequence_loaded)
		return;
	
	// Keep track of if we should loop or not
	music_files[track].loop = loop;
	
	// Is this already playing, or would it be playing if we weren't muted?
	if (music_files[track].playing || music_files[track].muted)
		return;
	
	// TODO: fix the code that calls the music system so that we don't have two tracks running at once
	// For now, stop any other tracks
	music_stop();
	
	// If we're muted, mark this track as muted, and bail out
	if (mute_music) {
		music_files[track].muted = 1;
		return;
	}
	
	// Initialize the music player and attach the sequence
	require_noerr(result = NewMusicPlayer(&music_files[track].player), fail);
	require_noerr(result = MusicPlayerSetSequence(music_files[track].player, music_files[track].sequence), fail);
	
	// Determine the track length if we don't know it already
	if (music_files[track].track_length <= 1.0) {
		UInt32 track_count, i;
		require_noerr(result = MusicSequenceGetTrackCount(music_files[track].sequence, &track_count), fail);

		for (i = 0; i < track_count; i++) {
			MusicTrack midi_track;
			MusicTimeStamp track_length;
			UInt32 property_size = sizeof(MusicTimeStamp);
			
			// Get the track within the MIDI file
			require_noerr(result = MusicSequenceGetIndTrack(music_files[track].sequence, i, &midi_track), fail);
			
			// Determine its length
			require_noerr(result = MusicTrackGetProperty(midi_track, kSequenceTrackProperty_TrackLength, &track_length, &property_size), fail);
			
			// Update the music track length if this MIDI track is longer
			if (track_length > music_files[track].track_length)
				music_files[track].track_length = track_length;
		}		
	}
	
	// Seek and pre-roll to the beginning
	require_noerr(result = MusicPlayerSetTime(music_files[track].player, 0), fail);
	require_noerr(result = MusicPlayerPreroll(music_files[track].player), fail);
	
	// Start playing
	require_noerr(result = MusicPlayerStart(music_files[track].player), fail);
	
	// Mark as playing
	music_files[track].playing = 1;
	
	return;
		
fail:
	WARNING2("unexpected error playing MIDI track; result=%ld", result);
	music_files[track].unplayable = 1;
	return;	
}
Exemple #17
0
static void
read_all_cnf (kpathsea kpse)
{
  string *cnf_files;
  string *cnf;
  const_string cnf_path = kpathsea_init_format (kpse, kpse_cnf_format);

  kpse->cnf_hash = hash_create (CNF_HASH_SIZE);

  cnf_files = kpathsea_all_path_search (kpse, cnf_path, CNF_NAME);
  if (cnf_files && *cnf_files) {
    for (cnf = cnf_files; *cnf; cnf++) {
      string line;
      string msg;
      unsigned lineno = 0;
      FILE *cnf_file = xfopen (*cnf, FOPEN_R_MODE);
      if (kpse->record_input)
        kpse->record_input (*cnf);

      while ((line = read_line (cnf_file)) != NULL) {
        unsigned len;
        lineno++;
        len = strlen (line);
        /* Strip trailing spaces. */
        while (len > 0 && ISSPACE(line[len-1])) {
          line[len - 1] = 0;
          --len;
        }
        /* Concatenate consecutive lines that end with \.  */
        while (len > 0 && line[len - 1] == '\\') {
          string next_line = read_line (cnf_file);
          lineno++;
          line[len - 1] = 0;
          if (!next_line) {
            WARNING2 ("%s:%d: (kpathsea) Last line of file ends with \\",
                       *cnf, lineno);
          } else {
            string new_line;
            new_line = concat (line, next_line);
            free (line);
            line = new_line;
            len = strlen (line);
          }
        }

        msg = do_line (kpse, line);
        if (msg) {
          WARNING4 ("%s:%d: (kpathsea) %s on line: %s",
                    *cnf, lineno, msg, line);
        }
        free (line);
      }

      xfclose (cnf_file, *cnf);
      free (*cnf);
    }
    free (cnf_files);
  } else {
    string warn = getenv ("KPATHSEA_WARNING");
    if (!(warn && STREQ (warn, "0"))) {
      WARNING1
  ("kpathsea: configuration file texmf.cnf not found in these directories: %s",
        cnf_path);
    }
  }
}
/** read the command-line options
 *
 * \return length of modified argv
 *
 * \todo possibly maintain a list of dirs to search??
 */
int
setup_options(int argc, char *argv[])
{
	char *str = NULL;
	int pos, i;

	/* first set up defaults */
	for (i = 0; i < (int) ARRAY_LENGTH(env_vars); ++i)
	{
		if ((str = getenv(env_vars[i].name)))
			*env_vars[i].dest = xstrdup(str);
		else if (strcmp(env_vars[i].name, ENVIRON_SAVEDIR) == 0
			&& (str = get_homedir()))
		{
			size_t len = strlen(str) + strlen(PACKAGE_TARNAME) + 3;

			*env_vars[i].dest = xmalloc(len);
			sprintf(*env_vars[i].dest, "%s/.%s", str, PACKAGE_TARNAME);
			free(str);
		}
		else
			*env_vars[i].dest = xstrdup(env_vars[i].def_val);
	}

	/* set up default values */
	options.want_audio = 1;
	options.want_intro = 1;
	options.want_cheats = 0;
	options.want_fullscreen = 0;
	options.want_debug = 0;
	options.feat_shorter_advanced_training = 0;
	options.feat_random_nauts =0;    //Naut Randomize, Nikakd, 10/8/10
	options.feat_compat_nauts =10;   //Naut Compatibility, Nikakd, 10/8/10
	options.feat_no_cTraining =1;    //No Capsule Training, Nikakd, 10/8/10
	options.feat_no_backup =1;       //No Backup crew required -Leon
	options.cheat_no_damage=0;       //Damaged Equipment Cheat, Nikakd, 10/8/10
	options.feat_random_eq=0;
	options.feat_eq_new_name =0;
	options.cheat_altasOnMoon=0;
	options.cheat_addMaxS=1;
	options.boosterSafety=0;

	fixpath_options();

	/* now try to read config file, if it exists */
	if (read_config_file() < 0)
		/* if not, then write default config template */
		write_default_config();

	/* first pass: command line options */
	for (pos = 1; pos < argc; ++pos)
	{
		str = argv[pos];

		if (str[0] != '-')
			continue;

		if (!str[1])
			continue;

		if (strcmp(str, "--") == 0)
		{
			shift_argv(argv + pos, argc - pos, 1);
			argc--;
			break;
		}

		/* check what option matches */
		if (strcmp(str, "-h") == 0)
			usage(0);
		else if (strcmp(str, "-i") == 0)
			options.want_intro = 0;
		else if (strcmp(str, "-n") == 0)
			options.want_cheats = 1;
		else if (strcmp(str, "-a") == 0)
			options.want_audio = 0;
		else if (strcmp(str, "-f") == 0)
			options.want_fullscreen = 1;
		else if (strcmp(str, "-v") == 0)
			options.want_debug++;
		else
		{
			ERROR2("unknown option %s", str);
			usage(1);
		}

		shift_argv(argv + pos, argc - pos, 1);
		argc--;
		pos--; /* for loop will advance it again */
	}

	/* second pass: variable assignments */
	for (pos = 1; pos < argc; ++pos)
	{
		/** \todo should use PATH_MAX or something similar here */
		char name[32 + 1], *value;
		int offset = 0;
		int fields = 0;

		fields = sscanf(argv[pos], "%32[A-Z_]=%n", name, &offset);

		/* it is unclear whether %n increments return value */
		if (fields < 1)
			continue;

		value = argv[pos] + offset;

		for (i = 0; i < (int) ARRAY_LENGTH(env_vars); ++i)
		{
			if (strcmp(name, env_vars[i].name) == 0)
			{
				free(*env_vars[i].dest);
				*env_vars[i].dest = xstrdup(value);
				break;
			}
		}

		if (i == (int) ARRAY_LENGTH(env_vars))
			WARNING2("unsupported command line variable `%s'", name);

		/* remove matched string from argv */
		shift_argv(argv + pos, argc - pos, 1);

		/*
		 * now we have one fewer arg, pos points to the next arg,
		 * keep it this way after incrementing it on top of the loop
		 */
		pos--;
		argc--;
	}

	fixpath_options();

	return argc;
}