home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / ircd4652.zip / ircd-df-4.6.5-os2 / src / list.c < prev    next >
C/C++ Source or Header  |  1997-12-28  |  12KB  |  560 lines

  1. /************************************************************************
  2.  *   IRC - Internet Relay Chat, ircd/list.c
  3.  *   Copyright (C) 1990 Jarkko Oikarinen and
  4.  *                      University of Oulu, Finland
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation; either version 1, or (at your option)
  9.  *   any later version.
  10.  *
  11.  *   This program is distributed in the hope that it will be useful,
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *   GNU General Public License for more details.
  15.  *
  16.  *   You should have received a copy of the GNU General Public License
  17.  *   along with this program; if not, write to the Free Software
  18.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* -- Jto -- 20 Jun 1990
  22.  * extern void free() fixed as suggested by
  23.  * gruner@informatik.tu-muenchen.de
  24.  */
  25.  
  26. /* -- Jto -- 03 Jun 1990
  27.  * Added chname initialization...
  28.  */
  29.  
  30. /* -- Jto -- 24 May 1990
  31.  * Moved is_full() to channel.c
  32.  */
  33.  
  34. /* -- Jto -- 10 May 1990
  35.  * Added #include <sys.h>
  36.  * Changed memset(xx,0,yy) into bzero(xx,yy)
  37.  */
  38.  
  39. #ifndef lint
  40. static  char sccsid[] = "@(#)list.c    2.24 4/20/94 (C) 1988 University of Oulu, \
  41. Computing Center and Jarkko Oikarinen";
  42. #endif
  43.  
  44. #include "struct.h"
  45. #include "common.h"
  46. #include "sys.h"
  47. #include "h.h"
  48. #include "numeric.h"
  49. #ifdef    DBMALLOC
  50. #include "malloc.h"
  51. #endif
  52. void    free_link PROTO((Link *));
  53. Link    *make_link PROTO(());
  54.  
  55. #ifdef    DEBUGMODE
  56. static    struct    liststats {
  57.     int    inuse;
  58. } cloc, crem, users, servs, links, classs, aconfs;
  59.  
  60. #endif
  61.  
  62. void    outofmemory();
  63.  
  64. int    flinks = 0;
  65. Link    *freelink = NULL;
  66.  
  67. int    numclients = 0;
  68.  
  69. void    initlists()
  70. {
  71. #ifdef    DEBUGMODE
  72.     bzero((char *)&cloc, sizeof(cloc));
  73.     bzero((char *)&crem, sizeof(crem));
  74.     bzero((char *)&users, sizeof(users));
  75.     bzero((char *)&servs, sizeof(servs));
  76.     bzero((char *)&links, sizeof(links));
  77.     bzero((char *)&classs, sizeof(classs));
  78.     bzero((char *)&aconfs, sizeof(aconfs));
  79. #endif
  80. }
  81.  
  82. void    outofmemory()
  83. {
  84.     Debug((DEBUG_FATAL, "Out of memory: restarting server..."));
  85.     restart("Out of Memory");
  86. }
  87.  
  88.     
  89. /*
  90. ** Create a new aClient structure and set it to initial state.
  91. **
  92. **    from == NULL,    create local client (a client connected
  93. **            to a socket).
  94. **
  95. **    from,    create remote client (behind a socket
  96. **            associated with the client defined by
  97. **            'from'). ('from' is a local client!!).
  98. */
  99. aClient    *make_client(from, servr)
  100. aClient    *from, *servr;
  101. {
  102.     Reg1    aClient *cptr = NULL;
  103.     Reg2    unsigned size = CLIENT_REMOTE_SIZE;
  104.  
  105.     /*
  106.      * Check freelists first to see if we can grab a client without
  107.      * having to call malloc.
  108.      */
  109.     if (!from)
  110.         size = CLIENT_LOCAL_SIZE;
  111.  
  112.     if (!(cptr = (aClient *)MyMalloc(size)))
  113.         outofmemory();
  114.     bzero((char *)cptr, (int)size);
  115.  
  116. #ifdef    DEBUGMODE
  117.     if (size == CLIENT_LOCAL_SIZE)
  118.         cloc.inuse++;
  119.     else
  120.         crem.inuse++;
  121. #endif
  122.  
  123.     /* Note:  structure is zero (calloc) */
  124.     cptr->from = from ? from : cptr; /* 'from' of local client is self! */
  125.     cptr->next = NULL; /* For machines with NON-ZERO NULL pointers >;) */
  126.     cptr->prev = NULL;
  127.     cptr->hnext = NULL;
  128.     cptr->user = NULL;
  129.     cptr->serv = NULL;
  130.     cptr->srvptr = servr;
  131.     cptr->status = STAT_UNKNOWN;
  132.     cptr->fd = -1;
  133.     (void)strcpy(cptr->username, "unknown");
  134.     if (size == CLIENT_LOCAL_SIZE)
  135.         {
  136.         cptr->since = cptr->lasttime =
  137.           cptr->lastnick = cptr->firsttime = time(NULL);
  138.         cptr->confs = NULL;
  139.         cptr->sockhost[0] = '\0';
  140.         cptr->buffer[0] = '\0';
  141.         cptr->authfd = -1;
  142.         }
  143.     return (cptr);
  144. }
  145.  
  146. void    free_client(cptr)
  147. aClient    *cptr;
  148. {
  149.     MyFree((char *)cptr);
  150. }
  151.  
  152. /*
  153. ** 'make_user' add's an User information block to a client
  154. ** if it was not previously allocated.
  155. */
  156. anUser    *make_user(cptr)
  157. aClient *cptr;
  158. {
  159.     Reg1    anUser    *user;
  160.  
  161.     user = cptr->user;
  162.     if (!user)
  163.         {
  164.         user = (anUser *)MyMalloc(sizeof(anUser));
  165. #ifdef    DEBUGMODE
  166.         users.inuse++;
  167. #endif
  168.         user->away = NULL;
  169.         user->refcnt = 1;
  170.         user->joined = 0;
  171.         user->channel = NULL;
  172.         user->invited = NULL;
  173.         user->silence = NULL;
  174.         cptr->user = user;
  175.         }
  176.     return user;
  177. }
  178.  
  179. aServer    *make_server(cptr)
  180. aClient    *cptr;
  181. {
  182.     Reg1    aServer    *serv = cptr->serv;
  183.  
  184.     if (!serv)
  185.         {
  186.         serv = (aServer *)MyMalloc(sizeof(aServer));
  187. #ifdef    DEBUGMODE
  188.         servs.inuse++;
  189. #endif
  190.         serv->user = NULL;
  191.         serv->nexts = NULL;
  192.         *serv->by = '\0';
  193.         *serv->up = '\0';
  194.         cptr->serv = serv;
  195.         }
  196.     return cptr->serv;
  197. }
  198.  
  199. /*
  200. ** free_user
  201. **    Decrease user reference count by one and realease block,
  202. **    if count reaches 0
  203. */
  204. void    free_user(user, cptr)
  205. Reg1    anUser    *user;
  206. aClient    *cptr;
  207. {
  208.     if (--user->refcnt <= 0)
  209.         {
  210.         if (user->away)
  211.             MyFree((char *)user->away);
  212.         /*
  213.          * sanity check
  214.          */
  215.         if (user->joined || user->refcnt < 0 ||
  216.             user->invited || user->channel)
  217. #ifdef DEBUGMODE
  218.             dumpcore("%#x user (%s!%s@%s) %#x %#x %#x %d %d",
  219.                 cptr, cptr ? cptr->name : "<noname>",
  220.                 user->username, user->host, user,
  221.                 user->invited, user->channel, user->joined,
  222.                 user->refcnt);
  223. #else
  224.             sendto_ops("* %#x user (%s!%s@%s) %#x %#x %#x %d %d *",
  225.                 cptr, cptr ? cptr->name : "<noname>",
  226.                 user->username, user->host, user,
  227.                 user->invited, user->channel, user->joined,
  228.                 user->refcnt);
  229. #endif
  230.         MyFree((char *)user);
  231. #ifdef    DEBUGMODE
  232.         users.inuse--;
  233. #endif
  234.         }
  235. }
  236.  
  237. /*
  238.  * taken the code from ExitOneClient() for this and placed it here.
  239.  * - avalon
  240.  */
  241. void    remove_client_from_list(cptr)
  242. Reg1    aClient    *cptr;
  243. {
  244.     checklist();
  245.     if (cptr->prev)
  246.         cptr->prev->next = cptr->next;
  247.     else
  248.         {
  249.         client = cptr->next;
  250.         client->prev = NULL;
  251.         }
  252.     if (cptr->next)
  253.         cptr->next->prev = cptr->prev;
  254.     if (IsPerson(cptr)) /* Only persons can have been added before */
  255.         {
  256.         add_history(cptr);
  257.         off_history(cptr); /* Remove all pointers to cptr */
  258.         }
  259.     if (cptr->user)
  260.         (void)free_user(cptr->user, cptr);
  261.     if (cptr->serv)
  262.         {
  263.         if (cptr->serv->user)
  264.             free_user(cptr->serv->user, cptr);
  265.         MyFree((char *)cptr->serv);
  266. #ifdef    DEBUGMODE
  267.         servs.inuse--;
  268. #endif
  269.         }
  270. #ifdef    DEBUGMODE
  271.     if (cptr->fd == -2)
  272.         cloc.inuse--;
  273.     else
  274.         crem.inuse--;
  275. #endif
  276.     (void)free_client(cptr);
  277.     numclients--;
  278.     return;
  279. }
  280.  
  281. /*
  282.  * although only a small routine, it appears in a number of places
  283.  * as a collection of a few lines...functions like this *should* be
  284.  * in this file, shouldnt they ?  after all, this is list.c, isnt it ?
  285.  * -avalon
  286.  */
  287. void    add_client_to_list(cptr)
  288. aClient    *cptr;
  289. {
  290.     /*
  291.      * since we always insert new clients to the top of the list,
  292.      * this should mean the "me" is the bottom most item in the list.
  293.      */
  294.     cptr->next = client;
  295.     client = cptr;
  296.     if (cptr->next)
  297.         cptr->next->prev = cptr;
  298.     return;
  299. }
  300.  
  301. /*
  302.  * Look for ptr in the linked listed pointed to by link.
  303.  */
  304. Link    *find_user_link(lp, ptr)
  305. Reg1    Link    *lp;
  306. Reg2    aClient *ptr;
  307. {
  308.   if (ptr)
  309.     while (lp)
  310.        {
  311.         if (lp->value.cptr == ptr)
  312.             return (lp);
  313.         lp = lp->next;
  314.         }
  315.     return NULL;
  316. }
  317.  
  318. /*
  319.  * Look for a match in a list of strings. Go through the list, and run
  320.  * match() on it. Side effect: if found, this link is moved to the top of
  321.  * the list.
  322.  */
  323. int    find_str_match_link(lp, str)
  324. Reg1    Link    **lp; /* Two **'s, since we might modify the original *lp */
  325. Reg2    char    *str;
  326. {
  327.     Link    *ptr, **head = lp;
  328.  
  329.     if (lp && *lp)
  330.     {
  331.         if (!match((*lp)->value.cp, str))
  332.             return 1;
  333.         for (; (*lp)->next; *lp = (*lp)->next)
  334.             if (!match((*lp)->next->value.cp, str))
  335.             {
  336.                 Link *temp = (*lp)->next;
  337.                 *lp = (*lp)->next->next;
  338.                 temp->next = *head;
  339.                 *head = temp;
  340.                 return 1;
  341.             }
  342.         return 0;
  343.     }
  344.     return 0;
  345. }
  346.  
  347. void    free_str_list(lp)
  348. Reg1    Link    *lp;
  349. {
  350.     Reg2    Link    *next;
  351.  
  352.  
  353.     while (lp) {
  354.         next = lp->next;
  355.         MyFree((char *)lp->value.cp);
  356.         free_link(lp);
  357.         lp = next;
  358.     }
  359.         
  360.     return;
  361. }
  362.  
  363.  
  364. #define    LINKSIZE    (4072/sizeof(Link))
  365.  
  366. Link    *make_link()
  367. {
  368.     Link    *lp;
  369.     int    i;
  370.  
  371.     /* "caching" slab-allocator... ie. we're allocating one pages
  372.        (hopefully - upped to the Linux default, not dbuf.c) worth of 
  373.        link-structures at time to avoid all the malloc overhead.
  374.        All links left free from this process or separately freed 
  375.        by a call to free_link() are moved over to freelink-list.
  376.        Impact? Let's see... -Donwulff */
  377.     if(freelink==NULL) {
  378.         lp = (Link *)MyMalloc(LINKSIZE*sizeof(Link));
  379.         freelink=lp+1;
  380.         flinks+=LINKSIZE;
  381.         for(i=1;i<(LINKSIZE-1);i++)
  382.             (lp+i)->next=lp+i+1; (lp+i)->next=NULL;
  383.     } else {
  384.         lp = freelink;
  385.         freelink=freelink->next;
  386.     }
  387. #ifdef    DEBUGMODE
  388.     links.inuse++;
  389. #endif
  390.     return lp;
  391. }
  392.  
  393. void    free_link(lp)
  394. Reg1    Link    *lp;
  395. {
  396.     lp->next=freelink;
  397.     freelink=lp;
  398. #ifdef    DEBUGMODE
  399.     links.inuse--;
  400. #endif
  401. }
  402.  
  403. Ban    *make_ban()
  404. {
  405.     Reg1    Ban    *lp;
  406.  
  407.     lp = (Ban *)MyMalloc(sizeof(Ban));
  408. #ifdef    DEBUGMODE
  409.     links.inuse++;
  410. #endif
  411.     return lp;
  412. }
  413.  
  414. void    free_ban(lp)
  415. Reg1    Ban    *lp;
  416. {
  417.     MyFree((char *)lp);
  418. #ifdef    DEBUGMODE
  419.     links.inuse--;
  420. #endif
  421. }
  422.  
  423. aClass    *make_class()
  424. {
  425.     Reg1    aClass    *tmp;
  426.  
  427.     tmp = (aClass *)MyMalloc(sizeof(aClass));
  428. #ifdef    DEBUGMODE
  429.     classs.inuse++;
  430. #endif
  431.     return tmp;
  432. }
  433.  
  434. void    free_class(tmp)
  435. Reg1    aClass    *tmp;
  436. {
  437.     MyFree((char *)tmp);
  438. #ifdef    DEBUGMODE
  439.     classs.inuse--;
  440. #endif
  441. }
  442.  
  443. aSqlineItem    *make_sqline()
  444. {
  445.     Reg1    aSqlineItem *asqline;
  446.  
  447.     asqline = (struct SqlineItem *)MyMalloc(sizeof(aSqlineItem));
  448.     asqline->next = NULL;
  449.     asqline->sqline = asqline->reason = NULL;
  450.  
  451.     return (asqline);
  452. }
  453.  
  454. aConfItem    *make_conf()
  455. {
  456.     Reg1    aConfItem *aconf;
  457.  
  458.     aconf = (struct ConfItem *)MyMalloc(sizeof(aConfItem));
  459. #ifdef    DEBUGMODE
  460.     aconfs.inuse++;
  461. #endif
  462.     bzero((char *)&aconf->ipnum, sizeof(struct in_addr));
  463.     aconf->next = NULL;
  464.     aconf->host = aconf->passwd = aconf->name = NULL;
  465.     aconf->status = CONF_ILLEGAL;
  466.     aconf->clients = 0;
  467.     aconf->port = 0;
  468.     aconf->hold = 0;
  469.     Class(aconf) = 0;
  470.     return (aconf);
  471. }
  472.  
  473. void    delist_conf(aconf)
  474. aConfItem    *aconf;
  475. {
  476.     if (aconf == conf)
  477.         conf = conf->next;
  478.     else
  479.         {
  480.         aConfItem    *bconf;
  481.  
  482.         for (bconf = conf; aconf != bconf->next; bconf = bconf->next)
  483.             ;
  484.         bconf->next = aconf->next;
  485.         }
  486.     aconf->next = NULL;
  487. }
  488.  
  489. void    free_sqline(asqline)
  490. aSqlineItem *asqline;
  491. {
  492.     del_queries((char *)asqline);
  493.     MyFree(asqline->sqline);
  494.     MyFree(asqline->reason);
  495.     MyFree((char *)asqline);
  496.     return;
  497. }
  498.  
  499. void    free_conf(aconf)
  500. aConfItem *aconf;
  501. {
  502.     del_queries((char *)aconf);
  503.     MyFree(aconf->host);
  504.     if (aconf->passwd)
  505.         bzero(aconf->passwd, strlen(aconf->passwd));
  506.     MyFree(aconf->passwd);
  507.     MyFree(aconf->name);
  508.     MyFree((char *)aconf);
  509. #ifdef    DEBUGMODE
  510.     aconfs.inuse--;
  511. #endif
  512.     return;
  513. }
  514.  
  515. #ifdef    DEBUGMODE
  516. void    send_listinfo(cptr, name)
  517. aClient    *cptr;
  518. char    *name;
  519. {
  520.     int    inuse = 0, mem = 0, tmp = 0;
  521.  
  522.     sendto_one(cptr, ":%s %d %s :Local: inuse: %d(%d)",
  523.            me.name, RPL_STATSDEBUG, name, inuse += cloc.inuse,
  524.            tmp = cloc.inuse * CLIENT_LOCAL_SIZE);
  525.     mem += tmp;
  526.     sendto_one(cptr, ":%s %d %s :Remote: inuse: %d(%d)",
  527.            me.name, RPL_STATSDEBUG, name,
  528.            crem.inuse, tmp = crem.inuse * CLIENT_REMOTE_SIZE);
  529.     mem += tmp;
  530.     inuse += crem.inuse;
  531.     sendto_one(cptr, ":%s %d %s :Users: inuse: %d(%d)",
  532.            me.name, RPL_STATSDEBUG, name, users.inuse,
  533.            tmp = users.inuse * sizeof(anUser));
  534.     mem += tmp;
  535.     inuse += users.inuse,
  536.     sendto_one(cptr, ":%s %d %s :Servs: inuse: %d(%d)",
  537.            me.name, RPL_STATSDEBUG, name, servs.inuse,
  538.            tmp = servs.inuse * sizeof(aServer));
  539.     mem += tmp;
  540.     inuse += servs.inuse,
  541.     sendto_one(cptr, ":%s %d %s :Links: inuse: %d(%d)",
  542.            me.name, RPL_STATSDEBUG, name, links.inuse,
  543.            tmp = links.inuse * sizeof(Link));
  544.     mem += tmp;
  545.     inuse += links.inuse,
  546.     sendto_one(cptr, ":%s %d %s :Classes: inuse: %d(%d)",
  547.            me.name, RPL_STATSDEBUG, name, classs.inuse,
  548.            tmp = classs.inuse * sizeof(aClass));
  549.     mem += tmp;
  550.     inuse += classs.inuse,
  551.     sendto_one(cptr, ":%s %d %s :Confs: inuse: %d(%d)",
  552.            me.name, RPL_STATSDEBUG, name, aconfs.inuse,
  553.            tmp = aconfs.inuse * sizeof(aConfItem));
  554.     mem += tmp;
  555.     inuse += aconfs.inuse,
  556.     sendto_one(cptr, ":%s %d %s :Totals: inuse %d %d",
  557.            me.name, RPL_STATSDEBUG, name, inuse, mem);
  558. }
  559. #endif
  560.