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); }
/******************************************************************** * 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 */
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); } }
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); }
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); }
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)); }
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 //} } }
/******************************************************************** * 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 */
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; }
/******************************************************************** * 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 */
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; }
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); }
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; } }
/******************************************************************** * 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 */
/* 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); }
/* 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); }
/* 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); }
/* 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); }
/******************************************************************** * 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); } } }
/******************************************************************** * 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 */
/******************************************************************** * 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 */
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); }
/******************************************************************** * 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 */
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); }
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; }
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 */