Example #1
0
void printflike2
attach_log(struct attach *atr, const char *fmt, ...)
{
	va_list	ap;
	char   *prefix;
	u_int	n;

	va_start(ap, fmt);
	xvasprintf(&prefix, fmt, ap);
	va_end(ap);

	n = 0;
	while (atr != NULL) {
		if (TAILQ_EMPTY(&atr->children)) {
			if (atr->name == NULL) {
				log_debug3("%s:%*s%u, %s: offset %zu, size %zu,"
				    " body %zu", prefix, n + 1, " ", atr->idx,
				    atr->type, atr->data, atr->size, atr->body);
			} else {
				log_debug3("%s:%*s%u, %s: offset %zu, size %zu,"
				    " body %zu: %s", prefix, n + 1, " ",
				    atr->idx, atr->type, atr->data, atr->size,
				    atr->body, atr->name);
			}
		} else {
			log_debug3("%s:%*s%u, %s", prefix, n + 1, " ", atr->idx,
			    atr->type);
		}

		atr = attach_visit(atr, &n);
	}

	xfree(prefix);
}
Example #2
0
/********************************************************************
* FUNCTION check_manager_hello
*
* Verify that the same NETCONF protocol verion is supported
* by the manager and this server
* 
* INPUTS:
*    scb == session control block
*    val == value struct for the hello message to check
*
* RETURNS:
*   status
*********************************************************************/
static status_t
    check_manager_hello (ses_cb_t *scb,
                         val_value_t *val)
{
    val_value_t  *caps, *cap;

    /* look for the NETCONF base capability string */
    caps = val_find_child(val, NC_MODULE, NCX_EL_CAPABILITIES);
    if (caps && caps->res == NO_ERR) {

        if (ncx_protocol_enabled(NCX_PROTO_NETCONF11)) {
            for (cap = val_find_child(caps, NC_MODULE, NCX_EL_CAPABILITY);
                 cap != NULL;
                 cap = val_find_next_child(caps, NC_MODULE, 
                                           NCX_EL_CAPABILITY, cap)) {
                if (cap->res == NO_ERR) {
                    if (!xml_strcmp(VAL_STR(cap), CAP_BASE_URN11)) {
                        if (LOGDEBUG3) {
                            log_debug3("\nagt_hello: set "
                                       "protocol to base:1.1");
                        }
                        return ses_set_protocol(scb, NCX_PROTO_NETCONF11);
                    }
                }
            }
        }

        if (ncx_protocol_enabled(NCX_PROTO_NETCONF10)) {
            for (cap = val_find_child(caps, NC_MODULE, NCX_EL_CAPABILITY);
                 cap != NULL;
                 cap = val_find_next_child(caps, NC_MODULE, 
                                           NCX_EL_CAPABILITY, cap)) {
                if (cap->res == NO_ERR) {
                    if (!xml_strcmp(VAL_STR(cap), CAP_BASE_URN)) {
                        if (LOGDEBUG3) {
                            log_debug3("\nagt_hello: set "
                                       "protocol to base:1.0");
                        }
                        return ses_set_protocol(scb, NCX_PROTO_NETCONF10);
                    }
                }
            }
        }
    }

    log_info("\nagt_hello: no NETCONF base:1.0 or base:1.1 URI found");
    return ERR_NCX_MISSING_VAL_INST;

} /* check_manager_hello */
Example #3
0
static void web_set_url_cover_art(GtkClipboard* board, const gchar* uri, gpointer p)
{
  library_view_t* view = (library_view_t* ) p;
  if (uri != NULL) {
    char* image_uri = mc_strdup(uri);
    hre_trim(image_uri);
    log_debug3("got uri %s, view = %p", image_uri, view);
    if ((strncasecmp(image_uri, "http://", 7) == 0) ||
      (strncasecmp(image_uri, "https://", 8) == 0)) {
      GtkTreeSelection* sel = gtk_tree_view_get_selection(view->tview);
      GtkTreeModel* model;
      GtkTreeIter iter;
      log_debug2("tree selection: %p", sel);
      if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
        log_debug("ok");
        int row = gtk_list_model_iter_to_row(GTK_LIST_MODEL(model), iter);
        track_t* track = playlist_model_get_track(view->playlist_model, row);
        log_debug2("track = %p", track);
        const char* artid = track_get_artid(track);
        log_debug3("fetch image %s, %s", image_uri, artid);
        fetch_image(image_uri, artid, image_fetched, view);
      } else {
        GtkMessageDialog* dialog = GTK_MESSAGE_DIALOG(
                                    gtk_message_dialog_new(btb_main_window(view->btb),
                                                           GTK_DIALOG_DESTROY_WITH_PARENT,
                                                           GTK_MESSAGE_ERROR,
                                                           GTK_BUTTONS_CLOSE,
                                                           _("Please select a track to set the cover art for")
                                                           )
                                    );
        gtk_dialog_run (GTK_DIALOG (dialog));
        gtk_widget_destroy (GTK_WIDGET(dialog));        
      }
    } else {
      GtkMessageDialog* dialog = GTK_MESSAGE_DIALOG( 
                                  gtk_message_dialog_new (btb_main_window(view->btb),
                                                         GTK_DIALOG_DESTROY_WITH_PARENT,
                                                         GTK_MESSAGE_ERROR,
                                                         GTK_BUTTONS_CLOSE,
                                                         _("Copy an http URL for an image to the clipboard")
                                                         )
                                  );
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (GTK_WIDGET(dialog));        
    }
    mc_free(image_uri);
  }
}
Example #4
0
void library_view_destroy(library_view_t* view)
{
  // first store the column widths
  playlist_column_enum e;
  for(e = PLAYLIST_MODEL_COL_NR; e < PLAYLIST_MODEL_N_COLUMNS; ++e) {
    char path [500];
    sprintf(path, "library.column.%s.width", column_id(e));
    int w = gtk_tree_view_column_get_width(view->cols[e]);
    log_debug3("%s = %d", path, w);
    el_config_set_int(btb_config(view->btb), path, w);
    g_object_unref(view->cols[e]);
  }
  mc_free(view->cols);
  
  if (view->run_timeout) {
    log_error("timeout has not been stopped before destroying!");
    library_view_stop_info_updater(view);
  }
  
  playlist_model_destroy(view->playlist_model);
  string_model_destroy(view->genre_model);
  string_model_destroy(view->artist_model);
  string_model_destroy(view->album_model);
  playlists_model_destroy(view->playlists_model);
  
  if (view->current_lyric_track_id != NULL) { 
    mc_free(view->current_lyric_track_id);
  }
  
  mc_free(view);
}
Example #5
0
void
parent_fetch_cmd(struct child *child, struct children *children,
    struct mail_ctx *mctx, struct msg *msg)
{
	struct mail			*m = mctx->mail;
	struct child_deliver_data	*data;
 	uid_t				 uid = msg->data.uid;
	gid_t				 gid = msg->data.gid;

	data = xmalloc(sizeof *data);
	data->child = child;
	data->msgid = msg->id;
	data->account = mctx->account;
	data->hook = child_deliver_cmd_hook;
	data->mctx = mctx;
	data->cmddata = msg->data.cmddata;
	data->mail = m;
	data->name = "command";
	data->uid = uid;
	data->gid = gid;
	child = child_start(
	    children, uid, gid, child_deliver, parent_deliver, data, child);
	log_debug3("parent: command "
	    "child %ld started (uid %lu)", (long) child->pid, (u_long) uid);
}
Example #6
0
static void library_set_aspect_filter(library_view_t* view, aspect_enum aspect)
{
  log_debug("aspect");
  
  set_t* filtered_artists = library_filtered_artists(view->library);
  set_t* filtered_albums = library_filtered_albums(view->library);
  
  log_debug3("albums %d, artists %d", set_count(filtered_albums), set_count(filtered_artists));
  
  if (aspect == GENRE_ASPECT) {
    string_model_set_valid(view->artist_model, filtered_artists);
    string_model_set_valid(view->album_model, filtered_albums);
    if (set_count(filtered_artists) <= set_count(filtered_albums)) {
      library_view_aspect_page(view, ARTIST_ASPECT);
    } else {
      library_view_aspect_page(view, ALBUM_ASPECT);
    }
  } else if (aspect == ALBUM_ASPECT) {
    string_model_set_valid(view->artist_model, filtered_artists);
  } else if (aspect == ARTIST_ASPECT) {
    string_model_set_valid(view->album_model, filtered_albums);
    library_view_aspect_page(view, ALBUM_ASPECT);
  }
  
  playlist_model_set_valid(view->playlist_model, library_filtered_tracks(view->library));
  get_column_layout(view, playlist_model_tracks_hash(view->playlist_model));
}
Example #7
0
static void library_view_play_at(library_view_t* view, int track)
{
  playlist_player_t* player = backtobasics_player(view->btb);

  log_debug3("model: %lld, player: %lld",
              playlist_model_tracks_hash(view->playlist_model),
              playlist_player_get_hash(player)
              );
              
  if (playlist_model_tracks_hash(view->playlist_model) != playlist_player_get_hash(player) ) {
    playlist_t* pl = playlist_model_get_selected_playlist(view->playlist_model);
    playlist_log(pl);
    playlist_player_set_playlist(player, pl);
    playlist_player_set_repeat(player, PLP_NO_REPEAT);
    view->time_in_ms = -1;
    playlist_player_set_track(player, track); // implies play
  } else {
    //if (!playlist_player_is_paused(player)) {
    if (track != playlist_player_get_track_index(player)) {
      playlist_player_set_track(player, track); // implies play
    } else {
      playlist_player_play(player);
    }
    //} else { // paused, play again
    //}
  }
}
Example #8
0
/********************************************************************
* FUNCTION read_txid_file
*
* Read the transaction ID file and return the current ID value found
*
* INPUTS:
*    txidfile == full filespec of the transaction ID file
*    curid == address of return ID
*
* OUTPUTS:
*    *curid == return current ID (if return NO_ERR
*
* RETURNS:
*    status
*********************************************************************/
static status_t
    read_txid_file (const xmlChar *txidfile,
                    cfg_transaction_id_t *curid)
{

    assert( txidfile && "txidfile is NULL" );
    assert( curid && "curid is NULL" );

    *curid = 0;
    status_t res = NO_ERR;
    FILE *fil = fopen((const char *)txidfile, "r");
    if (!fil) {
        res = errno_to_status();
        log_error("\nError: Open txid file for read failed (%s)", 
                  get_error_string(res));
        return res;
    } 

    char buffer [128];
    if (fgets(buffer, sizeof buffer, fil)) {
        /* expecting just 1 line containing the ASCII encoding of
         * the transaction ID  */
        log_debug4("\nRead transaction ID line '%s'", buffer);

        uint32 len = xml_strlen((const xmlChar *)buffer);
        if (len > 1) {
            /* strip ending newline */
            buffer[len-1] = 0;

            ncx_num_t num;
            ncx_init_num(&num);
            res = ncx_convert_num((xmlChar *)buffer, NCX_NF_DEC, NCX_BT_UINT64,
                                  &num);
            if (res == NO_ERR) {
                agt_cfg_txid = num.ul;
                *curid = num.ul;
                log_debug3("\nGot transaction ID line '%llu'", 
                           (unsigned long long)num.ul);
            } else {
                log_error("\nError: txid is not valid (%s)",
                          get_error_string(res));
            }
            ncx_clean_num(NCX_BT_UINT64, &num);
        } else {
            res = ERR_NCX_INVALID_NUM;
            log_error("\nError: txid is not valid (%s)",
                      get_error_string(res));
        }
    } else {
        res = errno_to_status();
        log_error("\nError: Read txid file failed (%s)", 
                  get_error_string(res));
    }

    fclose(fil);

    return res;

} /* read_txid_file */
Example #9
0
static cue_t *mp3cue_readcue_in_hash(const char *path, int update_data)
{
  char *fullpath = make_path(path);
  char *cuefile = isCueFile(fullpath);
  log_debug3("reading cuefile %s for %s", cuefile, fullpath);
  cue_t *cue = (cue_t *) mc_take_over(cue_new(cuefile));
  struct stat st;
  stat(cuefile, &st);
  MK_READONLY(st);
  if (cue != NULL && cue_valid(cue)) {
    int added = 0;
    int i, N;

    // check if cue already exists in hash. If not, create whole cue in hash and read in again.
    for (i = 0, N = cue_count(cue); i < N; i++) {
      cue_entry_t *entry = cue_entry(cue, i);
      char *p = make_path2(path, cue_entry_vfile(entry));

      log_debug2("p=%s", p);
      if (datahash_exists(DATA, p)) {
        // update entry only if requested
        if ( update_data ) {
          // only update the data in d, otherwise we won't be thread safe!
          // Never deallocate an entry in the hash!
          // We also know, that when the track title is changed, there will be a
          // new entry in the hash, so, we get some rubbish but don't care.
          // We update the file sizes and the cue_entry here.

          // So we need a monitor around the file operations that act on the hash
          // data.

          data_entry_t *dd = datahash_get(DATA, p);
          cue_entry_destroy(dd->entry);
          dd->entry=entry;
          dd->st[0]=st;

          // we don't need to update dd->path as dd->path and p must be equal
        }
      } else {
        data_entry_t *d = data_entry_new(p, entry, &st);
        datahash_put(DATA, p, d);
        added = 1;
      }

      mc_free(p);
    }

    if (added) {
      mc_free(cuefile);
      mc_free(fullpath);
      return mp3cue_readcue_in_hash(path, false);
    }
  }

  mc_free(cuefile);
  mc_free(fullpath);
  return cue;
}
Example #10
0
/********************************************************************
* FUNCTION agt_init1
* 
* Initialize the Server Library: stage 1: CLI and profile
* 
* TBD -- put platform-specific server init here
*
* INPUTS:
*   argc == command line argument count
*   argv == array of command line strings
*   showver == address of version return quick-exit status
*   showhelp == address of help return quick-exit status
*
* OUTPUTS:
*   *showver == TRUE if user requsted version quick-exit mode
*   *showhelp == TRUE if user requsted help quick-exit mode
*
* RETURNS:
*   status of the initialization procedure
*********************************************************************/
status_t 
    agt_init1 (int argc,
               char *argv[],
               boolean *showver,
               help_mode_t *showhelpmode)
{
    status_t  res;

    if (agt_init_done) {
        return NO_ERR;
    }

    log_debug3("\nServer Init Starting...");

    res = NO_ERR;

    /* initialize shutdown variables */
    agt_shutdown = FALSE;
    agt_shutdown_started = FALSE;
    agt_shutmode = NCX_SHUT_NONE;
    dlq_createSQue(&agt_dynlibQ);

    *showver = FALSE;
    *showhelpmode = HELP_MODE_NONE;

    /* allow cleanup to run even if this fn does not complete */
    agt_init_done = TRUE;

    init_server_profile();

    /* setup $HOME/.yuma directory */
    res = ncxmod_setup_yumadir();
    if (res != NO_ERR) {
        return res;
    }

    /* get the command line params and also any config file params */
    res = agt_cli_process_input(argc, argv, &agt_profile, showver, 
                                showhelpmode);
    if (res != NO_ERR) {
        return res;
    } /* else the agt_profile is filled in */

    /* check if quick exit mode */
    if (*showver || (*showhelpmode != HELP_MODE_NONE)) {
        return NO_ERR;
    }

    /* loglevel and log file already set */
    return res;

} /* agt_init1 */
Example #11
0
library_view_t* library_view_new(Backtobasics* btb, library_t* library)
{
  library_view_t* view = (library_view_t*) mc_malloc(sizeof(library_view_t));
  view->btb = btb;
  view->builder = btb->builder;
  view->library = library;
  
  view->playlist_model = mc_take_over(playlist_model_new());
  //view->library_list_changed = el_false;
  //view->library_list_hash = playlist_model_tracks_hash(view->playlist_model);
  
  view->genre_model = string_model_new();
  view->artist_model = string_model_new();
  view->album_model = string_model_new();
  
  view->aspect = GENRE_ASPECT;
  view->previous_aspect = NONE_ASPECT;
  
  playlist_model_set_playlist(view->playlist_model, library_current_selection(view->library, _("Library")));
  
  string_model_set_array(view->genre_model, library_genres(view->library), el_false);
  string_model_set_array(view->artist_model, library_artists(view->library), el_false);
  string_model_set_array(view->album_model, library_albums(view->library), el_false);
  
  view->run_timeout = el_true;
  view->time_in_ms = -1;
  view->len_in_ms = -1;
  view->track_index = -1;
  view->track_id = NULL;
  view->sliding = 0;
  view->repeat = -1;
  
  view->img_w = el_config_get_int(btb_config(view->btb), "image_art.width", 200);
  view->img_h = el_config_get_int(btb_config(view->btb), "image_art.height", 200);
  log_debug3("image art w=%d, h=%d", view->img_w, view->img_h);
  
  view->btn_play = NULL;
  view->btn_pause = NULL;
  view->cols = NULL;
  
  view->ignore_sel_changed = el_false;
  
  view->playlists_model = playlists_model_new(view->library);
  
  view->current_lyric_track_id = NULL;
  
  view->column_layout_changing = el_false;
  
  return view;
}
Example #12
0
void
parent_fetch_action(struct child *child, struct children *children,
    struct deliver_ctx *dctx, struct msg *msg)
{
	struct actitem			*ti = msg->data.actitem;
	struct mail			*m = dctx->mail;
	struct mail			*md = &dctx->wr_mail;
	struct child_deliver_data	*data;
 	uid_t				 uid = msg->data.uid;
	gid_t				 gid = msg->data.gid;

	memset(md, 0, sizeof *md);
	/*
	 * If writing back, open a new mail now and set its ownership so it
	 * can be accessed by the child.
	 */
	if (ti->deliver->type == DELIVER_WRBACK) {
		if (mail_open(md, IO_BLOCKSIZE) != 0) {
			log_warn("parent: failed to create mail");
			parent_fetch_error(child, msg);
			return;
		}
		if (geteuid() == 0 &&
		    shm_owner(&md->shm, conf.child_uid, conf.child_gid) != 0) {
			mail_destroy(md);
			log_warn("parent: failed to set mail ownership");
			parent_fetch_error(child, msg);
			return;
		}
		md->decision = m->decision;
	}

	data = xmalloc(sizeof *data);
	data->child = child;
	data->msgid = msg->id;
	data->account = dctx->account;
	data->hook = child_deliver_action_hook;
	data->actitem = ti;
	data->dctx = dctx;
	data->mail = m;
	data->name = "deliver";
	data->uid = uid;
	data->gid = gid;
	child = child_start(
	    children, uid, gid, child_deliver, parent_deliver, data, child);
	log_debug3("parent: deliver "
	    "child %ld started (uid %lu)", (long) child->pid, (u_long) uid);
}
Example #13
0
segmenter_t *find_seg_entry(cue_entry_t * e)
{
  char *id = cue_entry_alloc_id(e);
  seglist_lock(SEGMENT_LIST);
  seg_entry_t *se = seglist_start_iter(SEGMENT_LIST, LIST_FIRST);
  while (se != NULL && strcmp(se->id, id) != 0) {
    se = seglist_next_iter(SEGMENT_LIST);
  }
  log_debug3("found segment %p for id %s", se, id);
  mc_free(id);
  seglist_unlock(SEGMENT_LIST);
  if (se == NULL) {
    return NULL;
  } else {
    return se->segment;
  }
}
Example #14
0
/********************************************************************
* FUNCTION agt_cfg_free_transaction
*
* Clean and free a agt_cfg_transaction_t struct
*
* INPUTS:
*    txcb == transaction struct to free
*********************************************************************/
void
    agt_cfg_free_transaction (agt_cfg_transaction_t *txcb)
{
    if (txcb == NULL) {
        return;
    }

    /* clear current config txid if any */
    if (txcb->txid) {
        cfg_template_t *cfg = cfg_get_config_id(txcb->cfg_id);
        if (cfg) {
            if (cfg->cur_txid == txcb->txid) {
                log_debug3("\nClearing current txid for %s config",
                           cfg->name);
                cfg->cur_txid = 0;
            }
        }
    }

    /* clean undo queue */
    while (!dlq_empty(&txcb->undoQ)) {
        agt_cfg_undo_rec_t *undorec = (agt_cfg_undo_rec_t *)
            dlq_deque(&txcb->undoQ);
        agt_cfg_free_undorec(undorec);
    }

    /* clean audit queue */
    while (!dlq_empty(&txcb->auditQ)) {
        agt_cfg_audit_rec_t *auditrec = (agt_cfg_audit_rec_t *)
            dlq_deque(&txcb->auditQ);
        agt_cfg_free_auditrec(auditrec);
    }

    /* clean dead node queue */
    while (!dlq_empty(&txcb->deadnodeQ)) {
        agt_cfg_nodeptr_t *nodeptr = (agt_cfg_nodeptr_t *)
            dlq_deque(&txcb->deadnodeQ);
        agt_cfg_free_nodeptr(nodeptr);
    }

    m__free(txcb);

}  /* agt_cfg_free_transaction */
Example #15
0
/* Sleep for lock. */
int
locksleep(const char *hdr, const char *path, long long *used)
{
	useconds_t	us;

	if (*used == 0)
		srandom((u_int) getpid());

	us = LOCKSLEEPTIME + (random() % LOCKSLEEPTIME);
	log_debug3("%s: %s: "
	    "sleeping %.3f seconds for lock", hdr, path, us / 1000000.0);
	usleep(us);

	*used += us;
	if (*used < LOCKTOTALTIME)
		return (0);
	log_warnx("%s: %s: "
	    "couldn't get lock in %.3f seconds", hdr, path, *used / 1000000.0);
	return (-1);
}
Example #16
0
/* Search state 2. */
int
imap_state_search2(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_imap_data	*data = a->data;
	char			*line, *ptr;
	u_int			 uid;

	if (imap_getln(a, fctx, IMAP_UNTAGGED, &line) != 0)
		return (FETCH_ERROR);
	if (line == NULL)
		return (FETCH_BLOCK);

	/* Skip the header. */
	if (strncasecmp(line, "* SEARCH", 8) != 0)
		return (imap_bad(a, line));
	line += 8;

	/* Read each UID and save it. */
	do {
		while (isspace((u_char) *line))
			line++;
		ptr = strchr(line, ' ');
		if (ptr == NULL)
			ptr = strchr(line, '\0');
		if (ptr == line)
			break;

		if (sscanf(line, "%u", &uid) != 1)
			return (imap_bad(a, line));
		ARRAY_ADD(&data->wanted, uid);
		log_debug3("%s: fetching UID: %u", a->name, uid);

		line = ptr;
	} while (*line == ' ');

	fctx->state = imap_state_search3;
	return (FETCH_AGAIN);
}
Example #17
0
/* Check mail against next rule or part of expression. */
int
mail_match(struct mail_ctx *mctx, struct msg *msg, struct msgbuf *msgbuf)
{
	struct account	*a = mctx->account;
	struct mail	*m = mctx->mail;
	struct expritem	*ei;
	struct replstrs	*users;
	int		 should_free, this = -1, error = MAIL_CONTINUE;
	char		 desc[DESCBUFSIZE];

	set_wrapped(m, ' ');

	/* If blocked, check for msgs from parent. */
	if (mctx->msgid != 0) {
		if (msg == NULL || msg->id != mctx->msgid)
			return (MAIL_BLOCKED);
		mctx->msgid = 0;

		if (msg->type != MSG_DONE)
			fatalx("unexpected message");
		if (msgbuf->buf != NULL && msgbuf->len != 0) {
			strb_destroy(&m->tags);
			m->tags = msgbuf->buf;
			reset_tags(&m->tags);
		}

		ei = mctx->expritem;
		switch (msg->data.error) {
		case MATCH_ERROR:
			return (MAIL_ERROR);
		case MATCH_TRUE:
			this = 1;
			break;
		case MATCH_FALSE:
			this = 0;
			break;
		default:
			fatalx("unexpected response");
		}
		apply_result(ei, &mctx->result, this);

		goto next_expritem;
	}

	/* Check for completion and end of ruleset. */
	if (mctx->done)
		return (MAIL_DONE);
	if (mctx->rule == NULL) {
		switch (conf.impl_act) {
		case DECISION_NONE:
			log_warnx("%s: reached end of ruleset. no "
			    "unmatched-mail option; keeping mail",  a->name);
			m->decision = DECISION_KEEP;
			break;
		case DECISION_KEEP:
			log_debug2("%s: reached end of ruleset. keeping mail",
			    a->name);
			m->decision = DECISION_KEEP;
			break;
		case DECISION_DROP:
			log_debug2("%s: reached end of ruleset. dropping mail",
			    a->name);
			m->decision = DECISION_DROP;
			break;
		}
		return (MAIL_DONE);
	}

	/* Expression not started. Start it. */
	if (mctx->expritem == NULL) {
		/* Start the expression. */
		mctx->result = 0;
		mctx->expritem = TAILQ_FIRST(mctx->rule->expr);
	}

	/* Check this expression item and adjust the result. */
	ei = mctx->expritem;

	/* Handle short-circuit evaluation. */
	switch (ei->op) {
	case OP_NONE:
		break;
	case OP_AND:
		/* And and the result is already false. */
		if (!mctx->result)
			goto next_expritem;
		break;
	case OP_OR:
		/* Or and the result is already true. */
		if (mctx->result)
			goto next_expritem;
		break;
	}

	switch (ei->match->match(mctx, ei)) {
	case MATCH_ERROR:
		return (MAIL_ERROR);
	case MATCH_PARENT:
		return (MAIL_BLOCKED);
	case MATCH_TRUE:
		this = 1;
		break;
	case MATCH_FALSE:
		this = 0;
		break;
	default:
		fatalx("unexpected op");
	}
	apply_result(ei, &mctx->result, this);

	ei->match->desc(ei, desc, sizeof desc);
	log_debug3("%s: tried %s, result now %d", a->name, desc, mctx->result);

next_expritem:
	/* Move to the next item. If there is one, then return. */
	mctx->expritem = TAILQ_NEXT(mctx->expritem, entry);
	if (mctx->expritem != NULL)
		return (MAIL_CONTINUE);

	log_debug3("%s: finished rule %u, result %d", a->name, mctx->rule->idx,
	    mctx->result);

	/* If the result was false, skip to find the next rule. */
	if (!mctx->result)
		goto next_rule;
	log_debug2("%s: matched to rule %u", a->name, mctx->rule->idx);

	/*
	 * If this rule is stop, mark the context so when we get back after
	 * delivery we know to stop.
	 */
	if (mctx->rule->stop)
		mctx->done = 1;

	/* Handle nested rules. */
	if (!TAILQ_EMPTY(&mctx->rule->rules)) {
		log_debug2("%s: entering nested rules", a->name);

		/*
		 * Stack the current rule (we are at the end of it so the
		 * the expritem must be NULL already).
		 */
		ARRAY_ADD(&mctx->stack, mctx->rule);

		/* Continue with the first rule of the nested list. */
		mctx->rule = TAILQ_FIRST(&mctx->rule->rules);
		return (MAIL_CONTINUE);
	}
	mctx->matched = 1;

	/* Handle lambda actions. */
	if (mctx->rule->lambda != NULL) {
		users = find_delivery_users(mctx, NULL, &should_free);

		chained = MAXACTIONCHAIN;
		if (fill_from_action(mctx,
		    mctx->rule, mctx->rule->lambda, users) != 0) {
			if (should_free)
				ARRAY_FREEALL(users);
			return (MAIL_ERROR);
		}

		if (should_free)
			ARRAY_FREEALL(users);
		error = MAIL_DELIVER;
	}

	/* Fill the delivery action queue. */
	if (!ARRAY_EMPTY(mctx->rule->actions)) {
		chained = MAXACTIONCHAIN;
		if (fill_from_strings(mctx,
		    mctx->rule, mctx->rule->actions) != 0)
			return (MAIL_ERROR);
		error = MAIL_DELIVER;
	}

next_rule:
	/* Move to the next rule. */
	mctx->ruleidx = mctx->rule->idx;	/* save last index */
	mctx->rule = TAILQ_NEXT(mctx->rule, entry);

	/* If no more rules, try to move up the stack. */
	while (mctx->rule == NULL) {
		if (ARRAY_EMPTY(&mctx->stack))
			break;
		log_debug2("%s: exiting nested rules", a->name);
		mctx->rule = ARRAY_LAST(&mctx->stack);
		mctx->rule = TAILQ_NEXT(mctx->rule, entry);
		ARRAY_TRUNC(&mctx->stack, 1);
	}

	return (error);
}
Example #18
0
/* Open state. */
int
fetch_mbox_state_open(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_mbox_data	*data = a->data;
	struct fetch_mbox_mbox	*fmbox;
	char			*ptr;
	struct stat		 sb;
	uintmax_t		 size;
	long long		 used;

	fmbox = ARRAY_ITEM(&data->fmboxes, data->index);

	log_debug2("%s: trying path: %s", a->name, fmbox->path);
	if (stat(fmbox->path, &sb) != 0)
		goto error;
	if (S_ISDIR(sb.st_mode)) {
		errno = EISDIR;
		goto error;
	}
	if (sb.st_size == 0) {
		fctx->state = fetch_mbox_state_next;
		return (FETCH_AGAIN);
	}
	if (sb.st_size < 5) {
		log_warnx("%s: %s: mbox too small", a->name, fmbox->path);
		return (FETCH_ERROR);
	}
	size = sb.st_size;
	if (size > SIZE_MAX) {
		log_warnx("%s: %s: mbox too big", a->name, fmbox->path);
		return (FETCH_ERROR);
	}
	fmbox->size = size;

	log_debug3("%s: opening mbox, size %ju", a->name, size);
	used = 0;
	do {
		fmbox->fd = openlock(fmbox->path, O_RDWR, conf.lock_types);
		if (fmbox->fd == -1) {
			if (errno == EAGAIN) {
				if (locksleep(a->name, fmbox->path, &used) != 0)
					return (FETCH_ERROR);
				continue;
			}
			goto error;
		}
	} while (fmbox->fd < 0);

	/* mmap the file. */
	fmbox->base = mmap(
	    NULL, fmbox->size, PROT_READ|PROT_WRITE, MAP_SHARED, fmbox->fd, 0);
	madvise(fmbox->base, fmbox->size, MADV_SEQUENTIAL);
	if (fmbox->base == MAP_FAILED) {
		fmbox->base = NULL;
		goto error;
	}
	data->off = 0;

	ptr = memchr(fmbox->base, '\n', fmbox->size);
	if (strncmp(fmbox->base, "From ", 5) != 0) {
		log_warnx("%s: %s: not an mbox", a->name, fmbox->path);
		return (FETCH_ERROR);
	}

	fctx->state = fetch_mbox_state_mail;
	return (FETCH_AGAIN);

error:
	if (fmbox->base != NULL) {
		munmap(fmbox->base, fmbox->size);
		fmbox->base = NULL;
	}
	if (fmbox->fd != -1) {
		closelock(fmbox->fd, fmbox->path, conf.lock_types);
		fmbox->fd = -1;
	}
	log_warn("%s: %s", a->name, fmbox->path);
	return (FETCH_ERROR);
}
Example #19
0
/********************************************************************
* FUNCTION agt_init2
* 
* Initialize the Server Library
* The agt_profile is set and the object database is
* ready to have YANG modules loaded
*
* RPC and data node callbacks should be installed
* after the module is loaded, and before the running config
* is loaded.
*
* RETURNS:
*   status
*********************************************************************/
status_t 
    agt_init2 (void)
{
    val_value_t        *clivalset;
    ncx_module_t       *retmod;
    val_value_t        *val;
    agt_dynlib_cb_t    *dynlib;
    xmlChar            *savestr, *revision, savechar;
    cfg_template_t     *cfg;
    status_t            res;
    uint32              modlen;
    boolean             startup_loaded;

    log_debug3("\nServer Init-2 Starting...");

    startup_loaded = FALSE;

    /* init user callback support */
    agt_cb_init();
    agt_commit_complete_init();
    agt_commit_validate_init();
    agt_not_queue_notification_cb_init();

    /* initial signal handler first to allow clean exit */
    agt_signal_init();

    /* initialize the server timer service */
    agt_timer_init();
    
    /* initialize the RPC server callback structures */
    res = agt_rpc_init();
    if (res != NO_ERR) {
        log_debug3("\nError in rpc_init");
        return res;
    }

    /* initialize the NCX connect handler */
    res = agt_connect_init();
    if (res != NO_ERR) {
        log_debug3("\nError in agt_connect_init");
        return res;
    }

    /* initialize the NCX hello handler */
    res = agt_hello_init();
    if (res != NO_ERR) {
        log_debug3("\nError in agt_hello_init");
        return res;
    }

    /* setup an empty <running> config 
     * The config state is still CFG_ST_INIT
     * so no user access can occur yet (except OP_LOAD by root)
     */
    res = cfg_init_static_db(NCX_CFGID_RUNNING);
    if (res != NO_ERR) {
        return res;
    }

    /* set the 'ordered-by system' sorted/not-sorted flag */
    ncx_set_system_sorted(agt_profile.agt_system_sorted);

    /* set the 'top-level mandatory objects allowed' flag */
    ncx_set_top_mandatory_allowed(!agt_profile.agt_running_error);

    /*** All Server profile parameters should be set by now ***/

    /* must set the server capabilities after the profile is set */
    res = agt_cap_set_caps(agt_profile.agt_targ, 
                           agt_profile.agt_start,
                           agt_profile.agt_defaultStyle);
    if (res != NO_ERR) {
        return res;
    }

    /* setup the candidate config if it is used */
    if (agt_profile.agt_targ==NCX_AGT_TARG_CANDIDATE) {
        res = cfg_init_static_db(NCX_CFGID_CANDIDATE);
        if (res != NO_ERR) {
            return res;
        }
    }

    /* setup the startup config if it is used */
    if (agt_profile.agt_start==NCX_AGT_START_DISTINCT) {
        res = cfg_init_static_db(NCX_CFGID_STARTUP);
        if (res != NO_ERR) {
            return res;
        }
    }

    /* initialize the server access control model */
    res = agt_acm_init();
    if (res != NO_ERR) {
        return res;
    }

    /* initialize the session handler data structures */
    agt_ses_init();

    /* load the system module */
    res = agt_sys_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the NETCONF state monitoring data model module */
    res = agt_state_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the NETCONF Notifications data model module */
    res = agt_not_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the NETCONF /proc monitoring data model module */
    res = agt_proc_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the partial lock module */
    res = y_ietf_netconf_partial_lock_init
        (y_ietf_netconf_partial_lock_M_ietf_netconf_partial_lock,
         NULL);
    if (res != NO_ERR) {
        return res;
    }
#if 0  // OpenClovis: we do not want this by default
    /* load the NETCONF interface monitoring data model module */
    res = agt_if_init();
    if (res != NO_ERR) {
        return res;
    }
#endif
    /* initialize the NCX server core callback functions.
     * the schema (yuma-netconf.yang) for these callbacks was 
     * already loaded in the common ncx_init
     * */
    res = agt_ncx_init();
    if (res != NO_ERR) {
        return res;
    }

    /* load the yuma-time-filter module */
    res = y_yuma_time_filter_init
        (y_yuma_time_filter_M_yuma_time_filter, NULL);
    if (res != NO_ERR) {
        return res;
    }

    /* load the yuma-arp module */
    res = y_yuma_arp_init(y_yuma_arp_M_yuma_arp, NULL);
    if (res != NO_ERR) {
        return res;
    }

    /* check the module parameter set from CLI or conf file
     * for any modules to pre-load
     */
    res = NO_ERR;
    clivalset = agt_cli_get_valset();
    if (clivalset) {

        if (LOGDEBUG) {
            log_debug("\n\nnetconfd final CLI + .conf parameters:\n");
            val_dump_value_max(clivalset, 0, NCX_DEF_INDENT, DUMP_VAL_LOG,
                               NCX_DISPLAY_MODE_PLAIN, FALSE, /* withmeta */
                               TRUE /* config only */);
            log_debug("\n");
        }

        /* first check if there are any deviations to load */
        val = val_find_child(clivalset, NCXMOD_NETCONFD, NCX_EL_DEVIATION);
        while (val) {
            res = ncxmod_load_deviation(VAL_STR(val), 
                                        &agt_profile.agt_savedevQ);
            if (res != NO_ERR) {
                return res;
            } else {
                val = val_find_next_child(clivalset,
                                          NCXMOD_NETCONFD,
                                          NCX_EL_DEVIATION,
                                          val);
            }
        }

        val = val_find_child(clivalset, NCXMOD_NETCONFD, NCX_EL_MODULE);

        /* attempt all dynamically loaded modules */
        while (val && res == NO_ERR) {
            /* see if the revision is present in the
             * module parameter or not
             */
            modlen = 0;
            revision = NULL;
            savestr = NULL;
            savechar = '\0';

            if (yang_split_filename(VAL_STR(val), &modlen)) {
                savestr = &(VAL_STR(val)[modlen]);
                savechar = *savestr;
                *savestr = '\0';
                revision = savestr + 1;
            }

#ifdef STATIC_SERVER
            /* load just the module
             * SIL initialization is assumed to be
             * handled elsewhere
             */
             res = ncxmod_load_module(VAL_STR(val),
                                     revision,
                                     &agt_profile.agt_savedevQ,
                                     &retmod);
            }
            
#else
            /* load the SIL and it will load its own module */
            res = agt_load_sil_code(VAL_STR(val), revision, FALSE);
            if (res == ERR_NCX_SKIPPED) {
                log_warn("\nWarning: SIL code for module '%s' not found",
                         VAL_STR(val));
                res = ncxmod_load_module(VAL_STR(val),
                                         revision,
                                         &agt_profile.agt_savedevQ,
                                         &retmod);
            }
#endif

            if (savestr != NULL) {
                *savestr = savechar;
            }

            if (res == NO_ERR) {
                val = val_find_next_child(clivalset,
                                          NCXMOD_NETCONFD,
                                          NCX_EL_MODULE,
                                          val);
            }
        }
    }
Example #20
0
/********************************************************************
* FUNCTION mgr_xml_skip_subtree
* 
* Already encountered an error, so advance nodes until the
* matching start-node is reached or a terminating error occurs
*   - end of input
*   - start depth level reached
*
* INPUTS:
*   reader == XmlReader already initialized from File, Memory,
*             or whatever
*   startnode  == xml_node_t of the start node of the sub-tree to skip
* RETURNS:
*   status of the operation
* SIDE EFFECTS:
*   the xmlreader state is advanced until the current node is the
*   end node of the specified start node or a fatal error occurs
*********************************************************************/
status_t 
    mgr_xml_skip_subtree (xmlTextReaderPtr reader,
                          const xml_node_t *startnode)
{
    xml_node_t       node;
    const xmlChar   *qname, *badns;
    uint32           len;
    int              ret, depth, nodetyp;
    xmlns_id_t       nsid;
    boolean          done, justone;
    status_t         res;

#ifdef DEBUG
    if (!reader || !startnode) {
        return SET_ERROR(ERR_INTERNAL_PTR);
    }
#endif

    justone = FALSE;

    switch (startnode->nodetyp) {
    case XML_NT_START:
        break;
    case XML_NT_EMPTY:
        return NO_ERR;
    case XML_NT_STRING:
        justone = TRUE;
        break;
    case XML_NT_END:
        return NO_ERR;
    default:
        return SET_ERROR(ERR_INTERNAL_VAL);
    }
    xml_init_node(&node);
    res = mgr_xml_consume_node_noadv(reader, &node);
    if (res == NO_ERR) {
        res = xml_endnode_match(startnode, &node);
        if (res == NO_ERR) {
            xml_clean_node(&node);
            return NO_ERR;
        }
    }

    xml_clean_node(&node);
    if (justone) {
        return NO_ERR;
    }

    done = FALSE;
    while (!done) {

        /* advance the node pointer */
        ret = xmlTextReaderRead(reader);
        if (ret != 1) {
            /* fatal error */
            return ERR_XML_READER_EOF;
        }

        /* get the node depth to match the end node correctly */
        depth = xmlTextReaderDepth(reader);
        if (depth == -1) {
            /* not sure if this can happen, treat as fatal error */
            return ERR_XML_READER_INTERNAL;
        } else if (depth <= startnode->depth) {
            /* this depth override will cause errors to be ignored
             *   - wrong namespace in matching end node
             *   - unknown namespace in matching end node
             *   - wrong name in 'matching' end node
             */
            done = TRUE;
        }

        /* get the internal nodetype, check it and convert it */
        nodetyp = xmlTextReaderNodeType(reader);

        /* get the element QName */
        qname = xmlTextReaderConstName(reader);
        if (qname) {
            /* check for namespace prefix in the name 
             * only error is 'unregistered namespace ID'
             * which doesn't matter in this case
             */
            nsid = 0;
            (void)xml_check_ns(reader, qname, &nsid, &len, &badns);
        } else {
            qname = (const xmlChar *)"";
        }

        /* check the normal case to see if the search is done */
        if (depth == startnode->depth &&
            !xml_strcmp(qname, startnode->qname) &&
            nodetyp == XML_ELEMENT_DECL) {
            done = TRUE;
        }

#ifdef XML_UTIL_DEBUG
        log_debug3("\nxml_skip: %s L:%d T:%s",
               qname, depth, xml_get_node_name(nodetyp));
#endif
    }

    return NO_ERR;

}  /* mgr_xml_skip_subtree */
/********************************************************************
 * FUNCTION handle_alias_parm
 * 
 * alias def
 * alias def=def-value
 *
 * Handle the alias command, based on the parameter
 *
 * INPUTS:
 *    varstr == alias command line
 *    setonly == TRUE if expecting set version only; ignore show alias
 *               FALSE if expecting show alias or set alias
 *    loginfo == TRUE if log-level=info should be used
 *               FALSE if log-level=debug2 should be used
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    handle_alias_parm (const xmlChar *varstr,
                       boolean setonly,
                       boolean loginfo)
{
    const xmlChar *valptr = NULL;    
    uint32    nlen = 0;
    status_t  res;

    res = parse_alias(varstr, &nlen, &valptr);
    if (res == NO_ERR) {
        if (valptr) {
            /* setting an alias */
            alias_cb_t *alias = find_alias(varstr, nlen);
            if (alias) {
                if (LOGDEBUG3) {
                    log_debug3("\nAbout to replace alias '%s'"
                               "\n  old value: '%s'"
                               "\n  new value: '%s'",
                               alias->name, 
                               alias->value ? alias->value : EMPTY_STRING,
                               valptr);
                }
                /* modify an existing alias */
                res = set_alias(alias, valptr);
                if (res == NO_ERR) {
                    if (loginfo) {
                        log_info("\nUpdated alias '%s'\n", alias->name);
                    } else {
                        log_debug2("\nUpdated alias '%s'", alias->name);
                    }
                } else {
                    log_error("\nError: invalid alias value '%s'\n",
                              valptr);
                }
            } else {
                /* create a new alias */
                alias = new_alias(varstr, nlen);
                if (alias == NULL) {
                    res = ERR_INTERNAL_MEM;
                } else {
                    res = set_alias(alias, valptr);
                    if (res == NO_ERR) {
                        res = add_alias(alias);
                        if (res == NO_ERR) {
                            if (loginfo) {
                                log_info("\nAdded alias '%s'\n", alias->name);
                            } else {
                                log_debug2("\nAdded alias '%s'", alias->name);
                            }
                        } else {
                            log_error("\nError: alias was not added '%s'\n",
                                      get_error_string(res));
                        }
                    } else {
                        log_error("\nError: invalid alias value '%s'\n",
                                  valptr);
                        free_alias(alias);
                    }
                }
            }
        } else if (!setonly) {
            /* just provided a name; show alias */
            show_alias_name(varstr, nlen);
        } else if (LOGDEBUG) {
            log_debug("\nSkipping alias '%s' because no value set", varstr);
        }
    } else if (res == ERR_NCX_INVALID_NAME) {
        log_error("\nError: invalid alias (%s)", get_error_string(res));
    } else {
        log_error("\nError: invalid alias '%s' (%s)", varstr,
                  get_error_string(res));
    }
    return res;

}  /* handle_alias_parm */
Example #22
0
/********************************************************************
* FUNCTION agt_top_dispatch_msg
* 
* Find the appropriate top node handler and call it
* called by the transport manager (through the session manager)
* when a new message is detected
*
* INPUTS:
*   scb == session control block containing the xmlreader
*          set at the start of an incoming message.
*
* RETURNS:
*  none
*********************************************************************/
void
    agt_top_dispatch_msg (ses_cb_t **ppscb)
{
    ses_total_stats_t  *myagttotals;
    agt_profile_t      *profile;
    xml_node_t          top;
    status_t            res;
    top_handler_t       handler;
    ses_cb_t           *scb = *ppscb;
    
#ifdef DEBUG
    if (!scb) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    myagttotals = ses_get_total_stats();
    profile = agt_get_profile();

    xml_init_node(&top);

    /* get the first node */
    res = agt_xml_consume_node(scb, 
                               &top, 
                               NCX_LAYER_TRANSPORT, 
                               NULL);
    if (res != NO_ERR) {
        scb->stats.inBadRpcs++;
        myagttotals->stats.inBadRpcs++;
        myagttotals->droppedSessions++;

        if (LOGINFO) {
            log_info("\nagt_top: bad msg for session %d (%s)",
                     scb->sid, 
                     get_error_string(res));
        }

        xml_clean_node(&top);
        agt_ses_free_session(scb);

        /* set the supplied ptr to ptr to scb to NULL so that the 
         * caller of this function knows that it was deallotcated */
        *ppscb=NULL;
        return;
    }

    log_debug3("\nagt_top: got node");
    if (LOGDEBUG4 && scb->state != SES_ST_INIT) {
        xml_dump_node(&top);
    }

    /* check node type and if handler exists, then call it */
    if (top.nodetyp==XML_NT_START || top.nodetyp==XML_NT_EMPTY) {
        /* find the owner, elname tuple in the topQ */
        handler = top_find_handler(top.module, top.elname);
        if (handler) {
            /* call the handler */
            (*handler)(scb, &top);
        } else {
            res = ERR_NCX_DEF_NOT_FOUND;
        }
    } else {
        res = ERR_NCX_WRONG_NODETYP;
    }

    /* check any error trying to invoke the top handler */
    if (res != NO_ERR) {
        scb->stats.inBadRpcs++;
        myagttotals->stats.inBadRpcs++;
        myagttotals->droppedSessions++;
        
        if (LOGINFO) {
            log_info("\nagt_top: bad msg for session %d (%s)",
                     scb->sid, 
                     get_error_string(res));
        }

        agt_ses_free_session(scb);

        /* set the supplied ptr to ptr to scb to NULL so that the 
         * caller of this function knows that it was deallotcated */
        *ppscb=NULL;

    } else if (profile->agt_stream_output &&
               scb->state == SES_ST_SHUTDOWN_REQ) {
        /* session was closed */
        agt_ses_kill_session(scb,
                             scb->killedbysid,
                             scb->termreason);
        /* set the supplied ptr to ptr to scb to NULL so that the 
         * caller of this function knows that it was deallotcated */
        *ppscb=NULL;
    }

    xml_clean_node(&top);

} /* agt_top_dispatch_msg */
Example #23
0
int
deliver_pipe_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
	struct account			*a = dctx->account;
	struct mail			*m = dctx->mail;
	struct deliver_pipe_data	*data = ti->data;
	char				*s, *cause, *err;
	int				 status;
	struct cmd			*cmd = NULL;
	char				*lbuf;
	size_t				 llen;

	s = replacepath(&data->cmd, m->tags, m, &m->rml, dctx->udata->home);
	if (s == NULL || *s == '\0') {
		log_warnx("%s: empty command", a->name);
		goto error;
	}

	if (data->pipe) {
		log_debug2("%s: piping to \"%s\"", a->name, s);
		cmd = cmd_start(s, CMD_IN|CMD_ONCE, m->data, m->size, &cause);
	} else {
		log_debug2("%s: executing \"%s\"", a->name, s);
		cmd = cmd_start(s, 0, NULL, 0, &cause);
	}
	if (cmd == NULL)
		goto error_cause;
	log_debug3("%s: %s: started", a->name, s);

	llen = IO_LINESIZE;
	lbuf = xmalloc(llen);

	do {
		status = cmd_poll(
		    cmd, NULL, &err, &lbuf, &llen, conf.timeout, &cause);
		if (status == -1) {
			xfree(lbuf);
			goto error_cause;
		}
		if (status == 0 && err != NULL)
			log_warnx("%s: %s: %s", a->name, s, err);
	} while (status == 0);
	status--;

	xfree(lbuf);

	if (status != 0) {
		log_warnx("%s: %s: command returned %d", a->name, s, status);
		goto error;
	}

	cmd_free(cmd);
	xfree(s);
	return (DELIVER_SUCCESS);

error_cause:
	log_warnx("%s: %s: %s", a->name, s, cause);
	xfree(cause);

error:
	if (cmd != NULL)
		cmd_free(cmd);
	if (s != NULL)
		xfree(s);
	return (DELIVER_FAILURE);
}
Example #24
0
/********************************************************************
* FUNCTION consume_node
* 
* Internal consume XML node function
* see agt_xml_consume_node for details.
*
* EXTRA INPUTS:
*   eoferr == TRUE if an End of File error should be generated
*          == FALSE if not
*    nserr == TRUE if bad namespace should be checked
*          == FALSE if not
*    clean == TRUE is a string should be cleaned before returned 
*          == FALSE if a string node should be returned as-is
*
* RETURNS:
*   status of the operation
*   Try to fail on fatal errors only
*********************************************************************/
static status_t 
    consume_node (ses_cb_t *scb,
                  boolean advance,
                  xml_node_t *node,
                  ncx_layer_t layer,
                  xml_msg_hdr_t *msghdr,
                  boolean eoferr,
                  boolean nserr,
                  boolean clean)
{
    int             ret, nodetyp;
    const xmlChar  *badns;
    xmlChar        *valstr, *namestr;
    uint32          len;
    status_t        res, res2;
    boolean         done;

    /* init local vars */
    done = FALSE;
    res = NO_ERR;
    res2 = NO_ERR;
    badns = NULL;

    /* loop past any unused xmlTextReader node types */
    while (!done) {
        /* check if a new node should be read */
        if (advance) {
            /* advance the node pointer */
            ret = xmlTextReaderRead(scb->reader);
            if (ret != 1) {
                /* do not treat this as an internal error */
                res = ERR_XML_READER_EOF;
                if (msghdr && eoferr) {
                    /* generate an operation-failed error */
                    agt_record_error(scb, 
                                     msghdr, 
                                     layer, 
                                     res, 
                                     NULL, 
                                     NCX_NT_NONE,
                                     NULL, 
                                     NCX_NT_NONE,
                                     NULL);
                }
                return res;
            }
        }

        /* get the node depth to match the end node correctly */
        node->depth = xmlTextReaderDepth(scb->reader);
        if (node->depth == -1) {
            /* this never actaully happens */
            SET_ERROR(ERR_XML_READER_INTERNAL);
            node->depth = 0;
        }

        /* get the internal nodetype, check it and convert it */
        nodetyp = xmlTextReaderNodeType(scb->reader);
        switch (nodetyp) {
        case XML_ELEMENT_NODE:
            /* classify element as empty or start */
            if (xmlTextReaderIsEmptyElement(scb->reader)) {
                node->nodetyp = XML_NT_EMPTY;
            } else {
                node->nodetyp = XML_NT_START;
            }
            done = TRUE;
            break;
        case XML_ELEMENT_DECL:
            node->nodetyp = XML_NT_END;
            done = TRUE;
            break;
        case XML_TEXT_NODE:
     /* case XML_DTD_NODE: */
            node->nodetyp = XML_NT_STRING;
            done = TRUE;
            break;
        default:
            /* unused node type -- keep trying */
            if (LOGDEBUG3) {
                log_debug3("\nxml_consume_node: skip unused node (%s)",
                           xml_get_node_name(nodetyp));
            }
            advance = TRUE;
        }
    }

    /* finish the node, depending on its type */
    switch (node->nodetyp) {
    case XML_NT_START:
    case XML_NT_END:
    case XML_NT_EMPTY:
        /* get the element QName */
        namestr = xml_strdup(xmlTextReaderConstName(scb->reader));
        if (!namestr) {
            res = ERR_INTERNAL_MEM;
        } else {
            node->qname = namestr;

            /* check for namespace prefix in the name 
             * only error returned is unknown-namespace 
             */
            len = 0;
            res = xml_check_ns(scb->reader, 
                               namestr, 
                               &node->nsid, 
                               &len, 
                               &badns);
            if (!nserr && res != NO_ERR) {
                node->nsid = xmlns_inv_id();
                len = 0;
                res = NO_ERR;
            }
            
            /* set the element name to the char after the prefix, if any */
            node->elname = (const xmlChar *)(namestr+len);
        
            /* get all the attributes, except for XML_NT_END */
            if (res == NO_ERR && node->nodetyp != XML_NT_END) {
                res2 = get_all_attrs(scb, 
                                     node,
                                     &node->attrs, 
                                     layer, 
                                     msghdr, 
                                     nserr);
            }

            /* Set the node module */
            if (res == NO_ERR) {
                if (node->nsid) {
                    node->module = xmlns_get_module(node->nsid);
                } else {
                    /* no entry, use the default module (ncx) */
                    node->module = NCX_DEF_MODULE;
                }
            }
        }
        break;
    case XML_NT_STRING:
        /* get the text value -- this is a malloced string */
        node->simval = NULL;
        valstr = xmlTextReaderValue(scb->reader);
        if (valstr) {
            if (clean) {
                node->simfree = xml_copy_clean_string(valstr);
            } else {
                node->simfree = xml_strdup(valstr);
            }
            if (node->simfree) {
                node->simlen = xml_strlen(node->simfree);
                node->simval = (const xmlChar *)node->simfree;
            }

            /* see if this is a QName string; if so save the NSID */
            xml_check_qname_content(scb->reader, node);

            xmlFree(valstr);
        }
        if (!node->simval) {
            /* prevent a NULL ptr reference */
            node->simval = EMPTY_STRING;
            node->simlen = 0;
            node->simfree = NULL;
        }
        break;
    default:
        break;
    }

    if ((res != NO_ERR) && msghdr) {
        if (badns) {
            /* generate an operation-failed error */
            agt_record_error(scb,
                             msghdr,
                             layer, 
                             res, 
                             node,
                             NCX_NT_STRING, 
                             badns, 
                             NCX_NT_NONE, 
                             NULL);
        } else {
            agt_record_error(scb,
                             msghdr,
                             layer,
                             res, 
                             node,
                             NCX_NT_NONE,
                             NULL, 
                             NCX_NT_NONE, 
                             NULL);
        }
    }

    if (LOGDEBUG4) {
        log_debug4("\nxml_consume_node: return (%d)", 
                   (res==NO_ERR) ? res2 : res);
        if (scb->state != SES_ST_INIT) {
            xml_dump_node(node);
        }
    }

    /* return general error first, then attribute error 
     * It doesn't really matter since the caller will 
     * assume all error reports have been queued upon return
     */
    return (res==NO_ERR) ? res2 : res;

}  /* consume_node */
Example #25
0
int
deliver_mbox_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
    struct account			*a = dctx->account;
    struct mail			*m = dctx->mail;
    struct deliver_mbox_data	*data = ti->data;
    char				*path, *ptr, *lptr, *from = NULL;
    const char			*msg;
    size_t				 len, llen;
    int				 fd, saved_errno;
    FILE				*f;
    gzFile				 gzf;
    long long			 used;
    sigset_t			 set, oset;
    struct stat			 sb;

    f = gzf = NULL;
    fd = -1;

    path = replacepath(&data->path, m->tags, m, &m->rml, dctx->udata->home);
    if (path == NULL || *path == '\0') {
        log_warnx("%s: empty path", a->name);
        goto error;
    }
    if (data->compress) {
        len = strlen(path);
        if (len < 3 || strcmp(path + len - 3, ".gz") != 0) {
            path = xrealloc(path, 1, len + 4);
            strlcat(path, ".gz", len + 4);
        }
    }
    log_debug2("%s: saving to mbox %s", a->name, path);

    /* Save the mbox path. */
    add_tag(&m->tags, "mbox_file", "%s", path);

    /* Check permissions and ownership. */
    if (stat(path, &sb) != 0) {
        if (conf.no_create || errno != ENOENT)
            goto error_log;

        log_debug2("%s: creating %s", a->name, xdirname(path));
        if (xmkpath(xdirname(path), -1, conf.file_group, DIRMODE) != 0)
            goto error_log;
    } else {
        if ((msg = checkmode(&sb, UMASK(FILEMODE))) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
        if ((msg = checkowner(&sb, -1)) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
        if ((msg = checkgroup(&sb, conf.file_group)) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
    }

    /* Create or open the mbox. */
    used = 0;
    do {
        if (conf.no_create)
            fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types);
        else {
            fd = createlock(path, O_WRONLY|O_APPEND,
                            -1, conf.file_group, FILEMODE, conf.lock_types);
        }
        if (fd == -1 && errno == EEXIST)
            fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types);
        if (fd == -1) {
            if (errno == EAGAIN) {
                if (locksleep(a->name, path, &used) != 0)
                    goto error;
                continue;
            }
            goto error_log;
        }
    } while (fd < 0);

    /* Open gzFile or FILE * for writing. */
    if (data->compress) {
        if ((gzf = gzdopen(fd, "a")) == NULL) {
            errno = ENOMEM;
            goto error_log;
        }
    } else {
        if ((f = fdopen(fd, "a")) == NULL)
            goto error_log;
    }

    /*
     * mboxes are a pain: if we are interrupted after this we risk
     * having written a partial mail. So, block SIGTERM until we're
     * done.
     */
    sigemptyset(&set);
    sigaddset(&set, SIGTERM);
    if (sigprocmask(SIG_BLOCK, &set, &oset) < 0)
        fatal("sigprocmask failed");

    /* Write the from line. */
    from = make_from(m, dctx->udata->name);
    if (deliver_mbox_write(f, gzf, from, strlen(from)) < 0) {
        xfree(from);
        goto error_unblock;
    }
    if (deliver_mbox_write(f, gzf, "\n", 1) < 0) {
        xfree(from);
        goto error_unblock;
    }
    log_debug3("%s: using from line: %s", a->name, from);
    xfree(from);

    /* Write the mail, escaping from lines. */
    line_init(m, &ptr, &len);
    while (ptr != NULL) {
        if (ptr != m->data) {
            /* Skip leading >s. */
            lptr = ptr;
            llen = len;
            while (*lptr == '>' && llen > 0) {
                lptr++;
                llen--;
            }

            if (llen >= 5 && strncmp(lptr, "From ", 5) == 0) {
                log_debug2("%s: quoting from line: %.*s",
                           a->name, (int) len - 1, ptr);
                if (deliver_mbox_write(f, gzf, ">", 1) < 0)
                    goto error_unblock;
            }
        }

        if (deliver_mbox_write(f, gzf, ptr, len) < 0)
            goto error_unblock;

        line_next(m, &ptr, &len);
    }

    /* Append newlines. */
    if (m->data[m->size - 1] == '\n') {
        if (deliver_mbox_write(f, gzf, "\n", 1) < 0)
            goto error_unblock;
    } else {
        if (deliver_mbox_write(f, gzf, "\n\n", 2) < 0)
            goto error_unblock;
    }

    /* Flush buffers and sync. */
    if (gzf == NULL) {
        if (fflush(f) != 0)
            goto error_unblock;
    } else {
        if (gzflush(gzf, Z_FINISH) != Z_OK) {
            errno = EIO;
            goto error_unblock;
        }
    }
    if (fsync(fd) != 0)
        goto error_unblock;

    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
        fatal("sigprocmask failed");

    if (gzf != NULL)
        gzclose(gzf);
    if (f != NULL)
        fclose(f);
    closelock(fd, path, conf.lock_types);

    xfree(path);
    return (DELIVER_SUCCESS);

error_unblock:
    saved_errno = errno;
    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
        fatal("sigprocmask failed");
    errno = saved_errno;

error_log:
    log_warn("%s: %s", a->name, path);

error:
    if (gzf != NULL)
        gzclose(gzf);
    if (f != NULL)
        fclose(f);
    if (fd != -1)
        closelock(fd, path, conf.lock_types);

    if (path != NULL)
        xfree(path);
    return (DELIVER_FAILURE);
}
Example #26
0
void
child_deliver_cmd_hook(pid_t pid, struct account *a, unused struct msg *msg,
    struct child_deliver_data *data, int *result)
{
	struct mail_ctx			*mctx = data->mctx;
	struct mail			*m = data->mail;
	struct match_command_data	*cmddata = data->cmddata;
	int				 flags, status, found = 0;
	char				*s, *cause, *lbuf, *out, *err, tag[24];
	size_t				 llen;
	struct cmd		 	*cmd = NULL;
	struct rmlist			 rml;
	u_int				 i;

	/* If this is the parent, do nothing. */
	if (pid != 0) {
		xfree(mctx);
		return;
	}

	/* Sort out the command. */
	s = replacepath(
	    &cmddata->cmd, m->tags, m, &m->rml, find_tag(m->tags, "home"));
        if (s == NULL || *s == '\0') {
		log_warnx("%s: empty command", a->name);
		goto error;
        }

	log_debug2("%s: %s: started (ret=%d re=%s)", a->name, s, cmddata->ret,
	    cmddata->re.str == NULL ? "none" : cmddata->re.str);
	flags = CMD_ONCE;
	if (cmddata->pipe)
		flags |= CMD_IN;
	if (cmddata->re.str != NULL)
		flags |= CMD_OUT;
	cmd = cmd_start(s, flags, m->data, m->size, &cause);
	if (cmd == NULL) {
		log_warnx("%s: %s: %s", a->name, s, cause);
		goto error;
	}

	llen = IO_LINESIZE;
	lbuf = xmalloc(llen);

	for (;;) {
		/* Stop early if looking for regexp only. */
		if (found && cmddata->ret == -1) {
			log_debug3("%s: %s: found. stopping early", a->name, s);
			status = 1;
			break;
		}

		status = cmd_poll(
		    cmd, &out, &err, &lbuf, &llen, conf.timeout, &cause);
		if (status == -1) {
			log_warnx("%s: %s: %s", a->name, s, cause);
			goto error;
		}
       		if (status != 0)
			break;
		if (err != NULL)
			log_warnx("%s: %s: %s", a->name, s, err);
		if (out == NULL)
			continue;
		log_debug3("%s: %s: out: %s", a->name, s, out);
		if (found)
			continue;

		found = re_string(&cmddata->re, out, &rml, &cause);
		if (found == -1) {
			log_warnx("%s: %s", a->name, cause);
			goto error;
		}
		if (found != 1)
			continue;
		/* Save the matches. */
		if (!rml.valid)
			continue;
		for (i = 0; i < NPMATCH; i++) {
			if (!rml.list[i].valid)
				break;
			xsnprintf(tag, sizeof tag, "command%u", i);
			add_tag(&m->tags, tag, "%.*s", (int) (rml.list[i].eo -
			    rml.list[i].so), out + rml.list[i].so);
		}
	}
	status--;

	log_debug2("%s: %s: returned %d, found %d", a->name, s, status, found);

	cmd_free(cmd);
	xfree(s);
	xfree(lbuf);

	status = cmddata->ret == status;
	if (cmddata->ret != -1 && cmddata->re.str != NULL)
		*result = (found && status) ? MATCH_TRUE : MATCH_FALSE;
	else if (cmddata->ret != -1 && cmddata->re.str == NULL)
		*result = status ? MATCH_TRUE : MATCH_FALSE;
	else if (cmddata->ret == -1 && cmddata->re.str != NULL)
		*result = found ? MATCH_TRUE : MATCH_FALSE;
	else
		*result = MATCH_ERROR;
	return;

error:
	if (cause != NULL)
		xfree(cause);
	if (cmd != NULL)
		cmd_free(cmd);
	if (s != NULL)
		xfree(s);
	if (lbuf != NULL)
		xfree(lbuf);
	*result = MATCH_ERROR;
}
Example #27
0
static gboolean library_view_update_info(library_view_t* view)
{
  if (view->run_timeout) {
    
    // update play buttons
    playlist_player_t* player = backtobasics_player(view->btb);
    if (view->btn_play == NULL) {
      view->btn_play = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_library_play"));
    }
    if (view->btn_pause == NULL) {
      view->btn_pause = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_library_pause"));
    }
    GtkWidget* btn_play = view->btn_play;
    GtkWidget* btn_pause = view->btn_pause;
    if (!playlist_player_is_playing(player)) {
      if (!gtk_widget_get_visible(btn_play)) gtk_widget_show_all(btn_play);
      if (gtk_widget_get_visible(btn_pause)) gtk_widget_hide(btn_pause);
    } else if (playlist_player_is_playing(player)) {
      if (gtk_widget_get_visible(btn_play)) gtk_widget_hide(btn_play);
      if (!gtk_widget_get_visible(btn_pause)) gtk_widget_show_all(btn_pause);
    }
    
    // update slider and time
    long tr_tm = playlist_player_get_track_position_in_ms(player);
    track_t* track = playlist_player_get_track(player);
    int index = playlist_player_get_track_index(player);
    
    int a = tr_tm / 1000;
    int b = view->time_in_ms / 1000;
    
    if (a != b) {
      view->time_in_ms = tr_tm;
      int min = tr_tm / 1000 / 60;
      int sec = (tr_tm / 1000) % 60;
      { 
        char s[200]; 
        sprintf(s,"<span size=\"x-small\"><b><i>%02d:%02d</i></b></span>", min, sec);
        GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_time"));
        gtk_label_set_markup(lbl, s);
        
        // update presets
        reflect_presets(view->btb);
      }
      
      GtkScale* sc_playback = GTK_SCALE(gtk_builder_get_object(view->builder, "sc_library_playback"));
      double perc = 0.0;
      if (track != NULL) {
        int len_in_ms = track_get_length_in_ms(track);
        
        if (len_in_ms != view->len_in_ms) {
          view->len_in_ms = len_in_ms;
          int min = len_in_ms / 1000 / 60;
          int sec = (len_in_ms / 1000) % 60;
          {
            char s[200];
            sprintf(s,"<span size=\"x-small\"><b><i>%02d:%02d</i></b></span>", min, sec);
            GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_total"));
            gtk_label_set_markup(lbl, s);
          }
        }
        
        perc = (((double) tr_tm) / ((double) len_in_ms)) * 100.0;
        if (!view->sliding) {
          gtk_range_set_value(GTK_RANGE(sc_playback), perc);
        }
      }

      // update track info
      if (index != view->track_index || 
            (track != NULL && track_get_id(track) != view->track_id)) {
        log_debug3("updating track info, index = %d, %p", index, track);
        view->track_index = index;
        if (track != NULL) {
          
          // fetch lyric if possible
          if (strcmp(track_get_lyric(track),"") == 0) {
            struct lyric_cb* cb = (struct lyric_cb*) mc_malloc(sizeof(struct lyric_cb));
            cb->track_id = mc_strdup(track_get_id(track));
            cb->view = view;
            fetch_lyric(track, library_view_process_lyric, cb);
          } else {
            struct lyric_cb* cb = (struct lyric_cb*) mc_malloc(sizeof(struct lyric_cb));
            cb->track_id = mc_strdup(track_get_id(track));
            cb->view = view;
            library_view_process_lyric(mc_strdup(track_get_lyric(track)), cb);
          }
            
          // Print artist info
          view->track_id = track_get_id(track);
          log_debug2("artid = %s", track_get_artid(track));
          char s[200];
          char c = ',';
          char c1 = ',';
          char *artist = text_to_html(track_get_artist(track));
          char *title = text_to_html(track_get_title(track));
          char *piece = text_to_html(track_get_piece(track));
          
          if (strcmp(track_get_artist(track), "") == 0) { c = ' '; }
          if (strcmp(track_get_piece(track), "") == 0) { c1 = ' '; }
          snprintf(s, 125,
                   "%s%c %s%c %s", 
                   artist,
                   c,
                   piece,
                   c1,
                   title
                   );
          mc_free(artist);
          mc_free(title);
          mc_free(piece);
          char ss[400];
          log_debug2("s = %s", s);
          sprintf(ss,"<span size=\"x-small\"><i><b>%s</b></i></span>",s);
          GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_song_info"));
          gtk_label_set_markup(lbl, ss);
          
          log_debug2("artid = %s", track_get_artid(track));
          file_info_t* info = file_info_new(track_get_artid(track));
          if (!file_info_is_file(info)) {
            file_info_destroy(info);
            char *path = backtobasics_logo(view->btb); 
            info = file_info_new(path);
            mc_free(path);
            //info = file_info_new(backtobasics_logo(view->btb));
          }
          
          if (file_info_is_file(info)) {
            GError *err = NULL;
            GdkPixbuf* pb = gdk_pixbuf_new_from_file_at_scale(file_info_path(info),
                                                              view->img_w, view->img_h,
                                                              TRUE,
                                                              &err
                                                              );
            if (pb != NULL) {
              GtkImage* img = GTK_IMAGE(gtk_builder_get_object(view->builder, "img_art"));
              gtk_image_set_from_pixbuf(img, pb);
              g_object_unref(pb);
            } else {
              log_error3("error loading image art: %d, %s", err->code, err->message);
              //g_free(err);
            }
          }
          file_info_destroy(info);
        }

        log_debug("track hash");

        
        // Select the track in the librarylist if the librarylist is still
        // the same
        if (playlist_model_tracks_hash(view->playlist_model) == playlist_player_get_hash(player)) {
          GtkTreeView* tview = view->tview;
          GtkTreePath* path = gtk_tree_path_new();
          gtk_tree_path_append_index(path, index);
          gtk_tree_view_set_cursor(tview, path, NULL, FALSE);
          gtk_tree_path_free(path);
        } 
        log_debug("track hash 2");
        
      }

      //log_debug3("lib hash = %lld, pl hash = %lld", view->library_list_hash, playlist_player_get_hash(player));
      
      // TODO
      if (playlist_model_tracks_hash(view->playlist_model) ==  playlist_player_get_hash(player)) {
        //view->track_index = -1;
      } else {
        
        GtkTreeView* tview = view->tview;
        GtkTreeSelection* sel = gtk_tree_view_get_selection(tview);
        gtk_tree_selection_unselect_all(sel);
      }
      
    }
    
    // update repeat info
    playlist_player_repeat_t repeat = playlist_player_get_repeat(player);
    if (view->repeat != repeat) {
      log_debug3("repeat = %d, view repeat = %d", repeat, view->repeat);
      view->repeat = repeat;
      GtkWidget* r_btn = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_repeat"));
      GtkWidget* r1_btn = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_repeat_one"));
      GtkWidget* rlist_btn = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_repeat_all"));
      log_debug4("r = %p, r1 = %p, rall = %p", r_btn, r1_btn, rlist_btn);
      switch (repeat) {
        case PLP_NO_REPEAT: {
          gtk_widget_show_all(r_btn);
          gtk_widget_hide(rlist_btn);
          gtk_widget_hide(r1_btn);
        }
        break;
        case PLP_TRACK_REPEAT: {
          gtk_widget_hide(r_btn);
          gtk_widget_show_all(r1_btn);
          gtk_widget_hide(rlist_btn);
        }
        break;
        case PLP_LIST_REPEAT: {
          gtk_widget_hide(r1_btn);
          gtk_widget_show_all(rlist_btn);
          gtk_widget_hide(r_btn);
        }
        break;
      }
    }

    
    return TRUE;
  } else {
    return FALSE;
  }
}
/********************************************************************
 * FUNCTION process_apply
 * (config mode input received)
 *  Handle the apply command and check if there are edits
 *  to apply to the server.  If so apply the edits.
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    session_cb == session control block to use
 *
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    process_apply (server_cb_t *server_cb,
                   session_cb_t *session_cb)
{
    if (dlq_empty(&session_cb->config_editQ)) {
        if (LOGDEBUG2) {
            log_debug2("\nSkipping apply, no edits");
        }
        session_cb->config_edit_dirty = FALSE;
        return NO_ERR;
    }

    /* make a dummy config root -- it will not be used; only the child
     * nodes added to this container will be added to the <config>
     * parameter in the <edit-config> operation
     */
    val_value_t *configval = xml_val_new_root(NCX_EL_CONFIG, xmlns_nc_id());
    if (configval == NULL) {
        log_error("\nError: malloc failed");
        return ERR_INTERNAL_MEM;
    }
 
    status_t res = NO_ERR;
    boolean anyedits = FALSE;
    uint32 editcnt = dlq_count(&session_cb->config_editQ);
    
    while (!dlq_empty(&session_cb->config_editQ)) {
        config_edit_t *edit = (config_edit_t *)
            dlq_deque(&session_cb->config_editQ);

        /* compare the edit to the shadow config to see if it
         * represents any change or not   */
        boolean ischange = check_edit(session_cb, edit);

        if (ischange) {
            /** TBD: add to tree and collapse all edits!!! */
            val_add_child(edit->edit_payload, configval);
            edit->edit_payload = NULL;
            anyedits = TRUE;
        } else if (LOGDEBUG3) {
            log_debug3("\nSkipping edit due to no change:\n");
            val_dump_value(edit->edit_payload, 0);
        }
        free_config_edit(edit);
    }

    if (!anyedits) {
        val_free_value(configval);
        return NO_ERR;
    }

    if (server_cb->program_mode == PROG_MODE_SERVER) {
        if (LOGDEBUG) {
            if (editcnt == 1) {
                log_debug("\nApplying 1 edit\n");
            } else {
                log_debug("\nApplying %u edits\n", editcnt);
            }
        }
    } else {
        if (LOGINFO) {
            const xmlChar *sesname = (session_cb->session_cfg)
                ? session_cb->session_cfg->name : NCX_EL_DEFAULT;

            if (editcnt == 1) {
                log_info("\nApplying 1 edit to session '%s'\n", sesname);
            } else {
                log_info("\nApplying %u edits to session '%s'\n", editcnt,
                         sesname);
            }
        }
    }

    session_cb->command_mode = CMD_MODE_CONF_APPLY;
    session_cb->config_edit_dirty = FALSE;

    res = send_edit_config_to_server(server_cb, session_cb, NULL,
                                     configval, TRUE, session_cb->timeout,
                                     OP_DEFOP_MERGE);
    /* configval consumed no matter what! */

    return res;

}  /* process_apply */