Example #1
0
File: server.c Project: ZhouYii/Nit
int main(int argc, char** argv) {
    FILE* db = fopen(".nitdb", "r");
    if(db == NULL) {
        FILE* temp = fopen(".nitdb", "w");
        fclose(temp);
    }
    int socket_fd = 0, conn_fd =0;
    struct sockaddr_in server_addr;
    socket_fd = socket(PF_INET, SOCK_STREAM, 0);
    if(socket_fd == -1) 
        err_handler("Failed to get socked file descriptor");
    /* Zero the IPV6 compatibility bits */
    memset(&server_addr, '0', sizeof(server_addr));
    memset(&buf, '\0', sizeof(buf));
    memset(&cmd_buf, '\0', sizeof(cmd_buf));

    server_addr.sin_family = AF_INET;
    /* Standardize endian-ness */
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(PORT_NUM);
    if(bind(socket_fd, (struct sockaddr*) &server_addr, sizeof(server_addr)) == -1)
        err_handler("Failed to bind port");
    if(listen(socket_fd, 10) == -1)
        err_handler("Failed to listen on port");

    while(1) {
        conn_fd = accept(socket_fd, (struct sockaddr*) NULL, NULL);
        printf("ACCEPTED");
        /* Recieve opcode */
        while(recv(conn_fd, cmd_buf, BUF_SIZE, NO_FLAGS) > 0) 
        {
            send(conn_fd, ACK, strlen(ACK), NO_FLAGS);
            memset(buf, '\0', sizeof(buf));
            if(recv(conn_fd, buf, BUF_SIZE, NO_FLAGS) <= 0) {
                close(conn_fd);
                break;
            }
            send(conn_fd, ACK, strlen(ACK), NO_FLAGS);
            /* Take action */
            if(strcmp(cmd_buf, OP_SEND_FILE) == 0)
                recv_file(conn_fd);
            if(strcmp(cmd_buf, OP_GET_FILE) == 0) 
                send_file(conn_fd);
        }
        close(conn_fd);
    }
    return 0;
}
Example #2
0
File: server.c Project: ZhouYii/Nit
void recv_file(int conn_fd) {
    /* Client sends encoded file path and permissions */
    char *perm_ptr, *filepath = buf;
    if((perm_ptr = strstr(buf, SEPARATOR)) != NULL) {
        *(perm_ptr) = '\0';
        /* Stick in a NULL and advance a pointer, effectively making two
         * strings. One for file path, one for permissions */
        perm_ptr += strlen(SEPARATOR);
        FILE* f = fopen(filepath, "w");
        if(f == NULL)
            err_handler("Failed to open file");
        build_dirs(filepath, 0);
        memset(buf, '\0', sizeof(buf));
        while(recv(conn_fd, buf, BUF_SIZE, NO_FLAGS) > 0) {
            if(strncmp(buf, OP_EOF, strlen(OP_EOF)) == 0) {
                fflush(f);
                break;
            }
            fputs(buf, f);
            send(conn_fd, ACK, strlen(ACK), NO_FLAGS);
            /* Clear the buffer for accurate comparisons */
            memset(buf, '\0', sizeof(buf));
        }
        if(strcmp(buf, OP_EOF) == 0)
            printf("File transfer successful\n");
        fflush(NULL);
        fclose(f);
    }
}
Example #3
0
static void
E_handler(lcb_socket_t sock, short which, void *arg)
{
    lcbio_CTX *ctx = arg;
    lcbio_IOSTATUS status;
    (void)sock;

    if (which & LCB_READ_EVENT) {
        unsigned nb;
        status = lcbio_E_rdb_slurp(ctx, &ctx->ior);
        nb = rdb_get_nused(&ctx->ior);

        if (nb >= ctx->rdwant) {
            invoke_read_cb(ctx, nb);
            if (E_free_detached(ctx)) {
                return;
            }
        }
        if (!LCBIO_IS_OK(status)) {
            lcb_error_t err = convert_lcberr(ctx, status);
            lcbio_ctx_senderr(ctx, err);
            return;
        }
    }

    if (which & LCB_WRITE_EVENT) {
        if (ctx->wwant) {
            ctx->wwant = 0;
            ctx->procs.cb_flush_ready(ctx);
            if (ctx->err) {
                return;
            }
        } else if (ctx->output) {
            status = lcbio_E_rb_write(ctx, &ctx->output->rb);
            if (!LCBIO_IS_OK(status)) {
                deactivate_watcher(ctx);
                ctx->err = convert_lcberr(ctx, status);
                err_handler(ctx);
                return;
            }
        }
    }

    lcbio_ctx_schedule(ctx);
}
Example #4
0
int
create_file_names_for_track (_main_data * main_data, int track, char **wfp,
			     char **efp)
{
  static char *buffer;
  int rc;
  char *conv_str = NULL;
  GtkWidget *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);

  rc = parse_rx_format_string (&buffer,
			       ((char *) config_read (CONF_CDDB_FORMATSTR)),
			       track, main_data->disc_artist,
			       main_data->disc_title, main_data->disc_year,
			       main_data->track[track].title);
  if (rc < 0)
    {
      err_handler (GTK_WINDOW(main_window), RX_PARSING_ERR,
		   _
		   ("Check if the filename format string contains format characters other than %a %# %v %y or %s."));
      return 0;
    }

  if (buffer[0] == 0)
    strcpy (buffer, main_data->track[track].title);

  conv_str = g_locale_from_utf8 (buffer, -1, NULL, NULL, NULL);

  remove_non_unix_chars (conv_str);
  convert_slashes (conv_str, '-');
  if ((int) config_read (CONF_GNRL_CONVSPC))
    {
      convert_spaces (conv_str, '_');
    }

  if (wfp)
    mk_strcat (wfp, wd, conv_str, wfext, NULL);
  if (efp)
    mk_strcat (efp, ed, conv_str, ecfext, NULL);

  g_free (conv_str);

  return 1;
}
Example #5
0
int
add_argv (char **dest, char *content)
{
  size_t i;
  GtkWidget *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);

  i = 0;

  while (content[i++] != '\0');

  if ((*dest = malloc (i)) == NULL)
    {
      err_handler (GTK_WINDOW(main_window), MALLOC_ERR, NULL);
      return FALSE;
    }

  strcpy (*dest, content);
  return TRUE;
}
Example #6
0
void
read_an_item (int item_num, char *src)
{
  char *str;
  char *p_char;
  float *p_float;
  int *p_int;
  int i, len;
  GtkWindow *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);

  switch (config_rw_data[item_num].type)
    {
    case STRING:
      str = (char *) config_rw_data[item_num].m_id;
      strcpy (str, src);
      /* Strip \n */
      len = strlen (str);
      for (i = 0; i < len && str[i] != '\0'; i++)
	if (str[i] == '\n')
	  str[i--] = '\0';
      break;

    case CHAR:
      p_char = (char *) config_rw_data[item_num].m_id;
      *p_char = src[0];
      break;

    case FLOAT:
      p_float = (float *) config_rw_data[item_num].m_id;
      sscanf (src, "%f", p_float);
      break;

    case INT:
      p_int = (int *) config_rw_data[item_num].m_id;
      sscanf (src, "%d", p_int);
      break;

    default:
      err_handler (GTK_WINDOW(main_window), CONFIG_PARSE_ERR, NULL);
      break;
    }
}
Example #7
0
int
process_options (char *options, char **argv, int start, int end)
{
  int current, i, j, flag;
  char buf[MAX_SINGLE_OPTION_LENGTH];
  GtkWidget *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);

  current = start;
  i = 0;
  while (options[i] != '\0')
    {
      while (isspace (options[i]))
	i++;
      j = 0;
      flag = 0;
      while (!isspace (options[i])
	     && options[i] != '\0' && j < MAX_SINGLE_OPTION_LENGTH - 1)
	{
	  /* It really has something other than spaces */
	  flag = 1;
	  buf[j++] = options[i++];
	}
      buf[j] = '\0';

      /* If it really has something */
      if (flag)
	{
	  if (current < end)
	    {
	      if (add_argv (&argv[current], buf) == FALSE)
		return -1;
	    }
	  else
	    {
	      err_handler (GTK_WINDOW(main_window), TOO_MANY_ARGS_ERR, NULL);
	    }
	  current++;
	}
    }
  return current - start;
}
Example #8
0
/*
*		xcalloc(size_tnelem,size_tsize)
*/
char	*xcalloc(size_t nelem, size_t size)
{
	register char	*p;

	/* Do the actual memory allocation */

	if((p = calloc(nelem, size)) == NULL) {
		/* Failure, call the error hook */
		if(mestat != NULL) mestat->xerrcals++;
		p = err_handler(p, nelem, size, errno, "calloc");
	}

	/* Record statistics */

	if(mestat != NULL) {
		mestat->xcallocs++;
		if(p == NULL) mestat->xfails++;
	}

	/* Exit with the pointer */

	return(p);
}
Example #9
0
/*
*		xrealloc(voidptr,size_tsize)
*/
char	*xrealloc(void *ptr, size_t size)
{
	register void	*p;

	/* Do the actual memory allocation */

	if((p = realloc(ptr, size)) == NULL) {
		/* Failure, call the error hook */
		if(mestat != NULL) mestat->xerrcals++;
		p = err_handler(ptr, (size_t) 1, size, errno,
			"realloc");
	}

	/* Record statistics */

	if(mestat != NULL) {
		mestat->xreallocs++;
		if(p == NULL) mestat->xfails++;
	}

	/* Exit with the pointer */

	return(p);
}
Example #10
0
void
read_config (void)
{
  FILE *file;
  char buf[MAX_CONFIG_LINE_LENGTH + 1];
  int i, offset;
  int flag;
  GtkWidget *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);

  memset (&config, 0, sizeof (_config));

  file = fopen (construct_file_name (getenv ("HOME"), ".ripperXrc"), "r");

  if (file == NULL)
    {
      config_to_default (-1);
      if (errno != ENOENT)
	{
	  err_handler (GTK_WINDOW(main_window), CONFIG_OPEN_ERR, NULL);
	  return;
	}
      write_config ();
      return;
    }

  while (fgets (buf, sizeof (buf), file) != NULL)
    {
      /* Comments */
      if (strncasecmp ("//", buf, 2) == 0)
	continue;
      for (i = 0, offset = 0; i < num_entry && offset == 0; i++)
	{
	  /* Find the match */
	  if (strncasecmp (config_rw_data[i].f_id, buf,
			   strlen (config_rw_data[i].f_id)) == 0)
	    {
	      /* General::WavRatio = asdf... */
	      offset += strlen (config_rw_data[i].f_id);
	      while (buf[offset++] != '=');
	    }
	}
      i--;

      /* Mark that this field has been read */
      config_rw_data[i].flag = TRUE;

      /* Skip blank lines */
      if (is_str_blank (buf + offset))
	continue;

      /* Skip spaces */
      while (isspace (buf[offset++]));
      offset--;

      read_an_item (i, buf + offset);
    }

  for (i = 0, flag = FALSE; i < num_entry; i++)
    {
      if (config_rw_data[i].flag == FALSE)
	{
	  flag = TRUE;
	  config_to_default (i);
	}
    }

  if (flag)
    err_handler (GTK_WINDOW(main_window), CONFIG_EMPTY_ITEM_ERR, "");

  return;
}
Example #11
0
void
write_config (void)
{
  FILE *file;
  int fd;
  int i;
  char *str;
  char t_char;
  float t_float;
  int t_int;
  GtkWidget *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);

  fd = open (construct_file_name (getenv ("HOME"), ".ripperXrc"),
	     O_WRONLY | O_TRUNC);

  if (fd < 0)
    {
      if (errno == ENOENT)
	{
	  if (dialog_handler (WIDGET_CREATE, FALSE, DL_CREATE_CONFIG_CONFIRM,
			      FALSE, NULL, NULL, 0) == FALSE)
	    return;
	  fd = open (construct_file_name (getenv ("HOME"), ".ripperXrc"),
		     O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
	  if (fd < 0)
	    {
	      err_handler (GTK_WINDOW(main_window), CONFIG_CREATION_ERR, "");
	      return;
	    }
	}
      else
	err_handler (GTK_WINDOW(main_window), CONFIG_OPEN_ERR, "");
    }

  if ((file = fdopen (fd, "w")) == NULL)
    {
      err_handler (GTK_WINDOW(main_window), FDOPEN_ERR, "Cannot re-open config file as a stream");
      close (fd);
      return;
    }

  fputs ("//\n", file);
  fputs ("// ~/.ripperXrc\n", file);
  fputs ("// This is the resource file for ripperX.\n", file);
  fputs ("// If you edit this file with an editor, you must leave all\n",
	 file);
  fputs ("// parameters in the order in which they appear.  Also note\n",
	 file);
  fputs ("// that this file is overwritten each time ripperX is run.\n",
	 file);
  fputs
    ("//\n// You can configure everything in the config menu within ripperX.\n",
     file);
  fputs ("//\n\n", file);

  fprintf (file, "//-V %s\n\n", VERSION);

  for (i = 0; i < num_entry; i++)
    {
      switch (config_rw_data[i].type)
	{
	case STRING:
	  str = (char *) config_rw_data[i].m_id;

	  fprintf (file, "%s = %s\n", config_rw_data[i].f_id, str);
	  break;

	case CHAR:
	  t_char = *(char *) config_rw_data[i].m_id;

	  fprintf (file, "%s = %c\n", config_rw_data[i].f_id, t_char);
	  break;

	case FLOAT:
	  t_float = *(float *) config_rw_data[i].m_id;

	  fprintf (file, "%s = %f\n", config_rw_data[i].f_id, t_float);
	  break;

	case INT:
	  t_int = *(int *) config_rw_data[i].m_id;

	  fprintf (file, "%s = %d\n", config_rw_data[i].f_id, t_int);
	  break;
	}
    }
  fclose (file);
  return;
}
Example #12
0
char *dir_window_handler(enum InterfaceCommon ops, const char *cur_dir)
{
    static GtkWidget *filew;
    static int id;
    static char buf[ MAX_FILE_PATH_LENGTH ];
    static const char *saved_cur_dir;

    switch(ops)
    {
        case WIDGET_CREATE :
        {
            struct stat st;
            char check_dir[ MAX_FILE_PATH_LENGTH + 1];
            char *checked_dir;
            saved_cur_dir = cur_dir;
            checked_dir = check_dir;
            strncpy(check_dir, cur_dir, MAX_FILE_PATH_LENGTH);

            /* Add a final / to input directory string if missing and input string is only a
            directory (i.e. no filename); but pass through any other strings.  This allows
            GtkFileSelection widget to show proper directory level upon entering. */
            if((lstat(checked_dir, &st) >= 0) && (S_ISDIR(st.st_mode)))
            {
                if((check_dir[ strlen(checked_dir) - 1 ] != '/')
                        && (strlen(checked_dir) > 0)
                        && (strlen(checked_dir) < MAX_FILE_PATH_LENGTH))
                {
                    checked_dir = strcat(check_dir, "/");
                }
            }

            filew = gtk_file_selection_new(_("Select a directory"));
            gtk_window_set_position(GTK_WINDOW(filew), GTK_WIN_POS_MOUSE);
            gtk_file_selection_show_fileop_buttons(GTK_FILE_SELECTION(filew));

            id = g_signal_connect(G_OBJECT(filew), "destroy",
                                  G_CALLBACK(dw_cancel_clicked),
                                  NULL);
            g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filew) ->ok_button),
                             "clicked",
                             G_CALLBACK(dw_ok_clicked), NULL);
            g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filew) ->cancel_button),
                             "clicked",
                             G_CALLBACK(dw_cancel_clicked),
                             NULL);
            gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), checked_dir);
            gtk_widget_hide(GTK_WIDGET(GTK_FILE_SELECTION(filew) ->fileop_del_file));
            gtk_widget_hide(GTK_WIDGET(GTK_FILE_SELECTION(filew) ->fileop_ren_file));
            gtk_widget_set_sensitive(GTK_WIDGET(GTK_FILE_SELECTION(filew) ->file_list),
                                     FALSE);
            gtk_widget_show(filew);
            gtk_main();
            g_signal_handler_disconnect(G_OBJECT(filew), id);
            strncpy(buf,
                    gtk_file_selection_get_filename(GTK_FILE_SELECTION(filew)),
                    sizeof(buf));
            gtk_widget_destroy(filew);
            return buf;
        }

        case OP_OK :
        {
            struct stat st;
	    //FIXME - should be const, make copy??
            gchar *temp = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(filew));

            if(lstat(temp, &st) < 0)
            {
                err_handler(INVALID_FILE_SELECTION_ERR, NULL);
                return NULL;
            }

            if(!S_ISDIR(st.st_mode))
            {
                gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew),
                                                file_path_without_name(temp));
                temp = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(filew));
            }

            /* remove final directory ../ from directory string if present */
            if(strlen(temp) > 3)
            {
                if((temp[ strlen(temp) - 1 ] == '/') &&
                        (temp[ strlen(temp) - 2 ] == '.') &&
                        (temp[ strlen(temp) - 3 ] == '.') &&
                        (temp[ strlen(temp) - 4 ] == '/'))
                {
                    temp[ strlen(temp) - 3 ] = '\0';
                    gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew),
                                                    temp);
                }
            }

            /* remove final directory ./ from directory string if present */
            if(strlen(temp) > 2)
            {
                if((temp[ strlen(temp) - 1 ] == '/') &&
                        (temp[ strlen(temp) - 2 ] == '.') &&
                        (temp[ strlen(temp) - 3 ] == '/'))
                {
                    temp[ strlen(temp) - 2 ] = '\0';
                    gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew),
                                                    temp);
                }
            }

            gtk_main_quit();
            return NULL;
        }

        case OP_CANCEL :
            gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), saved_cur_dir);
            gtk_main_quit();
            return NULL;
    }

    return NULL;
}
Example #13
0
int lock_file(char *file_name, int is_temp)
{
    int fd;
    char *temp;
    char buf[ MAX_FILE_NAME_LENGTH ];

    fd = open(file_name,
              O_CREAT | O_EXCL,
              S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH);

    if(fd >= 0)
    {
        close(fd);
        unlink(file_name);
    }
    else
    {
        if(errno == EEXIST)
            if(config.ask_when_file_exists == FALSE || is_temp == TRUE)
            {
                if(config.make_mp3_from_existing_wav)
                {
                    return 1;
                }

                /* Prepend config.prepend_char until we succeed open() */
                if(strlen(file_name) >
                        MAX_FILE_NAME_LENGTH + MAX_FILE_PATH_LENGTH - 2)
                {
                    return - 1;
                }
                else
                {
                    temp = file_name_without_path(file_name);
                    strcpy(buf, temp);
                    temp[ 0 ] = config.prepend_char;
                    strcpy(temp + 1, buf);

                    /* now try again */
                    if(lock_file(file_name, is_temp) < 0)
                    {
                        return - 1;
                    }
                }
            }
            else
            {
                if(config.make_mp3_from_existing_wav)
                {
                    return 1;
                }

                if(dialog_handler(WIDGET_CREATE, FALSE,
                                  DL_OVERWRITE_CONFIRM,
                                  FALSE,
                                  file_name_without_path(file_name),
                                  NULL, 0) == TRUE)
                    /* Just return. Cdparanoia or 8hz-mp3 will overwrite on it */
                {
                    return 0;
                }

                /* Let's ask the user what s/he wants */
                temp = file_name_without_path(file_name);
                strcpy(buf, temp);

                if(dialog_handler(WIDGET_CREATE, TRUE,
                                  DL_ENTER_FILE_NAME,
                                  TRUE,
                                  buf, buf, sizeof(buf) - 1) == FALSE)
                    /* The user does not want to continue. return error */
                {
                    return - 1;
                }

                strcpy(temp, buf);

                /* now try again */
                if(lock_file(file_name, is_temp) < 0)
                {
                    return - 1;
                }
            }
        else /* an other error (maybe directory not existent */
        {
            err_handler(CREATING_FILE_ERROR, file_name);
            return - 1;
        }
    }

    return 0;
}
Example #14
0
void job_controller(int ops, _main_data *main_data)
{
    static int cur_type = -1;
    static int wav_cur_track = -1;
    static int mp3_cur_track = -1;
    static int mp3_nxt_track = -1;
    static pid_t wav_pg_pid = -1;
    static pid_t mp3_pg_pid = -1;
    static pid_t wav_pi_pid = -1;
    static pid_t mp3_pi_pid = -1;
    static int wav_read_fd;
    static int mp3_read_fd;
    static _stat stat;
    static _main_data *saved_main_data;
    static char *wav_file_path, *enc_file_path;
    unsigned wav_current = 0;
    unsigned mp3_current = 0;
    double wav_progress;
    double mp3_progress;
    char msg[ MAX_PLUGIN_OUTPUT_LENGTH ];
    char *str;
    int temp, temp_track;

    switch(ops)
    {
        case JC_START :
            /* called once when the go button is clicked. */
            saved_main_data = main_data;

            if(wav_cur_track != -1)
            {
                err_handler(JOB_IN_PROGRESS_ERR, NULL);
                job_finisher(main_data);
                return;
            }

            if(find_next_job(main_data, wav_cur_track, WAV,
                             &wav_cur_track, &cur_type) < 0)
            {
                /* ok, no more wavs to rip, try looking for mp3s */
                if(find_next_job(main_data, mp3_cur_track, MP3,
                                 &mp3_cur_track, &cur_type) < 0)
                {
                    /* nothing at all found */
                    err_handler(NOTHING_TO_DO_ERR, NULL);
                    job_finisher(main_data);
                    return;
                }

                create_file_names_for_track(main_data, mp3_cur_track,
                                            &wav_file_path, &enc_file_path);

                calc_stat(main_data, &stat, mp3_current,
                          mp3_cur_track, MP3, CALC_START_SESSION);
                calc_stat(main_data, &stat, mp3_current,
                          mp3_cur_track, MP3, CALC_START);

                /* start encoding */
                if(start_ripping_encoding(MP3, main_data->track[ mp3_cur_track ].begin,
                                          main_data->track[ mp3_cur_track ].length,
                                          mp3_cur_track,
                                          wav_file_path,
                                          enc_file_path,
                                          &mp3_pg_pid,
                                          &mp3_pi_pid,
                                          &mp3_read_fd) < 0)
                {
                    job_finisher(main_data);
                    return;
                }

                stat.encoding = TRUE;
            }
            else
            {
                /* found the first wav to rip */
                create_file_names_for_track(main_data, wav_cur_track, &wav_file_path, &enc_file_path);
                calc_stat(main_data, &stat, wav_current, wav_cur_track, WAV, CALC_START_SESSION);
                calc_stat(main_data, &stat, wav_current, wav_cur_track, WAV, CALC_START);

                /* start ripping */
                if(start_ripping_encoding(WAV, main_data->track[ wav_cur_track ].begin,
                                          main_data->track[ wav_cur_track ].length,
                                          wav_cur_track,
                                          wav_file_path,
                                          enc_file_path,
                                          &wav_pg_pid,
                                          &wav_pi_pid,
                                          &wav_read_fd) < 0)
                {
                    job_finisher(main_data);
                    return;
                }

                stat.ripping = TRUE;

                /* Find the next track to encode if any */
                if(find_next_job(main_data, mp3_cur_track, MP3, &mp3_nxt_track, &cur_type) < 0 ||
                        !main_data->track[ mp3_nxt_track ].make_mp3)
                {
                    mp3_nxt_track = -1;
                }
            }

            /* Create wav/mp3 status frame */
            wm_status_frame_handler(WIDGET_CREATE, cur_type, &stat, NULL);

            job_controller_timeout_start();
            return;

        case JC_UPDATE :
            main_data = saved_main_data;

            /* Part 1: check progress on the rip */
            if(stat.ripping == TRUE)
            {
                temp = read_and_process_plugin_output(wav_read_fd, &wav_progress, msg);
                wav_current = main_data->track[ wav_cur_track ].length * wav_progress;

                switch(temp)
                {
                    case PLUGIN_MSG_PARSE_ERR :
                        /* Nothing to do. Let's wait more */
                        break;

                    case PLUGIN_PROGRESS_MSG :
                        /* progress report, update status display */
                        calc_stat(main_data, &stat, wav_current,
                                  wav_cur_track, WAV, CALC_UPDATE);

                        /* Update status widget */
                        if(msg[ 0 ] == '\0')
                        {
                            str = NULL;
                        }
                        else
                        {
                            str = msg;
                        }

                        wm_status_frame_handler(WIDGET_UPDATE, WAV, &stat, str);
                        break;

                    case PLUGIN_NO_MSG_AVAILABLE :

                        /* Check if the plugin has exited
                           It only happens when ripperX failed to execute the plugin */
                        if(wav_pi_pid >= 0)
                            if(waitpid(wav_pi_pid, NULL, WNOHANG) == wav_pi_pid)
                            {
                                err_handler(PLUGIN_NOT_PRESENT_ERR,
                                            _("Maybe ripperX has failed to execute the plugin"));
                                wav_pi_pid = -1;
                                job_controller_timeout_stop();
                                job_controller(JC_ABORT_ALL_DELETE, main_data);
                                return;
                            }

                        /* Check if the job is finished */
                        if(waitpid(wav_pg_pid, NULL, WNOHANG) == wav_pg_pid)
                        {
                            /* One job finished, go for next one */

                            /* kill the plugin */
                            if(waitpid(wav_pi_pid, NULL, WNOHANG) != wav_pi_pid)
                            {
                                kill(-wav_pi_pid, SIGTERM);
                                waitpid(wav_pi_pid, NULL, 0);
                            }

                            /* Close the fd */
                            close(wav_read_fd);

                            /* stop calculating stats */
                            calc_stat(main_data, &stat, wav_current,
                                      wav_cur_track, WAV, CALC_STOP);

                            /* Mark that it exists */
                            main_data->track[ wav_cur_track ].wav_exist = TRUE;

                            /* find next track to rip */
                            temp_track = wav_cur_track;

                            if(find_next_job(main_data, wav_cur_track, WAV, &wav_cur_track, &cur_type) < 0)
                            {
                                /* All finished - no more rips */
                                wav_pg_pid = -1;
                                wav_pi_pid = -1;
                                wav_cur_track = -1;
                                cur_type = -1;
                                stat.ripping = FALSE;

                                /* if we are only ripping, finish up for good */
                                if(!main_data->track[ temp_track ].make_mp3)
                                {
                                    calc_stat(main_data, &stat, wav_current,
                                              temp_track, WAV, CALC_STOP_SESSION);

                                    job_controller_timeout_stop();
                                    job_finisher(main_data);
                                    return;
                                }
                            }
                            else
                            {
                                /* if we are only ripping, update the stats */
                                if(!main_data->track[ temp_track ].make_mp3)
                                {
                                    stat.tracks_done++;
                                    stat.tracks_remain--;
                                }

                                /*  start ripping the next track */
                                create_file_names_for_track(main_data, wav_cur_track,
                                                            &wav_file_path, &enc_file_path);
                                calc_stat(main_data, &stat, wav_current,
                                          wav_cur_track, WAV, CALC_START);

                                if(start_ripping_encoding(WAV,
                                                          main_data->track[ wav_cur_track ].begin,
                                                          main_data->track[ wav_cur_track ].length,
                                                          wav_cur_track,
                                                          wav_file_path,
                                                          enc_file_path,
                                                          &wav_pg_pid, &wav_pi_pid,
                                                          &wav_read_fd) < 0)
                                {
                                    calc_stat(main_data, &stat, wav_current,
                                              wav_cur_track, WAV, CALC_STOP_SESSION);
                                    job_controller_timeout_stop();
                                    job_finisher(main_data);
                                    return;
                                }
                            }
                        } /* end if job is finished section */

                        break;
                } /* end rip switch */
            } /* end rip progress check */

            /* Part 2: check progress on the encode */
            if(stat.encoding == TRUE)
            {
                temp = read_and_process_plugin_output(mp3_read_fd, &mp3_progress, msg);
                mp3_current = main_data->track[ mp3_cur_track ].length * mp3_progress;

                switch(temp)
                {
                    case PLUGIN_MSG_PARSE_ERR :
                        /* Nothing to do. Let's wait more */
                        break;

                    case PLUGIN_PROGRESS_MSG :
                        /* progress report, update status display */
                        calc_stat(main_data, &stat, mp3_current,
                                  mp3_cur_track, MP3, CALC_UPDATE);

                        /* Update status widget */
                        if(msg[ 0 ] == '\0')
                        {
                            str = NULL;
                        }
                        else
                        {
                            str = msg;
                        }

                        wm_status_frame_handler(WIDGET_UPDATE, MP3, &stat, str);
                        break;

                    case PLUGIN_NO_MSG_AVAILABLE :

                        /* Check if the plugin has exited
                           It only happens when ripperX failed to execute the plugin */
                        if(mp3_pi_pid >= 0)
                            if(waitpid(mp3_pi_pid, NULL, WNOHANG) == mp3_pi_pid)
                            {
                                err_handler(PLUGIN_NOT_PRESENT_ERR,
                                            _("Maybe ripperX has failed to execute the plugin"));
                                mp3_pi_pid = -1;
                                job_controller_timeout_stop();
                                job_controller(JC_ABORT_ALL_DELETE, main_data);
                                return;
                            }

                        /* Check if the job is finished */
                        if(waitpid(mp3_pg_pid, NULL, WNOHANG) == mp3_pg_pid)
                        {
                            /* One job finished, go for next one */

                            /* kill the plugin */
                            if(waitpid(mp3_pi_pid, NULL, WNOHANG) != mp3_pi_pid)
                            {
                                kill(-mp3_pi_pid, SIGTERM);
                                waitpid(mp3_pi_pid, NULL, 0);
                            }

                            /* Close the fd */
                            close(mp3_read_fd);

                            /* stop calculating stats */
                            calc_stat(main_data, &stat, mp3_current,
                                      mp3_cur_track, MP3, CALC_STOP);

                            main_data->track[ mp3_cur_track ].mp3_exist = TRUE;

                            /* Delete WAV file if he/she doesn't want it */
                            if(!config.keep_wav)
                            {
                                create_file_names_for_track(main_data, mp3_cur_track,
                                                            &wav_file_path, &enc_file_path);

                                if(unlink(wav_file_path) < 0)
                                {
                                    err_handler(FILE_DELETE_ERR, wav_file_path);
                                }

                                /* Mark that it has been deleted */
                                main_data->track[ mp3_cur_track ].wav_exist = FALSE;

                                /* Delete WAV work directory if this was the last WAV file,
                                   and the mp3 work dir is different */
                                if(stat.tracks_remain <= 1)
                                    if(strcmp(config.wav_path,config.mp3_path) != 0)
                                    {
                                        rmdir(file_path_without_name(wav_file_path));
                                    }
                            }

                            /* find next track to encode */
                            temp_track = mp3_cur_track;

                            if(find_next_job(main_data, mp3_cur_track, MP3, &mp3_nxt_track, &cur_type) < 0)
                            {
                                /* All finished - no more encoding - done for good! */
                                mp3_pg_pid = -1;
                                mp3_pi_pid = -1;
                                mp3_cur_track = mp3_nxt_track = -1;
                                cur_type = -1;
                                calc_stat(main_data, &stat, mp3_current,
                                          temp_track, MP3, CALC_STOP_SESSION);
                                job_controller_timeout_stop();
                                stat.encoding = FALSE;

                                job_finisher(main_data);
                                return;
                            }

                            mp3_cur_track = -1;

                            stat.tracks_done++;
                            stat.tracks_remain--;
                            stat.encoding = FALSE;

                        } /* end if job is finished section */

                        break;
                } /* end encode switch */
            } /* end encode progress check */

            if(!stat.encoding && mp3_nxt_track != -1 && main_data->track[ mp3_nxt_track ].wav_exist)
            {
                /* start encoding */
                mp3_cur_track = mp3_nxt_track;
                mp3_nxt_track = -1;
                create_file_names_for_track(main_data, mp3_cur_track, &wav_file_path, &enc_file_path);
                calc_stat(main_data, &stat, mp3_current, mp3_cur_track, MP3, CALC_START);

                if(start_ripping_encoding(MP3, main_data->track[ mp3_cur_track ].begin,
                                          main_data->track[ mp3_cur_track ].length,
                                          mp3_cur_track,
                                          wav_file_path,
                                          enc_file_path,
                                          &mp3_pg_pid, &mp3_pi_pid,
                                          &mp3_read_fd) < 0)
                {
                    calc_stat(main_data, &stat, mp3_current, mp3_cur_track, MP3, CALC_STOP_SESSION);
                    job_controller_timeout_stop();
                    job_finisher(main_data);
                }

                stat.encoding = TRUE;
            }

            /* end of JC_UPDATE */
            return;
        case JC_PAUSE :
            main_data = saved_main_data;

            if(wav_pg_pid >= 0)
                if(waitpid(wav_pg_pid, NULL, WNOHANG) != wav_pg_pid)
                {
                    kill(wav_pg_pid, SIGTSTP);
                }

            if(wav_pi_pid >= 0)
                if(waitpid(wav_pi_pid, NULL, WNOHANG) != wav_pi_pid)
                {
                    kill(wav_pi_pid, SIGTSTP);
                }

            if(mp3_pg_pid >= 0)
                if(waitpid(mp3_pg_pid, NULL, WNOHANG) != mp3_pg_pid)
                {
                    kill(mp3_pg_pid, SIGTSTP);
                }

            if(mp3_pi_pid >= 0)
                if(waitpid(mp3_pi_pid, NULL, WNOHANG) != mp3_pi_pid)
                {
                    kill(mp3_pi_pid, SIGTSTP);
                }

            calc_stat(main_data, &stat, wav_current, wav_cur_track, WAV, CALC_PAUSE);
            job_controller_timeout_stop();
            return;

        case JC_CONT :
            main_data = saved_main_data;

            if(wav_pg_pid >= 0)
                if(waitpid(wav_pg_pid, NULL, WNOHANG) != wav_pg_pid)
                {
                    kill(wav_pg_pid, SIGCONT);
                }

            if(wav_pi_pid >= 0)
                if(waitpid(wav_pi_pid, NULL, WNOHANG) != wav_pi_pid)
                {
                    kill(wav_pi_pid, SIGCONT);
                }

            if(mp3_pg_pid >= 0)
                if(waitpid(mp3_pg_pid, NULL, WNOHANG) != mp3_pg_pid)
                {
                    kill(mp3_pg_pid, SIGCONT);
                }

            if(mp3_pi_pid >= 0)
                if(waitpid(mp3_pi_pid, NULL, WNOHANG) != mp3_pi_pid)
                {
                    kill(mp3_pi_pid, SIGCONT);
                }

            calc_stat(main_data, &stat, wav_current, wav_cur_track, cur_type, CALC_CONT);
            job_controller_timeout_start();
            return;

        case JC_ABORT :
        case JC_ABORT_DELETE :
        case JC_ABORT_ALL :
        case JC_ABORT_ALL_DELETE :
            main_data = saved_main_data;

            if(wav_pg_pid >= 0)
                if(waitpid(wav_pg_pid, NULL, WNOHANG) != wav_pg_pid)
                {
                    job_controller(JC_CONT, NULL);
                    kill(-wav_pg_pid, SIGTERM);
                    waitpid(wav_pg_pid, NULL, 0);
                }

            if(wav_pi_pid >= 0)
                if(waitpid(wav_pi_pid, NULL, WNOHANG) != wav_pi_pid)
                {
                    kill(-wav_pi_pid, SIGTERM);
                    waitpid(wav_pi_pid, NULL, 0);
                }

            if(mp3_pg_pid >= 0)
                if(waitpid(mp3_pg_pid, NULL, WNOHANG) != mp3_pg_pid)
                {
                    job_controller(JC_CONT, NULL);
                    kill(-mp3_pg_pid, SIGTERM);
                    waitpid(mp3_pg_pid, NULL, 0);
                }

            if(mp3_pi_pid >= 0)
                if(waitpid(mp3_pi_pid, NULL, WNOHANG) != mp3_pi_pid)
                {
                    kill(-mp3_pi_pid, SIGTERM);
                    waitpid(mp3_pi_pid, NULL, 0);
                }

            /* Close the pipe or pty */
            close(wav_read_fd);
            close(mp3_read_fd);
            calc_stat(main_data, &stat, wav_current, wav_cur_track, cur_type, CALC_STOP_SESSION);

            /* Destroy status widget */
            wm_status_frame_handler(WIDGET_DESTROY, WAV, &stat, msg);

            if((ops == JC_ABORT_ALL_DELETE) || (ops == JC_ABORT_DELETE))
            {
                create_file_names_for_track(main_data, wav_cur_track, &wav_file_path, NULL);

                if(wav_cur_track != -1)
                {
                    create_file_names_for_track(main_data, wav_cur_track, &wav_file_path, &enc_file_path);

                    if(unlink(wav_file_path) < 0)
                    {
                        err_handler(FILE_DELETE_ERR, wav_file_path);
                    }
                }

                if(mp3_cur_track != -1)
                {
                    create_file_names_for_track(main_data, mp3_cur_track, NULL, &enc_file_path);

                    if(unlink(enc_file_path) < 0)
                    {
                        err_handler(FILE_DELETE_ERR, enc_file_path);
                    }
                }
            }
            else
            {
                /* Mark that it exists */
                if(wav_cur_track != -1)
                {
                    main_data->track[ wav_cur_track ].wav_exist = TRUE;
                }

                if(mp3_cur_track != -1)
                {
                    main_data->track[ mp3_cur_track ].mp3_exist = TRUE;
                }
            }

            wav_cur_track = -1;
            mp3_cur_track = -1;
            cur_type = -1;
            calc_stat(main_data, &stat, wav_current,
                      wav_cur_track, cur_type, CALC_STOP_SESSION);
            job_controller_timeout_stop();
            job_finisher(main_data);
            return;
    }
}
int scan_cd(_main_data *main_data)
{
    pid_t pid;
    char **argv;
    char tmp[ MAX_COMMAND_LENGTH ];
    int null_fd, pty_fd, tty_fd;
    int return_value;

    /* Open a pty */
    if(openpty(&pty_fd, &tty_fd, NULL, NULL, NULL))
    {
        err_handler(PTY_OPEN_ERR, NULL);
        return - 1;
    }

    /* Open /dev/null */
    if((null_fd = open("/dev/null", O_WRONLY)) < 0)
    {
        err_handler(NULL_OPEN_ERR, NULL);
        return - 1;
    }

    /* Create argvs */
    sprintf(tmp, "%s -Q", config.ripper.ripper);

    if((argv = create_argv_for_execution_using_shell(tmp)) == NULL)
    {
        return - 1;
    }

    /* Fork */
    if((pid = fork()) < 0)
    {
        err_handler(FORK_ERR, NULL);
        return - 1;
    }

    if(pid == 0)
    {
        int stderr_fd;

        /* This code will be excuted in the child process */
        /* Save stderr before attaching to the tty */
        stderr_fd = dup(2);
        dup2(tty_fd, 2);

        /* Throw away stdout to the black hole */
        dup2(null_fd, 1);

        /* Execute cdparanoia */
        execvp(argv[ 0 ], argv);

        dup2(stderr_fd, 2);
        perror(_("Failed to exec cdparanoia :"));
        _exit(127);
    }

    close(null_fd);

    return_value = process_cd_contents_output(main_data, pty_fd);
    /* Kill again the zombie */
    waitpid(pid, NULL, 0);

    return return_value;
}
Example #16
0
int
create_filenames_from_format (_main_data * main_data)
{
  int i;
  int rc2;
  static unsigned char *df;
  GtkWidget *main_window = main_window_handler(MW_REQUEST_MW, NULL, NULL);
  char *rip_path = (char *) config_read (CONF_GNRL_RIP_PATH);
  char *enc_path = (char *) config_read (CONF_GNRL_ENC_PATH);

  i = strlen (rip_path) - 1;
  if (i >= 0 && rip_path[i] == '/')
    rip_path[i] = 0;
  i = strlen (enc_path) - 1;
  if (i >= 0 && enc_path[i] == '/')
    enc_path[i] = 0;

  char *dirformat = (char *) config_read (CONF_CDDB_DIRFORMATSTR);
  char *rip_path = (char *) config_read (CONF_GNRL_RIP_PATH);
  char *enc_path = (char *) config_read (CONF_GNRL_ENC_PATH);

  if (((char *) config_read (CONF_CDDB_MKDIRS))
      && dirformat[0])
    {
      rc2 = parse_rx_format_string (&df,
				    dirformat, -1,
				    main_data->disc_artist,
				    main_data->disc_title,
				    main_data->disc_year, "");
      if (rc2 < 0)
	{
	  err_handler (GTK_WINDOW(main_window), RX_PARSING_ERR,
		       "Check if the directory format string contains format characters other than %a %# %v %y or %s.");
	  return 0;
	}

      remove_non_unix_chars (df);
      if ((int) config_read (CONF_CDDB_CONVSPC))
	{
	  convert_spaces (df, '_');
	}

      if (strlen (df) > 0)
	{
	  mk_strcat (&wd, rip_path, "/", df, "/", NULL);
	  mk_strcat (&ed, enc_path, "/", df, "/", NULL);

	  create_dir (wd);
	  create_dir (ed);
	}
      else
	{
	  mk_strcat (&wd, rip_path, "/", NULL);
	  mk_strcat (&ed, enc_path, "/", NULL);
	}

    }
  else
    {
      mk_strcat (&wd, rip_path, "/", NULL);
      mk_strcat (&ed, enc_path, "/", NULL);
    }

  if ((int) config_read (CONF_GNRL_APP_FILE_EXT))
    {
      wfext = ".wav";
      char *encoder_type = (char *) config_read (CONF_ENCOD_TYPE);
      if (encoder_type == OGG)
	ecfext = ".ogg";
      else if (encoder_type == FLAC)
	ecfext = ".flac";
      else if (encoder_type == MP2)
	ecfext = ".mp2";
      else if (encoder_type == MUSE)
	ecfext = ".mpc";
      else
	ecfext = ".mp3";
    }
  else
    wfext = ecfext = "";
  return 1;
}
//
//                  stdout-\ pty/tty            stdout -\ pty/tty
// ripper/encoder           ---------> plugin            ---------> ripperX
//                  stderr-/                    stderr
//
//
//
int execute_ripper_encoder_with_plugin(char *pg_com,
                                       char *pi_com,
                                       int *program_pid, int *plugin_pid,
                                       int *read_fd)
{
    int pty_fd0, tty_fd0, pty_fd1, tty_fd1;
    char **program_argv, **plugin_argv;
    pid_t pid;

    // build argvs
    if((program_argv
            = create_argv_for_execution_using_shell(pg_com)) == NULL)
    {
        return - 1;
    }

    if((plugin_argv
            = create_argv_for_execution_using_shell(pi_com)) == NULL)
    {
        free_argv(program_argv);
        return - 1;
    }

    /* Open two pty/tty pairs */
    if(openpty(&pty_fd0, &tty_fd0, NULL, NULL, NULL))
    {
        free_argv(plugin_argv);
        free_argv(program_argv);
        err_handler(PTY_OPEN_ERR, NULL);
        return - 1;
    }

    if(openpty(&pty_fd1, &tty_fd1, NULL, NULL, NULL))
    {
        free_argv(plugin_argv);
        free_argv(program_argv);
        close(pty_fd0);
        close(tty_fd0);
        err_handler(PTY_OPEN_ERR, NULL);
        return - 1;
    }

    // fork & exec & link plugin
    if((pid = fork()) < 0)
    {
        free_argv(plugin_argv);
        free_argv(program_argv);
        close(pty_fd0);
        close(tty_fd0);
        close(pty_fd1);
        close(tty_fd1);
        err_handler(FORK_ERR, NULL);
        return - 1;
    }

    *plugin_pid = pid;

    if(pid == 0)
    {
        // We're in the child process
        // save stderr
        int stderr_fd;
        stderr_fd = dup(2);

        dup2(pty_fd0, 0);
        dup2(tty_fd1, 1);

        setpgrp();
        execvp(plugin_argv[ 0 ], plugin_argv);

        dup2(stderr_fd, 2);
        perror(_("Failed to exec plugin"));
        _exit(127);
    }

    // we're in the parent process
    close(pty_fd0);
    close(tty_fd1);

    // fork the real program
    if((pid = fork()) < 0)
    {
        free_argv(plugin_argv);
        free_argv(program_argv);
        close(tty_fd0);
        close(pty_fd1);
        kill(*plugin_pid, SIGTERM);
        err_handler(FORK_ERR, NULL);
        return - 1;
    }

    *program_pid = pid;

    if(pid == 0)
    {
        // We're in the child process
        // save stderr
        int stderr_fd;
        stderr_fd = dup(2);

        dup2(tty_fd0, 1);
        dup2(tty_fd0, 2);

        setpgrp();
        execvp(program_argv[ 0 ], program_argv);

        dup2(stderr_fd, 2);
        perror(_("Failed to exec the specified program"));
        _exit(127);
    }

    close(tty_fd0);
    free_argv(plugin_argv);
    free_argv(program_argv);
    *read_fd = pty_fd1;

    return 0;
}
int process_cd_contents_output(_main_data *main_data, int fd)
{
    FILE *stream;
    char buf[ BUF_LENGTH_FOR_F_SCAN_CD ];
    char errmsg[ 1024 ];
    int i, read_offset, track_num;
    char *temp;
    int err_code = CD_PARANOIA_MISC_ERR;	// err... what should it default to?
    int cdparanoia_toc = FALSE;				// assume failure to get the table of contents

    /* Reopen the pipe as stream */
    if((stream = fdopen(fd, "r")) == NULL)
    {
        err_handler(FDOPEN_ERR, _("Cannot reopen pty as stream"));
        return - 1;
    }

    temp = fgets(buf, sizeof(buf), stream);

    /* make sure we get cdparanoia, or else there is a problem */
    if(strncmp("cdparanoia III", buf, 14) != 0)
    {
        strcpy(errmsg, buf);
        err_handler(CD_PARANOIA_MISC_ERR, errmsg);
        return - 1;
    }

    // read lines until we see "Table of contents" or another error message
    do
    {
        temp = fgets(buf, sizeof(buf), stream);

        // this is a good response
        if(strncmp("Table of contents", temp, 17) == 0)
        {
            cdparanoia_toc = TRUE;
            break;
        }

        // there is no disc in the drive
        if(strncmp("Unable to open disc.", temp, 20) == 0)
        {
            err_code = CD_PARANOIA_NO_DISC;
            break;
        }

        // the user does not have permissions to open the cdrom
        // (when -sv is not used)
        if(strncmp("/dev/cdrom exists but isn\'t accessible.", temp, 39) == 0)
        {
            err_code = CD_PARANOIA_NO_PERMS;
            break;
        }

        // the user does not have permissions to open the cdrom
        // (when -d <device> is used) or the device does not exist
        if(strncmp("Unable to open cdrom drive", temp, 26) == 0)
        {
            err_code = CD_PARANOIA_MISC_ERR;
            break;
        }

        // the user does not have permissions to open the cdrom
        // (when -sv is used)
        //     OR
        // there are no CDROM devices available
        if(strncmp("No cdrom drives accessible to", temp, 29) == 0)
        {
            err_code = CD_PARANOIA_MISC_ERR;
            break;
        }
    }
    while(temp != NULL);

    /* Just to be sure, If we weren't able to read from pty it may
     * indicate exec failure */
    if(temp == NULL)
    {
        err_handler(PIPE_READ_ERR, NULL);
        return - 1;
    }

    // if we didn't get a TOC, display an error message
    if(cdparanoia_toc != TRUE)
    {
        //strncpy( errmsg, buf, BUF_LENGTH_FOR_F_SCAN_CD );
        //err_handler( err_code, errmsg );
        err_handler(err_code, NULL);
        return - 1;
    }

    /* Skip two more lines */
    for(i = 0; i < 2; i++)
    {
        fgets(buf, sizeof(buf), stream);
    }

    /* Process the output from cdparanoia */
    track_num = 0;
    temp = fgets(buf, sizeof(buf), stream);

    while(temp != NULL && strlen(buf) > 5)
    {
        /* fix for cdparanoia 9.7 */
        if(strncmp("TOTAL", buf, 5) != 0)
        {
            read_offset = 0;

            /* Skip unnecessary parts */
            while(*(buf + read_offset++) != '.') ;

            /* Read length */
            sscanf(buf + read_offset, "%u", &main_data->track[ track_num ].length);

            /* Skip */
            while(*(buf + read_offset++) != '[') ;

            /* Read begin */
            while(*(buf + read_offset++) != ']');

            sscanf(buf + read_offset, "%u", &main_data->track[ track_num ].begin);

            /* Get default track title */
            strncpy(main_data->track[ track_num ].title,
                    get_default_track_title(track_num),
                    MAX_FILE_NAME_LENGTH);

            track_num++;
        }

        temp = fgets(buf, sizeof(buf), stream);
    }

    /* Record the number of tracks */
    main_data->num_tracks = track_num;

    /* Record the total length */
    main_data->total_length = (int)((main_data->track[track_num - 1].begin + main_data->track[track_num - 1].length) / 75);

    /* Close the pipe */
    fclose(stream);

    return 0;
}