Back to index

tetex-bin  3.0
Functions
browser.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void launch_browser (const char *filename)

Function Documentation

void launch_browser ( const char *  filename)

Definition at line 163 of file browser.c.

{
    const char *browser;
    int pid;
    struct xchild *my_child;
    struct xio *my_io;
    int err_pipe[2];
    
    /* try to set it from possible resources: First command-line argument
       or X resource, then environment variables, then default_browser_cmd
    */
    for (;;) {
       if ((browser = resource.browser) != NULL)
           break;
       if ((browser = getenv("BROWSER")) != NULL)
           break;
       if ((browser = getenv("WWWBROWSER")) != NULL)
           break;
       XDVI_INFO((stderr, "Browser not set (xdvi.wwwBrowser, -browser or $BROWSER environment variable)."));
       XDVI_INFO((stderr, "Using built-in default: `%s'",
                 default_browser_cmd));
       browser = default_browser_cmd;
       break;
    }
    
    /* fork first time so that we can wait for children, without
       freezing the GUI.  FIXME: this copies stuff from
       fork_process for the inter-process communication stuff -
       it would be better to have this in one function. */
    my_child = xmalloc(sizeof *my_child);
    my_io = xmalloc(sizeof *my_io);
    statusline_print(STATUS_MEDIUM, "Trying to launch browser ...");
    /* flush output buffers to avoid double buffering (i.e. data
       waiting in the output buffer being written twice, by the parent
       and the child) */
    fflush(stdout);
    fflush(stderr);
       
    if (pipe(err_pipe) < 0) {
       perror("pipe");
       _exit(-1);
    }
       
    switch (pid = fork()) {
    case -1:  /* forking error */
       perror("fork");
       close(err_pipe[0]);
       close(err_pipe[1]);
       return;
    case 0:   /* child */
       {
           char *tmp_browser = xstrdup(browser);

           close(err_pipe[0]);     /* no reading from stderr */
              
           /* make stderr of child go to err_pipe[1] */
           if (dup2(err_pipe[1], STDERR_FILENO) != STDERR_FILENO) {
              perror("dup2 for stderr");
              _exit(EXIT_FAILURE);
              return;       /* make compiler happy */
           }
              
           /*
             BROWSER is a colon-separated list of commands, in decreasing preference;
             use the first that can be forked successfully. Note that the return
             value of the command isn't used at all (with GUI programs, xdvi shouldn't
             hang until they terminate!)
           */
           while (tmp_browser != NULL) {
              char *next = strchr(tmp_browser, ':');
              if (next != NULL) {
                  *next++ = '\0';
              }
              TRACE_HTEX((stderr, "trying browser |%s|", tmp_browser));
              /* fork a second time to start the browser */
              if (fork_browser(tmp_browser, filename)) { /* foking worked */
                  _exit(EXIT_SUCCESS);
              }
              tmp_browser = next;
           }
           /* child arrives here only if none of the commands worked */
           XDVI_WARNING((stderr, "None of the browser commands in the `browser' resource (%s) worked\n",
                       browser));
           free(tmp_browser);
           _exit(EXIT_FAILURE);
       }
    default: /* parent */
       close(err_pipe[1]);  /* no writing to stderr */

       my_io->next = NULL;
       my_io->fd = err_pipe[0];
       my_io->xio_events = XIO_IN;
#if HAVE_POLL
       my_io->pfd = NULL;
#endif
       my_io->read_proc = read_child_error;
       my_io->write_proc = NULL;
           
       my_child->next = NULL;
       my_child->pid = pid;
       my_child->name = NULL;
       my_child->proc = handle_child_exit;
       my_child->data = NULL;
       my_child->io = my_io;
           
       set_chld(my_child);
       statusline_print(STATUS_MEDIUM, "Trying to launch browser ... done.");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function: