home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / thread / active.c next >
Encoding:
C/C++ Source or Header  |  1993-12-12  |  20.8 KB  |  812 lines

  1. /*
  2.     SNEWS 1.0
  3.  
  4.     active.c - routines to manipulate the active and ng files
  5.  
  6.  
  7.     Copyright (C) 1991  John McCombs, Christchurch, NEW ZEALAND
  8.                         john@ahuriri.gen.nz
  9.                         PO Box 2708, Christchurch, NEW ZEALAND
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License, version 1, as
  13.     published by the Free Software Foundation.
  14.  
  15.     This program is distributed in the hope that it will be useful,
  16.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.     GNU General Public License for more details.
  19.  
  20.     See the file COPYING, which contains a copy of the GNU General
  21.     Public License.
  22. */
  23.  
  24.  
  25. #include "defs.h"
  26. #include "active.h"
  27.  
  28. extern INFO my_stuff;
  29.  
  30.  
  31. /*
  32.  *  These private variables are used to do all the i/o on the active
  33.  *  file.
  34.  */
  35. static FILE        *active_file;
  36. static ACTIVE      *local_head;
  37. static POST_GROUPS *pg;
  38.  
  39.  
  40. /*--------------------------- load the active file --------------------------*/
  41. ACTIVE *load_active_file(void)
  42. {
  43.     /*
  44.      *  This routine opens the active file.  It reads the data, allocating
  45.      *  ACTIVE elements in a linked list.  Returns a pointer to the head of
  46.      *  the linked list.
  47.      */
  48.     char   fn[80], buf[81];
  49.     char   *p;
  50.     ACTIVE *this, *head = NULL ;
  51.     long   posn = 0;
  52.     int    ct = 0;
  53.     int    ct_gp = 0;
  54.  
  55.     /* open the file */
  56.     strcpy(fn, my_stuff.news_dir);
  57.     strcat(fn, "active");
  58.     if ((active_file = fopen(fn, "r+b")) == NULL) {
  59.         fprintf(errf, "cannot open %s\n", fn);
  60.         exit(1);
  61.     }
  62.  
  63.     /* read and store */
  64.     while (fgets(buf, 80, active_file) != NULL) {
  65.  
  66.         /* exit on ^Z on column 1 */
  67.         if (buf[0] == '\x1A')
  68.             break;
  69.  
  70.         ct++;
  71.  
  72.         if (strlen(buf) > 0) {
  73.  
  74.             if (head == NULL) {
  75.                 head = this = xmalloc(sizeof (ACTIVE));
  76.                 head->last = NULL;
  77.                 head->index = ct_gp;
  78.             } else {
  79.                 ct_gp++;
  80.                 this->next = xmalloc(sizeof (ACTIVE));
  81.                 this->next->last = this;
  82.                 this = this->next;
  83.                 this->index = ct_gp;
  84.             }
  85.  
  86.             if ((this) == NULL) {
  87.                 fprintf(errf, "cannot allocate memory for active list\n");
  88.                 exit(1);
  89.             }
  90.  
  91.  
  92.             if ((p = strtok(buf, " ")) == NULL) {
  93.                 fprintf(errf, "active file corrupt at line %d\n", ct);
  94.                 exit(1);
  95.             }
  96.             strcpy(this->group, p);
  97.  
  98.             if ((p = strtok(NULL, " ")) == NULL) {
  99.                 fprintf(errf, "active file corrupt at line %d\n", ct);
  100.                 exit(1);
  101.             }
  102.             strcpy(this->gp_file, p);
  103.  
  104.             if ((p = strtok(NULL, " ")) == NULL) {
  105.                 fprintf(errf, "active file corrupt at line %d\n", ct);
  106.                 exit(1);
  107.             }
  108.             this->lo_num = atol(p);
  109.  
  110.             if ((p = strtok(NULL, " ")) == NULL) {
  111.                 fprintf(errf, "active file corrupt at line %d\n", ct);
  112.                 exit(1);
  113.             }
  114.             this->hi_num = atol(p);
  115.  
  116.             this->num_pos = posn;
  117.             this->read_list = NULL;
  118.         }
  119.  
  120.         posn = ftell(active_file);
  121.     }
  122.  
  123.     this->next = NULL;
  124.  
  125.     local_head = head;
  126.  
  127.     /* load up the posting list */
  128.     pg = post_group_file();
  129.  
  130.     return(head);
  131. }
  132.  
  133.  
  134.  
  135.  
  136. /*------------------------- close the active file ---------------------------*/
  137. void close_active_file(void)
  138. {
  139.     /*
  140.      *  Close the active file and deallocate the linked list
  141.      */
  142.  
  143.     ACTIVE *this;
  144.  
  145.     this = local_head;
  146.  
  147.     while (this != NULL) {
  148.         local_head = this;
  149.         this = this->next;
  150.         free(local_head);
  151.     }
  152.  
  153.     fclose(active_file);
  154.  
  155.     free_ng();
  156.  
  157. }
  158.  
  159.  
  160. /*------------------------- close the active file ---------------------------*/
  161. void close_active(void)
  162. {
  163.     /*
  164.      *  Close the active file
  165.      */
  166.  
  167.  
  168.     fclose(active_file);
  169.  
  170. }
  171.  
  172.  
  173.  
  174. /*--------------------------- load the newsgroups file --------------------------*/
  175. POST_GROUPS *post_group_file(void)
  176. {
  177.     /*
  178.      *  This routine opens the active file.  It reads the data, allocating
  179.      *  POST_GROUPS elements in a linked list.  Returns a pointer to the head
  180.      *  of the linked list.
  181.      */
  182.     char        fn[80], buf[81], *p;
  183.     POST_GROUPS *this, *head = NULL ;
  184.     int         ct = 0;
  185.     FILE        *ngf;
  186.  
  187.     /* open the file - if none, retun null, ie no posts allowed */
  188.     strcpy(fn, my_stuff.news_dir);
  189.     strcat(fn, "ng");
  190.     if ((ngf = fopen(fn, "rb")) == NULL) {
  191.         return(NULL);
  192.     }
  193.  
  194.     /* read and store */
  195.     while (fgets(buf, 80, ngf) != NULL) {
  196.  
  197.         /* exit on ^Z on column 1 */
  198.         if (buf[0] == '\x1A')
  199.             break;
  200.  
  201.         ct++;
  202.  
  203.         if (strlen(buf) > 0) {
  204.  
  205.             if (head == NULL) {
  206.                 head = this = xmalloc(sizeof (ACTIVE));
  207.             } else {
  208.                 this->next = xmalloc(sizeof (ACTIVE));
  209.                 this = this->next;
  210.             }
  211.  
  212.             if ((this) == NULL) {
  213.                 fprintf(errf, "cannot allocate memory for newsgroup list\n");
  214.                 exit(1);
  215.             }
  216.  
  217.  
  218.             if ((p = strtok(buf, " \n\r\t")) == NULL) {
  219.                 fprintf(errf, "newsgroup 'ng' file corrupt at line %d\n", ct);
  220.                 exit(1);
  221.             }
  222.  
  223.             strcpy(this->group, p);
  224.         }
  225.  
  226.     }
  227.  
  228.     this->next = NULL;
  229.  
  230.     fclose(ngf);
  231.  
  232.     return(head);
  233. }
  234.  
  235.  
  236.  
  237.  
  238. /*------------------------- close the active file ---------------------------*/
  239. void free_ng()
  240. {
  241.     /*
  242.      *  deallocate the post_groups linked list
  243.      */
  244.  
  245.     POST_GROUPS *this;
  246.  
  247.     this = pg;
  248.  
  249.     while (this != NULL) {
  250.         pg = this;
  251.         this = this->next;
  252.         free(pg);
  253.     }
  254.  
  255.     pg = NULL;
  256.  
  257. }
  258.  
  259.  
  260.  
  261.  
  262. /*------------------------- check group in post list -------------------------*/
  263. int check_valid_post_group(char *ng)
  264. {
  265.     /*
  266.      *  Check a string as a valid newsgroup name.  Returns TRUE if found
  267.      */
  268.  
  269.     POST_GROUPS *this;
  270.  
  271.     this = pg;
  272.  
  273.     while (this != NULL) {
  274.         if (strcmp(ng, this->group) == 0)
  275.             return(TRUE);
  276.         this = this->next;
  277.     }
  278.  
  279.     return (FALSE);
  280. }
  281.  
  282.  
  283.  
  284.  
  285. /*-------------------- find a newsgroup in active list ----------------------*/
  286. ACTIVE *find_news_group(char *group)
  287. {
  288.     /*
  289.      *  This routine searches the active structure for the specified
  290.      *  newsgroup, and returns a pointer to the entry, or to group
  291.      *  junk if not found.  The search for junk is made via a recursive
  292.      *  call.  Fatal if junk not found
  293.      */
  294.  
  295.     ACTIVE *this;
  296.  
  297.     this = local_head;
  298.  
  299.     while ((this != NULL) && (stricmp(group, this->group) != 0)) {
  300.         this = this->next;
  301.     }
  302.  
  303.     if (this == NULL) {
  304.         if (stricmp(group, "junk") != 0) {
  305.             this = find_news_group("junk");
  306.         } else {
  307.             fprintf(errf, "active file must have newsgroup junk\n");
  308.             exit(1);
  309.         }
  310.     }
  311.  
  312.     return(this);
  313.  
  314. }
  315.  
  316.  
  317.  
  318.  
  319. /*-------------------------- update active file ---------------------------*/
  320. void update_active_entry(ACTIVE *a)
  321. {
  322.     /*
  323.      *  This routine takes a pointer to an active entry and updates
  324.      *  its data on disk
  325.      */
  326.  
  327.     char buf[(ACTIVE_NUM_LEN*2) + 2];
  328.     int  n;
  329.     long where;
  330.  
  331.     sprintf(buf, "%08ld %08ld", a->lo_num, a->hi_num);
  332.  
  333.     n = (ACTIVE_NUM_LEN*2) + 1;
  334.     where = a->num_pos + strlen(a->group) + 1 + strlen(a->gp_file) + 1;
  335.     fseek(active_file, where, SEEK_SET);
  336.     if (fwrite(buf, 1, n, active_file) != n) {
  337.         fprintf(errf, "active file update failed for %s\n", a->group);
  338.         exit(1);
  339.     }
  340.  
  341.     fflush(active_file);
  342. }
  343.  
  344.  
  345.  
  346.  
  347.  
  348. /*------------------- make newsgroup name and directory --------------------*/
  349. char *make_news_group_name(char *ng)
  350. {
  351.     /*
  352.      *  This routine takes the newsgroup name, replaces the '.' with
  353.      *  '\' and creates the directory if none exists.  The returned name
  354.      *  has a trailing '\'
  355.      */
  356.  
  357.     static char fn[512];
  358.     ACTIVE *tmp;
  359.  
  360.  
  361.     tmp = find_news_group(ng);
  362.  
  363.     sprintf(fn, "%snewsbase\\%s", my_stuff.news_dir, tmp->gp_file);
  364.  
  365.     return(&fn[0]);
  366. }
  367.  
  368.  
  369.  
  370.  
  371.  
  372. /*-------------------------- save the seen list -------------------------*/
  373. void load_read_list(void)
  374. {
  375.     /*
  376.      *  Load the user's list of seen articles
  377.      */
  378.  
  379.     FILE   *tmp_file;
  380.     ACTIVE *act;
  381.     int    i, continue_flag;
  382.     int    articles;
  383.     char   *a, buf[256], *p, real_name[80];
  384.  
  385.     /* allocate the arrays and set to unread, ie FALSE */
  386.     act = local_head;
  387.     while (act != NULL) {
  388.  
  389.         articles = (int)(act->hi_num - act->lo_num);
  390.         if (articles > 0) {
  391.             a = act->read_list = xmalloc(articles * sizeof(int));
  392.             for (i = 0; i < articles; i++) {
  393.                 *(a+i) = FALSE;
  394.             }
  395.         } else {
  396.             act->read_list = NULL;
  397.         }
  398.         act = act->next;
  399.     }
  400.  
  401.     /* read and process the file - if not present, just carry on */
  402.     strcpy(buf, my_stuff.news_dir);
  403.     strcat(buf, my_stuff.user);
  404.     strcat(buf, ".nrc");
  405.     if ((tmp_file = fopen(buf, "r")) != NULL) {
  406.  
  407.         continue_flag = FALSE;
  408.         while (fgets(buf, 255, tmp_file) != NULL) {
  409.  
  410.             p = strtok(buf, " \n\r");
  411.  
  412.             if (!continue_flag) {
  413.  
  414.                 strcpy(real_name, p);
  415.                 act = find_news_group(p);
  416.                 articles = (int)(act->hi_num - act->lo_num);
  417.  
  418.                 /* if no articles or unknown group eat the rest */
  419.                 p = strtok(NULL, " \n\r");
  420.  
  421.             }
  422.  
  423.             /* scan the rest of the line getting numbers and setting flags */
  424.             continue_flag = FALSE;
  425.             while (p != NULL) {
  426.  
  427.                 /* check for continuation backslash */
  428.                 if (*p != '\\') {
  429.                     i = (int) (atol(p) - (act->lo_num + 1));
  430.                     if ((i >= 0) && (i < articles) &&
  431.                     ((stricmp(act->group, "junk") != 0) ||
  432.                     (stricmp(real_name, "junk") == 0))) {
  433.                         *((act->read_list)+i) = TRUE;
  434.                     }
  435.                 } else {
  436.                     continue_flag = TRUE;
  437.                     break;
  438.                 }
  439.                 p = strtok(NULL, " \n\r");
  440.             }
  441.         }
  442.  
  443.         fclose(tmp_file);
  444.     }
  445. }
  446.  
  447.  
  448.  
  449.  
  450.  
  451. /*-------------------------- load the seen list -------------------------*/
  452. void save_read_list(void)
  453. {
  454.     /*
  455.      *  Save the user's list of read articles and deallocate storage
  456.      */
  457.  
  458.  
  459.     FILE   *tmp_file;
  460.     ACTIVE *act;
  461.     int    i, articles, ct;
  462.     char   buf[256];
  463.  
  464.     /* open the file */
  465.     strcpy(buf, my_stuff.news_dir);
  466.     strcat(buf, my_stuff.user);
  467.     strcat(buf, ".nrc");
  468.     if ((tmp_file = fopen(buf, "w")) == NULL) {
  469.         fprintf(errf, "can't open user's rc file for output\n");
  470.         exit(1);
  471.     }
  472.  
  473.     /* write out the lists and deallocate the arrays */
  474.     act = local_head;
  475.     while (act != NULL) {
  476.  
  477.         articles = (int)(act->hi_num - act->lo_num);
  478.         if (articles > 0) {
  479.             fprintf(tmp_file, "%s ", act->group);
  480.  
  481.             ct = 0;
  482.  
  483.             for (i = 0; i < articles; i++) {
  484.                 if(*((act->read_list)+i)) {
  485.                     ct++;
  486.                     fprintf(tmp_file, "%d ", i+act->lo_num+1);
  487.                     if ((ct % 10) == 0)
  488.                         fprintf(tmp_file, "\\ \n");
  489.                 }
  490.             }
  491.  
  492.             fprintf(tmp_file, "\n");
  493.             if (act->read_list != NULL) {
  494.                 free(act->read_list);
  495.             }
  496.         }
  497.         act = act->next;
  498.     }
  499.  
  500.     fclose(tmp_file);
  501.  
  502. }
  503.  
  504. /* required keywords table
  505.    bmask is the identifying bit for a
  506.    particular function.  This allows
  507.    synonyms to be defined */
  508. static const struct {
  509.    char         *pstr;   /* required keyword string */
  510.    unsigned int  fldoff; /* offset of target field in my_stuff */
  511.    unsigned int  bmask;  /* ident bit */
  512.    unsigned char attr;   /* processing attribute */
  513.    #define  VANILLA  '\0'
  514.    #define  PATHSLASH '\x01'
  515.    #define  UNBATCHD  '\x02'
  516.    #define  ALLTOKS   '\x03'
  517.    }  reqparm [] = {
  518.       { "mailserv", offsetof(INFO, mail_server), 0x80000000, VANILLA },
  519.       { "nodename", offsetof(INFO,my_site), 0x40000000, VANILLA },
  520.       { "newsdir", offsetof(INFO,incoming_dir), 0x20000000, PATHSLASH },
  521.       { "domain", offsetof(INFO,my_domain), 0x10000000, VANILLA },
  522.       { "tempdir", offsetof(INFO,temp_name), 0x08000000, UNBATCHD },
  523.       { "mailbox", offsetof(INFO,user), 0x04000000, VANILLA },
  524.       { "Signature", offsetof(INFO,signature), 0x02000000, VANILLA },
  525.       { "name", offsetof(INFO,my_name), 0x01000000, ALLTOKS },
  526.       { "Organization", offsetof(INFO,my_organisation), 0x00800000, ALLTOKS },
  527.       { "Editor", offsetof(INFO,editor), 0x00400000, ALLTOKS },
  528.       { "32BITOS2.Editor", offsetof(INFO,editor), 0x00400000, ALLTOKS },
  529.       { "Home", offsetof(INFO,home), 0x00200000, PATHSLASH },
  530.       { "Aliases", offsetof(INFO,my_alias), 0x00100000, VANILLA }
  531.    };
  532. #define NKEYWD  (sizeof(reqparm) / sizeof(reqparm[0]))
  533.  
  534. /*------------------------- load UUPC rc files ---------------------------*/
  535. int load_stuff( char **errfld, char **errmsg )
  536. {
  537.     /*
  538.      *  Trawl the UUPC files to get the stuff we need - return TRUE
  539.      *  if completed ok
  540.      */
  541.  
  542.     int  i;
  543.     char buf[256];
  544.     char *fn, *p, *v, *cp;
  545.     FILE *tmp;
  546.  
  547.     unsigned long kwmask = 0;  /* keyword-present bits */
  548.  
  549.  
  550.     /* news base directory */
  551.     if ((fn = getenv("UUPCNEWS")) == NULL) {
  552.         fprintf(errf, "UUPCNEWS environment variable undefined\n");
  553.         exit(1);
  554.     }
  555.  
  556.     /* give it a trailing \ */
  557.     strcpy(my_stuff.news_dir, fn);
  558.     if (my_stuff.news_dir[ strlen(my_stuff.news_dir)-1 ] != '\\')
  559.         strcat(my_stuff.news_dir, "\\");
  560.  
  561.  
  562.  
  563.     /* read the system file first */
  564.     for (i = 0; i < 2; i++) {
  565.  
  566.         /* choose the file to open */
  567.         if (i == 0) {
  568.             fn = getenv("UUPCSYSRC");
  569.             if (fn == NULL) {
  570.                 fprintf(errf, "Enviroment variable UUPCSYSRC not defined\n");
  571.             }
  572.         } else {
  573.             fn = getenv("UUPCUSRRC");
  574.             if (fn == NULL) {
  575.                 fprintf(errf, "Enviroment variable UUPCUSRRC not defined\n");
  576.             }
  577.         }
  578.  
  579.  
  580.         if ((tmp = fopen(fn, "r")) != NULL) {
  581.  
  582.             while (fgets(buf, 255, tmp)) {
  583.                 p = strtok(buf, " =\r\n");
  584.                 if ( (p != NULL) && (*p != '#') ) {
  585.                     unsigned pix;
  586.                     unsigned tmask;
  587.  
  588.                     v = strtok(NULL, " =\r\n");
  589.  
  590.                     for ( pix = 0; pix < NKEYWD; pix++ )
  591.                         {
  592.                         if (stricmp(p, reqparm[pix].pstr) == 0) {
  593.                            /* process a keyword */
  594.                            tmask = reqparm[pix].bmask;
  595.                            if ( tmask & kwmask ) /* duplicate */
  596.                               {
  597.                               *errfld = reqparm[pix].pstr;
  598.                               *errmsg = "Duplicate keyword %s\n";
  599.                               return FALSE;
  600.                               }
  601.                            kwmask |= tmask;
  602.                            /* copy string to target field */
  603.                            cp = (char *)&my_stuff;
  604.                            cp += reqparm[pix].fldoff;
  605.                            strcpy( cp, v);
  606.  
  607.                            /* attribute processing */
  608.                            switch ( reqparm[pix].attr )
  609.                              {
  610.                              case VANILLA:  break;  /* we were done */
  611.                              case PATHSLASH: { /* add backslash to end if needed */
  612.                                if ( cp[ strlen(cp) - 1] != '\\' )
  613.                                   strcat( cp, "\\" );
  614.                                break;
  615.                                }
  616.                              case UNBATCHD: { /* the temp unbatch dir */
  617.                                strcat( cp, "\\$unbatch" );
  618.                                break;
  619.                                }
  620.                              case ALLTOKS:  { /* get all value tokens */
  621.                                v = strtok(NULL, " =\r\n");
  622.                                while (v != NULL) {
  623.                                    strcat( cp, " ");
  624.                                    strcat( cp, v);
  625.                                    v = strtok(NULL, " =\r\n");
  626.                                    }
  627.                                }
  628.  
  629.                              }  /* end of attr switch */
  630.                            break;
  631.                            }  /* end of keyword compare if */
  632.                         } /* end of for pix */
  633.                     /* unknown keyword will be ignored */
  634.  
  635.                 }
  636.             }
  637.             fclose (tmp);
  638.  
  639.         } else {
  640.             fprintf(errf, "Cannot open %s\n", fn);
  641.         }
  642.     }
  643.  
  644.     if ( kwmask == 0xFFF00000 )
  645.        return TRUE;
  646.     for ( i = 0; i < NKEYWD; i++ )
  647.         {
  648.         if ( ! ( kwmask & reqparm[i].bmask ) )
  649.            { /* non-specified bit */
  650.            *errfld = reqparm[i].pstr;
  651.            *errmsg = "Keyword %s not specified\n";
  652.            return FALSE;
  653.            }
  654.         }
  655.     /* should HALT here */
  656.     *errfld = "";
  657.     *errmsg = "Unknown RC error\n";
  658.     return FALSE;
  659. }
  660.  
  661.  
  662.  
  663. /*--------------------------- unpack the batch ------------------------*/
  664. FILE *open_out_file(char *ng)
  665. {
  666.     /*
  667.      *  This routine creates a filename from the newsgroup name.
  668.      *  The active file counter are updated.
  669.      */
  670.  
  671.     ACTIVE *gp;
  672.     char   *fn;
  673.     FILE   *tmp;
  674.  
  675.     gp = find_news_group(ng);
  676.     fn = make_news_group_name(gp->group);
  677.  
  678.     (gp->hi_num)++;
  679.     update_active_entry(gp);
  680.  
  681.     if ((tmp = fopen(fn, "r+b")) == NULL) {
  682.         fprintf(errf,"active: cannot open text file %s\n", fn);
  683.         exit(1);
  684.     }
  685.     fseek(tmp, 0, SEEK_END);
  686.  
  687.     return(tmp);
  688.  
  689.  
  690. }
  691.  
  692.  
  693. /*--------------------------- unpack the batch ------------------------*/
  694. FILE *open_index_file(char *ng)
  695. {
  696.     /*
  697.      *  This routine open the index file for the newsgroup
  698.      */
  699.  
  700.     ACTIVE *gp;
  701.     char   fnx[256], *fn;
  702.     FILE   *tmp;
  703.  
  704.     /* printf("news: ng found = %s\n", ng); */
  705.     gp = find_news_group(ng);
  706.     fn = make_news_group_name(gp->group);
  707.     sprintf(fnx, "%s.IDX", fn);
  708.  
  709.     if((tmp = fopen(fnx, "r+b")) == NULL) {
  710.         fprintf(errf, "active: cannot open index file %s\n", fn);
  711.         exit(1);
  712.     }
  713.     fseek(tmp, 0, SEEK_END);
  714.  
  715.     return(tmp);
  716.  
  717. }
  718.  
  719.  
  720.  
  721. /*------------------------- post sequence number ----------------------------*/
  722. int post_sequence(void)
  723. {
  724.     /*
  725.      *  Get the sequnce number from the seq file if it exists - if
  726.      *  not create it
  727.      */
  728.  
  729.     FILE *seq_file;
  730.     char fn[256];
  731.     int  seq;
  732.  
  733.     strcpy(fn, my_stuff.news_dir);
  734.     strcat(fn, "nseq");
  735.  
  736.     if ((seq_file = fopen(fn, "r+")) != NULL) {
  737.         fscanf(seq_file, "%d", &seq);
  738.         seq++;
  739.         rewind(seq_file);
  740.     } else {
  741.         seq = 0;
  742.         seq_file = fopen(fn, "w");
  743.     }
  744.  
  745.     fprintf(seq_file, "%d", seq);
  746.  
  747.     fclose(seq_file);
  748.     return(seq);
  749. }
  750.  
  751.  
  752. /*-------------------------------- safeish malloc --------------------------*/
  753. void *xmalloc(size_t size)
  754. {
  755.     void *p;
  756.     if ((p = malloc(size)) == NULL) {
  757.         exit(1);
  758.     }
  759.  
  760.     return(p);
  761. }
  762.  
  763.  
  764. ALII  *load_alias_file( void )
  765. {
  766.   FILE *  afile;
  767.   ALII   *wp, *pp;
  768.   char    buf[256], cpy[256];
  769.   char   *cp;
  770.   int     nicklen;
  771.  
  772.   szalias = 0;
  773.   pp = NULL;
  774.   if ((afile = fopen(my_stuff.my_alias, "r")) != NULL)
  775.        {
  776.        while (fgets(buf, 255, afile))
  777.              {
  778.              if ( ( strlen( buf ) > 3 ) && ( buf[0] != '#' ) )
  779.                 {
  780.                 wp = (ALII *)xmalloc( sizeof(ALII) );
  781.  
  782.                 strcpy( cpy, buf );
  783.                 strcpy( wp->nick, strtok( cpy, " " ) );
  784.                 nicklen = strlen( wp->nick );
  785.                 if ( nicklen > szalias )  szalias = nicklen;
  786.  
  787.                 strcpy( cpy, buf );
  788.                 cp = strchr( cpy, '"' );
  789.                 if ( cp )
  790.                    {
  791.                    strcpy( wp->name, strtok( cp, "\"" ) );
  792.                    strcpy( cpy, buf );
  793.                    cp = strchr( cpy, '<' );
  794.                    if ( cp )
  795.                       strcpy( wp->addr, strtok( cp, "<>" ) );
  796.                    else
  797.                       wp->addr[0] = '\0';
  798.                    }
  799.                 else
  800.                    wp->name[0] = '\0';
  801.  
  802.                 wp->nextp = pp;  pp = wp;
  803.                 }
  804.              }
  805.  
  806.        }
  807.  
  808.   fclose( afile );
  809.   return pp;
  810.  
  811. }
  812.