home *** CD-ROM | disk | FTP | other *** search
- /*
- * Project : tin - a threaded Netnews reader
- * Module : art.c
- * Author : I.Lea & R.Skrenta
- * Created : 01-04-91
- * Updated : 12-05-92
- * Notes :
- * Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
- * You may freely copy or redistribute this software,
- * so long as there is no profit made from its use, sale
- * trade or reproduction. You may not change this copy-
- * right notice, and it must be included in any copy made
- */
-
- #include "tin.h"
-
- char index_file[PATH_LEN];
- char *glob_art_group;
- static long last_read_article;
-
-
- /*
- * Construct the pointers to the basenotes of each thread
- * arts[] contains every article in the group. inthread is
- * set on each article that is after the first article in the
- * thread. Articles which have been expired have their thread
- * set to -2 (ART_EXPIRED).
- */
-
- void find_base (only_unread)
- int only_unread;
- {
- register int i;
- register int j;
-
- top_base = 0;
-
- debug_print_arts ();
-
- if (only_unread) {
- for (i = 0; i < top; i++) {
- if (IGNORE_ART(i) || arts[i].inthread != FALSE) {
- continue;
- }
- if (top_base >= max_art) {
- expand_art ();
- }
- if (arts[i].unread == ART_UNREAD) {
- base[top_base++] = i;
- } else {
- for (j = i ; j >= 0 ; j = arts[j].thread) {
- if (arts[j].unread) {
- base[top_base++] = i;
- break;
- }
- }
- }
- }
- } else {
- for (i = 0; i < top; i++) {
- if (IGNORE_ART(i) || arts[i].inthread != FALSE) {
- continue;
- }
- if (top_base >= max_art) {
- expand_art ();
- }
- base[top_base++] = i;
- }
- }
- }
-
- /*
- * Count the number of non-expired articles in arts[]
- */
-
- int num_of_arts ()
- {
- int sum = 0;
- register int i;
-
- for (i = 0; i < top; i++) {
- if (arts[i].thread != ART_EXPIRED) {
- sum++;
- }
- }
-
- return sum;
- }
-
- /*
- * Do we have an entry for article art?
- */
-
- int valid_artnum (art)
- long art;
- {
- register int i;
-
- for (i = 0; i < top; i++)
- if (arts[i].artnum == art)
- return i;
-
- return -1;
- }
-
- /*
- * Return TRUE if arts[] contains any expired articles
- * (articles we have an entry for which don't have a corresponding
- * article file in the spool directory)
- */
-
- int purge_needed ()
- {
- register int i;
-
- for (i = 0; i < top; i++)
- if (arts[i].thread == ART_EXPIRED)
- return TRUE;
-
- return FALSE;
- }
-
- /*
- * Main group indexing routine. Group should be the name of the
- * newsgroup, i.e. "comp.unix.amiga". group_path should be the
- * same but with the .'s turned into /'s: "comp/unix/amiga"
- *
- * Will read any existing index, create or incrementally update
- * the index by looking at the articles in the spool directory,
- * and attempt to write a new index if necessary.
- */
-
- void index_group (group, group_path)
- char *group;
- char *group_path;
- {
- int killed = FALSE;
- int modified = FALSE;
- glob_art_group = group;
-
- set_signals_art ();
-
- if (! update) {
- sprintf (msg, txt_group, group);
- wait_message (msg);
- }
- hash_reclaim ();
- free_art_array ();
-
- /*
- * load articles from index file if it exists
- */
- read_index_file (group);
-
- /*
- * add any articles to arts[] that are new or were killed
- */
- modified = read_group (group, group_path);
-
- if (modified || purge_needed ()) {
- write_index_file (group);
- }
- read_newsrc_line (group);
- killed = kill_any_articles (group); /* do after read_newsrc_line() */
- make_threads (FALSE);
- find_base (show_only_unread);
-
- if ((modified || killed) && ! update) {
- clear_message ();
- }
- }
-
- /*
- * Index a group. Assumes any existing index has already been
- * loaded.
- */
-
- int read_group (group, group_path)
- char *group;
- char *group_path;
- {
- FILE *fp;
- int count = 0;
- int modified = FALSE;
- int respnum;
- long art;
- register int i;
-
- setup_base (group, group_path); /* load article numbers into base[] */
-
- for (i = 0; i < top_base; i++) { /* for each article # */
- art = base[i];
-
- /*
- * Do we already have this article in our index? Change thread from
- * (ART_EXPIRED) to (ART_NORMAL) if so and skip the header eating.
- */
-
- if ((respnum = valid_artnum (art)) >= 0 || art <= last_read_article) {
- if (respnum >= 0) {
- arts[respnum].thread = ART_NORMAL;
- arts[respnum].unread = ART_UNREAD;
- }
- continue;
- }
-
- if (! modified) {
- modified = TRUE; /* we've modified the index */
- /* it will need to be re-written */
- }
-
- if ((fp = open_header_fp (group_path, art)) == (FILE *) 0) {
- continue;
- }
-
- /*
- * Add article to arts[]
- */
- if (top >= max_art)
- expand_art();
-
- arts[top].artnum = art;
- arts[top].thread = ART_NORMAL;
-
- set_article (&arts[top]);
-
- if (! parse_headers (fp, &arts[top])) {
- debug_nntp ("read_group", "FAILED parse_header()");
- continue;
- }
-
- fclose (fp);
- last_read_article = arts[top].artnum; /* used if arts are killed */
- top++;
-
- if (++count % MODULO_COUNT_NUM == 0 && ! update) {
- #ifndef SLOW_SCREEN_UPDATE
- sprintf (msg, txt_indexing_num, group, count);
- #else
- sprintf (msg, txt_indexing, group);
- #endif
- wait_message (msg);
- }
- }
-
- return modified;
- }
-
-
- /*
- * Go through the articles in arts[] and use .thread to snake threads
- * through them. Use the subject line to construct threads. The
- * first article in a thread should have .inthread set to FALSE, the
- * rest TRUE. Only do unexprired articles we haven't visited yet
- * (arts[].thread == -1 ART_NORMAL).
- */
-
- void make_threads (rethread)
- int rethread;
- {
- extern int cur_groupnum;
- register int i;
- register int j;
-
- if (!cmd_line) {
- if (thread_arts) {
- wait_message (txt_threading_arts);
- } else {
- wait_message (txt_unthreading_arts);
- }
- }
-
- /*
- * .thread & .inthread need to be reset if re-threading arts[]
- */
- if (rethread && active[my_group[cur_groupnum]].attribute.thread) {
- for (i=0 ; i < top ; i++) {
- arts[i].thread = ART_NORMAL;
- arts[i].inthread = FALSE;
- }
- }
-
- switch (sort_art_type) {
- case SORT_BY_NOTHING: /* don't sort at all */
- qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
- break;
- case SORT_BY_SUBJ_DESCEND:
- case SORT_BY_SUBJ_ASCEND:
- qsort ((char *) arts, top, sizeof (struct article_t), subj_comp);
- break;
- case SORT_BY_FROM_DESCEND:
- case SORT_BY_FROM_ASCEND:
- qsort ((char *) arts, top, sizeof (struct article_t), from_comp);
- break;
- case SORT_BY_DATE_DESCEND:
- case SORT_BY_DATE_ASCEND:
- qsort ((char *) arts, top, sizeof (struct article_t), date_comp);
- break;
- default:
- break;
- }
-
- if (thread_arts == 0 || active[my_group[cur_groupnum]].attribute.thread == 0) {
- return;
- }
-
- for (i = 0; i < top; i++) {
- if (arts[i].thread != ART_NORMAL || IGNORE_ART(i)) {
- continue;
- }
- for (j = i+1; j < top; j++) {
- if (! IGNORE_ART(j) &&
- ((arts[i].subject == arts[j].subject) ||
- ((arts[i].part || arts[i].patch) &&
- arts[i].archive == arts[j].archive))) {
- arts[i].thread = j;
- arts[j].inthread = TRUE;
- break;
- }
- }
- }
- }
-
-
- int parse_headers (fp, h)
- FILE *fp;
- struct article_t *h;
- {
- char buf[HEADER_LEN];
- char buf2[HEADER_LEN];
- char art_from_addr[LEN];
- char art_full_name[LEN];
- char *ptr, *ptrline, *s;
- int n = 0, len = 0, lineno = 0;
- int flag;
- int got_subject = FALSE;
- int got_from = FALSE;
- int got_date = FALSE;
- int got_archive = FALSE;
- extern int errno;
-
- buf[HEADER_LEN-1] = '\0';
-
- while (fread (buf, sizeof (buf)-1, 1, fp) != 1 && errno == EINTR)
- ; /* spin on signal interrupts */
-
- if ((n = strlen (buf)) == 0) {
- return FALSE;
- }
-
- buf[n-1] = '\0';
-
- ptr = buf;
-
- while (1) {
- for (ptrline = ptr; *ptr && *ptr != '\n'; ptr++) {
- if (((*ptr) & 0xFF) < ' ') {
- *ptr = ' ';
- }
- }
- flag = *ptr;
- *ptr++ = '\0';
- lineno++;
-
- if (! got_from && match_header (ptrline, "From", buf2, HEADER_LEN)) {
- parse_from (buf2, art_from_addr, art_full_name);
- h->from = hash_str (art_from_addr);
- h->name = hash_str (art_full_name);
- got_from = TRUE;
- } else if (! got_subject && match_header (ptrline, "Subject", buf2, HEADER_LEN)) {
- s = eat_re (buf2);
- h->subject = hash_str (eat_re (s));
- got_subject = TRUE;
- } else if (! got_date && match_header (ptrline, "Date", buf2, HEADER_LEN)) {
- parse_date (buf2, h->date);
- got_date = TRUE;
- } else if (match_header (ptrline, "Archive-name", buf2, HEADER_LEN) ||
- match_header (ptrline, "Archive-Name", buf2, HEADER_LEN)) {
- if ((s = (char *) strchr (buf2, '/')) != NULL) {
- if (strncmp (s+1, "part", 4) == 0 ||
- strncmp (s+1, "Part", 4) == 0) {
- h->part = str_dup (s+5);
- len = (int) strlen (h->part);
- if (h->part[len-1] == '\n') {
- h->part[len-1] = '\0';
- }
- } else {
- if (strncmp (s+1,"patch",5) == 0 ||
- strncmp (s+1,"Patch",5) == 0) {
- h->patch = str_dup (s+6);
- len = (int) strlen (h->patch);
- if (h->patch[len-1] == '\n') {
- h->patch[len-1] = '\0';
- }
- }
- }
- if (h->part || h->patch) {
- s = buf2;
- while (*s && *s != '/')
- s++;
- *s = '\0';
- s = buf2;
- h->archive = hash_str (s);
- got_archive = TRUE;
- }
- }
- }
-
- if (! flag || lineno > 25 || got_archive) {
- if (got_subject && got_from && got_date) {
- debug_print_header (h);
- return TRUE;
- } else {
- return FALSE;
- }
- }
- }
- /* NOTREACHED */
- }
-
- /*
- * Write out an index file. Write the group name first so if
- * local indexing is done so we can disambiguate between group
- * name hash collisions by looking at the index file.
- */
-
- void write_index_file (group)
- char *group;
- {
- char nam[LEN];
- FILE *fp;
- int *iptr;
- int realnum;
- register int i;
-
- set_tin_uid_gid();
-
- sprintf (nam, "%s.%d", index_file, process_id);
- if ((fp = fopen (nam, "w")) == NULL) {
- perror_message (txt_cannot_open, nam);
- return;
- }
-
- /*
- * dump group header info.
- */
- if (sort_art_type != SORT_BY_NOTHING) {
- qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
- }
- fprintf (fp, "%s\n", group);
- fprintf (fp, "%d\n", num_of_arts ());
- if (top <= 0) {
- fprintf (fp, "0\n");
- } else {
- if (last_read_article > arts[top-1].artnum) {
- fprintf (fp, "%ld\n", last_read_article);
- } else {
- fprintf (fp, "%ld\n", arts[top-1].artnum);
- }
- }
-
- /*
- * dump articles
- */
- realnum = 0;
- for (i = 0; i < top; i++) {
- if (arts[i].thread == ART_EXPIRED) {
- continue;
- }
- #ifdef DEBUG
- debug_print_header (&arts[i]);
- #endif
- fprintf(fp, "%ld\n", arts[i].artnum);
-
- iptr = (int *) arts[i].subject;
- iptr--;
-
- if (! arts[i].subject) {
- fprintf(fp, " \n");
- } else if (*iptr < 0 || *iptr > top) {
- fprintf(fp, " %s\n", arts[i].subject);
- *iptr = realnum;
- } else if (*iptr == i) {
- fprintf(fp, " %s\n", arts[i].subject);
- } else {
- fprintf(fp, "%%%d\n", *iptr);
- }
-
- iptr = (int *) arts[i].from;
- iptr--;
-
- if (! arts[i].from) {
- fprintf (fp, " \n");
- } else if (*iptr < 0 || *iptr > top) {
- fprintf (fp, " %s\n", arts[i].from);
- *iptr = realnum;
- } else if (*iptr == i) {
- fprintf(fp, " %s\n", arts[i].from);
- } else {
- fprintf(fp, "%%%d\n", *iptr);
- }
-
- iptr = (int *) arts[i].name;
- iptr--;
-
- if (! arts[i].name) {
- fprintf (fp, " \n");
- } else if (*iptr < 0 || *iptr > top) {
- fprintf (fp, " %s\n", arts[i].name);
- *iptr = realnum;
- } else if (*iptr == i) {
- fprintf(fp, " %s\n", arts[i].name);
- } else {
- fprintf(fp, "%%%d\n", *iptr);
- }
-
- fprintf (fp, "%s\n", arts[i].date);
-
- iptr = (int *) arts[i].archive;
- iptr--;
-
- if (! arts[i].archive) {
- fprintf (fp, "\n");
- } else if (*iptr < 0 || *iptr > top) {
- fprintf (fp, " %s\n", arts[i].archive);
- *iptr = realnum;
- } else if (arts[i].part || arts[i].patch) {
- if (*iptr == i) {
- fprintf(fp, " %s\n", arts[i].archive);
- } else {
- fprintf (fp, "%%%d\n", *iptr);
- }
- } else {
- fprintf (fp, "\n");
- }
-
- if (! arts[i].part) {
- fprintf (fp, " \n");
- } else {
- fprintf (fp, "%s\n", arts[i].part);
- }
-
- if (! arts[i].patch) {
- fprintf (fp, " \n");
- } else {
- fprintf (fp, "%s\n", arts[i].patch);
- }
-
- realnum++;
- }
- fclose (fp);
- rename_file (nam, index_file);
- chmod (index_file, 0644);
- set_real_uid_gid();
- if (debug == 2) {
- sprintf (msg, "cp %s INDEX", index_file);
- system (msg);
- }
- }
-
- /*
- * Read in an index file.
- *
- * index file header
- * 1. newsgroup name (ie. alt.sources)
- * 2. number of articles (ie. 26)
- * 3. number of last read article (ie. 210)
- * 4. Is this a complete/killed index file (ie. COMPLETE/KILLED)
- *
- * index file record
- * 1. article number (ie. 183) [mandatory]
- * 2. Subject: line (ie. Which newsreader?) [mandatory]
- * 3. From: line (addr) (ie. iain@norisc) [mandatory]
- * 4. From: line (name) (ie. Iain Lea) [mandatory]
- * 5. Date: of posting (ie. 911231125959) [mandatory]
- * 6. Archive: name (ie. compiler) [optional]
- * 7. Part number of Archive: name (ie. 01) [optional]
- * 8. Patch number of Archive: name (ie. 01) [optional]
- */
-
- int read_index_file (group_name)
- char *group_name;
- {
- int error = 0;
- int i, n;
- char buf[LEN], *p;
- FILE *fp = NULL;
-
- top = 0;
- last_read_article = 0L;
-
- if ((fp = open_index_fp (group_name)) == NULL) {
- return FALSE;
- }
-
- /*
- * load header - discard group name, num. of arts in index file after any arts were killed
- */
- if (fgets(buf, sizeof buf, fp) == NULL ||
- fgets(buf, sizeof buf, fp) == NULL) {
- error = 0;
- goto corrupt_index;
- }
- i = atoi (buf);
-
- /*
- * num. of last_read_article including any that were killed
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 1;
- goto corrupt_index;
- }
- last_read_article = (long) atol (buf);
-
- /*
- * load articles
- */
- for (; top < i ; top++) {
- if (top >= max_art) {
- expand_art ();
- }
-
- arts[top].thread = ART_EXPIRED;
- set_article (&arts[top]);
-
- /*
- * Article no.
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 2;
- goto corrupt_index;
- }
- arts[top].artnum = (long) atol (buf);
-
- /*
- * Subject:
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 3;
- goto corrupt_index;
- }
-
- if (buf[0] == '%') {
- n = atoi (&buf[1]);
- if (n >= top || n < 0) {
- error = 4;
- goto corrupt_index;
- }
- arts[top].subject = arts[n].subject;
- } else if (buf[0] == ' ') {
- for (p = &buf[1]; *p && *p != '\n'; p++)
- continue;
- *p = '\0';
- arts[top].subject = hash_str (&buf[1]);
- } else {
- error = 5;
- goto corrupt_index;
- }
-
- /*
- * From: (addr part)
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 6;
- goto corrupt_index;
- }
-
- if (buf[0] == '%') {
- n = atoi (&buf[1]);
- if (n >= top || n < 0) {
- error = 7;
- goto corrupt_index;
- }
- arts[top].from = arts[n].from;
- } else if (buf[0] == ' ') {
- for (p = &buf[1]; *p && *p != '\n'; p++)
- continue;
- *p = '\0';
- arts[top].from = hash_str (&buf[1]);
- } else {
- error = 8;
- goto corrupt_index;
- }
-
- /*
- * From: (full name)
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 9;
- goto corrupt_index;
- }
-
- if (buf[0] == '%') {
- n = atoi (&buf[1]);
- if (n > top || n < 0) {
- error = 10;
- goto corrupt_index;
- }
- if (n == top) { /* no full name so .name = .from */
- arts[top].name = arts[top].from;
- } else {
- arts[top].name = arts[n].name;
- }
- } else if (buf[0] == ' ') {
- for (p = &buf[1]; *p && *p != '\n'; p++)
- continue;
- *p = '\0';
- arts[top].name = hash_str (&buf[1]);
- } else {
- error = 11;
- goto corrupt_index;
- }
-
- /*
- * Date:
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 12;
- goto corrupt_index;
- }
-
- buf[strlen (buf)-1] = '\0';
- my_strncpy (arts[top].date, buf, 12);
-
- /*
- * Archive-name:
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 13;
- goto corrupt_index;
- }
-
- if (buf[0] == '\n') {
- arts[top].archive = (char *) 0;
- } else if (buf[0] == '%') {
- n = atoi (&buf[1]);
- if (n > top || n < 0) {
- error = 14;
- goto corrupt_index;
- }
- arts[top].archive = arts[n].archive;
- } else if (buf[0] == ' ') {
- for (p = &buf[1]; *p && *p != '\n' ; p++)
- continue;
- *p = '\0';
- arts[top].archive = hash_str (&buf[1]);
- } else {
- error = 15;
- goto corrupt_index;
- }
-
- /*
- * part no.
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 16;
- goto corrupt_index;
- }
-
- if (buf[0] != ' ') {
- buf[strlen (buf)-1] = '\0';
- arts[top].part = str_dup (buf);
- }
-
- /*
- * patch no.
- */
- if (fgets(buf, sizeof buf, fp) == NULL) {
- error = 17;
- goto corrupt_index;
- }
-
- if (buf[0] != ' ') {
- buf[strlen (buf)-1] = '\0';
- arts[top].patch = str_dup (buf);
- }
-
- debug_print_header (&arts[top]);
- }
-
- fclose(fp);
- return TRUE;
-
- corrupt_index:
- if (! update) {
- sprintf (msg, txt_corrupt_index, index_file, error, top);
- error_message (msg, "");
- }
-
- if (debug == 2) {
- sprintf (msg, "cp %s INDEX.BAD", index_file);
- system (msg);
- }
-
- last_read_article = 0L;
- if (fp) {
- fclose(fp);
- }
- set_tin_uid_gid();
- unlink (index_file);
- set_real_uid_gid();
- top = 0;
- return FALSE;
- }
-
-
- /*
- * Look in the local $HOME/RCDIR/INDEXDIR (or wherever) directory for the
- * index file for the given group. Hashing the group name gets
- * a number. See if that #.1 file exists; if so, read first line.
- * Group we want? If no, try #.2. Repeat until no such file or
- * we find an existing file that matches our group.
- */
-
- void find_index_file (group)
- char *group;
- {
- char *p;
- FILE *fp;
- int i = 1;
- static char buf[LEN];
- char dir[PATH_LEN];
- unsigned long h;
-
- h = hash_groupname (group);
-
- if (read_news_via_nntp && xindex_supported) {
- sprintf (index_file, "/tmp/xindex.%d", process_id);
- return;
- }
-
- if (local_index) {
- my_strncpy (dir, indexdir, sizeof (dir));
- } else {
- sprintf (dir, "%s/%s", spooldir, INDEXDIR);
- }
-
- while (TRUE) {
- sprintf (index_file, "%s/%lu.%d", dir, h, i);
-
- if ((fp = fopen (index_file, "r")) == (FILE *) 0) {
- return;
- }
-
- if (fgets (buf, sizeof (buf), fp) == (char *) 0) {
- fclose (fp);
- return;
- }
- fclose (fp);
-
- for (p = buf; *p && *p != '\n'; p++) {
- continue;
- }
- *p = '\0';
-
- if (strcmp (buf, group) == 0) {
- return;
- }
- i++;
- }
- }
-
- /*
- * Run the index file updater only for the groups we've loaded.
- */
-
- void do_update ()
- {
- int i, j;
- char group_path[PATH_LEN];
- char *p;
- long beg_epoch, end_epoch;
-
- if (verbose) {
- time (&beg_epoch);
- }
-
- for (i = 0; i < group_top; i++) {
- my_strncpy (group_path, active[my_group[i]].name, sizeof (group_path));
- for (p = group_path ; *p ; p++) {
- if (*p == '.') {
- *p = '/';
- }
- }
- if (verbose) {
- printf ("%s %s\n", (catchup ? "Catchup" : "Updating"),
- active[my_group[i]].name);
- fflush (stdout);
- }
- index_group (active[my_group[i]].name, group_path);
- if (catchup) {
- for (j = 0; j < top; j++) {
- arts[j].unread = ART_READ;
- }
- update_newsrc (active[my_group[i]].name, my_group[i], FALSE);
- }
- }
-
- if (verbose) {
- time (&end_epoch);
- sprintf (msg, "%s %d groups in %ld seconds\n",
- (catchup ? "Caughtup" : "Updated"), group_top, end_epoch - beg_epoch);
- wait_message (msg);
- }
- }
-
- /*
- * convert date from ctime format to sortable format
- * "24 Jul 91 12:59:59", "Mon, 24 Jul 91 12:59:59" and
- * "Mon, 24 Jul 1991 12:59:59" are parsed and produce
- * output of the form "910724125959"
- */
-
- char *parse_date (date, str)
- char *date;
- char *str;
- {
- char buf[4];
- int i = 0;
-
- /* Check for extraneous day-of-week at start of date */
- while (isalpha(date[i]) || date[i] == ',' || date[i] == ' ') {
- i++;
- }
-
- if (date[i+1] == ' ') { /* ie. "2 Aug..." instead of "12 Aug... */
- str[4] = '0'; /* day */
- str[5] = date[i++];
- i++;
- } else {
- str[4] = date[i++]; /* day */
- str[5] = date[i++];
- i++;
- }
-
- buf[0] = date[i++]; /* month in Jan,Feb,.. form */
- buf[1] = date[i++];
- buf[2] = date[i++];
- buf[3] = '\0';
-
- i++;
-
- str[0] = date[i++]; /* year */
- str[1] = date[i++];
- if (isdigit(date[i])) { /* 19xx format */
- str[0] = date[i++];
- str[1] = date[i++];
- }
-
- i++;
-
- if (strcmp (buf, "Jan") == 0) { /* convert Jan to 01 etc */
- str[2] = '0';
- str[3] = '1';
- } else if (strcmp (buf, "Feb") == 0) {
- str[2] = '0';
- str[3] = '2';
- } else if (strcmp (buf, "Mar") == 0) {
- str[2] = '0';
- str[3] = '3';
- } else if (strcmp (buf, "Apr") == 0) {
- str[2] = '0';
- str[3] = '4';
- } else if (strcmp (buf, "May") == 0) {
- str[2] = '0';
- str[3] = '5';
- } else if (strcmp (buf, "Jun") == 0) {
- str[2] = '0';
- str[3] = '6';
- } else if (strcmp (buf, "Jul") == 0) {
- str[2] = '0';
- str[3] = '7';
- } else if (strcmp (buf, "Aug") == 0) {
- str[2] = '0';
- str[3] = '8';
- } else if (strcmp (buf, "Sep") == 0) {
- str[2] = '0';
- str[3] = '9';
- } else if (strcmp (buf, "Oct") == 0) {
- str[2] = '1';
- str[3] = '0';
- } else if (strcmp (buf, "Nov") == 0) {
- str[2] = '1';
- str[3] = '1';
- } else if (strcmp (buf, "Dec") == 0) {
- str[2] = '1';
- str[3] = '2';
- } else {
- str[2] = '0';
- str[3] = '0';
- }
-
- str[6] = date[i++]; /* hour */
- str[7] = date[i++];
-
- i++;
-
- str[8] = date[i++]; /* minutes */
- str[9] = date[i++];
-
- i++;
-
- str[10] = date[i++]; /* seconds */
- str[11] = date[i++];
-
- str[12] = '\0'; /* terminate string */
-
- return (str);
- }
-
-
- int artnum_comp (p1, p2)
- char *p1;
- char *p2;
- {
- struct article_t *s1 = (struct article_t *) p1;
- struct article_t *s2 = (struct article_t *) p2;
-
- /* s1->artnum less than s2->artnum */
- if (s1->artnum < s2->artnum) {
- return -1;
- }
- /* s1->artnum greater than s2->artnum */
- if (s1->artnum > s2->artnum) {
- return 1;
- }
- return 0;
- }
-
-
- int subj_comp (p1, p2)
- char *p1;
- char *p2;
- {
- struct article_t *s1 = (struct article_t *) p1;
- struct article_t *s2 = (struct article_t *) p2;
-
- /* return result of strcmp (reversed for descending) */
- return (sort_art_type == SORT_BY_SUBJ_ASCEND
- ? my_stricmp (s1->subject, s2->subject)
- : my_stricmp (s2->subject, s1->subject));
- }
-
-
- int from_comp (p1, p2)
- char *p1;
- char *p2;
- {
- struct article_t *s1 = (struct article_t *) p1;
- struct article_t *s2 = (struct article_t *) p2;
-
- /* return result of strcmp (reversed for descending) */
- return (sort_art_type == SORT_BY_FROM_ASCEND
- ? my_stricmp (s1->from, s2->from)
- : my_stricmp (s2->from, s1->from));
- }
-
-
- int date_comp (p1, p2)
- char *p1;
- char *p2;
- {
- struct article_t *s1 = (struct article_t *) p1;
- struct article_t *s2 = (struct article_t *) p2;
- /* return result of strcmp (reversed for descending) */
- return (sort_art_type == SORT_BY_DATE_ASCEND
- ? strcmp (s1->date, s2->date)
- : strcmp (s2->date, s1->date));
- }
-
-
- void set_article (art)
- struct article_t *art;
- {
- art->subject = (char *) 0;
- art->from = (char *) 0;
- art->name = (char *) 0;
- art->date[0] = '\0';
- art->archive = (char *) 0;
- art->part = (char *) 0;
- art->patch = (char *) 0;
- art->unread = ART_UNREAD;
- art->inthread = FALSE;
- art->killed = FALSE;
- art->tagged = FALSE;
- art->hot = FALSE;
- }
-