Exemplo n.º 1
0
/*----------------------------------------------------------------------
    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);
}
Exemplo n.º 2
0
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 */
}
Exemplo n.º 3
0
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();
}
Exemplo n.º 4
0
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 **) &ltmp);

	    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);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
/*
 * 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);
}
Exemplo n.º 7
0
Arquivo: print.c Projeto: nysan/alpine
/*----------------------------------------------------------------------
       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);
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
Arquivo: msgno.c Projeto: mavit/alpine
/*----------------------------------------------------------------------
   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);
}
Exemplo n.º 10
0
Arquivo: color.c Projeto: nysan/alpine
/*
 * 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);
}
Exemplo n.º 11
0
/*
 * 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*/
}
Exemplo n.º 12
0
/*
 * 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);
}
Exemplo n.º 13
0
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);
}
Exemplo n.º 14
0
/*
 * 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);
}
Exemplo n.º 15
0
/* {{{ 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));
}
Exemplo n.º 16
0
Arquivo: msgno.c Projeto: mavit/alpine
/*----------------------------------------------------------------------
  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;
}
Exemplo n.º 17
0
/* {{{ 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));
}
Exemplo n.º 18
0
Arquivo: msgno.c Projeto: mavit/alpine
/*----------------------------------------------------------------------
  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);
}
Exemplo n.º 19
0
/*
 * 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);
}
Exemplo n.º 20
0
Arquivo: msgno.c Projeto: mavit/alpine
/*
 * 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);
}
Exemplo n.º 21
0
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);
}
Exemplo n.º 22
0
/* ----------------------------------------------------------------------
   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
}
Exemplo n.º 23
0
struct sockaddr *ip_newsockaddr (size_t *len)
{
  return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN);
}
Exemplo n.º 24
0
/*
 * 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);
}
Exemplo n.º 25
0
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);
}
Exemplo n.º 26
0
/*
 * 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);
}
Exemplo n.º 27
0
/*----------------------------------------------------------------------
  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;
}
Exemplo n.º 28
0
/* {{{ 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));
}
Exemplo n.º 29
0
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 */
}
Exemplo n.º 30
0
/*----------------------------------------------------------------------
     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);
}