static GList *
mh_profile_read( XfceMailwatchMHMailbox *mh, const gchar *mh_profile )
{
    GIOChannel      *ioc;
    GError          *error = NULL;
    gchar           *line = NULL;
    GList           *li = NULL;

    DBG( "-->>" );

    ioc = g_io_channel_new_file( mh_profile, "r", &error );
    if ( !ioc ) {
        xfce_mailwatch_log_message( mh->mailwatch, XFCE_MAILWATCH_MAILBOX( mh ),
                                    XFCE_MAILWATCH_LOG_ERROR,
                                    "Failed to open file %s: %s",
                                    mh_profile, error->message );
        g_error_free( error );
        return ( NULL );
    }
    g_io_channel_set_encoding( ioc, NULL, NULL );

    while ( ( line = mh_profile_readline( mh, mh_profile, ioc ) ) ) {
        MHProfileEntry          *entry;

        entry = mh_profile_entry_create_new( line );
        if ( entry ) {
            li = g_list_prepend( li, entry );
        }
        else {
            xfce_mailwatch_log_message( mh->mailwatch, XFCE_MAILWATCH_MAILBOX( mh ),
                    XFCE_MAILWATCH_LOG_WARNING,
                    _( "Malformed line %s in %s ignored." ), line, mh_profile );
        }
        g_free( line );
    }

    g_io_channel_shutdown( ioc, FALSE, NULL );
    g_io_channel_unref( ioc );

    DBG( "<<--" );
    return ( li );
}
static gboolean
maildir_check_mail_timeout( gpointer data )
{
    XfceMailwatchMaildirMailbox *maildir = XFCE_MAILWATCH_MAILDIR_MAILBOX( data );
    GThread                     *th;

    if( g_atomic_pointer_get( &maildir->thread ) ) {
        xfce_mailwatch_log_message( maildir->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX( maildir ),
                                    XFCE_MAILWATCH_LOG_WARNING,
                                    _( "Previous thread hasn't exited yet, not checking mail this time." ) );
        return TRUE;
    }

    th = g_thread_create( maildir_main_thread, maildir, FALSE, NULL );
    g_atomic_pointer_set( &maildir->thread, th );

    return TRUE;
}
static void
maildir_check_mail( XfceMailwatchMaildirMailbox *maildir )
{
    gchar           *path = NULL;
    struct stat     st;

    DBG( "-->>" );
    
    g_mutex_lock( maildir->mutex );
    if ( !maildir->path || !*(maildir->path) ) {
        goto out;
    }

    path = g_build_filename( maildir->path, "new", NULL );
    if ( stat( path, &st ) < 0 ) {
        xfce_mailwatch_log_message( maildir->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX( maildir ),
                                    XFCE_MAILWATCH_LOG_ERROR,
                                    _( "Failed to get status of file %s: %s" ),
                                    path, g_strerror( errno ) );
        goto out;
    }
        
    if ( !S_ISDIR( st.st_mode ) ) {
        xfce_mailwatch_log_message( maildir->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX( maildir ),
                                    XFCE_MAILWATCH_LOG_ERROR,
                                    _( "%s is not a directory. Is %s really a valid maildir?" ),
                                    path, maildir->path );
        goto out;
    }

    if ( st.st_mtime > maildir->mtime ) {
        GDir        *dir;
        GError      *error = NULL;

        dir = g_dir_open( path, 0, &error );
        
        if ( dir ) {
            int             count_new = 0;
            const gchar     *entry;
            
            while ( ( entry = g_dir_read_name( dir ) ) ) {
                count_new++;

                /* only check every 25 entries */
                if( !( count_new % 25 ) ) {
                    if( !g_atomic_int_get( &maildir->running ) ) {
                        g_dir_close( dir );
                        g_atomic_pointer_set( &maildir->thread, NULL );
                        return;
                    }
                }
            }
            g_dir_close( dir );

            xfce_mailwatch_signal_new_messages( maildir->mailwatch,
                    (XfceMailwatchMailbox *) maildir, count_new );
        }
        else {
            xfce_mailwatch_log_message( maildir->mailwatch,
                                        XFCE_MAILWATCH_MAILBOX( maildir ),
                                        XFCE_MAILWATCH_LOG_ERROR,
                                        "%s", error->message );
            g_error_free( error );
        }
        maildir->mtime = st.st_mtime;
    }

out:
    g_mutex_unlock( maildir->mutex );
    if ( path ) {
        g_free( path );
    }

    DBG( "<<--" );
}
static void
mbox_check_mail( XfceMailwatchMboxMailbox *mbox )
{
    gchar           *mailbox;
    struct stat     st;
    guint           num_new = 0;

    g_mutex_lock( mbox->settings_mutex );
    if ( !mbox->fn ) {
        g_mutex_unlock( mbox->settings_mutex );
        return;
    }
    mailbox = g_strdup( mbox->fn );
    g_mutex_unlock( mbox->settings_mutex );

    /* For some reason g_stat() doesn't update
     * ctime */
    if ( stat( mailbox, &st ) < 0 ) {
        xfce_mailwatch_log_message( mbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX( mbox ),
                                    XFCE_MAILWATCH_LOG_ERROR,
                                    _( "Failed to get status of file %s: %s" ),
                                    mailbox, g_strerror( errno ) );
        g_free( mailbox );
        return;
    }

    if ( st.st_ctime > mbox->ctime ) {
        gboolean        in_header = FALSE;
        gboolean        cur_new = FALSE;
        gchar           *p;
        GIOChannel      *ioc;
        gsize           nl;
        GError          *error = NULL;

        num_new = 0;

        ioc = g_io_channel_new_file( mailbox, "r", &error );
        if ( !ioc ) {
            xfce_mailwatch_log_message( mbox->mailwatch,
                                        XFCE_MAILWATCH_MAILBOX( mbox ),
                                        XFCE_MAILWATCH_LOG_ERROR,
                                        error->message );
            g_free( mailbox );
            g_error_free( error );
            return;
        }
        if ( g_io_channel_set_encoding( ioc, NULL, &error ) != G_IO_STATUS_NORMAL ) {
            xfce_mailwatch_log_message( mbox->mailwatch,
                                        XFCE_MAILWATCH_MAILBOX( mbox ),
                                        XFCE_MAILWATCH_LOG_WARNING,
                                        error->message );
            g_error_free( error );
            error = NULL;
        }
       
        if ( mbox->size && st.st_size > (guint)mbox->size ) {
            /* G_SEEK_CUR is same as G_SEEK_SET in this context. */
            if ( g_io_channel_seek_position( ioc, mbox->size, G_SEEK_CUR, &error ) !=  G_IO_STATUS_NORMAL ) {
                xfce_mailwatch_log_message( mbox->mailwatch,
                                            XFCE_MAILWATCH_MAILBOX( mbox ),
                                            XFCE_MAILWATCH_LOG_ERROR,
                                            error->message );
                g_io_channel_unref( ioc );
                g_free( mailbox );
                g_error_free( error );
                return;
            }
            num_new += mbox->new_messages;
        }

        while ( g_io_channel_read_line( ioc, &p, NULL, &nl, NULL ) == G_IO_STATUS_NORMAL ) {
            p[nl] = 0;
            
            if ( !in_header ) {
                if ( !strncmp( p, "From ", 5 ) ) {
                    in_header = TRUE;
                    cur_new = TRUE;
                }
            }
            else {
                if ( *p == 0 ) {
                    in_header = FALSE;

                    if ( cur_new ) {
                        num_new++;
                    }
                }
                else if ( !strncmp( p, "Status: ", 8 ) ) {
                    gchar       *q = p + 8;
                    if ( strchr( q, 'R' ) || strchr( q, 'O' ) ) {
                        cur_new = FALSE;
                    }
                }
                else if ( !strncmp( p, "X-Mozilla-Status: ", 18 ) ) {
                    if ( strncmp( p + 18, "0000", 4 ) ) {
                        cur_new = FALSE;
                    }
                }
            }
            g_free( p );

            if( !g_atomic_int_get( &mbox->running ) ) {
                g_io_channel_unref( ioc );
                g_free( mailbox );
                return;
            }
        }
        g_io_channel_unref( ioc );
        
        if ( st.st_size > (guint)mbox->size && num_new <= mbox->new_messages ) {
            /* Assume mailbox opened and some headers added by client */
            num_new = mbox->new_messages = 0;
        }
        else {
            mbox->new_messages = num_new;
        }

        xfce_mailwatch_signal_new_messages( mbox->mailwatch, (XfceMailwatchMailbox *) mbox, num_new );

        mbox->ctime = st.st_ctime;
        mbox->size = st.st_size;
    }
    g_free( mailbox );
}
static void
mh_check_mail( XfceMailwatchMHMailbox *mh )
{
    struct stat     st;

    DBG( "-->>" );

    if ( !mh->mh_profile_fn ) {
        mh->mh_profile_fn = mh_get_profile_filename();
    }
    
    if ( stat( mh->mh_profile_fn, &st ) == 0 ) {
        if ( st.st_ctime != mh->mh_profile_ctime ) {
            mh_read_config( mh );
            mh->mh_profile_ctime = st.st_ctime;
        }
    }
    else {
        xfce_mailwatch_log_message( mh->mailwatch, XFCE_MAILWATCH_MAILBOX( mh ),
                                    XFCE_MAILWATCH_LOG_WARNING,
                                    _( "Failed to get status of file %s: %s" ),
                                    mh->mh_profile_fn, strerror( errno ) );
    }

    if ( !mh->mh_sequences_fn ) {
        return;
    }

    if ( stat( mh->mh_sequences_fn, &st ) < 0 ) {
        xfce_mailwatch_log_message( mh->mailwatch, XFCE_MAILWATCH_MAILBOX( mh ),
                                    XFCE_MAILWATCH_LOG_ERROR,
                                    _( "Failed to get status of file %s: %s" ),
                                    mh->mh_sequences_fn, strerror( errno ) );
    }
    else {
        if ( st.st_ctime != mh->mh_sequences_ctime ) {
            GList           *seqlist;
            gchar           *unseen;
            gulong          num_new = 0;

            mh->mh_sequences_ctime = st.st_ctime;

            seqlist = mh_profile_read( mh, mh->mh_sequences_fn );

#ifdef DEBUG
            mh_profile_print( seqlist );
#endif

            unseen = mh_profile_entry_get_value( seqlist,
                    mh->unseen_sequence ? mh->unseen_sequence : MH_UNSEEN_SEQ  );
            mh_profile_free( seqlist );
            if ( unseen ) {
                gchar       **v;
                guint       i;

                v = g_strsplit_set( unseen, " \t\r\n", 0 );
                g_free( unseen );

                for ( i = 0; v[i] != NULL; i++ ) {
                    gchar       *q = NULL;
                    gulong      l1, l2;

                    l1 = strtoul( v[i], &q, 10 );
                    if ( q && *q ) {
                        q++;

                        l2 = strtoul( q, NULL, 10 );
                        if ( l2 ) {
                            l1 = 1 + l2 - l1;
                        }
                        else {
                            /* In this case some sort of error occured */
                            l1 = 1;
                        }
                    }
                    else {
                        l1 = 1;
                    }

                    num_new += l1;
                }
                g_strfreev( v );
            }
            xfce_mailwatch_signal_new_messages( mh->mailwatch, XFCE_MAILWATCH_MAILBOX( mh ), num_new );
        }
    }

    DBG( "<<--" );
}
static gchar *
mh_profile_readline( XfceMailwatchMHMailbox *mh, const gchar *mh_profile, GIOChannel *ioc )
{
    gchar           *line = NULL, *curline;
    gsize           nread, newline;
    GIOStatus       status;
    GError          *error = NULL;

    g_return_val_if_fail( ioc != NULL, NULL );

    status = g_io_channel_read_line( ioc, &curline,
                                     &nread, &newline,
                                     &error );
    while ( status == G_IO_STATUS_NORMAL ) {
        gchar       c;

        curline[newline] = 0;

        if ( !*curline ) {
            /* An mh profile shouldn't contain blank lines. Ignore 'em */
            g_free( curline );
        }
        else {
            if ( !line ) {
                if ( g_ascii_isspace( *curline ) ) {
                    /* The profile isn't right, ignore */
                    curline = g_strstrip( curline );
                }

                line = curline;
            }
            else {
                gchar       *p;

                curline = g_strstrip( curline );

                p = g_strconcat( line, curline, NULL );

                g_free( line );
                g_free( curline );

                line = p;
            }

            if ( g_io_channel_read_chars( ioc, &c, 1, &nread, NULL ) == G_IO_STATUS_NORMAL ) {
                if ( !g_ascii_isspace( c ) || g_ascii_iscntrl( c ) ) {
                    /* g_ascii_iscntrl() is supposed to catch newlines */
                    g_io_channel_seek_position( ioc, -1, G_SEEK_CUR, NULL );
                    break;
                }
            }
        }

        status = g_io_channel_read_line( ioc, &curline,
                                         &nread, &newline,
                                         &error );
    }

    if ( status == G_IO_STATUS_ERROR ) {
        xfce_mailwatch_log_message( mh->mailwatch, XFCE_MAILWATCH_MAILBOX( mh ),
                                    XFCE_MAILWATCH_LOG_WARNING,
                                    "Error reading file %s: %s",
                                    mh_profile, error->message );

        g_error_free( error );
    }

    return ( line );
}