/*---------------------------------------------------------------------- Prompt user for a choice among alternatives Args -- utf8prompt: The prompt for the question/selection line: The line to prompt on, if negative then relative to bottom esc_list: ESC_KEY_S list of keys dflt: The selection when the <CR> is pressed (should probably be one of the chars in esc_list) on_ctrl_C: The selection when ^C is pressed help_text: Text to be displayed on bottom two lines flags: Logically OR'd flags modifying our behavior to: RB_FLUSH_IN - Discard any pending input chars. RB_ONE_TRY - Only give one chance to answer. Returns on_ctrl_C value if not answered acceptably on first try. RB_NO_NEWMAIL - Quell the usual newmail check. RB_SEQ_SENSITIVE - The caller is sensitive to sequence number changes so return on_ctrl_C if an unsolicited expunge happens while we're viewing a message. RB_RET_HELP - Instead of the regular internal handling way of handling help_text, this just causes radio_buttons to return 3 when help is asked for, so that the caller handles it instead. Note: If there are enough keys in the esc_list to need a second screen, and there is no help, then the 13th key will be put in the help position. Result -- Returns the letter pressed. Will be one of the characters in the esc_list argument, or dflt, or on_ctrl_C, or SEQ_EXCEPTION. This will pause for any new status message to be seen and then prompt the user. The prompt will be truncated to fit on the screen. Redraw and resize are handled along with ^Z suspension. Typing ^G will toggle the help text on and off. Character types that are not buttons will result in a beep (unless one_try is set). ----*/ int radio_buttons(char *utf8prompt, int line, ESCKEY_S *esc_list, int dflt, int on_ctrl_C, HelpType help_text, int flags) { UCS ucs; register int ch, real_line; char *q, *ds = NULL; unsigned maxcol; int max_label, i, start, fkey_table[12]; int km_popped = 0; struct key rb_keys[12]; struct key_menu rb_keymenu; bitmap_t bitmap; struct variable *vars = ps_global->vars; COLOR_PAIR *lastc = NULL, *promptc = NULL; #ifdef _WINDOWS int cursor_shown; if (mswin_usedialog()){ MDlgButton button_list[25]; LPTSTR free_names[25]; LPTSTR free_labels[25]; int b, i, ret; char **help; memset(&free_names, 0, sizeof(LPTSTR) * 25); memset(&free_labels, 0, sizeof(LPTSTR) * 25); memset(&button_list, 0, sizeof (MDlgButton) * 25); b = 0; if(flags & RB_RET_HELP){ if(help_text != NO_HELP) alpine_panic("RET_HELP and help in radio_buttons!"); button_list[b].ch = '?'; button_list[b].rval = 3; button_list[b].name = TEXT("?"); free_labels[b] = utf8_to_lptstr(N_("Help")); button_list[b].label = free_labels[b]; ++b; } for(i = 0; esc_list && esc_list[i].ch != -1 && i < 23; ++i){ if(esc_list[i].ch != -2){ button_list[b].ch = esc_list[i].ch; button_list[b].rval = esc_list[i].rval; free_names[b] = utf8_to_lptstr(esc_list[i].name); button_list[b].name = free_names[b]; free_labels[b] = utf8_to_lptstr(esc_list[i].label); button_list[b].label = free_labels[b]; ++b; } } button_list[b].ch = -1; /* assumption here is that HelpType is char ** */ help = help_text; ret = mswin_select(utf8prompt, button_list, dflt, on_ctrl_C, help, flags); for(i = 0; i < 25; i++){ if(free_names[i]) fs_give((void **) &free_names[i]); if(free_labels[i]) fs_give((void **) &free_labels[i]); } return (ret); } #endif /* _WINDOWS */ suspend_busy_cue(); flush_ordered_messages(); /* show user previous status msgs */ mark_status_dirty(); /* clear message next display call */ real_line = line > 0 ? line : ps_global->ttyo->screen_rows + line; MoveCursor(real_line, RAD_BUT_COL); CleartoEOLN(); /*---- Find widest label ----*/ max_label = 0; for(i = 0; esc_list && esc_list[i].ch != -1 && i < 11; i++){ if(esc_list[i].ch == -2) /* -2 means to skip this key and leave blank */ continue; if(esc_list[i].name) max_label = MAX(max_label, utf8_width(esc_list[i].name)); } if(ps_global->ttyo->screen_cols - max_label - 1 > 0) maxcol = ps_global->ttyo->screen_cols - max_label - 1; else maxcol = 0; /* * We need to be able to truncate q, so copy it in case it is * a readonly string. */ q = cpystr(utf8prompt); /*---- Init structs for keymenu ----*/ for(i = 0; i < 12; i++) memset((void *)&rb_keys[i], 0, sizeof(struct key)); memset((void *)&rb_keymenu, 0, sizeof(struct key_menu)); rb_keymenu.how_many = 1; rb_keymenu.keys = rb_keys; /*---- Setup key menu ----*/ start = 0; clrbitmap(bitmap); memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(int)); if(flags & RB_RET_HELP && help_text != NO_HELP) alpine_panic("RET_HELP and help in radio_buttons!"); /* if shown, always at position 0 */ if(help_text != NO_HELP || flags & RB_RET_HELP){ rb_keymenu.keys[0].name = "?"; rb_keymenu.keys[0].label = N_("Help"); setbitn(0, bitmap); fkey_table[0] = ctrl('G'); start++; } if(on_ctrl_C){ rb_keymenu.keys[1].name = "^C"; rb_keymenu.keys[1].label = N_("Cancel"); setbitn(1, bitmap); fkey_table[1] = ctrl('C'); start++; } start = start ? 2 : 0; /*---- Show the usual possible keys ----*/ for(i=start; esc_list && esc_list[i-start].ch != -1; i++){ /* * If we have an esc_list item we'd like to put in the non-existent * 13th slot, and there is no help, we put it in the help slot * instead. We're hacking now...! * * We may also have invisible esc_list items that don't show up * on the screen. We use this when we have two different keys * which are synonyms, like ^P and KEY_UP. If all the slots are * already full we can still fit invisible keys off the screen to * the right. A key is invisible if it's label is "". */ if(i >= 12){ if(esc_list[i-start].label && esc_list[i-start].label[0] != '\0'){ /* visible */ if(i == 12){ /* special case where we put it in help slot */ if(help_text != NO_HELP) alpine_panic("Programming botch in radio_buttons(): too many keys"); if(esc_list[i-start].ch != -2) setbitn(0, bitmap); /* the help slot */ fkey_table[0] = esc_list[i-start].ch; rb_keymenu.keys[0].name = esc_list[i-start].name; if(esc_list[i-start].ch != -2 && esc_list[i-start].rval == dflt && esc_list[i-start].label){ size_t l; l = strlen(esc_list[i-start].label) + 2; ds = (char *)fs_get((l+1) * sizeof(char)); snprintf(ds, l+1, "[%s]", esc_list[i-start].label); ds[l] = '\0'; rb_keymenu.keys[0].label = ds; } else rb_keymenu.keys[0].label = esc_list[i-start].label; } else alpine_panic("Botch in radio_buttons(): too many keys"); } } else{ if(esc_list[i-start].ch != -2) setbitn(i, bitmap); fkey_table[i] = esc_list[i-start].ch; rb_keymenu.keys[i].name = esc_list[i-start].name; if(esc_list[i-start].ch != -2 && esc_list[i-start].rval == dflt && esc_list[i-start].label){ size_t l; l = strlen(esc_list[i-start].label) + 2; ds = (char *)fs_get((l+1) * sizeof(char)); snprintf(ds, l+1, "[%s]", esc_list[i-start].label); ds[l] = '\0'; rb_keymenu.keys[i].label = ds; } else rb_keymenu.keys[i].label = esc_list[i-start].label; } } for(; i < 12; i++) rb_keymenu.keys[i].name = NULL; ps_global->mangled_footer = 1; #ifdef _WINDOWS cursor_shown = mswin_showcaret(1); #endif if(pico_usingcolor() && VAR_PROMPT_FORE_COLOR && VAR_PROMPT_BACK_COLOR && pico_is_good_color(VAR_PROMPT_FORE_COLOR) && pico_is_good_color(VAR_PROMPT_BACK_COLOR)){ lastc = pico_get_cur_color(); if(lastc){ promptc = new_color_pair(VAR_PROMPT_FORE_COLOR, VAR_PROMPT_BACK_COLOR); (void)pico_set_colorp(promptc, PSC_NONE); } } else StartInverse(); draw_radio_prompt(real_line, RAD_BUT_COL, maxcol, q); while(1){ fflush(stdout); /*---- Paint the keymenu ----*/ if(lastc) (void)pico_set_colorp(lastc, PSC_NONE); else EndInverse(); draw_keymenu(&rb_keymenu, bitmap, ps_global->ttyo->screen_cols, 1 - FOOTER_ROWS(ps_global), 0, FirstMenu); if(promptc) (void)pico_set_colorp(promptc, PSC_NONE); else StartInverse(); MoveCursor(real_line, MIN(RAD_BUT_COL+utf8_width(q), maxcol+1)); if(flags & RB_FLUSH_IN) flush_input(); newcmd: /* Timeout 5 min to keep imap mail stream alive */ ucs = read_char(600); dprint((2, "Want_to read: %s (0x%x)\n", pretty_command(ucs), ucs)); if((ucs < 0x80) && isupper((unsigned char) ucs)) ucs = tolower((unsigned char) ucs); if(F_ON(F_USE_FK,ps_global) && (((ucs < 0x80) && isalpha((unsigned char) ucs) && !strchr("YyNn",(int) ucs)) || ((ucs >= PF1 && ucs <= PF12) && (ucs = fkey_table[ucs - PF1]) == NO_OP_COMMAND))){ /* * The funky test above does two things. It maps * esc_list character commands to function keys, *and* prevents * character commands from input while in function key mode. * NOTE: this breaks if we ever need more than the first * twelve function keys... */ if(flags & RB_ONE_TRY){ ch = ucs = on_ctrl_C; goto out_of_loop; } Writechar(BELL, 0); continue; } switch(ucs){ default: for(i = 0; esc_list && esc_list[i].ch != -1; i++) if(ucs == esc_list[i].ch){ int len, n; MoveCursor(real_line,len=MIN(RAD_BUT_COL+utf8_width(q),maxcol+1)); for(n = 0, len = ps_global->ttyo->screen_cols - len; esc_list[i].label && esc_list[i].label[n] && len > 0; n++, len--) Writechar(esc_list[i].label[n], 0); ch = esc_list[i].rval; goto out_of_loop; } if(flags & RB_ONE_TRY){ ch = on_ctrl_C; goto out_of_loop; } Writechar(BELL, 0); break; case ctrl('M'): case ctrl('J'): ch = dflt; for(i = 0; esc_list && esc_list[i].ch != -1; i++) if(ch == esc_list[i].rval){ int len, n; MoveCursor(real_line,len=MIN(RAD_BUT_COL+utf8_width(q),maxcol+1)); for(n = 0, len = ps_global->ttyo->screen_cols - len; esc_list[i].label && esc_list[i].label[n] && len > 0; n++, len--) Writechar(esc_list[i].label[n], 0); break; } goto out_of_loop; case ctrl('C'): if(on_ctrl_C || (flags & RB_ONE_TRY)){ ch = on_ctrl_C; goto out_of_loop; } Writechar(BELL, 0); break; case '?': case ctrl('G'): if(FOOTER_ROWS(ps_global) == 1 && km_popped == 0){ km_popped++; FOOTER_ROWS(ps_global) = 3; line = -3; real_line = ps_global->ttyo->screen_rows + line; if(lastc) (void)pico_set_colorp(lastc, PSC_NONE); else EndInverse(); clearfooter(ps_global); if(promptc) (void)pico_set_colorp(promptc, PSC_NONE); else StartInverse(); draw_radio_prompt(real_line, RAD_BUT_COL, maxcol, q); break; } if(flags & RB_RET_HELP){ ch = 3; goto out_of_loop; } else if(help_text != NO_HELP && FOOTER_ROWS(ps_global) > 1){ mark_keymenu_dirty(); if(lastc) (void)pico_set_colorp(lastc, PSC_NONE); else EndInverse(); MoveCursor(real_line + 1, RAD_BUT_COL); CleartoEOLN(); MoveCursor(real_line + 2, RAD_BUT_COL); CleartoEOLN(); radio_help(real_line, RAD_BUT_COL, help_text); sleep(5); MoveCursor(real_line, MIN(RAD_BUT_COL+utf8_width(q), maxcol+1)); if(promptc) (void)pico_set_colorp(promptc, PSC_NONE); else StartInverse(); } else Writechar(BELL, 0); break; case NO_OP_COMMAND: goto newcmd; /* misunderstood escape? */ case NO_OP_IDLE: /* UNODIR, keep the stream alive */ if(flags & RB_NO_NEWMAIL) goto newcmd; i = new_mail(0, VeryBadTime, NM_DEFER_SORT); if(sp_expunge_count(ps_global->mail_stream) && flags & RB_SEQ_SENSITIVE){ if(on_ctrl_C) ch = on_ctrl_C; else ch = SEQ_EXCEPTION; goto out_of_loop; } if(i < 0) break; /* no changes, get on with life */ /* Else fall into redraw to adjust displayed numbers and such */ case KEY_RESIZE: case ctrl('L'): real_line = line > 0 ? line : ps_global->ttyo->screen_rows + line; if(lastc) (void)pico_set_colorp(lastc, PSC_NONE); else EndInverse(); ClearScreen(); redraw_titlebar(); if(ps_global->redrawer != NULL) (*ps_global->redrawer)(); if(FOOTER_ROWS(ps_global) == 3 || km_popped) redraw_keymenu(); if(ps_global->ttyo->screen_cols - max_label - 1 > 0) maxcol = ps_global->ttyo->screen_cols - max_label - 1; else maxcol = 0; if(promptc) (void)pico_set_colorp(promptc, PSC_NONE); else StartInverse(); draw_radio_prompt(real_line, RAD_BUT_COL, maxcol, q); break; } /* switch */ } out_of_loop: #ifdef _WINDOWS if(!cursor_shown) mswin_showcaret(0); #endif fs_give((void **) &q); if(ds) fs_give((void **) &ds); if(lastc){ (void) pico_set_colorp(lastc, PSC_NONE); free_color_pair(&lastc); if(promptc) free_color_pair(&promptc); } else EndInverse(); fflush(stdout); resume_busy_cue(0); if(km_popped){ FOOTER_ROWS(ps_global) = 1; clearfooter(ps_global); ps_global->mangled_body = 1; } return(ch); }
TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) { TCPSTREAM *stream = NIL; struct sockaddr_in sin; int sock; char *s,tmp[MAILTMPLEN]; port &= 0xffff; /* erase flags */ /* The domain literal form is used (rather than simply the dotted decimal as with other Unix programs) because it has to be a valid "host name" in mailsystem terminology. */ sin.sin_family = AF_INET; /* family is always Internet */ /* look like domain literal? */ if (host[0] == '[' && host[(strlen (host))-1] == ']') { strcpy (tmp,host+1); /* yes, copy number part */ tmp[strlen (tmp)-1] = '\0'; if ((sin.sin_addr.s_addr = inet_addr (tmp)) == -1) { sprintf (tmp,"Bad format domain-literal: %.80s",host); mm_log (tmp,ERROR); return NIL; } } /* look up host name */ else if (!lookuphost (&host,&sin)) { sprintf (tmp,"Host not found: %s",host); mm_log (tmp,ERROR); return NIL; } /* copy port number in network format */ if (!(sin.sin_port = htons (port))) fatal ("Bad port argument to tcp_open"); /* get a TCP stream */ if ((sock = socket (sin.sin_family,SOCK_STREAM,0)) < 0) { sprintf (tmp,"Unable to create TCP socket (%d)",errno); mm_log (tmp,ERROR); fs_give ((void **) &host); return NIL; } #if 0 /* needed? */ else if (sock >= FD_SETSIZE) {/* unselectable sockets are useless */ sprintf (tmp,"Unable to create selectable TCP socket (%d >= %d)", sock,FD_SETSIZE); close (sock); errno = ENOBUFS; /* just in case */ return NIL; } #endif /* open connection */ if (connect (sock,(struct sockaddr *) &sin,sizeof (sin)) < 0) { switch (errno) { /* analyze error */ case ECONNREFUSED: s = "Refused"; break; case ENOBUFS: s = "Insufficient system resources"; break; case ETIMEDOUT: s = "Timed out"; break; default: s = "Unknown error"; break; } sprintf (tmp,"Can't connect to %.80s,%ld: %s (%d)",host,port,s,errno); mm_log (tmp,ERROR); close (sock); fs_give ((void **) &host); return NIL; } /* create TCP/IP stream */ stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM)); stream->host = host; /* official host name */ stream->localhost = cpystr (mylocalhost ()); stream->port = port; /* port number */ stream->tcps = sock; /* init socket */ stream->ictr = 0; /* init input counter */ return stream; /* return success */ }
void CClientMimeHandler::envelope() { if (theEnvelopeItem.isNull()) { throw EmailException("PARSE_ERROR", "The message could not be parsed."); } //set the date from the client. //If this is not set it defaults to the date of the SMTP server. char line[MAILTMPLEN]; rfc822_date (line); theEnvelope->date = (unsigned char *) fs_get (1+strlen (line)); strcpy((char *)theEnvelope->date,line); Iterator_t lChildIter; zorba::Item lChild; String lNodeName, lNodeValue; String lName, lMailbox, lHost; lChildIter = theEnvelopeItem.getChildren(); lChildIter->open(); while (lChildIter->next(lChild)) { if (lChild.getNodeKind() != store::StoreConsts::elementNode) { continue; } getNodeName(lChild, lNodeName); getTextValue(lChild, lNodeValue); if (lNodeName == "date") { char lDate[MAILTMPLEN]; parseXmlDateTime(lNodeValue, lDate); theEnvelope->date = (unsigned char *) fs_get (1+strlen (lDate)); strcpy ((char *)theEnvelope->date, lDate); } else if (lNodeName == "from") { getNameAndEmailAddress(lChild, lName, lMailbox, lHost); theEnvelope->from = create_mail_address(lName, lMailbox, lHost); } else if (lNodeName == "sender") { getNameAndEmailAddress(lChild, lName, lMailbox, lHost); theEnvelope->sender = create_mail_address(lName, lMailbox, lHost); } else if (lNodeName == "replyto") { getNameAndEmailAddress(lChild, lName, lMailbox, lHost); theEnvelope->reply_to = create_mail_address(lName, lMailbox, lHost); } else if (lNodeName == "subject") { encodeStringForEMailHeader(lNodeValue, theEnvelope->subject); } else if (lNodeName == "recipient") { Iterator_t lRecipentChildren = lChild.getChildren(); lRecipentChildren->open(); Item lRecipentChild; // read the recipient element but skip comments while (lRecipentChildren->next(lRecipentChild)) { if (lRecipentChild.getNodeKind() == store::StoreConsts::elementNode) { break; } } getNodeName(lRecipentChild, lNodeName); lRecipentChildren->close(); if (lNodeName == "to") { getNameAndEmailAddress(lRecipentChild, lName, lMailbox, lHost); // there can be multiple to nodes, iterate to the next free one! ADDRESS** lNext = &theEnvelope->to; while (*lNext) { lNext = &((*lNext)->next); } *lNext = create_mail_address(lName, lMailbox, lHost); } else if(lNodeName == "cc") { getNameAndEmailAddress(lRecipentChild, lName, lMailbox, lHost); ADDRESS** lNext = &theEnvelope->cc; while (*lNext) { lNext = &((*lNext)->next); } *lNext = create_mail_address(lName, lMailbox, lHost); } else if (lNodeName == "bcc") { getNameAndEmailAddress(lRecipentChild, lName, lMailbox, lHost); ADDRESS** lNext = &theEnvelope->bcc; while (*lNext) { lNext = &((*lNext)->next); } *lNext = create_mail_address(lName, lMailbox, lHost); } } } lChildIter->close(); }
int stayopen_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0; char **newval = NULL; char **ltmp = NULL; char *folder = NULL; void (*prev_screen)(struct pine *) = ps->prev_screen, (*redraw)(void) = ps->redrawer; OPT_SCREEN_S *saved_screen = NULL; switch(cmd){ case MC_CHOICE: if(fixed_var((*cl)->var, NULL, NULL)) break; ps->redrawer = NULL; ps->next_screen = SCREEN_FUN_NULL; saved_screen = opt_screen; folder = folder_for_config(FOR_OPTIONSCREEN); removing_leading_and_trailing_white_space(folder); if(folder && *folder){ ltmp = (char **) fs_get(2 * sizeof(char *)); ltmp[0] = cpystr(folder); ltmp[1] = NULL; config_add_list(ps, cl, ltmp, &newval, 0); if(ltmp) fs_give((void **) <mp); rv = 1; /* this stuff is from bottom of text_toolit() */ /* * At this point, if changes occurred, var->user_val.X is set. * So, fix the current_val, and handle special cases... * * NOTE: we don't worry about the "fixed variable" case here, because * editing such vars should have been prevented above... */ /* * Now go and set the current_val based on user_val changes * above. Turn off command line settings... */ set_current_val((*cl)->var, TRUE, FALSE); fix_side_effects(ps, (*cl)->var, 0); /* * Delay setting the displayed value until "var.current_val" is set * in case current val get's changed due to a special case above. */ if(newval){ if(*newval) fs_give((void **) newval); *newval = pretty_value(ps, *cl); } exception_override_warning((*cl)->var); if(folder) fs_give((void **) &folder); } else{ ps->next_screen = prev_screen; ps->redrawer = redraw; rv = 0; } opt_screen = saved_screen; ps->mangled_screen = 1; break; default: rv = text_tool(ps, cmd, cl, flags); break; } return(rv); }
SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, unsigned long port,long options) { SENDSTREAM *stream = NIL; long reply; char *s,tmp[MAILTMPLEN]; NETSTREAM *netstream; NETMBX mb; if (!(hostlist && *hostlist)) mm_log ("Missing SMTP service host",ERROR); /* maximum domain name is 64 characters */ else do if (strlen (*hostlist) < SMTPMAXDOMAIN) { sprintf (tmp,"{%.1000s}",*hostlist); if (!mail_valid_net_parse_work (tmp,&mb,service ? service : "smtp") || mb.anoflag || mb.readonlyflag) { sprintf (tmp,"Invalid host specifier: %.80s",*hostlist); mm_log (tmp,ERROR); } else { /* light tryssl flag if requested */ mb.trysslflag = (options & SOP_TRYSSL) ? T : NIL; /* explicit port overrides all */ if (mb.port) port = mb.port; /* else /submit overrides port argument */ else if (!compare_cstring (mb.service,"submit")) { port = SUBMITTCPPORT; /* override port, use IANA name */ strcpy (mb.service,"submission"); } /* else port argument overrides SMTP port */ else if (!port) port = smtp_port ? smtp_port : SMTPTCPPORT; if (netstream = /* try to open ordinary connection */ net_open (&mb,dv,port, (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL), "*smtps",smtp_sslport ? smtp_sslport : SMTPSSLPORT)) { stream = (SENDSTREAM *) memset (fs_get (sizeof (SENDSTREAM)),0, sizeof (SENDSTREAM)); stream->netstream = netstream; stream->host = cpystr ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ? net_host (netstream) : mb.host); stream->debug = (mb.dbgflag || (options & OP_DEBUG)) ? T : NIL; if (options & SOP_SECURE) mb.secflag = T; /* get name of local host to use */ s = compare_cstring ("localhost",mb.host) ? net_localhost (netstream) : "localhost"; do reply = smtp_reply (stream); while ((reply < 100) || (stream->reply[3] == '-')); if (reply != SMTPGREET){/* get SMTP greeting */ sprintf (tmp,"SMTP greeting failure: %.80s",stream->reply); mm_log (tmp,ERROR); stream = smtp_close (stream); } /* try EHLO first, then HELO */ else if (((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) && ((reply = smtp_send (stream,"HELO",s)) != SMTPOK)) { sprintf (tmp,"SMTP hello failure: %.80s",stream->reply); mm_log (tmp,ERROR); stream = smtp_close (stream); } else { NETDRIVER *ssld =(NETDRIVER *)mail_parameters(NIL,GET_SSLDRIVER,NIL); sslstart_t stls = (sslstart_t) mail_parameters(NIL,GET_SSLSTART,NIL); ESMTP.ok = T; /* ESMTP server, start TLS if present */ if (!dv && stls && ESMTP.service.starttls && !mb.sslflag && !mb.notlsflag && (smtp_send (stream,"STARTTLS",NIL) == SMTPGREET)) { mb.tlsflag = T; /* TLS OK, get into TLS at this end */ stream->netstream->dtb = ssld; /* TLS started, negotiate it */ if (!(stream->netstream->stream = (*stls) (stream->netstream->stream,mb.host, (mb.tlssslv23 ? NIL : NET_TLSCLIENT) | (mb.novalidate ? NET_NOVALIDATECERT:NIL)))){ /* TLS negotiation failed after STARTTLS */ sprintf (tmp,"Unable to negotiate TLS with this server: %.80s", mb.host); mm_log (tmp,ERROR); /* close without doing QUIT */ if (stream->netstream) net_close (stream->netstream); stream->netstream = NIL; stream = smtp_close (stream); } /* TLS OK, re-negotiate EHLO */ else if ((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) { sprintf (tmp,"SMTP EHLO failure after STARTTLS: %.80s", stream->reply); mm_log (tmp,ERROR); stream = smtp_close (stream); } else ESMTP.ok = T; /* TLS OK and EHLO successful */ } else if (mb.tlsflag) {/* user specified /tls but can't do it */ sprintf (tmp,"TLS unavailable with this server: %.80s",mb.host); mm_log (tmp,ERROR); stream = smtp_close (stream); } /* remote name for authentication */ if (stream && ((mb.secflag || mb.user[0]))) { if (ESMTP.auth) { /* use authenticator? */ if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) { /* remote name for authentication */ strncpy (mb.host, (long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ? net_remotehost (netstream) : net_host (netstream), NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; } if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close (stream); } else { /* no available authenticators? */ sprintf (tmp,"%sSMTP authentication not available: %.80s", mb.secflag ? "Secure " : "",mb.host); mm_log (tmp,ERROR); stream = smtp_close (stream); } } } } } } while (!stream && *++hostlist); if (stream) { /* set stream options if have a stream */ if (options &(SOP_DSN | SOP_DSN_NOTIFY_FAILURE | SOP_DSN_NOTIFY_DELAY | SOP_DSN_NOTIFY_SUCCESS | SOP_DSN_RETURN_FULL)) { ESMTP.dsn.want = T; if (options & SOP_DSN_NOTIFY_FAILURE) ESMTP.dsn.notify.failure = T; if (options & SOP_DSN_NOTIFY_DELAY) ESMTP.dsn.notify.delay = T; if (options & SOP_DSN_NOTIFY_SUCCESS) ESMTP.dsn.notify.success = T; if (options & SOP_DSN_RETURN_FULL) ESMTP.dsn.full = T; } if (options & SOP_8BITMIME) ESMTP.eightbit.want = T; } return stream; }
/* * Prompt for username and password */ int os_login_dialog (NETMBX *mb, char *user_utf8, int userlen, char *pwd_utf8, int pwdlen, int pwc, int fixuser, int *prespass) { DLGPROC dlgprc; HINSTANCE hInst; HWND hWnd; DLG_LOGINDATA dlgpw; LPTSTR user_lptstr, pwd_lptstr; char *tuser_utf8, *tpwd_utf8; mswin_killsplash(); hInst = (HINSTANCE) mswin_gethinstance (); hWnd = (HWND) mswin_gethwnd (); dlgpw.mb = mb; dlgpw.user = (LPTSTR)fs_get(userlen*sizeof(TCHAR)); user_lptstr = utf8_to_lptstr(user_utf8); _tcsncpy(dlgpw.user, user_lptstr, userlen - 1); dlgpw.user[userlen - 1] = '\0'; fs_give((void **) &user_lptstr); dlgpw.userlen = userlen; dlgpw.pwd = (LPTSTR)fs_get(pwdlen*sizeof(TCHAR)); pwd_lptstr = utf8_to_lptstr(pwd_utf8); _tcsncpy(dlgpw.pwd, pwd_lptstr, pwdlen - 1); dlgpw.pwd[pwdlen - 1] = '\0'; fs_give((void **) &pwd_lptstr); dlgpw.pwdlen = pwdlen; dlgpw.fixuser = fixuser; dlgpw.pwc = pwc; dlgpw.rv = 0; dlgprc = login_dialog_proc; DialogBoxParam (hInst, MAKEINTRESOURCE (ps_global->install_flag ? IDD_LOGINDLG2 : IDD_LOGINDLG), NULL, dlgprc, (LPARAM)&dlgpw); if(dlgpw.rv == 0){ tuser_utf8 = lptstr_to_utf8(dlgpw.user); if(tuser_utf8){ strncpy(user_utf8, tuser_utf8, userlen - 1); user_utf8[userlen - 1] = '\0'; fs_give((void **) &tuser_utf8); } tpwd_utf8 = lptstr_to_utf8(dlgpw.pwd); if(tpwd_utf8){ strncpy(pwd_utf8, tpwd_utf8, pwdlen - 1); pwd_utf8[pwdlen - 1] = '\0'; fs_give((void **) &tpwd_utf8); } if(prespass) (*prespass) = dlgpw.prespass; } return(dlgpw.rv); }
/*---------------------------------------------------------------------- Open the printer Args: desc -- Description of item to print. Should have one trailing blank. Return value: < 0 is a failure. 0 a success. This does most of the work of popen so we can save the standard output of the command we execute and send it back to the user. ----*/ int open_printer(char *desc) { #ifndef _WINDOWS char command[201], prompt[200]; int cmd, rc, just_one; char *p, *init, *nick; char aname[100], wname[100]; char *printer; int done = 0, i, lastprinter, cur_printer = 0; HelpType help; char **list; static ESCKEY_S ekey[] = { /* TRANSLATORS: these are command labels for printing screen */ {'y', 'y', "Y", N_("Yes")}, {'n', 'n', "N", N_("No")}, /* TRANSLATORS: go to Previous Printer in list */ {ctrl('P'), 10, "^P", N_("Prev Printer")}, {ctrl('N'), 11, "^N", N_("Next Printer")}, {-2, 0, NULL, NULL}, /* TRANSLATORS: use Custom Print command */ {'c', 'c', "C", N_("CustomPrint")}, {KEY_UP, 10, "", ""}, {KEY_DOWN, 11, "", ""}, {-1, 0, NULL, NULL}}; #define PREV_KEY 2 #define NEXT_KEY 3 #define CUSTOM_KEY 5 #define UP_KEY 6 #define DOWN_KEY 7 trailer = NULL; init = NULL; nick = NULL; command[sizeof(command)-1] = '\0'; if(ps_global->VAR_PRINTER == NULL){ q_status_message(SM_ORDER | SM_DING, 3, 5, "No printer has been chosen. Use SETUP on main menu to make choice."); return(-1); } /* Is there just one print command available? */ just_one = (ps_global->printer_category!=3&&ps_global->printer_category!=2) || (ps_global->printer_category == 2 && !(ps_global->VAR_STANDARD_PRINTER && ps_global->VAR_STANDARD_PRINTER[0] && ps_global->VAR_STANDARD_PRINTER[1])) || (ps_global->printer_category == 3 && !(ps_global->VAR_PERSONAL_PRINT_COMMAND && ps_global->VAR_PERSONAL_PRINT_COMMAND[0] && ps_global->VAR_PERSONAL_PRINT_COMMAND[1])); if(F_ON(F_CUSTOM_PRINT, ps_global)) ekey[CUSTOM_KEY].ch = 'c'; /* turn this key on */ else ekey[CUSTOM_KEY].ch = -2; /* turn this key off */ if(just_one){ ekey[PREV_KEY].ch = -2; /* turn these keys off */ ekey[NEXT_KEY].ch = -2; ekey[UP_KEY].ch = -2; ekey[DOWN_KEY].ch = -2; } else{ ekey[PREV_KEY].ch = ctrl('P'); /* turn these keys on */ ekey[NEXT_KEY].ch = ctrl('N'); ekey[UP_KEY].ch = KEY_UP; ekey[DOWN_KEY].ch = KEY_DOWN; /* * count how many printers in list and find the default in the list */ if(ps_global->printer_category == 2) list = ps_global->VAR_STANDARD_PRINTER; else list = ps_global->VAR_PERSONAL_PRINT_COMMAND; for(i = 0; list[i]; i++) if(strcmp(ps_global->VAR_PRINTER, list[i]) == 0) cur_printer = i; lastprinter = i - 1; } help = NO_HELP; ps_global->mangled_footer = 1; while(!done){ if(init) fs_give((void **)&init); if(trailer) fs_give((void **)&trailer); if(just_one) printer = ps_global->VAR_PRINTER; else printer = list[cur_printer]; parse_printer(printer, &nick, &p, &init, &trailer, NULL, NULL); strncpy(command, p, sizeof(command)-1); command[sizeof(command)-1] = '\0'; fs_give((void **)&p); /* TRANSLATORS: Print something1 using something2. For example, Print configuration using printer three. */ snprintf(prompt, sizeof(prompt), _("Print %s using \"%s\" ? "), desc ? desc : "", *nick ? nick : command); prompt[sizeof(prompt)-1] = '\0'; fs_give((void **)&nick); cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global), ekey, 'y', 'x', help, RB_NORM); switch(cmd){ case 'y': q_status_message1(SM_ORDER, 0, 9, "Printing with command \"%s\"", command); done++; break; case 10: cur_printer = (cur_printer>0) ? (cur_printer-1) : lastprinter; break; case 11: cur_printer = (cur_printer<lastprinter) ? (cur_printer+1) : 0; break; case 'n': case 'x': done++; break; case 'c': done++; break; default: break; } } if(cmd == 'c'){ if(init) fs_give((void **)&init); if(trailer) fs_give((void **)&trailer); snprintf(prompt, sizeof(prompt), "Enter custom command : "); prompt[sizeof(prompt)-1] = '\0'; command[0] = '\0'; rc = 1; help = NO_HELP; while(rc){ int flags = OE_APPEND_CURRENT; rc = optionally_enter(command, -FOOTER_ROWS(ps_global), 0, sizeof(command), prompt, NULL, help, &flags); if(rc == 1){ cmd = 'x'; rc = 0; } else if(rc == 3) help = (help == NO_HELP) ? h_custom_print : NO_HELP; else if(rc == 0){ removing_trailing_white_space(command); removing_leading_white_space(command); q_status_message1(SM_ORDER, 0, 9, "Printing with command \"%s\"", command); } } } if(cmd == 'x' || cmd == 'n'){ q_status_message(SM_ORDER, 0, 2, "Print cancelled"); if(init) fs_give((void **)&init); if(trailer) fs_give((void **)&trailer); return(-1); } display_message('x'); ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S)); memset(ps_global->print, 0, sizeof(PRINT_S)); strncpy(aname, ANSI_PRINTER, sizeof(aname)-1); aname[sizeof(aname)-1] = '\0'; strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1); strncpy(wname, WYSE_PRINTER, sizeof(wname)-1); wname[sizeof(wname)-1] = '\0'; strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1); if(strucmp(command, ANSI_PRINTER) == 0 || strucmp(command, aname) == 0 || strucmp(command, WYSE_PRINTER) == 0 || strucmp(command, wname) == 0){ /*----------- Attached printer ---------*/ q_status_message(SM_ORDER, 0, 9, "Printing to attached desktop printer..."); display_message('x'); xonxoff_proc(1); /* make sure XON/XOFF used */ crlf_proc(1); /* AND LF->CR xlation */ if(strucmp(command, ANSI_PRINTER) == 0 || strucmp(command, aname) == 0){ fputs("\033[5i", stdout); ansi_off = 1; } else{ ansi_off = 0; printf("%c", 18); /* aux on for wyse60, Chuck Everett <*****@*****.**> */ } ps_global->print->fp = stdout; if(strucmp(command, ANSI_PRINTER) == 0 || strucmp(command, WYSE_PRINTER) == 0){ /* put formfeed at the end of the trailer string */ if(trailer){ int len = strlen(trailer); fs_resize((void **)&trailer, len+2); trailer[len] = '\f'; trailer[len+1] = '\0'; } else trailer = cpystr("\f"); } } else{ /*----------- Print by forking off a UNIX command ------------*/ dprint((4, "Printing using command \"%s\"\n", command ? command : "?")); ps_global->print->result = temp_nam(NULL, "pine_prt"); if(ps_global->print->result && (ps_global->print->pipe = open_system_pipe(command, &ps_global->print->result, NULL, PIPE_WRITE | PIPE_STDERR, 0, pipe_callback, NULL))){ ps_global->print->fp = ps_global->print->pipe->out.f; } else{ if(ps_global->print->result){ our_unlink(ps_global->print->result); fs_give((void **)&ps_global->print->result); } q_status_message1(SM_ORDER | SM_DING, 3, 4, "Error opening printer: %s", error_description(errno)); dprint((2, "Error popening printer \"%s\"\n", error_description(errno))); if(init) fs_give((void **)&init); if(trailer) fs_give((void **)&trailer); return(-1); } } ps_global->print->err = 0; if(init){ if(*init) fputs(init, ps_global->print->fp); fs_give((void **)&init); } cb.cbuf[0] = '\0'; cb.cbufp = cb.cbuf; cb.cbufend = cb.cbuf; #else /* _WINDOWS */ int status; LPTSTR desclpt = NULL; if(desc) desclpt = utf8_to_lptstr(desc); if (status = mswin_print_ready (0, desclpt)) { q_status_message1(SM_ORDER | SM_DING, 3, 4, "Error starting print job: %s", mswin_print_error(status)); if(desclpt) fs_give((void **) &desclpt); return(-1); } if(desclpt) fs_give((void **) &desclpt); q_status_message(SM_ORDER, 0, 9, "Printing to windows printer..."); display_message('x'); /* init print control structure */ ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S)); memset(ps_global->print, 0, sizeof(PRINT_S)); ps_global->print->err = 0; #endif /* _WINDOWS */ return(0); }
TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) { char *s,tmp[MAILTMPLEN]; TCPSTREAM *stream = NIL; int argblk[5],jfn; unsigned long i,j,k,l; char file[MAILTMPLEN]; port &= 0xffff; /* erase flags */ /* domain literal? */ if (host[0] == '[' && host[strlen (host)-1] == ']') { if (((i = strtoul (s = host+1,&s,10)) <= 255) && *s++ == '.' && ((j = strtoul (s,&s,10)) <= 255) && *s++ == '.' && ((k = strtoul (s,&s,10)) <= 255) && *s++ == '.' && ((l = strtoul (s,&s,10)) <= 255) && *s++ == ']' && !*s) { argblk[3] = (i << 24) + (j << 16) + (k << 8) + l; sprintf (tmp,"[%lu.%lu.%lu.%lu]",i,j,k,l); } else { sprintf (tmp,"Bad format domain-literal: %.80s",host); mm_log (tmp,ERROR); return NIL; } } else { /* host name */ argblk[1] = _GTHPN; /* get IP address and primary name */ argblk[2] = (int) (host-1); /* pointer to host */ argblk[4] = (int) (tmp-1); if (!jsys (GTHST,argblk)) { /* first try DEC's domain way */ argblk[1] = _GTHPN; /* get IP address and primary name */ argblk[2] = (int) (host-1); argblk[4] = (int) (tmp-1); if (!jsys (GTDOM,argblk)){/* try the CHIVES domain way */ argblk[1] = _GTHSN; /* failed, do the host table then */ if (!jsys (GTHST,argblk)) { sprintf (tmp,"No such host as %s",host); mm_log (tmp,ERROR); return NIL; } argblk[1] = _GTHNS; /* convert number to string */ argblk[2] = (int) (tmp-1); /* get the official name */ if (!jsys (GTHST,argblk)) strcpy (tmp,host); } } } sprintf (file,"TCP:.%o-%d;PERSIST:30;CONNECTION:ACTIVE",argblk[3],port); argblk[1] = GJ_SHT; /* short form GTJFN% */ argblk[2] = (int) (file-1); /* pointer to file name */ /* get JFN for TCP: file */ if (!jsys (GTJFN,argblk)) fatal ("Unable to create TCP JFN"); jfn = argblk[1]; /* note JFN for later */ /* want 8-bit bidirectional I/O */ argblk[2] = OF_RD|OF_WR|(FLD (8,monsym("OF%BSZ"))); if (!jsys (OPENF,argblk)) { sprintf (file,"Can't connect to %s,%d server",tmp,port); mm_log (file,ERROR); return NIL; } /* create TCP/IP stream */ stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM)); stream->host = cpystr (tmp); /* copy official host name */ argblk[1] = _GTHNS; /* convert number to string */ argblk[2] = (int) (tmp-1); argblk[3] = -1; /* want local host */ if (!jsys (GTHST,argblk)) strcpy (tmp,"LOCAL"); stream->localhost = cpystr (tmp); stream->port = port; /* save port number */ stream->jfn = jfn; /* init JFN */ return stream; }
/*---------------------------------------------------------------------- Accepts: stream -- mail stream to removed message references from msgs -- pointer to message manipulation struct flags MI_REFILTERING -- do includes appropriate for refiltering MI_STATECHGONLY -- when refiltering, maybe only re-include messages which have had state changes since they were originally filtered Returns 1 if any new messages are included (indicating that we need to re-sort) 0 if no new messages are included ----*/ int msgno_include(MAILSTREAM *stream, MSGNO_S *msgs, int flags) { long i, slop, old_total, old_size; int exbits, ret = 0; size_t len; MESSAGECACHE *mc; if(!msgs) return(ret); for(i = 1L; i <= stream->nmsgs; i++){ if(!msgno_exceptions(stream, i, "0", &exbits, FALSE)) exbits = 0; if((((flags & MI_REFILTERING) && (exbits & MSG_EX_FILTERED) && !(exbits & MSG_EX_FILED) && (!(flags & MI_STATECHGONLY) || (exbits & MSG_EX_STATECHG))) || (!(flags & MI_REFILTERING) && !(exbits & MSG_EX_FILTERED))) && get_lflag(stream, NULL, i, MN_EXLD)){ old_total = msgs->max_msgno; old_size = msgs->sort_size; slop = (msgs->max_msgno + 1L) % 64; msgs->sort_size = (msgs->max_msgno + 1L) + (64 - slop); len = (size_t) msgs->sort_size * sizeof(long); if(msgs->sort){ if(old_size != msgs->sort_size) fs_resize((void **)&(msgs->sort), len); } else msgs->sort = (long *)fs_get(len); ret = 1; msgs->sort[++msgs->max_msgno] = i; msgs->isort[i] = msgs->max_msgno; set_lflag(stream, msgs, msgs->max_msgno, MN_EXLD, 0); if(flags & MI_REFILTERING){ exbits &= ~(MSG_EX_FILTERED | MSG_EX_TESTED); msgno_exceptions(stream, i, "0", &exbits, TRUE); } if(old_total <= 0L){ /* if no previous messages, */ if(!msgs->select){ /* select the new message */ msgs->sel_size = 8L; len = (size_t)msgs->sel_size * sizeof(long); msgs->select = (long *)fs_get(len); } msgs->sel_cnt = 1L; msgs->sel_cur = 0L; msgs->select[0] = 1L; } } else if((flags & MI_REFILTERING) && (exbits & (MSG_EX_FILTERED | MSG_EX_TESTED)) && !(exbits & MSG_EX_FILED) && (!(exbits & MSG_EX_MANUNDEL) || ((mc = mail_elt(stream, i)) && mc->deleted)) && (!(flags & MI_STATECHGONLY) || (exbits & MSG_EX_STATECHG))){ /* * We get here if the message was filtered by a filter that * just changes status bits (it wasn't excluded), and now also * if the message was merely tested for filtering. It has also * not been manually undeleted. If it was manually undeleted, we * don't want to reprocess the filter, undoing the user's * manual undeleting. Of course, a new pine will re check this * message anyway, so the user had better be using this * manual undeleting only to temporarily save him or herself * from an expunge before Saving or printing or something. * Also, we want to still try filtering if the message has at * all been marked deleted, even if the there was any manual * undeleting, since this directly precedes an expunge, we want * to make sure the filter does the right thing before getting * rid of the message forever. */ exbits &= ~(MSG_EX_FILTERED | MSG_EX_TESTED); msgno_exceptions(stream, i, "0", &exbits, TRUE); } } return(ret); }
/* * We're not actually using the RGB value other than as a string which * maps into the color. * In fact, on some systems color 1 and color 4 are swapped, and color 3 * and color 6 are swapped. So don't believe the RGB values. * Still, it feels right to have them be the canonical values, so we do that. * * Actually we are using them more now. In color_to_val we map to the closest * color if we don't get an exact match. We ignore values over 255. * * More than one "name" can map to the same "rgb". * More than one "name" can map to the same "val". * The "val" for a "name" and for its "rgb" are the same. */ struct color_table * init_color_table(void) { struct color_table *ct = NULL, *t; int i, count; char colorname[12]; count = pico_count_in_color_table(); if(count > 0 && count <= 256+COL_TRANS()){ int ind, graylevel; struct { char rgb[RGBLEN+1]; int red, green, blue; } cube[256]; ct = (struct color_table *) fs_get((count+1) * sizeof(struct color_table)); if(ct) memset(ct, 0, (count+1) * sizeof(struct color_table)); /* * We boldly assume that 256 colors means xterm 256-color * color cube and grayscale. */ if(ANSI_COLOR() && (count == 256+COL_TRANS())){ int r, g, b, gray; for(r = 0; r < 6; r++) for(g = 0; g < 6; g++) for(b = 0; b < 6; b++){ ind = 16 + 36*r + 6*g + b; cube[ind].red = r ? (40*r + 55) : 0; cube[ind].green = g ? (40*g + 55) : 0; cube[ind].blue = b ? (40*b + 55) : 0; snprintf(cube[ind].rgb, sizeof(cube[ind].rgb), "%3.3d,%3.3d,%3.3d", cube[ind].red, cube[ind].green, cube[ind].blue); } for(gray = 0; gray < 24; gray++){ ind = gray + 232; graylevel = 10*gray + 8; cube[ind].red = graylevel; cube[ind].green = graylevel; cube[ind].blue = graylevel; snprintf(cube[ind].rgb, sizeof(cube[ind].rgb), "%3.3d,%3.3d,%3.3d", graylevel, graylevel, graylevel); } } for(i = 0, t = ct; t && i < count; i++, t++){ t->val = i; switch(i){ case COL_BLACK: strncpy(colorname, "black", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_RED: strncpy(colorname, "red", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_GREEN: strncpy(colorname, "green", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_YELLOW: strncpy(colorname, "yellow", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_BLUE: strncpy(colorname, "blue", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_MAGENTA: strncpy(colorname, "magenta", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_CYAN: strncpy(colorname, "cyan", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; case COL_WHITE: strncpy(colorname, "white", sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; break; default: snprintf(colorname, sizeof(colorname), "color%3.3d", i); break; } if(COL_TRANS() && i == count-1){ strncpy(colorname, MATCH_TRAN_COLOR, sizeof(colorname)); colorname[sizeof(colorname)-1] = '\0'; } add_to_color_name_list(t, colorname); if(count == 8+COL_TRANS()){ if(COL_TRANS() && i == count-1){ t->red = t->green = t->blue = -1; } else switch(i){ case COL_BLACK: t->red = t->green = t->blue = 0; add_to_color_name_list(t, "color008"); add_to_color_name_list(t, "colordgr"); add_to_color_name_list(t, "colormgr"); break; case COL_RED: t->red = 255; t->green = t->blue = 0; add_to_color_name_list(t, "color009"); break; case COL_GREEN: t->green = 255; t->red = t->blue = 0; add_to_color_name_list(t, "color010"); break; case COL_YELLOW: t->red = t->green = 255; t->blue = 0; add_to_color_name_list(t, "color011"); break; case COL_BLUE: t->red = t->green = 0; t->blue = 255; add_to_color_name_list(t, "color012"); break; case COL_MAGENTA: t->red = t->blue = 255; t->green = 0; add_to_color_name_list(t, "color013"); break; case COL_CYAN: t->red = 0; t->green = t->blue = 255; add_to_color_name_list(t, "color014"); break; case COL_WHITE: t->red = t->green = t->blue = 255; add_to_color_name_list(t, "color015"); add_to_color_name_list(t, "colorlgr"); break; } } else if(count == 16+COL_TRANS() || count == 256+COL_TRANS()){ if(COL_TRANS() && i == count-1){ t->red = t->green = t->blue = -1; } else /* * This set of RGB values seems to come close to describing * what a 16-color xterm gives you. */ switch(i){ case COL_BLACK: t->red = t->green = t->blue = 0; break; case COL_RED: /* actually dark red */ t->red = 174; t->green = t->blue = 0; break; case COL_GREEN: /* actually dark green */ t->green = 174; t->red = t->blue = 0; break; case COL_YELLOW: /* actually dark yellow */ t->blue = 0; t->red = t->green = 174; break; case COL_BLUE: /* actually dark blue */ t->blue = 174; t->red = t->green = 0; break; case COL_MAGENTA: /* actually dark magenta */ t->green = 0; t->red = t->blue = 174; break; case COL_CYAN: /* actually dark cyan */ t->red = 0; t->green = t->blue = 174; break; case COL_WHITE: /* actually light gray */ t->red = t->green = t->blue = 174; if(count == 16) add_to_color_name_list(t, "colorlgr"); break; case 8: /* dark gray */ t->red = t->green = t->blue = 64; if(count == 16){ add_to_color_name_list(t, "colordgr"); add_to_color_name_list(t, "colormgr"); } break; case 9: /* red */ t->red = 255; t->green = t->blue = 0; break; case 10: /* green */ t->green = 255; t->red = t->blue = 0; break; case 11: /* yellow */ t->blue = 0; t->red = t->green = 255; break; case 12: /* blue */ t->blue = 255; t->red = t->green = 0; break; case 13: /* magenta */ t->green = 0; t->red = t->blue = 255; break; case 14: /* cyan */ t->red = 0; t->green = t->blue = 255; break; case 15: /* white */ t->red = t->green = t->blue = 255; break; default: t->red = cube[i].red; t->green = cube[i].green; t->blue = cube[i].blue; switch(i){ case 238: add_to_color_name_list(t, "colordgr"); break; case 244: add_to_color_name_list(t, "colormgr"); break; case 250: add_to_color_name_list(t, "colorlgr"); break; } break; } } else{ if(COL_TRANS() && i == count-1){ t->red = t->green = t->blue = -1; } else switch(i){ case COL_BLACK: t->red = t->green = t->blue = 0; break; case COL_RED: /* actually dark red */ t->red = 255; t->green = t->blue = 0; break; case COL_GREEN: /* actually dark green */ t->green = 255; t->red = t->blue = 0; break; case COL_YELLOW: /* actually dark yellow */ t->blue = 0; t->red = t->green = 255; break; case COL_BLUE: /* actually dark blue */ t->blue = 255; t->red = t->green = 0; break; case COL_MAGENTA: /* actually dark magenta */ t->green = 0; t->red = t->blue = 255; break; case COL_CYAN: /* actually dark cyan */ t->red = 0; t->green = t->blue = 255; break; case COL_WHITE: /* actually light gray */ t->red = t->green = t->blue = 255; break; default: /* this will just be a string match */ t->red = t->green = t->blue = 256+i; break; } } } for(i = 0, t = ct; t && i < count; i++, t++){ t->rgb = (char *)fs_get((RGBLEN+1) * sizeof(char)); if(COL_TRANS() && i == count-1) snprintf(t->rgb, RGBLEN+1, MATCH_TRAN_COLOR); else snprintf(t->rgb, RGBLEN+1, "%3.3d,%3.3d,%3.3d", t->red, t->green, t->blue); } } return(ct); }
/* * Manage the display list cache. * * The cache is a circular array of DL_CACHE_S elements. It always * contains a contiguous set of display lines. * The lowest numbered line in the cache is * valid_low, and the highest is valid_high. Everything in between is * also valid. Index_of_low is where to look * for the valid_low element in the circular array. * * We make calls to dlc_prev and dlc_next to get new entries for the cache. * We need a starting value before we can do that. * * This returns a pointer to a dlc for the desired row. If you want the * actual display list line you call dlist(row) instead of dlc_mgr. */ DL_CACHE_S * dlc_mgr(long int row, DlMgrOps op, DL_CACHE_S *dlc_start) { int new_index, known_index, next_index; DL_CACHE_S *dlc = (DL_CACHE_S *)NULL; long next_row; long prev_row; if(op == Lookup){ if(row >= valid_low && row <= valid_high){ /* already cached */ new_index = ((row - valid_low) + index_of_low) % size_of_cache; dlc = &cache_array[new_index]; } else if(row > valid_high){ /* row is past where we've looked */ known_index = ((valid_high - valid_low) + index_of_low) % size_of_cache; next_row = valid_high + 1L; /* we'll usually be looking for row = valid_high + 1 */ while(next_row <= row){ new_index = (known_index + 1) % size_of_cache; dlc = dlc_next(&cache_array[known_index], &cache_array[new_index]); /* * This means somebody changed the file out from underneath * us. This would happen if dlc_next needed to ask for an * abe to figure out what the type of the next row is, but * adrbk_get_ae returned a NULL. I don't think that can * happen, but if it does... */ if(dlc->type == DlcNotSet){ dprint((1, "dlc_next returned DlcNotSet\n")); goto panic_abook_corrupt; } if(n_cached == size_of_cache){ /* replaced low cache entry */ valid_low++; index_of_low = (index_of_low + 1) % size_of_cache; } else n_cached++; valid_high++; next_row++; known_index = new_index; /* for next time through loop */ } } else if(row < valid_low){ /* row is back up the screen */ known_index = index_of_low; prev_row = valid_low - 1L; while(prev_row >= row){ new_index = (known_index - 1 + size_of_cache) % size_of_cache; dlc = dlc_prev(&cache_array[known_index], &cache_array[new_index]); if(dlc->type == DlcNotSet){ dprint((1, "dlc_prev returned DlcNotSet (1)\n")); goto panic_abook_corrupt; } if(n_cached == size_of_cache) /* replaced high cache entry */ valid_high--; else n_cached++; valid_low--; index_of_low = (index_of_low - 1 + size_of_cache) % size_of_cache; prev_row--; known_index = new_index; } } } else if(op == Initialize){ n_cached = 0; if(!cache_array || size_of_cache != 3 * MAX(as.l_p_page,1)){ if(cache_array) free_cache_array(&cache_array, size_of_cache); size_of_cache = 3 * MAX(as.l_p_page,1); cache_array = (DL_CACHE_S *)fs_get(size_of_cache * sizeof(DL_CACHE_S)); memset((void *)cache_array, 0, size_of_cache * sizeof(DL_CACHE_S)); } /* this will return NULL below and the caller should ignore that */ } /* * Flush all rows for a particular addrbook entry from the cache, but * keep the cache alive and anchored in the same place. The particular * entry is the one that dlc_start is one of the rows of. */ else if(op == FlushDlcFromCache){ long low_entry; next_row = dlc_start->global_row - 1; for(; next_row >= valid_low; next_row--){ next_index = ((next_row - valid_low) + index_of_low) % size_of_cache; if(!dlc_siblings(dlc_start, &cache_array[next_index])) break; } low_entry = next_row + 1L; /* * If low_entry now points one past a ListBlankBottom, delete that, * too, since it may not make sense anymore. */ if(low_entry > valid_low){ next_index = ((low_entry -1L - valid_low) + index_of_low) % size_of_cache; if(cache_array[next_index].type == DlcListBlankBottom) low_entry--; } if(low_entry > valid_low){ /* invalidate everything >= this */ n_cached -= (valid_high - (low_entry - 1L)); valid_high = low_entry - 1L; } else{ /* * This is the tough case. That entry was the first thing cached, * so we need to invalidate the whole cache. However, we also * need to keep at least one thing cached for an anchor, so * we need to get the dlc before this one and it should be a * dlc not related to this same addrbook entry. */ known_index = index_of_low; prev_row = valid_low - 1L; for(;;){ new_index = (known_index - 1 + size_of_cache) % size_of_cache; dlc = dlc_prev(&cache_array[known_index], &cache_array[new_index]); if(dlc->type == DlcNotSet){ dprint((1, "dlc_prev returned DlcNotSet (2)\n")); goto panic_abook_corrupt; } valid_low--; index_of_low = (index_of_low - 1 + size_of_cache) % size_of_cache; if(!dlc_siblings(dlc_start, dlc)) break; known_index = new_index; } n_cached = 1; valid_high = valid_low; } } /* * We have to anchor ourselves at a first element. * Here's how we start at the top. */ else if(op == FirstEntry){ initialize_dlc_cache(); n_cached++; dlc = &cache_array[0]; dlc = get_global_top_dlc(dlc); dlc->global_row = row; index_of_low = 0; valid_low = row; valid_high = row; } /* And here's how we start from the bottom. */ else if(op == LastEntry){ initialize_dlc_cache(); n_cached++; dlc = &cache_array[0]; dlc = get_global_bottom_dlc(dlc); dlc->global_row = row; index_of_low = 0; valid_low = row; valid_high = row; } /* * And here's how we start from an arbitrary position in the middle. * We root the cache at display line row, so it helps if row is close * to where we're going to be starting so that things are easy to find. * The dl that goes with line row is dl_start from addrbook number * adrbk_num_start. */ else if(op == ArbitraryStartingPoint){ AddrScrn_Disp dl; initialize_dlc_cache(); n_cached++; dlc = &cache_array[0]; /* * Save this in case fill_in_dl_field needs to free the text * it points to. */ dl = dlc->dl; *dlc = *dlc_start; dlc->dl = dl; dlc->global_row = row; index_of_low = 0; valid_low = row; valid_high = row; } else if(op == DoneWithCache){ n_cached = 0; if(cache_array) free_cache_array(&cache_array, size_of_cache); } return(dlc); panic_abook_corrupt: q_status_message(SM_ORDER | SM_DING, 5, 10, _("Addrbook changed unexpectedly, re-syncing...")); dprint((1, _("addrbook changed while we had it open?, re-sync\n"))); dprint((2, "valid_low=%ld valid_high=%ld index_of_low=%d size_of_cache=%d\n", valid_low, valid_high, index_of_low, size_of_cache)); dprint((2, "n_cached=%d new_index=%d known_index=%d next_index=%d\n", n_cached, new_index, known_index, next_index)); dprint((2, "next_row=%ld prev_row=%ld row=%ld\n", next_row, prev_row, row)); /* jump back to a safe starting point */ longjmp(addrbook_changed_unexpectedly, 1); /*NOTREACHED*/ }
/* * This is intended to be a generic tool to select strings from a list * of strings. * * Args lsel -- the items as well as the answer are contained in this list * flags -- There is some inconsistent flags usage. Notice that the * flag SFL_ALLOW_LISTMODE is a flag passed in the flags * argument whereas the flag SFL_NOSELECT is a per item * (that is, per LIST_SEL_S) flag. * title -- passed to conf_scroll_screen * pdesc -- passed to conf_scroll_screen * help -- passed to conf_scroll_screen * helptitle -- passed to conf_scroll_screen * * You have screen width - 4 columns to work with. If you want to overflow to * a second (or third or fourth) line for an item just send another item * in the list but with the SFL_NOSELECT flag set. Only the selectable lines * will be highlighted, which is kind of a crock, but it looked like a lot * of work to fix that. * * Returns 0 on successful choice * -1 if cancelled */ int select_from_list_screen(LIST_SEL_S *lsel, long unsigned int flags, char *title, char *pdesc, HelpType help, char *htitle, LIST_SEL_S *starting_val) { CONF_S *ctmp = NULL, *first_line = NULL; OPT_SCREEN_S screen; int j, lv, ret = -1; LIST_SEL_S *p; char *display; size_t l; ScreenMode listmode = SingleMode; int (*tool)(struct pine *, int, CONF_S **, unsigned); if(!lsel) return(ret); /* find longest value's length */ for(lv = 0, p = lsel; p; p = p->next){ if(!(p->flags & SFL_NOSELECT)){ display = p->display_item ? p->display_item : p->item ? p->item : ""; if(lv < (j = utf8_width(display))) lv = j; } } lv = MIN(lv, ps_global->ttyo->screen_cols - 4); tool = (flags & SFL_CTRLC) ? select_from_list_tool_allow_noselections : select_from_list_tool; /* * Convert the passed in list to conf_scroll lines. */ if(flags & SFL_ALLOW_LISTMODE){ if(flags & SFL_ONLY_LISTMODE) {assert(flags & SFL_STARTIN_LISTMODE);} for(p = lsel; p; p = p->next){ display = p->display_item ? p->display_item : p->item ? p->item : ""; new_confline(&ctmp); if(!first_line && !(p->flags & SFL_NOSELECT)) first_line = ctmp; if(!first_line && !(p->flags & SFL_NOSELECT)) if(!starting_val || (starting_val == p)) first_line = ctmp; /* generous allocation */ l = lv + 4 + strlen(display); ctmp->value = (char *) fs_get((l + 1) * sizeof(char)); utf8_snprintf(ctmp->value, l+1, " %-*.*w", lv, lv, display); ctmp->value[l] = '\0'; ctmp->d.l.lsel = p; ctmp->d.l.listmode = &listmode; if(flags & SFL_ONLY_LISTMODE){ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_olm_ctrlc; else ctmp->keymenu = &sel_from_list_olm; } else{ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_sm_ctrlc; else ctmp->keymenu = &sel_from_list_sm; } ctmp->help = help; ctmp->help_title = htitle; ctmp->tool = tool; ctmp->flags = CF_STARTITEM | ((p->flags & SFL_NOSELECT) ? CF_NOSELECT : 0); } } else{ assert(!(flags & SFL_ONLY_LISTMODE)); assert(!(flags & SFL_STARTIN_LISTMODE)); for(p = lsel; p; p = p->next){ display = p->display_item ? p->display_item : p->item ? p->item : ""; new_confline(&ctmp); if(!first_line && !(p->flags & SFL_NOSELECT)) if(!starting_val || (starting_val == p)) first_line = ctmp; l = lv + strlen(display); ctmp->value = (char *) fs_get((l + 1) * sizeof(char)); utf8_snprintf(ctmp->value, l+1, "%-*.*w", lv, lv, display); ctmp->value[l] = '\0'; ctmp->d.l.lsel = p; ctmp->d.l.listmode = &listmode; if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_ctrlc; else ctmp->keymenu = &sel_from_list; ctmp->help = help; ctmp->help_title = htitle; ctmp->tool = tool; ctmp->flags = CF_STARTITEM | ((p->flags & SFL_NOSELECT) ? CF_NOSELECT : 0); ctmp->valoffset = 4; } } /* just convert to start in listmode after the fact, easier that way */ if(flags & SFL_STARTIN_LISTMODE){ listmode = ListMode; for(ctmp = first_line; ctmp; ctmp = next_confline(ctmp)) if(!(ctmp->flags & CF_NOSELECT) && ctmp->value){ ctmp->value[0] = '['; ctmp->value[1] = ctmp->d.l.lsel->selected ? 'X' : SPACE; ctmp->value[2] = ']'; if(flags & SFL_ONLY_LISTMODE){ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_olm_ctrlc; else ctmp->keymenu = &sel_from_list_olm; } else{ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_lm_ctrlc; else ctmp->keymenu = &sel_from_list_lm; } } } memset(&screen, 0, sizeof(screen)); switch(conf_scroll_screen(ps_global, &screen, first_line, title, pdesc, 0)){ case 1: ret = 0; break; default: break; } ps_global->mangled_screen = 1; return(ret); }
ESCKEY_S * construct_combined_esclist(ESCKEY_S *list1, ESCKEY_S *list2) { ESCKEY_S *list; int i, j=0, count; count = 2; /* for blank key and for OTHER key */ for(i=0; list1 && list1[i].ch != -1; i++) count++; for(i=0; list2 && list2[i].ch != -1; i++) count++; list = (ESCKEY_S *) fs_get((count + 1) * sizeof(*list)); memset(list, 0, (count + 1) * sizeof(*list)); list[j].ch = -2; /* leave blank */ list[j].rval = 0; list[j].name = NULL; list[j++].label = NULL; list[j].ch = 'o'; list[j].rval = OTHER_RETURN_VAL; list[j].name = "O"; list[j].label = N_("OTHER CMDS"); /* * Make sure that O for OTHER CMD or the return val for OTHER CMD * isn't used for something else. */ for(i=0; list1 && list1[i].ch != -1; i++){ if(list1[i].rval == list[j].rval) alpine_panic("1bad rval in d_r"); if(F_OFF(F_USE_FK,ps_global) && list1[i].ch == list[j].ch) alpine_panic("1bad ch in ccl"); } for(i=0; list2 && list2[i].ch != -1; i++){ if(list2[i].rval == list[j].rval) alpine_panic("2bad rval in d_r"); if(F_OFF(F_USE_FK,ps_global) && list2[i].ch == list[j].ch) alpine_panic("2bad ch in ccl"); } j++; /* the visible set */ for(i=0; list1 && list1[i].ch != -1; i++){ if(i >= KEYS_PER_LIST && list1[i].label[0] != '\0') alpine_panic("too many visible keys in ccl"); list[j++] = list1[i]; } /* the rest are invisible */ for(i=0; list2 && list2[i].ch != -1; i++){ list[j] = list2[i]; list[j].label = ""; list[j++].name = ""; } list[j].ch = -1; return(list); }
/* * This should really be part of radio_buttons itself, I suppose. It was * easier to do it this way. This is for when there are more than 12 * possible commands. We could have all the radio_buttons calls call this * instead of radio_buttons, or rename this to radio_buttons. * * Radio_buttons is limited to 10 visible commands unless there is no Help, * in which case it is 11 visible commands. * Double_radio_buttons is limited to 16 visible commands because it uses * slots 3 and 4 for readability and the OTHER CMD. */ int double_radio_buttons(char *prompt, int line, ESCKEY_S *esc_list, int dflt, int on_ctrl_C, HelpType help_text, int flags) { ESCKEY_S *list = NULL, *list1 = NULL, *list2 = NULL; int i = 0, j; int v = OTHER_RETURN_VAL, listnum = 0; #ifdef _WINDOWS if(mswin_usedialog()) return(radio_buttons(prompt, line, esc_list, dflt, on_ctrl_C, help_text, flags)); #endif /* check to see if it will all fit in one */ while(esc_list && esc_list[i].ch != -1) i++; i++; /* for ^C */ if(help_text != NO_HELP) i++; if(i <= 12) return(radio_buttons(prompt, line, esc_list, dflt, on_ctrl_C, help_text, flags)); /* * Won't fit, split it into two lists. * * We can fit at most 8 items in the visible list. The rest of * the commands have to be invisible. Each of list1 and list2 should * have no more than 8 visible (name != "" || label != "") items. */ list1 = (ESCKEY_S *)fs_get((KEYS_PER_LIST+1) * sizeof(*list1)); memset(list1, 0, (KEYS_PER_LIST+1) * sizeof(*list1)); list2 = (ESCKEY_S *)fs_get((KEYS_PER_LIST+1) * sizeof(*list2)); memset(list2, 0, (KEYS_PER_LIST+1) * sizeof(*list2)); for(j=0,i=0; esc_list[i].ch != -1 && j < KEYS_PER_LIST; j++,i++) list1[j] = esc_list[i]; list1[j].ch = -1; for(j=0; esc_list[i].ch != -1 && j < KEYS_PER_LIST; j++,i++) list2[j] = esc_list[i]; list2[j].ch = -1; list = construct_combined_esclist(list1, list2); while(v == OTHER_RETURN_VAL){ v = radio_buttons(prompt,line,list,dflt,on_ctrl_C,help_text,flags); if(v == OTHER_RETURN_VAL){ fs_give((void **) &list); listnum = 1 - listnum; list = construct_combined_esclist(listnum ? list2 : list1, listnum ? list1 : list2); } } if(list) fs_give((void **) &list); if(list1) fs_give((void **) &list1); if(list2) fs_give((void **) &list2); return(v); }
/* {{{ mail_newerrorlist * * Mail instantiate ERRORLIST * Returns: new ERRORLIST list * Author: CJH */ static ERRORLIST *mail_newerrorlist(void) { return (ERRORLIST *) memset(fs_get(sizeof(ERRORLIST)), 0, sizeof(ERRORLIST)); }
/*---------------------------------------------------------------------- Initialize a message manipulation structure for the given total Accepts: msgs - pointer to pointer to message manipulation struct tot - number of messages to initialize with ----*/ void msgno_init(MSGNO_S **msgs, long int tot, SortOrder def_sort, int def_sort_rev) { long slop = (tot + 1L) % 64; size_t len; if(!msgs) return; if(!(*msgs)){ (*msgs) = (MSGNO_S *)fs_get(sizeof(MSGNO_S)); memset((void *)(*msgs), 0, sizeof(MSGNO_S)); } (*msgs)->sel_cur = 0L; (*msgs)->sel_cnt = 1L; (*msgs)->sel_size = 8L; len = (size_t)(*msgs)->sel_size * sizeof(long); if((*msgs)->select) fs_resize((void **)&((*msgs)->select), len); else (*msgs)->select = (long *)fs_get(len); (*msgs)->select[0] = (tot) ? 1L : 0L; (*msgs)->sort_size = (tot + 1L) + (64 - slop); len = (size_t)(*msgs)->sort_size * sizeof(long); if((*msgs)->sort) fs_resize((void **)&((*msgs)->sort), len); else (*msgs)->sort = (long *)fs_get(len); memset((void *)(*msgs)->sort, 0, len); for(slop = 1L ; slop <= tot; slop++) /* reusing "slop" */ (*msgs)->sort[slop] = slop; /* * If there is filtering happening, isort will become larger than sort. * Sort is a list of raw message numbers in their sorted order. There * are missing raw numbers because some of the messages are excluded * (MN_EXLD) from the view. Isort has one entry for every raw message * number, which maps to the corresponding msgno (the row in the sort * array). Some of the entries in isort are not used because those * messages are excluded, but the entry is still there because we want * to map from rawno to message number and the row number is the rawno. */ (*msgs)->isort_size = (*msgs)->sort_size; if((*msgs)->isort) fs_resize((void **)&((*msgs)->isort), len); else (*msgs)->isort = (long *)fs_get(len); (*msgs)->max_msgno = tot; (*msgs)->nmsgs = tot; /* set the inverse array */ msgno_reset_isort(*msgs); (*msgs)->sort_order = def_sort; (*msgs)->reverse_sort = def_sort_rev; (*msgs)->flagged_hid = 0L; (*msgs)->flagged_exld = 0L; (*msgs)->flagged_chid = 0L; (*msgs)->flagged_chid2= 0L; (*msgs)->flagged_coll = 0L; (*msgs)->flagged_usor = 0L; (*msgs)->flagged_tmp = 0L; (*msgs)->flagged_stmp = 0L; /* * This one is the total number of messages which are flagged * hid OR chid. It isn't the sum of those two because a * message may be flagged both at the same time. */ (*msgs)->flagged_invisible = 0L; /* * And this keeps track of visible threads in the THRD_INDX. This is * weird because a thread is visible if any of its messages are * not hidden, including those that are CHID hidden. You can't just * count up all the messages that are hid or chid because you would * miss a thread that has its top-level message hidden but some chid * message not hidden. */ (*msgs)->visible_threads = -1L; }
/* {{{ mail_newmessagelist * * Mail instantiate MESSAGELIST * Returns: new MESSAGELIST list * Author: CJH */ static MESSAGELIST *mail_newmessagelist(void) { return (MESSAGELIST *) memset(fs_get(sizeof(MESSAGELIST)), 0, sizeof(MESSAGELIST)); }
/*---------------------------------------------------------------------- return our index number for the given raw message number Accepts: msgs - pointer to message manipulation struct msgno - number that's important part Returns: our index number of given raw message ----*/ int msgno_exceptions(MAILSTREAM *stream, long int rawno, char *part, int *bits, int set) { PINELT_S **peltp; PARTEX_S **partp; MESSAGECACHE *mc; if(!stream || rawno < 1L || rawno > stream->nmsgs) return FALSE; /* * Get pointer to exceptional part list, and scan down it * for the requested part... */ if((mc = mail_elt(stream, rawno)) && (*(peltp = (PINELT_S **) &mc->sparep))) for(partp = &(*peltp)->exceptions; *partp; partp = &(*partp)->next){ if(part){ if(!strcmp(part, (*partp)->partno)){ if(bits){ if(set) (*partp)->handling = *bits; else *bits = (*partp)->handling; } return(TRUE); /* bingo! */ } } else if(bits){ /* * The caller provided flags, but no part. * We are looking to see if the bits are set in any of the * parts. This doesn't count parts with non-digit partno's (like * scores) because those are used differently. * any of the flags... */ if((*partp)->partno && *(*partp)->partno && isdigit((unsigned char) *(*partp)->partno) && (*bits & (*partp)->handling) == *bits) return(TRUE); } else /* * The caller didn't specify a part, so * they must just be interested in whether * the msg had any exceptions at all... */ return(TRUE); } if(set && part){ if(!*peltp){ *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S)); memset(*peltp, 0, sizeof(PINELT_S)); partp = &(*peltp)->exceptions; } (*partp) = (PARTEX_S *) fs_get(sizeof(PARTEX_S)); (*partp)->partno = cpystr(part); (*partp)->next = NULL; (*partp)->handling = *bits; return(TRUE); } if(bits) /* init bits */ *bits = 0; return(FALSE); }
/* * Dialog proc to handle index sort selection. * * Configures the dialog box on init and retrieves the settings on exit. */ BOOL CALLBACK __export args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { BOOL ret = FALSE; long i, j, block_size; char **args_text; LPTSTR args_text_lptstr, args_block_lptstr; switch (uMsg) { case WM_INITDIALOG: args_text = (char **)lParam; /* * First convert char *'s over to one big block of * Unicode */ i = 0; while(args_text && *args_text){ i += strlen(*args_text++); i += 2; } block_size = i; args_block_lptstr = (LPTSTR)fs_get((block_size+1)*sizeof(TCHAR)); args_text = (char **)lParam; i = 0; j = 0; while(args_text && *args_text){ args_text_lptstr = utf8_to_lptstr(*args_text++); while(args_text_lptstr[i] && j < block_size){ args_block_lptstr[j++] = args_text_lptstr[i++]; } args_block_lptstr[j++] = '\r'; args_block_lptstr[j++] = '\n'; fs_give((void **) &args_text_lptstr); i = 0; } args_block_lptstr[j] = '\0'; /* and replace everything selected with args_text */ SendDlgItemMessage(hDlg, IDC_ARGTEXT, WM_SETTEXT, (WPARAM) 0, (LPARAM) args_block_lptstr); fs_give((void **)&args_block_lptstr); return (1); case WM_CLOSE : ret = TRUE; EndDialog (hDlg, TRUE); break; case WM_COMMAND: switch (wParam) { case IDOK: ret = TRUE; EndDialog (hDlg, TRUE); break; } break; } return (ret); }
/* * Calculates all of the scores for the searchset and stores them in the * mail elts. Careful, this function uses patterns so if the caller is using * patterns then the caller will probably have to reset the pattern functions. * That is, will have to call first_pattern again with the correct type. * * Args: stream * searchset -- calculate scores for this set of messages * no_fetch -- we're in a callback from c-client, don't call c-client * * Returns 1 -- ok * 0 -- error, because of no_fetch */ int calculate_some_scores(MAILSTREAM *stream, SEARCHSET *searchset, int no_fetch) { PAT_S *pat = NULL; PAT_STATE pstate; char *savebits; long newscore, addtoscore, score; int error = 0; long rflags = ROLE_SCORE; long n, i; SEARCHSET *s; MESSAGECACHE *mc; HEADER_TOK_S *hdrtok; dprint((7, "calculate_some_scores\n")); if(nonempty_patterns(rflags, &pstate)){ /* calculate scores */ if(searchset){ /* this calls match_pattern which messes up searched bits */ savebits = (char *)fs_get((stream->nmsgs+1) * sizeof(char)); for(i = 1L; i <= stream->nmsgs; i++) savebits[i] = (mc = mail_elt(stream, i)) ? mc->searched : 0; /* * First set all the scores in the searchset to zero so that they * will no longer be undefined. */ score = 0L; for(s = searchset; s; s = s->next) for(n = s->first; n <= s->last; n++) set_msg_score(stream, n, score); for(pat = first_pattern(&pstate); !error && pat; pat = next_pattern(&pstate)){ newscore = pat->action->scoreval; hdrtok = pat->action->scorevalhdrtok; /* * This no_fetch probably isn't necessary since * we will actually have fetched this with * the envelope. Just making sure. */ if(hdrtok && no_fetch){ error++; break; } switch(match_pattern(pat->patgrp, stream, searchset, NULL, NULL, (no_fetch ? MP_IN_CCLIENT_CB : 0) | (SE_NOSERVER|SE_NOPREFETCH))){ case 1: if(!pat->action || pat->action->bogus) break; for(s = searchset; s; s = s->next) for(n = s->first; n <= s->last; n++) if(n > 0L && stream && n <= stream->nmsgs && (mc = mail_elt(stream, n)) && mc->searched){ if((score = get_msg_score(stream,n)) == SCORE_UNDEF) score = 0L; if(hdrtok) addtoscore = scorevalfrommsg(stream, n, hdrtok, no_fetch); else addtoscore = newscore; score += addtoscore; set_msg_score(stream, n, score); } break; case 0: break; case -1: error++; break; } } for(i = 1L; i <= stream->nmsgs; i++) if((mc = mail_elt(stream, i)) != NULL) mc->searched = savebits[i]; fs_give((void **)&savebits); if(error){ /* * Revert to undefined scores. */ score = SCORE_UNDEF; for(s = searchset; s; s = s->next) for(n = s->first; n <= s->last; n++) set_msg_score(stream, n, score); } } } return(error ? 0 : 1); }
int litsig_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { char **apval; int rv = 0; if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL)) return(rv); apval = APVAL((*cl)->var, ew); switch(cmd){ case MC_ADD: case MC_EDIT : if(apval){ char *input = NULL, *result = NULL, *err = NULL, *cstring_version; char *olddefval = NULL, *start_with; size_t len; if(!*apval && (*cl)->var->current_val.p && (*cl)->var->current_val.p[0]){ if(!strncmp((*cl)->var->current_val.p, DSTRING, (len=strlen(DSTRING)))){ /* strip DSTRING and trailing paren */ olddefval = (char *)fs_get(strlen((*cl)->var->current_val.p)+1); strncpy(olddefval, (*cl)->var->current_val.p+len, strlen((*cl)->var->current_val.p)-len-1); olddefval[strlen((*cl)->var->current_val.p)-len-1] = '\0'; start_with = olddefval; } else{ olddefval = cpystr((*cl)->var->current_val.p); start_with = olddefval; } } else start_with = (*apval) ? *apval : ""; input = (char *)fs_get((strlen(start_with)+1) * sizeof(char)); input[0] = '\0'; cstring_to_string(start_with, input); err = signature_edit_lit(input, &result, ((*cl)->var == role_comment_ptr) ? "COMMENT EDITOR" : "SIGNATURE EDITOR", ((*cl)->var == role_comment_ptr) ? h_composer_commentedit : h_composer_sigedit); if(!err){ if(olddefval && !strcmp(input, result) && want_to(_("Leave unset and use default "), 'y', 'y', NO_HELP, WT_FLUSH_IN) == 'y'){ rv = 0; } else{ cstring_version = string_to_cstring(result); if(apval && *apval) fs_give((void **)apval); if(apval){ *apval = cstring_version; cstring_version = NULL; } if(cstring_version) fs_give((void **)&cstring_version); rv = 1; } } else rv = 0; if(err){ q_status_message1(SM_ORDER, 3, 5, "%s", err); fs_give((void **)&err); } if(result) fs_give((void **)&result); if(olddefval) fs_give((void **)&olddefval); if(input) fs_give((void **)&input); } ps->mangled_screen = 1; break; default: rv = text_tool(ps, cmd, cl, flags); break; } /* * At this point, if changes occurred, var->user_val.X is set. * So, fix the current_val, and handle special cases... * * NOTE: we don't worry about the "fixed variable" case here, because * editing such vars should have been prevented above... */ if(rv == 1){ /* * Now go and set the current_val based on user_val changes * above. Turn off command line settings... */ set_current_val((*cl)->var, TRUE, FALSE); if((*cl)->value) fs_give((void **)&(*cl)->value); (*cl)->value = pretty_value(ps, *cl); exception_override_warning((*cl)->var); /* * The value of literal sig can affect whether signature file is * used or not. So it affects what we display for sig file variable. */ if((*cl)->next && (*cl)->next->var == &ps->vars[V_SIGNATURE_FILE]){ if((*cl)->next->value) fs_give((void **)&(*cl)->next->value); (*cl)->next->value = pretty_value(ps, (*cl)->next); } } return(rv); }
/* ---------------------------------------------------------------------- Execute the given mailcap command Args: cmd -- the command to execute image_file -- the file the data is in needsterminal -- does this command want to take over the terminal? ----*/ void exec_mailcap_cmd(MCAP_CMD_S *mc_cmd, char *image_file, int needsterminal) { #ifdef _WINDOWS STARTUPINFO start_info; PROCESS_INFORMATION proc_info; WINHAND childProcess; int success = 0; char *cmd; LPTSTR image_file_lpt = NULL; LPTSTR cmd_lpt = NULL; /* no special handling yet, but could be used to replace '*' hack */ if(mc_cmd) cmd = mc_cmd->command; else return; dprint((9, "run_viewer: command=%s\n", cmd ? cmd : "?")) ; if(image_file) image_file_lpt = utf8_to_lptstr(image_file); /* Set to READONLY so the viewer can't try to edit it and keep it around */ if(image_file_lpt) SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_READONLY); if(*cmd == '*' || (*cmd == '\"' && *(cmd+1) == '*')){ /* * It has been asked that there be the ability to do an * "Open With..." on attachments like you can from the * Windows file browser. After looking into this, it * seems that the only way to do this would be through * an undocumented hack. Here, we would pass "openas" as * the verb to mswin_shell_exec (also some changes in * mswin_shell_exec). Since this is the delicate world * of attachment handling, it seems right not to rely on * a hack. The interface wouldn't be too clean anyways, * as we would have to download the attachment only to * display the "Open With..." dialog. Go figure, some * things Microsoft just wants to keep to themselves. */ /* * 2/1/2007. No idea when the above comment was written, but it is * documented now at least. The below two urls describe the "openas" verb: * * http://blogs.msdn.com/oldnewthing/archive/2004/11/26/270710.aspx * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ * shellcc/platform/shell/programmersguide/shell_basics/ * shell_basics_extending/context.asp */ success = mswin_shell_exec(cmd, &childProcess) == 0; } else{ memset(&proc_info, 0, sizeof(proc_info)); memset(&start_info, 0, sizeof(start_info)); start_info.dwFlags = STARTF_FORCEONFEEDBACK; start_info.wShowWindow = SW_SHOWNORMAL; if(cmd) cmd_lpt = utf8_to_lptstr(cmd); if(CreateProcess(NULL, cmd_lpt, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &start_info, &proc_info) == TRUE){ q_status_message(SM_ORDER, 0, 4, "VIEWER command completed"); dprint ((3, "CreatProcess(%s) Success.\n", cmd ? cmd : "?")); childProcess = proc_info.hProcess; success = 1; } if(cmd_lpt) fs_give((void **) &cmd_lpt); } if(!success){ int rc = (int) GetLastError(); if(image_file_lpt) SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_NORMAL); our_unlink(image_file); q_status_message2(SM_ORDER, 3, 4, "\007Can't start viewer. %s%s.", (rc == 2 || rc == 3) ? "Viewer not found: " : (rc == 8) ? "Not enough memory" : "Windows error ", (rc == 2 || rc == 3) ? cmd : (rc == 8) ? "" : int2string(rc)); } if(image_file_lpt) fs_give((void **) &image_file_lpt); #elif OSX_TARGET char *command = NULL, *result_file = NULL, *p; char **r_file_h; PIPE_S *syspipe; int mode; if(!mc_cmd) return; if(mc_cmd->special_handling){ char *rhost; if(mime_os_specific_access()) osx_launch_special_handling(mc_cmd, image_file); else{ q_status_message(SM_ORDER, 0, 4, "VIEWER command cancelled"); our_unlink(image_file); } } else { char *cmd = mc_cmd->command; size_t l; l = 32 + strlen(cmd) + (2*strlen(image_file)); p = command = (char *) fs_get((l+1) * sizeof(char)); if(!needsterminal) /* put in background if it doesn't need terminal */ *p++ = '('; snprintf(p, l+1-(p-command), "%s", cmd); p += strlen(p); if(!needsterminal){ if(p-command+2 < l+1){ *p++ = ')'; *p++ = ' '; *p++ = '&'; } } if(p-command < l+1) *p++ = '\n'; if(p-command < l+1) *p = '\0'; dprint((9, "exec_mailcap_cmd: command=%s\n", command ? command : "?")); mode = PIPE_RESET; if(needsterminal == 1) r_file_h = NULL; else{ mode |= PIPE_WRITE | PIPE_STDERR; result_file = temp_nam(NULL, "pine_cmd"); r_file_h = &result_file; } if((syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)) != NULL){ close_system_pipe(&syspipe, NULL, pipe_callback); if(needsterminal == 1) q_status_message(SM_ORDER, 0, 4, "VIEWER command completed"); else if(needsterminal == 2) display_output_file(result_file, "VIEWER", " command result", 1); else display_output_file(result_file, "VIEWER", " command launched", 1); } else q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd); fs_give((void **)&command); if(result_file) fs_give((void **)&result_file); } #else char *command = NULL, *result_file = NULL, *p, *cmd, *q, *psef; char **r_file_h; PIPE_S *syspipe; int mode; size_t l; /* no os-specific command handling */ if(mc_cmd) cmd = mc_cmd->command; else return; #ifdef PSEFCMD psef = fs_get((60 + strlen(PSEFCMD) + strlen(image_file))*sizeof(char)); sprintf(psef, "PSEF=`%s | /bin/grep \"%s\" | /bin/grep -v grep`", PSEFCMD, image_file); q = fs_get((80 + 2*strlen(psef))*sizeof(char)); /* bigger than 62 */ sprintf(q, "/bin/sh -c '(%s; while test -n \"$PSEF\" ; do %s ; sleep %d ; done)' ;", psef, psef, ps_global->sleep); fs_give((void **) &psef); #else q = cpystr(""); #endif /* PSEFCMD */ l = 45 + strlen(cmd) + 2*strlen(image_file) + strlen(q); p = command = (char *)fs_get((l+1) * sizeof(char)); if(!needsterminal) /* put in background if it doesn't need terminal */ *p++ = '('; snprintf(p, l+1-(p-command), "%s ; %s sleep 5 ; rm -f %s", cmd, q, image_file); fs_give((void **)&q); command[l] = '\0'; p += strlen(p); if(!needsterminal && (p-command)+5 < l){ *p++ = ')'; *p++ = ' '; *p++ = '&'; } *p++ = '\n'; *p = '\0'; dprint((9, "exec_mailcap_cmd: command=%s\n", command ? command : "?")); mode = PIPE_RESET; if(needsterminal == 1) r_file_h = NULL; else{ mode |= PIPE_WRITE | PIPE_STDERR; result_file = temp_nam(NULL, "pine_cmd"); r_file_h = &result_file; } if((syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)) != NULL){ close_system_pipe(&syspipe, NULL, pipe_callback); if(needsterminal == 1) q_status_message(SM_ORDER, 0, 4, "VIEWER command completed"); else if(needsterminal == 2) display_output_file(result_file, "VIEWER", " command result", 1); else display_output_file(result_file, "VIEWER", " command launched", 1); } else q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd); fs_give((void **)&command); if(result_file) fs_give((void **)&result_file); #endif }
struct sockaddr *ip_newsockaddr (size_t *len) { return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN); }
/* * Break up the ldap-server string stored in the pinerc into its * parts. The structure is allocated here and should be freed by the caller. * * The original string looks like * <servername>[:port] <SPACE> "/base=<base>/impl=1/..." * * Args serv_str -- The original string from the pinerc to parse. * * Returns A pointer to a structure with filled in answers. * * Some of the members have defaults. If port is -1, that means to use * the default LDAP_PORT. If base is NULL, use "". Type and srch have * defaults defined in alpine.h. If cust is non-NULL, it overrides type and * srch. */ LDAP_SERV_S * break_up_ldap_server(char *serv_str) { char *lserv; char *q, *p, *tail; int i, only_one = 1; LDAP_SERV_S *info = NULL; if(!serv_str) return(info); info = (LDAP_SERV_S *)fs_get(sizeof(LDAP_SERV_S)); /* * Initialize to defaults. */ memset((void *)info, 0, sizeof(*info)); info->port = -1; info->srch = -1; info->type = -1; info->time = -1; info->size = -1; info->scope = -1; /* copy the whole string to work on */ lserv = cpystr(serv_str); if(lserv) removing_trailing_white_space(lserv); if(!lserv || !*lserv || *lserv == '"'){ if(lserv) fs_give((void **)&lserv); if(info) free_ldap_server_info(&info); return(NULL); } tail = lserv; while((tail = strindex(tail, SPACE)) != NULL){ tail++; if(*tail == '"' || *tail == '/'){ *(tail-1) = '\0'; break; } else only_one = 0; } /* tail is the part after server[:port] <SPACE> */ if(tail && *tail){ removing_leading_white_space(tail); (void)removing_double_quotes(tail); } /* get the optional port number */ if(only_one && (q = strindex(lserv, ':')) != NULL){ int ldapport = -1; *q = '\0'; if((ldapport = atoi(q+1)) >= 0) info->port = ldapport; } /* use lserv for serv even though it has a few extra bytes alloced */ info->serv = lserv; if(tail && *tail){ /* get the search base */ if((q = srchstr(tail, "/base=")) != NULL) info->base = remove_backslash_escapes(q+6); if((q = srchstr(tail, "/binddn=")) != NULL) info->binddn = remove_backslash_escapes(q+8); /* get the implicit parameter */ if((q = srchstr(tail, "/impl=1")) != NULL) info->impl = 1; /* get the rhs parameter */ if((q = srchstr(tail, "/rhs=1")) != NULL) info->rhs = 1; /* get the ref parameter */ if((q = srchstr(tail, "/ref=1")) != NULL) info->ref = 1; /* get the nosub parameter */ if((q = srchstr(tail, "/nosub=1")) != NULL) info->nosub = 1; /* get the tls parameter */ if((q = srchstr(tail, "/tls=1")) != NULL) info->tls = 1; /* get the tlsmust parameter */ if((q = srchstr(tail, "/tlsm=1")) != NULL) info->tlsmust = 1; /* get the search type value */ if((q = srchstr(tail, "/type=")) != NULL){ NAMEVAL_S *v; q += 6; if((p = strindex(q, '/')) != NULL) *p = '\0'; for(i = 0; (v = ldap_search_types(i)); i++) if(!strucmp(q, v->name)){ info->type = v->value; break; } if(p) *p = '/'; } /* get the search rule value */ if((q = srchstr(tail, "/srch=")) != NULL){ NAMEVAL_S *v; q += 6; if((p = strindex(q, '/')) != NULL) *p = '\0'; for(i = 0; (v = ldap_search_rules(i)); i++) if(!strucmp(q, v->name)){ info->srch = v->value; break; } if(p) *p = '/'; } /* get the scope */ if((q = srchstr(tail, "/scope=")) != NULL){ NAMEVAL_S *v; q += 7; if((p = strindex(q, '/')) != NULL) *p = '\0'; for(i = 0; (v = ldap_search_scope(i)); i++) if(!strucmp(q, v->name)){ info->scope = v->value; break; } if(p) *p = '/'; } /* get the time limit */ if((q = srchstr(tail, "/time=")) != NULL){ q += 6; if((p = strindex(q, '/')) != NULL) *p = '\0'; /* This one's a number */ if(*q){ char *err; err = strtoval(q, &i, 0, 500, 0, tmp_20k_buf, SIZEOF_20KBUF, "ldap timelimit"); if(err){ dprint((1, "%s\n", err ? err : "?")); } else info->time = i; } if(p) *p = '/'; } /* get the size limit */ if((q = srchstr(tail, "/size=")) != NULL){ q += 6; if((p = strindex(q, '/')) != NULL) *p = '\0'; /* This one's a number */ if(*q){ char *err; err = strtoval(q, &i, 0, 500, 0, tmp_20k_buf, SIZEOF_20KBUF, "ldap sizelimit"); if(err){ dprint((1, "%s\n", err ? err : "?")); } else info->size = i; } if(p) *p = '/'; } /* get the custom search filter */ if((q = srchstr(tail, "/cust=")) != NULL) info->cust = remove_backslash_escapes(q+6); /* get the nickname */ if((q = srchstr(tail, "/nick=")) != NULL) info->nick = remove_backslash_escapes(q+6); /* get the mail attribute name */ if((q = srchstr(tail, "/matr=")) != NULL) info->mailattr = remove_backslash_escapes(q+6); /* get the sn attribute name */ if((q = srchstr(tail, "/satr=")) != NULL) info->snattr = remove_backslash_escapes(q+6); /* get the gn attribute name */ if((q = srchstr(tail, "/gatr=")) != NULL) info->gnattr = remove_backslash_escapes(q+6); /* get the cn attribute name */ if((q = srchstr(tail, "/catr=")) != NULL) info->cnattr = remove_backslash_escapes(q+6); /* get the backup mail address */ if((q = srchstr(tail, "/mail=")) != NULL) info->mail = remove_backslash_escapes(q+6); } return(info); }
char * rfc2231_get_param(PARAMETER *parms, char *name, char **charset, char **lang) { char *buf, *p; int decode = 0, name_len, i; unsigned n; name_len = strlen(name); for(; parms ; parms = parms->next) if(!struncmp(name, parms->attribute, name_len)){ if(parms->attribute[name_len] == '*'){ for(p = &parms->attribute[name_len + 1], n = 0; *(p+n); n++) ; decode = *(p + n - 1) == '*'; if(isdigit((unsigned char) *p)){ char *pieces[RFC2231_MAX]; int count = 0, len; memset(pieces, 0, RFC2231_MAX * sizeof(char *)); while(parms){ n = 0; do n = (n * 10) + (*p - '0'); while(isdigit(*++p) && n < RFC2231_MAX); if(n < RFC2231_MAX){ pieces[n] = parms->value; if(n > count) count = n; } else{ q_status_message1(SM_ORDER | SM_DING, 0, 3, "Invalid attachment parameter segment number: %.25s", name); return(NULL); /* Too many segments! */ } while((parms = parms->next) != NULL) if(!struncmp(name, parms->attribute, name_len)){ if(*(p = &parms->attribute[name_len]) == '*' && isdigit((unsigned char) *++p)) break; else return(NULL); /* missing segment no.! */ } } for(i = len = 0; i <= count; i++) if(pieces[i]) len += strlen(pieces[i]); else{ q_status_message1(SM_ORDER | SM_DING, 0, 3, "Missing attachment parameter sequence: %.25s", name); return(NULL); /* hole! */ } buf = (char *) fs_get((len + 1) * sizeof(char)); for(i = len = 0; i <= count; i++){ if((n = *(p = pieces[i]) == '\"') != 0) /* quoted? */ p++; while(*p && !(n && *p == '\"' && !*(p+1))) buf[len++] = *p++; } buf[len] = '\0'; } else buf = cpystr(parms->value); /* Do any RFC 2231 decoding? */ if(decode){ char *converted = NULL, cs[1000]; cs[0] = '\0'; n = 0; if((p = strchr(buf, '\'')) != NULL){ n = (p - buf) + 1; *p = '\0'; strncpy(cs, buf, sizeof(cs)); cs[sizeof(cs)-1] = '\0'; *p = '\''; if(charset) *charset = cpystr(cs); if((p = strchr(&buf[n], '\'')) != NULL){ n = (p - buf) + 1; if(lang){ *p = '\0'; *lang = cpystr(p); *p = '\''; } } } if(n){ /* Suck out the charset & lang while decoding hex */ p = &buf[n]; for(i = 0; (buf[i] = *p) != '\0'; i++) if(*p++ == '%' && isxpair(p)){ buf[i] = X2C(p); p += 2; } } else fs_give((void **) &buf); /* problems!?! */ /* * Callers will expect the returned value to be UTF-8 * text, so we may need to translate here. */ if(buf) converted = convert_to_utf8(buf, cs, 0); if(converted && converted != buf){ fs_give((void **) &buf); buf = converted; } } return(buf); } else return(cpystr(parms->value ? parms->value : "")); } return(NULL); }
/* * Do an LDAP lookup to the server described in the info argument. * * Args info -- LDAP info for server. * string -- String to lookup. * cust -- Possible custom filter description. * wp_err -- We set this is we get a white pages error. * name_in_error -- Caller sets this if they want us to include the server * name in error messages. * * Returns Results of lookup, NULL if lookup failed. */ LDAP_SERV_RES_S * ldap_lookup(LDAP_SERV_S *info, char *string, CUSTOM_FILT_S *cust, WP_ERR_S *wp_err, int name_in_error) { char ebuf[900]; char buf[900]; char *serv, *base, *serv_errstr; char *mailattr, *snattr, *gnattr, *cnattr; int we_cancel = 0, we_turned_on = 0; LDAP_SERV_RES_S *serv_res = NULL; LDAP *ld; long pwdtrial = 0L; int ld_errnum; char *ld_errstr; if(!info) return(serv_res); serv = cpystr((info->serv && *info->serv) ? info->serv : "?"); if(name_in_error) snprintf(ebuf, sizeof(ebuf), " (%s)", (info->nick && *info->nick) ? info->nick : serv); else ebuf[0] = '\0'; serv_errstr = cpystr(ebuf); base = cpystr(info->base ? info->base : ""); if(info->port < 0) info->port = LDAP_PORT; if(info->type < 0) info->type = DEF_LDAP_TYPE; if(info->srch < 0) info->srch = DEF_LDAP_SRCH; if(info->time < 0) info->time = DEF_LDAP_TIME; if(info->size < 0) info->size = DEF_LDAP_SIZE; if(info->scope < 0) info->scope = DEF_LDAP_SCOPE; mailattr = (info->mailattr && info->mailattr[0]) ? info->mailattr : DEF_LDAP_MAILATTR; snattr = (info->snattr && info->snattr[0]) ? info->snattr : DEF_LDAP_SNATTR; gnattr = (info->gnattr && info->gnattr[0]) ? info->gnattr : DEF_LDAP_GNATTR; cnattr = (info->cnattr && info->cnattr[0]) ? info->cnattr : DEF_LDAP_CNATTR; /* * We may want to keep ldap handles open, but at least for * now, re-open them every time. */ dprint((3, "ldap_lookup(%s,%d)\n", serv ? serv : "?", info->port)); snprintf(ebuf, sizeof(ebuf), "Searching%s%s%s on %s", (string && *string) ? " for \"" : "", (string && *string) ? string : "", (string && *string) ? "\"" : "", serv); we_turned_on = intr_handling_on(); /* this erases keymenu */ we_cancel = busy_cue(ebuf, NULL, 0); if(wp_err->mangled) *(wp_err->mangled) = 1; #ifdef _SOLARIS_SDK if(info->tls || info->tlsmust) ldapssl_client_init(NULL, NULL); if((ld = ldap_init(serv, info->port)) == NULL) #else #if (LDAPAPI >= 11) if((ld = ldap_init(serv, info->port)) == NULL) #else if((ld = ldap_open(serv, info->port)) == NULL) #endif #endif { /* TRANSLATORS: All of the three args together are an error message */ snprintf(ebuf, sizeof(ebuf), _("Access to LDAP server failed: %s%s(%s)"), errno ? error_description(errno) : "", errno ? " " : "", serv); wp_err->wp_err_occurred = 1; if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); } else if(!ps_global->intr_pending){ int proto = 3, tlsmustbail = 0; char pwd[NETMAXPASSWD], user[NETMAXUSER]; char *passwd = NULL; char hostbuf[1024]; NETMBX mb; #ifndef _WINDOWS int rc; #endif memset(&mb, 0, sizeof(mb)); #ifdef _SOLARIS_SDK if(info->tls || info->tlsmust) rc = ldapssl_install_routines(ld); #endif if(ldap_v3_is_supported(ld) && our_ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &proto) == 0){ dprint((5, "ldap: using version 3 protocol\n")); } /* * If we don't set RESTART then the select() waiting for the answer * in libldap will be interrupted and stopped by our busy_cue. */ our_ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); /* * If we need to authenticate, get the password. We are not * supporting SASL authentication, just LDAP simple. */ if(info->binddn && info->binddn[0]){ char pmt[500]; char *space; snprintf(hostbuf, sizeof(hostbuf), "{%s}dummy", info->serv ? info->serv : "?"); /* * We don't handle multiple space-delimited hosts well. * We don't know which we're asking for a password for. * We're not connected yet so we can't know. */ if((space=strindex(hostbuf, ' ')) != NULL) *space = '\0'; mail_valid_net_parse_work(hostbuf, &mb, "ldap"); mb.port = info->port; mb.tlsflag = (info->tls || info->tlsmust) ? 1 : 0; try_password_again: if(mb.tlsflag && (pwdtrial > 0 || #ifndef _WINDOWS #ifdef _SOLARIS_SDK (rc == LDAP_SUCCESS) #else /* !_SOLARIS_SDK */ ((rc=ldap_start_tls_s(ld, NULL, NULL)) == LDAP_SUCCESS) #endif /* !_SOLARIS_SDK */ #else /* _WINDOWS */ 0 /* TODO: find a way to do this in Windows */ #endif /* _WINDOWS */ )) mb.tlsflag = 1; else mb.tlsflag = 0; if((info->tls || info->tlsmust) && !mb.tlsflag){ q_status_message(SM_ORDER, 3, 5, "Not able to start TLS encryption for LDAP server"); if(info->tlsmust) tlsmustbail++; } if(!tlsmustbail){ snprintf(pmt, sizeof(pmt), " %s", (info->nick && *info->nick) ? info->nick : serv); mm_login_work(&mb, user, pwd, pwdtrial, pmt, info->binddn); if(pwd && pwd[0]) passwd = pwd; } } /* * LDAPv2 requires the bind. v3 doesn't require it but we want * to tell the server we're v3 if the server supports v3, and if the * server doesn't support v3 the bind is required. */ if(tlsmustbail || ldap_simple_bind_s(ld, info->binddn, passwd) != LDAP_SUCCESS){ wp_err->wp_err_occurred = 1; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); if(!tlsmustbail && info->binddn && info->binddn[0] && pwdtrial < 2L && ld_errnum == LDAP_INVALID_CREDENTIALS){ pwdtrial++; q_status_message(SM_ORDER, 3, 5, _("Invalid password")); goto try_password_again; } snprintf(ebuf, sizeof(ebuf), _("LDAP server failed: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); if(wp_err->error) fs_give((void **)&wp_err->error); if(we_cancel) cancel_busy_cue(-1); ldap_unbind(ld); wp_err->error = cpystr(ebuf); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); } else if(!ps_global->intr_pending){ int srch_res, args, slen, flen; #define TEMPLATELEN 512 char filt_template[TEMPLATELEN + 1]; char filt_format[2*TEMPLATELEN + 1]; char filter[2*TEMPLATELEN + 1]; char scp[2*TEMPLATELEN + 1]; char *p, *q; LDAPMessage *res = NULL; int intr_happened = 0; int tl; tl = (info->time == 0) ? info->time : info->time + 10; our_ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &tl); our_ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &info->size); /* * If a custom filter has been passed in and it doesn't include a * request to combine it with the configured filter, then replace * any configured filter with the passed in filter. */ if(cust && cust->filt && !cust->combine){ if(info->cust) fs_give((void **)&info->cust); info->cust = cpystr(cust->filt); } if(info->cust && *info->cust){ /* use custom filter if present */ strncpy(filt_template, info->cust, sizeof(filt_template)); filt_template[sizeof(filt_template)-1] = '\0'; } else{ /* else use configured filter */ switch(info->type){ case LDAP_TYPE_SUR: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", snattr); break; case LDAP_TYPE_GIVEN: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", gnattr); break; case LDAP_TYPE_EMAIL: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", mailattr); break; case LDAP_TYPE_CN_EMAIL: snprintf(filt_template, sizeof(filt_template), "(|(%s=%%s)(%s=%%s))", cnattr, mailattr); break; case LDAP_TYPE_SUR_GIVEN: snprintf(filt_template, sizeof(filt_template), "(|(%s=%%s)(%s=%%s))", snattr, gnattr); break; case LDAP_TYPE_SEVERAL: snprintf(filt_template, sizeof(filt_template), "(|(%s=%%s)(%s=%%s)(%s=%%s)(%s=%%s))", cnattr, mailattr, snattr, gnattr); break; default: case LDAP_TYPE_CN: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", cnattr); break; } } /* just copy if custom */ if(info->cust && *info->cust) info->srch = LDAP_SRCH_EQUALS; p = filt_template; q = filt_format; memset((void *)filt_format, 0, sizeof(filt_format)); args = 0; while(*p && (q - filt_format) + 4 < sizeof(filt_format)){ if(*p == '%' && *(p+1) == 's'){ args++; switch(info->srch){ /* Exact match */ case LDAP_SRCH_EQUALS: *q++ = *p++; *q++ = *p++; break; /* Append wildcard after %s */ case LDAP_SRCH_BEGINS: *q++ = *p++; *q++ = *p++; *q++ = '*'; break; /* Insert wildcard before %s */ case LDAP_SRCH_ENDS: *q++ = '*'; *q++ = *p++; *q++ = *p++; break; /* Put wildcard before and after %s */ default: case LDAP_SRCH_CONTAINS: *q++ = '*'; *q++ = *p++; *q++ = *p++; *q++ = '*'; break; } } else *q++ = *p++; } if(q - filt_format < sizeof(filt_format)) *q = '\0'; filt_format[sizeof(filt_format)-1] = '\0'; /* * If combine is lit we put the custom filter and the filt_format * filter and combine them with an &. */ if(cust && cust->filt && cust->combine){ char *combined; size_t l; l = strlen(filt_format) + strlen(cust->filt) + 3; combined = (char *) fs_get((l+1) * sizeof(char)); snprintf(combined, l+1, "(&%s%s)", cust->filt, filt_format); strncpy(filt_format, combined, sizeof(filt_format)); filt_format[sizeof(filt_format)-1] = '\0'; fs_give((void **) &combined); } /* * Ad hoc attempt to make "Steve Hubert" match * Steven Hubert but not Steven Shubert. * We replace a <SPACE> with * <SPACE> (not * <SPACE> *). */ memset((void *)scp, 0, sizeof(scp)); if(info->nosub) strncpy(scp, string, sizeof(scp)); else{ p = string; q = scp; while(*p && (q - scp) + 1 < sizeof(scp)){ if(*p == SPACE && *(p+1) != SPACE){ *q++ = '*'; *q++ = *p++; } else *q++ = *p++; } } scp[sizeof(scp)-1] = '\0'; slen = strlen(scp); flen = strlen(filt_format); /* truncate string if it will overflow filter */ if(args*slen + flen - 2*args > sizeof(filter)-1) scp[(sizeof(filter)-1 - flen)/args] = '\0'; /* * Replace %s's with scp. */ switch(args){ case 0: snprintf(filter, sizeof(filter), "%s", filt_format); break; case 1: snprintf(filter, sizeof(filter), filt_format, scp); break; case 2: snprintf(filter, sizeof(filter), filt_format, scp, scp); break; case 3: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp); break; case 4: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp); break; case 5: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp); break; case 6: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp); break; case 7: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp); break; case 8: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp, scp); break; case 9: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp, scp, scp); break; case 10: default: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp, scp, scp, scp); break; } /* replace double *'s with single *'s in filter */ for(p = q = filter; *p; p++) if(*p != '*' || p == filter || *(p-1) != '*') *q++ = *p; *q = '\0'; (void) removing_double_quotes(base); dprint((5, "about to ldap_search(\"%s\", %s)\n", base ? base : "?", filter ? filter : "?")); if(ps_global->intr_pending) srch_res = LDAP_PROTOCOL_ERROR; else{ int msgid; time_t start_time; start_time = time((time_t *)0); dprint((6, "ldap_lookup: calling ldap_search\n")); msgid = ldap_search(ld, base, info->scope, filter, NULL, 0); if(msgid == -1) srch_res = our_ldap_get_lderrno(ld, NULL, NULL); else{ int lres; /* * Warning: struct timeval is not portable. However, since it is * part of LDAP api it must be portable to all platforms LDAP * has been ported to. */ struct timeval t; t.tv_sec = 1; t.tv_usec = 0; do { if(ps_global->intr_pending) intr_happened = 1; dprint((6, "ldap_result(id=%d): ", msgid)); if((lres=ldap_result(ld, msgid, LDAP_MSG_ALL, &t, &res)) == -1){ /* error */ srch_res = our_ldap_get_lderrno(ld, NULL, NULL); dprint((6, "error (-1 returned): ld_errno=%d\n", srch_res)); } else if(lres == 0){ /* timeout, no results available */ if(intr_happened){ ldap_abandon(ld, msgid); srch_res = LDAP_PROTOCOL_ERROR; if(our_ldap_get_lderrno(ld, NULL, NULL) == LDAP_SUCCESS) our_ldap_set_lderrno(ld, LDAP_PROTOCOL_ERROR, NULL, NULL); dprint((6, "timeout, intr: srch_res=%d\n", srch_res)); } else if(info->time > 0 && ((long)time((time_t *)0) - start_time) > info->time){ /* try for partial results */ t.tv_sec = 0; t.tv_usec = 0; lres = ldap_result(ld, msgid, LDAP_MSG_RECEIVED, &t, &res); if(lres > 0 && lres != LDAP_RES_SEARCH_RESULT){ srch_res = LDAP_SUCCESS; dprint((6, "partial result: lres=0x%x\n", lres)); } else{ if(lres == 0) ldap_abandon(ld, msgid); srch_res = LDAP_TIMEOUT; if(our_ldap_get_lderrno(ld, NULL, NULL) == LDAP_SUCCESS) our_ldap_set_lderrno(ld, LDAP_TIMEOUT, NULL, NULL); dprint((6, "timeout, total_time (%d), srch_res=%d\n", info->time, srch_res)); } } else{ dprint((6, "timeout\n")); } } else{ srch_res = ldap_result2error(ld, res, 0); dprint((6, "lres=0x%x, srch_res=%d\n", lres, srch_res)); } }while(lres == 0 && !(intr_happened || (info->time > 0 && ((long)time((time_t *)0) - start_time) > info->time))); } } if(intr_happened){ wp_exit = 1; if(we_cancel) cancel_busy_cue(-1); if(wp_err->error) fs_give((void **)&wp_err->error); else{ q_status_message(SM_ORDER, 0, 1, "Interrupt"); display_message('x'); fflush(stdout); } if(res) ldap_msgfree(res); if(ld) ldap_unbind(ld); res = NULL; ld = NULL; } else if(srch_res != LDAP_SUCCESS && srch_res != LDAP_TIMELIMIT_EXCEEDED && srch_res != LDAP_RESULTS_TOO_LARGE && srch_res != LDAP_TIMEOUT && srch_res != LDAP_SIZELIMIT_EXCEEDED){ wp_err->wp_err_occurred = 1; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); snprintf(ebuf, sizeof(ebuf), _("LDAP search failed: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); if(res) ldap_msgfree(res); if(ld) ldap_unbind(ld); res = NULL; ld = NULL; } else{ int cnt; cnt = ldap_count_entries(ld, res); if(cnt > 0){ if(srch_res == LDAP_TIMELIMIT_EXCEEDED || srch_res == LDAP_RESULTS_TOO_LARGE || srch_res == LDAP_TIMEOUT || srch_res == LDAP_SIZELIMIT_EXCEEDED){ wp_err->wp_err_occurred = 1; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); snprintf(ebuf, sizeof(ebuf), _("LDAP partial results: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); dprint((2, "%s\n", ebuf)); if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); } dprint((5, "Matched %d entries on %s\n", cnt, serv ? serv : "?")); serv_res = (LDAP_SERV_RES_S *)fs_get(sizeof(LDAP_SERV_RES_S)); memset((void *)serv_res, 0, sizeof(*serv_res)); serv_res->ld = ld; serv_res->res = res; serv_res->info_used = copy_ldap_serv_info(info); /* Save by reference? */ if(info->ref){ snprintf(buf, sizeof(buf), "%s:%s", serv, comatose(info->port)); serv_res->serv = cpystr(buf); } else serv_res->serv = NULL; serv_res->next = NULL; } else{ if(srch_res == LDAP_TIMELIMIT_EXCEEDED || srch_res == LDAP_RESULTS_TOO_LARGE || srch_res == LDAP_TIMEOUT || srch_res == LDAP_SIZELIMIT_EXCEEDED){ wp_err->wp_err_occurred = 1; wp_err->ldap_errno = srch_res; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); snprintf(ebuf, sizeof(ebuf), _("LDAP search failed: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); } dprint((5, "Matched 0 entries on %s\n", serv ? serv : "?")); if(res) ldap_msgfree(res); if(ld) ldap_unbind(ld); res = NULL; ld = NULL; } } } } if(we_cancel) cancel_busy_cue(-1); if(we_turned_on) intr_handling_off(); if(serv) fs_give((void **)&serv); if(base) fs_give((void **)&base); if(serv_errstr) fs_give((void **)&serv_errstr); return(serv_res); }
/*---------------------------------------------------------------------- Build flags string based on requested flags and what's set in messagecache Args: flags -- flags to test Result: allocated, space-delimited flags string is returned ----*/ char * flag_string(MAILSTREAM *stream, long rawno, long int flags) { MESSAGECACHE *mc; char *p, *q, *returned_flags = NULL; size_t len = 0; int k; mc = (rawno > 0L && stream && rawno <= stream->nmsgs) ? mail_elt(stream, rawno) : NULL; if(!mc) return returned_flags; if((flags & F_DEL) && mc->deleted) len += strlen("\\DELETED") + 1; if((flags & F_ANS) && mc->answered) len += strlen("\\ANSWERED") + 1; if((flags & F_FWD) && user_flag_is_set(stream, rawno, FORWARDED_FLAG)) len += strlen(FORWARDED_FLAG) + 1; if((flags & F_FLAG) && mc->flagged) len += strlen("\\FLAGGED") + 1; if((flags & F_SEEN) && mc->seen) len += strlen("\\SEEN") + 1; if((flags & F_KEYWORD) && stream->user_flags){ for(k = 0; k < NUSERFLAGS; k++){ if((q=stream_to_user_flag_name(stream, k)) && user_flag_is_set(stream, rawno, q)){ len += strlen(q) + 1; } } } returned_flags = (char *) fs_get((len+1) * sizeof(char)); p = returned_flags; *p = '\0'; if((flags & F_DEL) && mc->deleted) sstrncpy(&p, "\\DELETED ", len+1-(p-returned_flags)); if((flags & F_ANS) && mc->answered) sstrncpy(&p, "\\ANSWERED ", len+1-(p-returned_flags)); if((flags & F_FWD) && user_flag_is_set(stream, rawno, FORWARDED_FLAG)){ sstrncpy(&p, FORWARDED_FLAG, len+1-(p-returned_flags)); sstrncpy(&p, " ", len+1-(p-returned_flags)); } if((flags & F_FLAG) && mc->flagged) sstrncpy(&p, "\\FLAGGED ", len+1-(p-returned_flags)); if((flags & F_SEEN) && mc->seen) sstrncpy(&p, "\\SEEN ", len+1-(p-returned_flags)); if((flags & F_KEYWORD) && stream->user_flags){ for(k = 0; k < NUSERFLAGS; k++){ if((q=stream_to_user_flag_name(stream, k)) && user_flag_is_set(stream, rawno, q)){ sstrncpy(&p, q, len+1-(p-returned_flags)); sstrncpy(&p, " ", len+1-(p-returned_flags)); len += strlen(p) + 1; } } } if(p != returned_flags && (len+1-(p-returned_flags)>0)) *--p = '\0'; return returned_flags; }
/* {{{ mail_newfolderobjectlist * * Mail instantiate FOBJECTLIST * Returns: new FOBJECTLIST list * Author: CJH */ static FOBJECTLIST *mail_newfolderobjectlist(void) { return (FOBJECTLIST *) memset(fs_get(sizeof(FOBJECTLIST)), 0, sizeof(FOBJECTLIST)); }
TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) { TCPSTREAM *stream = NIL; int family; int sock = -1; int ctr = 0; int silent = (port & NET_SILENT) ? T : NIL; int *ctrp = (port & NET_NOOPENTIMEOUT) ? NIL : &ctr; char *s,tmp[MAILTMPLEN]; char *hostname = NIL; void *adr; size_t adrlen; void *cleanup = NIL; struct servent *sv = NIL; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); void *data,*next; port &= 0xffff; /* erase flags */ /* lookup service */ if (service && (sv = getservbyname (service,"tcp"))) port = ntohs (sv->s_port); /* The domain literal form is used (rather than simply the dotted decimal as with other Unix programs) because it has to be a valid "host name" in mailsystem terminology. */ /* look like domain literal? */ if (host[0] == '[' && host[(strlen (host))-1] == ']') { strcpy (tmp,host+1); /* yes, copy number part */ tmp[(strlen (tmp))-1] = '\0'; if (adr = ip_stringtoaddr (tmp,&adrlen,&family)) { (*bn) (BLOCK_TCPOPEN,NIL); /* get an open socket for this system */ sock = tcp_socket_open (family,adr,adrlen,port,tmp,ctrp, hostname = cpystr(host)); (*bn) (BLOCK_NONE,NIL); fs_give ((void **) &adr); } else sprintf (tmp,"Bad format domain-literal: %.80s",host); } else { /* lookup host name */ if (tcpdebug) { sprintf (tmp,"DNS resolution %.80s",host); mm_log (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); if (!(s = ip_nametoaddr (host,&adrlen,&family,&hostname,&next,&cleanup))) sprintf (tmp,"No such host as %.80s",host); (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); if (s) { /* DNS resolution won? */ if (tcpdebug) mm_log ("DNS resolution done",TCPDEBUG); do { (*bn) (BLOCK_TCPOPEN,NIL); if (((sock = tcp_socket_open (family,s,adrlen,port,tmp,ctrp, hostname)) < 0) && (s = ip_nametoaddr (NIL,&adrlen,&family,&hostname,&next, &cleanup)) && !silent) mm_log (tmp,WARN); (*bn) (BLOCK_NONE,NIL); } while ((sock < 0) && s);/* repeat until success or no more addreses */ } ip_nametoaddr (NIL,NIL,NIL,NIL,NIL,&cleanup); } if (sock < 0) { /* lost? */ if (!silent) mm_log (tmp,ERROR); if (hostname) fs_give ((void **) &hostname); } else { /* won */ stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0, sizeof (TCPSTREAM)); stream->port = port; /* port number */ /* init sockets */ stream->tcpsi = stream->tcpso = sock; /* stash in the snuck-in byte */ if (stream->ictr = ctr) *(stream->iptr = stream->ibuf) = tmp[0]; stream->host = hostname; /* copy official host name */ if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG); } return stream; /* return success */ }
/*---------------------------------------------------------------------- Ask a yes/no question in the status line Args: question -- string to prompt user with dflt -- The default answer to the question (should probably be y or n) on_ctrl_C -- Answer returned on ^C help -- Two line help text flags -- Flags to modify behavior WT_FLUSH_IN - Discard pending input. WT_SEQ_SENSITIVE - Caller is sensitive to sequence number changes caused by unsolicited expunges while we're viewing a message. Result: Messes up the status line, returns y, n, dflt, on_ctrl_C, or SEQ_EXCEPTION ---*/ int want_to(char *question, int dflt, int on_ctrl_C, HelpType help, int flags) { char *free_this = NULL, *free_this2 = NULL, *prompt; int rv, width; size_t len; if(!ps_global->ttyo) return(pre_screen_config_want_to(question, dflt, on_ctrl_C)); #ifdef _WINDOWS if (mswin_usedialog ()) { mswin_flush (); switch (mswin_yesno_utf8 (question)) { default: case 0: return (on_ctrl_C); case 1: return ('y'); case 2: return ('n'); } } #endif /*---- One problem with adding the (y/n) here is that shrinking the screen while in radio_buttons() will cause it to get chopped off. It would be better to truncate the question passed in here and leave the full "(y/n) [x] : " on. ----*/ len = strlen(question) + 4; free_this = (char *) fs_get(len); width = utf8_width(question); if(width + 2 < ps_global->ttyo->screen_cols){ snprintf(free_this, len, "%s? ", question); free_this[len-1] = '\0'; prompt = free_this; } else if(width + 1 < ps_global->ttyo->screen_cols){ snprintf(free_this, len, "%s?", question); free_this[len-1] = '\0'; prompt = free_this; } else if(width < ps_global->ttyo->screen_cols){ snprintf(free_this, len, "%s", question); free_this[len-1] = '\0'; prompt = free_this; } else{ free_this2 = (char *) fs_get(len); snprintf(free_this2, len, "%s? ", question); prompt = short_str(free_this2, free_this, len, ps_global->ttyo->screen_cols-1, MidDots); } if(on_ctrl_C == 'n') /* don't ever let cancel == 'n' */ on_ctrl_C = 0; rv = radio_buttons(prompt, (ps_global->ttyo->screen_rows > 4) ? - FOOTER_ROWS(ps_global) : -1, yorn, dflt, on_ctrl_C, help, flags); if(free_this) fs_give((void **) &free_this); if(free_this2) fs_give((void **) &free_this2); return(rv); }