Beispiel #1
0
void parse_line(char * sec, char * lin, dictionary * d)
{
    char        key[ASCIILINESZ+1];
    char        val[ASCIILINESZ+1];
    char    *   wher ;

    wher = strskp(lin); /* Skip leading spaces */
    if (*wher==';' || *wher=='#' || *wher==0)
        return ; /* Comment lines */
    else {
        if (sscanf(wher, "[%[^]]", sec)==1) {
            /* Valid section name */
            iniparser_add_entry(d, sec, NULL, NULL);
        } else if (sscanf (wher, "%[^=] = \"%[^\"]\"", key, val) == 2
               ||  sscanf (wher, "%[^=] = '%[^\']'",   key, val) == 2
               ||  sscanf (wher, "%[^=] = %[^;#]",     key, val) == 2) {
            strcpy(key, strcrop(key));
            /*
             * sscanf cannot handle "" or '' as empty value,
             * this is done here
             */
            if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
                val[0] = (char)0;
            } else {
                strcpy(val, strcrop(val));
            }
            iniparser_add_entry(d, sec, key, val);
        }
    }
}
Beispiel #2
0
dictionary * iniparser_load(const char * ininame)
{
    dictionary  *   d ;
    char        lin[ASCIILINESZ+1];
    char        sec[ASCIILINESZ+1];
    char        key[ASCIILINESZ+1];
    char        val[ASCIILINESZ+1];
    char    *   where ;
    FILE    *   ini ;
    int         lineno ;

    if ((ini=fopen(ininame, "r"))==NULL) {
        return NULL ;
    }

    sec[0]=0;

    /*
     * Initialize a new dictionary entry
     */
    if (!(d = dictionary_new(0))) {
	    fclose(ini);
	    return NULL;
    }
    lineno = 0 ;
    while (fgets(lin, ASCIILINESZ, ini)!=NULL) {
        lineno++ ;
        where = strskp(lin); /* Skip leading spaces */
        if (*where==';' || *where=='#' || *where==0)
            continue ; /* Comment lines */
        else {
            if (sscanf(where, "[%[^]]", sec)==1) {
                /* Valid section name */
                strcpy(sec, strlwc(sec));
                iniparser_add_entry(d, sec, NULL, NULL);
            } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2
                   ||  sscanf (where, "%[^=] = '%[^\']'",   key, val) == 2
                   ||  sscanf (where, "%[^=] = %[^;#]",     key, val) == 2) {
                strcpy(key, strlwc(strcrop(key)));
                /*
                 * sscanf cannot handle "" or '' as empty value,
                 * this is done here
                 */
                if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
                    val[0] = (char)0;
                } else {
                    strcpy(val, strcrop(val));
                }
                iniparser_add_entry(d, sec, key, val);
            }
        }
    }
    fclose(ini);
    return d ;
}
Beispiel #3
0
MODULE get_command (THREAD *thread)
{
    char
    *value;
    tcb = thread-> tcb;                 /*  Point to thread's context        */
    strcrop (buffer);
    strlwc  (buffer);
    value = strskp (buffer);
    if (value != buffer)
        strcpy (buffer, value);

    if (strnull (buffer))
        the_next_event = none_event;
    else if (streq (buffer, "help"))
        the_next_event = help_event;
    else if (strchr (buffer, '?'))
        the_next_event = help_event;
    else if (strncmp (buffer, "set server", 10) == 0)
        the_next_event = server_ip_event;
    else if (streq (buffer, "set debug"))
        the_next_event = debug_event;
    else if (streq (buffer, "set recursive"))
        the_next_event = recursive_event;
    else if (streq (buffer, "exit"))
        the_next_event = exit_event;
    else if (streq (buffer, "quit"))
        the_next_event = exit_event;
    else
    {
        if (strchr (buffer, ' ') != NULL)
            the_next_event = invalid_event;
        else
            the_next_event = request_event;
    }
}
Beispiel #4
0
int main(int argc, char * argv[])
{
    char * str ;

    str = "\t\tI'm a lumberkack and I'm OK      " ;
    printf("lowercase: [%s]\n", strlwc(str));
    printf("uppercase: [%s]\n", strupc(str));
    printf("skipped  : [%s]\n", strskp(str));
    printf("cropped  : [%s]\n", strcrop(str));
    printf("stripped : [%s]\n", strstrip(str));

    return 0 ;
}
Beispiel #5
0
MODULE check_server_response (THREAD *thread)
{
    struct_smtsock_read_reply 
        *sock_read_ok = NULL;
    int 
        error_code;
    byte 
        saved = 0;
    char 
        *sock_read_ok_data = NULL;

    tcb = thread-> tcb;                 /*  Point to thread's context        */

  START_BODY
    get_smtsock_read_reply (thread-> event-> body, &sock_read_ok);

    if (sock_read_ok-> size <= 0)
        set_error (tcb, ERROR_CODE, "Out of memory", NULL);
    RAISE_EXC_IF (sock_read_ok-> size <= 0, memory_error_event);

    sock_read_ok_data = (char *) sock_read_ok-> data;

    saved = sock_read_ok_data[sock_read_ok-> size];
    sock_read_ok_data[sock_read_ok-> size] = 0;
    strcrop (sock_read_ok_data);

    if ((error_code = atoi (sock_read_ok_data)) > SMTP_SERVER_ERROR)
      {
         set_error (tcb, ERROR_CODE, 
                    "REFUSED by SMTP server: ", sock_read_ok_data, NULL);
         raise_exception (server_response_error_event);
      }
    CHECK_EXC;

    the_next_event = server_response_ok_event;
    sock_read_ok_data[sock_read_ok-> size] = saved;
  END_BODY

    if (sock_read_ok)
        free_smtsock_read_reply (&sock_read_ok);
}
Beispiel #6
0
MODULE get_next_argument (THREAD *thread)
{
    char
        *value;

    tcb = thread-> tcb;                 /*  Point to thread's context        */
    if (++tcb-> arg_index <= tcb-> argc)
      {
        value = tcb-> argv [tcb-> arg_index - 1];
        if (*value == '-')
          {
            value++;
            strcrop (value);
            strlwc  (value);
            value = strskp (value);
            if (streq (value, "debug"))
                strcpy (buffer, "set debug");
            else
            if (streq (value, "rec"))
                strcpy (buffer, "set recursive");
            else
            if (streq (value, "server"))
              {
                if (++tcb-> arg_index <= tcb-> argc)
                    xstrcpy (buffer, "set server ",
                             tcb-> argv [tcb-> arg_index - 1], NULL);
                else
                    strcpy  (buffer, "set server");
              }
            else
                strcpy (buffer, value);
          }
        else
            strcpy (buffer, value);
      }
    else
        buffer [0] = '\0';
}
Beispiel #7
0
MODULE set_server_ip_value (THREAD *thread)
{
    char
    *ip_value;
    int
    index;
    tcb = thread-> tcb;                 /*  Point to thread's context        */

    ip_value = &buffer [10];
    ip_value = strskp (ip_value);
    strconvch (ip_value, '\r', '\0');
    strconvch (ip_value, '\n', '\0');
    strcrop   (ip_value);
    inaddr.s_addr = inet_addr (ip_value);
    if (inaddr.s_addr != 0xFFFFFFFFUL
            &&  inaddr.s_addr != 0)
    {
        if (server_list.ns_count == MAX_NS)
            server_list.ns_count--;
        for (index = server_list.ns_count - 1; index >= 0; index--)
        {
            server_list.ns_addr [index + 1].sin_addr.s_addr =
                server_list.ns_addr [index].sin_addr.s_addr;
            server_list.ns_addr [index + 1].sin_port =
                server_list.ns_addr [index].sin_port;
            server_list.recursive_accept [index + 1] =
                server_list.recursive_accept [index];
        }
        server_list.ns_addr [0].sin_addr.s_addr = inaddr.s_addr;
        server_list.ns_addr [0].sin_port = htons (DNS_PORT);
        server_list.recursive_accept [0] = dns_recursive;
        server_list.ns_count++;
    }
    else
        puts ("Invalid IP address !!!");
}
Beispiel #8
0
int smtp_send_mail_ex (
   SMTP *smtp)
{
   FILE
      *fpin;
   int
       iCnt;
   sock_t
       socket_handle;
   char
       message_boundary [256],
       strOut           [514],
       strFile          [256],
       strUUEFile       [256],
       buffer           [BUFFER_SIZE + 1],
      *charset,
      *nb_bit,
      *data,
      *p_buffer,
      *strRcptUserIds;
   Bool
       old_ip_nonblock = ip_nonblock;
   int
       rcptUserIdsLen;
  long
      current_date,
      current_time,
      out_size,
      in_size;
  char
     *quoted_subject = NULL,
     *in_buf,
     *out_buf;

   /* Check required parameters                                              */
   if (smtp == NULL)
       return (SMTP_ERROR_CONNECT);
   if (smtp->strDestUserIds == NULL)
       return (SMTP_ERROR_MISSING_DESTINATION);
   if (smtp->strSubject == NULL)
       return (SMTP_ERROR_MISSING_SUBJECT);
   if (smtp->strSmtpServer == NULL)
       return (SMTP_ERROR_MISSING_SERVER_NAME);

   /*  Make sure we block on socket accesses                                 */
   ip_nonblock = FALSE;
   sock_init ();

   /* Open up the SMTP port (25 most of the time). */

   if (smtp-> connect_retry_cnt < 1)
       smtp-> connect_retry_cnt = 3;

   nb_bit = "7";

   if (smtp-> strCharSet == NULL 
   || *smtp-> strCharSet == '\0')
       charset = "US-ASCII";
   else
     {
       charset = smtp-> strCharSet;
       nb_bit = "8";
       if (smtp-> strSubject)
         {
           if (lexcmp (charset, "iso-2022-jp") == 0
           ||  lexcmp (charset, "shift_jis")   == 0
           ||  lexcmp (charset, "utf-8")       == 0) {
               quoted_subject = encode_mimeb_string (NULL, 0,
                                                  (byte *) smtp->strSubject, charset);
           }
           else
               quoted_subject = encode_quoted_string (NULL, 0,
                                                  (byte *) smtp->strSubject, charset);
         }
     }
   socket_handle = connect_socket (smtp-> strSmtpServer,
                                   "smtp", "tcp", NULL,
                                   smtp-> connect_retry_cnt,
                                   smtp-> retry_wait_time);

   if (socket_handle == INVALID_SOCKET
   ||  getreply (socket_handle, smtp) > SMTP_SERVER_ERROR)
     {
       mem_strfree  (&quoted_subject);
       sock_term ();
       return (SMTP_ERROR_CONNECT);
     }

   /* Format a SMTP meassage header.                                         */
   /* Just say hello to the mail server.                                     */
   xstrcpy (strOut, "HELO ", get_hostname (), "\r\n", NULL);
   send_data (socket_handle, strOut);
   if (getreply (socket_handle, smtp) > SMTP_SERVER_ERROR)
     {
       CLEAN_SEND_MAIL;
       return (SMTP_ERROR_INIT);
     }
   /* Tell the mail server who the message is from. */
   xstrcpy (strOut, "MAIL FROM:<", smtp-> strSenderUserId, ">\r\n", NULL);
   send_data (socket_handle, strOut);
   if (getreply (socket_handle, smtp) > SMTP_SERVER_ERROR)
     {
       CLEAN_SEND_MAIL;
       return (SMTP_ERROR_INVALID_SENDER);
     }
   rcptUserIdsLen = 0;
   if (smtp-> strDestUserIds)
       rcptUserIdsLen += strlen (smtp->strDestUserIds) + 1;
   if (smtp-> strCcUserIds)
       rcptUserIdsLen += strlen (smtp->strCcUserIds)   + 1;
   if (smtp-> strBccUserIds)
       rcptUserIdsLen += strlen (smtp->strBccUserIds)  + 1;

   strRcptUserIds = (char *) mem_alloc (rcptUserIdsLen);
   p_buffer = strRcptUserIds;
   data = smtp-> strDestUserIds;
   while (*data)
       *p_buffer++ = *data++;
   if (smtp-> strCcUserIds)
     {
       *p_buffer++ = ';';
       data = smtp-> strCcUserIds;
       while (*data)
           *p_buffer++ = *data++;
     }
   if (smtp-> strBccUserIds)
     {
       *p_buffer++ = ';';
       data = smtp-> strBccUserIds;
       while (*data)
           *p_buffer++ = *data++;
     }
   *p_buffer = '\0';

   /* The following tells the mail server who to send it to.                 */
   iCnt = 0;
   if (*strRcptUserIds) {
       FOREVER
         {
            getstrfld (strRcptUserIds, iCnt++, 0, ",;", buffer);
            if (*buffer)
             {
               xstrcpy (strOut, "RCPT TO:<", buffer, ">\r\n", NULL);
               send_data (socket_handle, strOut);
               if (getreply (socket_handle, smtp) > SMTP_SERVER_ERROR)
                 {
                   CLEAN_SEND_MAIL;
                   return (SMTP_ERROR_INVALID_RECEIPT_USER);
                 }
             }

           else
               break;
         }
    }
    mem_free (strRcptUserIds);

   /* Now give it the Subject and the message to send.                       */
   send_data (socket_handle, "DATA\r\n");
   if (getreply (socket_handle, smtp) > SMTP_SERVER_ERROR)
     {
       CLEAN_SEND_MAIL;
       return (SMTP_ERROR_INVALID_DATA);
     }

   /* Set the date and time of the message.                                  */
   get_date_time_now (&current_date, &current_time);
   xstrcpy ( strOut, "Date: ", encode_mime_time (current_date, current_time),
             " \r\n", NULL );

   /* The following shows all who it was sent to. */
   if ( smtp-> strFullDestUserIds && *smtp-> strFullDestUserIds )
    {
       replacechrswith (smtp-> strFullDestUserIds, ";", ',');
       xstrcat (strOut, "To: ", smtp-> strFullDestUserIds, "\r\n", NULL);
     }
   else
    {
       replacechrswith (smtp-> strDestUserIds, ";", ',');
       xstrcat (strOut, "To: ", smtp-> strDestUserIds, "\r\n", NULL);
    }

   /* Set up the Reply-To path. */
   if (!smtp-> strRetPathUserId || !*smtp-> strRetPathUserId)
       smtp-> strRetPathUserId = smtp-> strSenderUserId;

   if ( strstr( smtp-> strRetPathUserId, "<" ) != NULL &&
        strstr( smtp-> strRetPathUserId, ">" ) != NULL )
       xstrcat (strOut, "Reply-To:",  smtp-> strRetPathUserId, "\r\n", NULL);
   else
       xstrcat (strOut, "Reply-To:<", smtp-> strRetPathUserId, ">\r\n", NULL);

   if ( smtp-> strFullSenderUserId && *smtp-> strFullSenderUserId )
     {
       xstrcat (strOut, "Sender: ", smtp-> strFullSenderUserId, "\r\n", NULL);
       xstrcat (strOut, "From: ",   smtp-> strFullSenderUserId, "\r\n", NULL);
     }
   else
     {
       xstrcat (strOut, "Sender: ", smtp-> strSenderUserId, "\r\n", NULL);
       xstrcat (strOut, "From: ",   smtp-> strSenderUserId, "\r\n", NULL);
     }
   send_data (socket_handle, strOut);

   *strOut = '\0';

   /* Post any CC's. */
   if (smtp->strFullCcUserIds && *smtp->strFullCcUserIds)
     {
       replacechrswith (smtp->strFullCcUserIds, ";", ',');
       xstrcat (strOut, "Cc:", smtp->strFullCcUserIds, "\r\n", NULL );
     }
   else
   if (smtp->strCcUserIds && *smtp->strCcUserIds)
     {
       replacechrswith (smtp->strCcUserIds, ";", ',');
       xstrcat (strOut, "Cc:", smtp->strCcUserIds, "\r\n", NULL );
     }

   /* Post any BCC's. */
   if (smtp->strFullBccUserIds && *smtp->strFullBccUserIds)
     {
       replacechrswith (smtp->strFullBccUserIds, ";", ',');
       xstrcat (strOut, "Bcc:", smtp->strFullBccUserIds, "\r\n", NULL);
     }
   else
   if (smtp->strBccUserIds && *smtp->strBccUserIds)
     {
       replacechrswith (smtp->strBccUserIds, ";", ',');
       xstrcat (strOut, "Bcc:", smtp->strBccUserIds, "\r\n", NULL);
     }
   /* Post any Return-Receipt-To. */
   if (smtp->strRrcpUserId && *smtp->strRrcpUserId)
       xstrcat (strOut, "Return-Receipt-To:", smtp->strRrcpUserId, ">\r\n",
                NULL);

   if (smtp->strMailerName && *smtp->strMailerName)
       xstrcat (strOut, "X-Mailer: ", smtp->strMailerName, "\r\n", NULL);
   else
       strcat  (strOut, "X-Mailer: sflmail function\r\n");

   /* Set the mime version. */
   get_date_time_now (&current_date, &current_time);
   sprintf (message_boundary, "%s.%ld.%ld", MESSAGE_BOUNDARY,
            current_date, current_time);

   if ( smtp->strHtmlMessageBody && *smtp->strHtmlMessageBody )
       xstrcat (strOut, "MIME-Version: 1.0\r\n",
                "Content-Type: multipart/alternative; boundary=\"", 
	            message_boundary,"\"\r\n", NULL);
   else
       xstrcat (strOut, "MIME-Version: 1.0\r\n",
                "Content-Type: Multipart/Mixed; boundary=\"", 
	            message_boundary,"\"\r\n", NULL);

   send_data (socket_handle, strOut);

   *strOut = '\0';
   /* Write out any message comment included. */
   if (smtp->strMsgComment && *smtp->strMsgComment)
       xstrcpy (strOut, "Comments: ", smtp->strMsgComment, "\r\n", NULL);

   /* Send the subject and message body. */
   if (quoted_subject)
       xstrcat (strOut, "Subject: ", quoted_subject, "\r\n\r\n", NULL);
   else
       xstrcat (strOut, "Subject: ", smtp->strSubject, "\r\n\r\n", NULL);
   send_data (socket_handle, strOut);

   /* Keep rfc822 in mind with all the sections.                             */
    if (smtp->strMessageBody && *smtp->strMessageBody)
      {
        /* check if we got html/alternate files                               */
        if ( smtp->strHtmlMessageBody && *smtp->strHtmlMessageBody )
          {
           xstrcpy (strOut,
                     "\r\n\r\n--", message_boundary, "\r\n",
                     "Content-Type: text/html; charset=", charset, "\r\n",
                     "Content-Transfer-Encoding: 7BIT\r\n",
                     "Content-description: Body of message\r\n\r\n", NULL);
           send_data (socket_handle, strOut);
           send_body (socket_handle, smtp->strHtmlMessageBody);
           send_data (socket_handle, "\r\n");
           xstrcpy (strOut,
                    "\r\n--", message_boundary, "\r\n",
                    "Content-Type: text/plain; charset=", charset, "\r\n",
                    "Content-Transfer-Encoding: ", nb_bit, "BIT\r\n",
                    "Content-description: Body of message\r\n\r\n", NULL);
           send_data (socket_handle, strOut);
           send_body (socket_handle, smtp-> strMessageBody);
           send_data (socket_handle, "\r\n");

         }
       else
         {
           xstrcpy (strOut,
                    "\r\n--", message_boundary, "\r\n",
                    "Content-Type: text/plain; charset=", charset, "\r\n",
                    "Content-Transfer-Encoding: ", nb_bit, "BIT\r\n",
                    "Content-description: Body of message\r\n\r\n", NULL);
           send_data (socket_handle, strOut);
           send_body (socket_handle, smtp-> strMessageBody);
           send_data (socket_handle, "\r\n");
         }
     }
   /* Include any Text type files and Attach them to the message. */
   if (smtp->strTxtFiles && *smtp->strTxtFiles)
     {
       iCnt = 0;
       FOREVER
         {
           getstrfld (smtp->strTxtFiles, iCnt++, 0, ",;", strFile);
           strcrop (strskp (strFile));
           if (*strFile)
             {
               fpin = fopen (strFile, "rb");
               if (!fpin)
                 {
                   strcpy (smtp->strlast_smtp_message, strFile);
                     {
                       CLEAN_SEND_MAIL;
                       return (SMTP_ERROR_MISSING_ATTACH_FILE);
                     }
                 }

               xstrcpy (strOut, "\r\n--", message_boundary, "\r\n",
                       "Content-Type: text/plain; charset=", charset, "\r\n",
                       "Content-Transfer-Encoding: ", nb_bit, "BIT\r\n",
                       "Content-Disposition: attachment; filename=",
                        getfilename (strFile), "\r\n\r\n", NULL);
               send_data (socket_handle, strOut);
               while (fgets (buffer, BUFFER_SIZE, fpin))
                 {
                   if (*buffer == '.')
                       write_TCP (socket_handle, ".", 1);
                   send_data (socket_handle, buffer);
                 }
               fclose (fpin);
             }
           else
               break;
         }
     }
/*--------------------------------------------------------------------------*/
dictionary*
iniparser_new (char *ininame)
{
    dictionary  *   d;
    char        lin[ASCIILINESZ+1];
    char        sec[ASCIILINESZ+1];
    char        key[ASCIILINESZ+1];
    char        val[ASCIILINESZ+1];
    char    *   where;
    FILE    *   ini;
    int         lineno;
    FileLock *  lock;

    lock = ini_file_lock (ininame, FALSE);
    if (!lock)
	ccsWarning ("unable to lock file %s, reads may conflict", ininame);

    ini = fopen (ininame, "r");
    if (!ini)
    {
	if (lock)
	    ini_file_unlock (lock );
	return NULL;
    }

    sec[0] = 0;

    /*
     * Initialize a new dictionary entry
     */
    d = dictionary_new (0);
    lineno = 0;

    while (fgets (lin, ASCIILINESZ, ini) != NULL)
    {
	++lineno;
	where = strskp (lin); /* Skip leading spaces */

	if (*where == ';' || *where == '#' || *where == 0)
	    continue; /* Comment lines */
	else
	{
	    val[0] = '\0';

	    if (sscanf (where, "[%[^]]", sec) == 1)
	    {
		/* Valid section name */
		strcpy (sec, strlwc (sec));
		iniparser_add_entry (d, sec, NULL, NULL);
	    }
	    else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2 ||
		     sscanf (where, "%[^=] = '%[^\']'",   key, val) == 2 ||
		     sscanf (where, "%[^=] = %[^\n]",     key, val) >= 1)
	    {
    		strcpy (key, strlwc (strcrop (key)));
		/*
		 * sscanf cannot handle "" or '' as empty value,
		 * this is done here
		 */

	    	if (!strcmp (val, "\"\"") || !strcmp (val, "''"))
    		{
		    val[0] = (char) 0;
		}
		else
		{
		    strcpy (val, strcrop (val));
		}

	    	iniparser_add_entry (d, sec, key, val);
    	    }
	}
    }

    fclose (ini);
    if (lock)
	ini_file_unlock (lock );

    return d;
}
Beispiel #10
0
Bool
ini_scan_section (
    FILE *inifile,
    char **keyword,
    char **value)
{
    int
        remaining;                      /*  Space remaining in line buffer   */
    char
        *first,
        *valueptr,
        *lineptr;

    /*  Read through file until we find what we are looking for              */
    while (file_read (inifile, iniline)) {
        strcrop (iniline);
        if (strnull (iniline))
            continue;                   /*  Skip empty lines                 */

        /*  Calculate space remaining in buffer after this line; we need to
         *  know this later if we start reading continuation lines.
         */
        remaining = LINE_MAX - strlen (iniline);
            
        first = strskp (iniline);       /*  Skip leading spaces              */
        if (*first == ';' || *first == '#' || *first == 0)
            continue;                   /*  Comment line                     */
        else
        if (*first == '!') {
            first = strskp (first + 1);
            trace (first);
        }
        else                            /*  Have name = value                */
        if (sscanf (first, "[%[^]]", ini_section) == 1) {
            *keyword = strlwc (ini_section);
            *value   = NULL;
            return (FALSE);             /*  New section name                 */
        }
        else
        if (streq (first, "[]")) {      /*  Allow empty section names        */
            strcpy (ini_section, "");
            *keyword = ini_section;
            *value   = NULL;
            return (FALSE);             /*  New section name                 */
        }
        else {
            if (*first == '"') {        /*  Name in quotes                   */
                valueptr = strchr (first + 1, '"');
                if (valueptr) {
                    first++;
                    *valueptr = ' ';
                    valueptr = strchr (valueptr + 1, '=');
                }
            }
            else
                valueptr = strchr (first, '=');

            if (valueptr == NULL) {
                coprintf ("E: illegal definition in ini file");
                return (FALSE);
            }
            *valueptr++ = '\0';
            strcpy (ini_keyword, strcrop (strlwc (first)));
            while (*valueptr == ' ')
                valueptr++;             /*    and leading spaces             */
            
            if (*valueptr == '"') {     /*  Have value in quotes             */
                /*  Get continuation lines as necessary and possible         */
                first = &strlast (valueptr);
                while (*first == '-' && remaining > 0) {
                    if (!file_readn (inifile, first, remaining))
                        break;                  /*  Abrubt end of file       */
                    strcrop (first);
                    remaining -= strlen (first) - 1;
                    first     += strlen (first) - 1;
                } 
                /*  Now find closing quote and terminate value there         */
                for (lineptr = valueptr + 1; *lineptr; lineptr++) {
                    if (*lineptr == '\\')
                        lineptr++;      /*  Ignore next char                 */
                    else
                    if (*lineptr == '"') {
                        lineptr [1] = '\0';
                        break;          /*  Closing quote, end of value      */
                    }
                }
            }
            else {                      /*  Have unquoted value              */
                strconvch (valueptr, ';', '\0');
                strconvch (valueptr, '#', '\0');
            }
            strcrop (valueptr);
            strcpy (ini_value, valueptr);
            *keyword = ini_keyword;
            *value   = ini_value;
            return (TRUE);              /*  Found keyword = value            */
        }
    }
    *keyword = NULL;
    return (FALSE);                     /*  End of file                      */
}