home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / other / irc / ircd / list2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-14  |  10.5 KB  |  516 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[] = "%W% %G% (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. #ifdef    DBMALLOC
  49. #include "malloc.h"
  50. #endif
  51. void    free_link PROTO((Link *));
  52. Link    *make_link PROTO(());
  53.  
  54. static    struct    liststats {
  55.     int    inuse;
  56.     int    free;
  57. } listc[8];
  58.  
  59. #define    LC_CLOC    0
  60. #define    LC_CREM 1
  61. #define    LC_SERV    2
  62. #define    LC_LINK    3
  63. #define    LC_USER    4
  64. #define    LC_CONF    5
  65. #define    LC_CLAS    6
  66. #define    LC_DBUF    7
  67.  
  68. void    outofmemory();
  69.  
  70. static    aClient    *clofree = NULL;
  71. static    aClient    *crefree = NULL;
  72. static    aClass    *clfree = NULL;
  73. static    aConfItem *cofree = NULL;
  74. static    anUser    *ufree = NULL;
  75. static    Link    *lfree = NULL;
  76. static    aServer    *sfree = NULL;
  77.  
  78. int    numclients = 0;
  79.  
  80. void    initlists()
  81. {
  82.     bzero(listc, sizeof(struct liststats)* 7);
  83. }
  84.  
  85. void    outofmemory()
  86. {
  87.     Debug((DEBUG_FATAL, "Out of memory: restarting server..."));
  88.     restart("Out of Memory");
  89. }
  90.  
  91.     
  92. /*
  93. ** Create a new aClient structure and set it to initial state.
  94. **
  95. **    from == NULL,    create local client (a client connected
  96. **            to a socket).
  97. **
  98. **    from,    create remote client (behind a socket
  99. **            associated with the client defined by
  100. **            'from'). ('from' is a local client!!).
  101. */
  102. aClient    *make_client(from)
  103. aClient    *from;
  104. {
  105.     Reg1    aClient *cptr = NULL;
  106.     Reg2    unsigned size = CLIENT_REMOTE_SIZE;
  107.  
  108.     /*
  109.      * Check freelists first to see if we can grab a client without
  110.      * having to call malloc.
  111.      */
  112.     if (!from)
  113.         {
  114.         size = CLIENT_LOCAL_SIZE;
  115.         if ((cptr = clofree))
  116.             {
  117.             clofree = cptr->next;
  118.             listc[LC_CLOC].free--;
  119.             Debug((DEBUG_LIST, "make_client(%#x) = %#x",
  120.                 from, cptr));
  121.             }
  122.         }
  123.     else if ((cptr = crefree))
  124.         {
  125.             crefree = cptr->next;
  126.             listc[LC_CREM].free--;
  127.             Debug((DEBUG_LIST, "make_client(%#x) = %#x",
  128.                 from, cptr));
  129.         }
  130.  
  131.     if (!cptr)
  132.         {
  133.         if (!(cptr = (aClient *)MyMalloc(size)))
  134.             outofmemory();
  135.         else
  136.             {
  137.             if (size == CLIENT_LOCAL_SIZE)
  138.                 listc[LC_CLOC].inuse++;
  139.             else
  140.                 listc[LC_CREM].inuse++;
  141.             }
  142.         }
  143.  
  144.     bzero((char *)cptr, (int)size);
  145.  
  146.     /* Note:  structure is zero (calloc) */
  147.     cptr->from = from ? from : cptr; /* 'from' of local client is self! */
  148.     cptr->next = NULL; /* For machines with NON-ZERO NULL pointers >;) */
  149.     cptr->prev = NULL;
  150.     cptr->hnext = NULL;
  151.     cptr->user = NULL;
  152.     cptr->serv = NULL;
  153.     cptr->status = STAT_UNKNOWN;
  154.     cptr->fd = -1;
  155.     (void)strcpy(cptr->username, "unknown");
  156.     if (size == CLIENT_LOCAL_SIZE)
  157.         {
  158.         cptr->since = cptr->lasttime = cptr->firsttime = time(NULL);
  159.         cptr->confs = NULL;
  160.         cptr->sockhost[0] = '\0';
  161.         cptr->buffer[0] = '\0';
  162.         cptr->authfd = -1;
  163.         }
  164.     return (cptr);
  165. }
  166.  
  167.  
  168. checksanity()
  169. {
  170.     register aClient *c;
  171.     register anUser    *u;
  172.     register aServer *s;
  173.  
  174.     for (c = client; c; c = c->next)
  175. #ifdef    LIST_DEBUG
  176.         if ((u = c->user) && (u->bcptr != c))
  177.             dumpcore("c %#x u %#x b %#x", c, u, u->bcptr);
  178.         else if ((s = c->serv) && s->bcptr != c)
  179.             dumpcore("c %#x s %#x b %#x", c, s, s->bcptr);
  180.         else
  181. #endif
  182.              if (u && u->refcnt <= 0)
  183.             dumpcore("c %#x u %#x r %d", c, u, u->refcnt);
  184. }
  185.  
  186.  
  187. void    free_client(cptr)
  188. aClient    *cptr;
  189. {
  190.     Debug((DEBUG_LIST, "free_client(%#x) %d", cptr, cptr->fd));
  191.     if (cptr->fd != -1)
  192.         {
  193.         bzero((char *)cptr, CLIENT_LOCAL_SIZE);
  194.         listc[LC_CLOC].free++;
  195.         cptr->next = clofree;
  196.         clofree = cptr;
  197.         }
  198.     else
  199.         {
  200.         bzero((char *)cptr, CLIENT_REMOTE_SIZE);
  201.         listc[LC_CREM].free++;
  202.         cptr->next = crefree;
  203.         crefree = cptr;
  204.         }
  205. }
  206.  
  207. /*
  208. ** 'make_user' add's an User information block to a client
  209. ** if it was not previously allocated.
  210. */
  211. anUser    *make_user(cptr)
  212. aClient *cptr;
  213. {
  214.     Reg1    anUser    *user;
  215.     char    c;
  216.  
  217.     user = cptr->user;
  218.     if (!user)
  219.         if ((user = ufree))
  220.             {
  221.             ufree = user->nextu;
  222.             listc[LC_USER].free--;
  223.             c = '-';
  224.             }
  225.     if (!user)
  226.         {
  227.         user = (anUser *)MyMalloc(sizeof(anUser));
  228.         listc[LC_USER].inuse++;
  229.         c = '=';
  230.         }
  231.     cptr->user = user;
  232.     user->nextu = NULL;
  233.     user->away = NULL;
  234.     user->refcnt = 1;
  235.     user->joined = 0;
  236.     user->channel = NULL;
  237.     user->invited = NULL;
  238.     Debug((DEBUG_LIST, "make_user(%#x) %c %#x %d",
  239.         cptr, c, user, user->refcnt));
  240.     user->bcptr = cptr;
  241.     return user;
  242. }
  243.  
  244. aServer    *make_server(cptr)
  245. aClient    *cptr;
  246. {
  247.     Reg1    aServer    *serv = cptr->serv;
  248.     char    c;
  249.  
  250.     if (!serv)
  251.         if ((serv = sfree))
  252.             {
  253.             sfree = serv->nexts;
  254.             listc[LC_SERV].free--;
  255.             c = '-';
  256.             }
  257.     if (!serv)
  258.         {
  259.         serv = (aServer *)MyMalloc(sizeof(aServer));
  260.         listc[LC_SERV].inuse++;
  261.         c = '=';
  262.         }
  263.     serv->user = NULL;
  264.     serv->nexts = NULL;
  265.     *serv->by = '\0';
  266.     *serv->up = '\0';
  267.     cptr->serv = serv;
  268. #ifdef    LIST_DEBUG
  269.     serv->bcptr = cptr;
  270. #endif
  271.     Debug((DEBUG_LIST, "make_server(%#x) %c %#x",
  272.         cptr, c, serv));
  273.     return cptr->serv;
  274. }
  275.  
  276. /*
  277. ** free_user
  278. **    Decrease user reference count by one and realease block,
  279. **    if count reaches 0
  280. */
  281. void    free_user(user, cptr)
  282. Reg1    anUser    *user;
  283. aClient    *cptr;
  284. {
  285.     if (cptr && user->bcptr && (user->bcptr != cptr))
  286.     {
  287.         dumpcore("user %#x bcptr %#x cptr %#x",
  288.             user, user->bcptr, cptr);
  289.         exit(0);
  290.     }
  291.     user->bcptr = cptr;
  292.     user->refcnt--;
  293.     Debug((DEBUG_LIST, "free_user(%#x,%#x) %d",
  294.         user, cptr, user->refcnt));
  295.     if (user->refcnt <= 0)
  296.         {
  297.         if (user->away)
  298.             (void)MyFree((char *)user->away);
  299.         bzero((char *)user, sizeof(*user));
  300.         user->nextu = ufree;
  301.         ufree = user;
  302.         listc[LC_USER].free++;
  303.         }
  304. }
  305.  
  306. /*
  307.  * taken the code from ExitOneClient() for this and placed it here.
  308.  * - avalon
  309.  */
  310. void    remove_client_from_list(cptr)
  311. Reg1    aClient    *cptr;
  312. {
  313.     checklist();
  314.     if (cptr->prev)
  315.         cptr->prev->next = cptr->next;
  316.     else
  317.         {
  318.         client = cptr->next;
  319.         client->prev = NULL;
  320.         }
  321.     if (cptr->next)
  322.         cptr->next->prev = cptr->prev;
  323.     if (cptr->user)
  324.         {
  325.         add_history(cptr);
  326.         off_history(cptr);
  327.         (void)free_user(cptr->user, cptr);
  328.         }
  329.     if (cptr->serv)
  330.         {
  331.         if (cptr->serv->user)
  332.             free_user(cptr->serv->user, cptr);
  333.         listc[LC_SERV].free++;
  334.         cptr->serv->nexts = sfree;
  335.         cptr->serv->bcptr = NULL;
  336.         sfree = cptr->serv;
  337.         }
  338.     free_client(cptr);
  339.     return;
  340. }
  341.  
  342. /*
  343.  * although only a small routine, it appears in a number of places
  344.  * as a collection of a few lines...functions like this *should* be
  345.  * in this file, shouldnt they ?  after all, this is list.c, isnt it ?
  346.  * -avalon
  347.  */
  348. void    add_client_to_list(cptr)
  349. aClient    *cptr;
  350. {
  351.     /*
  352.      * since we always insert new clients to the top of the list,
  353.      * this should mean the "me" is the bottom most item in the list.
  354.      */
  355.     cptr->next = client;
  356.     client = cptr;
  357.     if (cptr->next)
  358.         cptr->next->prev = cptr;
  359.     return;
  360. }
  361.  
  362. /*
  363.  * Look for ptr in the linked listed pointed to by link.
  364.  */
  365. Link    *find_user_link(lp, ptr)
  366. Reg1    Link    *lp;
  367. Reg2    aClient *ptr;
  368. {
  369.     while (lp && ptr)
  370.        {
  371.         if (lp->value.cptr == ptr)
  372.             return (lp);
  373.         lp = lp->next;
  374.         }
  375.     return NULL;
  376. }
  377.  
  378. Link    *make_link()
  379. {
  380.     Reg1    Link    *lp;
  381.     char    c;
  382.  
  383.     if ((lp = lfree))
  384.         {
  385.         lfree = lp->next;
  386.         listc[LC_LINK].free--;
  387.         c = '-';
  388.         }
  389.     else
  390.         {
  391.         lp = (Link *)MyMalloc(sizeof(Link)*3);
  392.         bzero((char *)lp+1, sizeof(Link)*2);
  393.         lp->next = lp+1;
  394.         lp->next->next = lp+2;
  395.         lp->next->next->next = lfree;
  396.         lfree = lp->next;
  397.         listc[LC_LINK].inuse += 3;
  398.         listc[LC_LINK].free += 2;
  399.         c = '=';
  400.         }
  401.     Debug((DEBUG_LIST, "make_link() %c %#x", c, lp));
  402.     return lp;
  403. }
  404.  
  405. void    free_link(lp)
  406. Reg1    Link    *lp;
  407. {
  408.     bzero((char *)lp, sizeof(*lp));
  409.     lp->next = lfree;
  410.     lfree = lp;
  411.     listc[LC_LINK].free++;
  412.     Debug((DEBUG_LIST, "free_link(%#x)", lp));
  413. }
  414.  
  415.  
  416. aClass    *make_class()
  417. {
  418.     Reg1    aClass    *tmp;
  419.  
  420.     if ((tmp = clfree))
  421.         {
  422.         listc[LC_CLAS].free--;
  423.         clfree = tmp->next;
  424.         Debug((DEBUG_LIST, "make_class() - %#x", tmp));
  425.         }
  426.     else
  427.         {
  428.         tmp = (aClass *)MyMalloc(sizeof(aClass));
  429.         listc[LC_CLAS].inuse++;
  430.         Debug((DEBUG_LIST, "make_class() = %#x", tmp));
  431.         }
  432.     return tmp;
  433. }
  434.  
  435. void    free_class(tmp)
  436. Reg1    aClass    *tmp;
  437. {
  438.     bzero((char *)tmp, sizeof(*tmp));
  439.     tmp->next = clfree;
  440.     clfree = tmp;
  441.     listc[LC_CLAS].free++;
  442.     Debug((DEBUG_LIST, "free_class(%#x)", tmp));
  443. }
  444.  
  445. aConfItem    *make_conf()
  446. {
  447.     Reg1    aConfItem *aconf;
  448.     char    c;
  449.  
  450.     if ((aconf = cofree))
  451.         {
  452.         cofree = aconf->next;
  453.         listc[LC_CONF].free--;
  454.         c = '-';
  455.         }
  456.     else
  457.         {
  458.         aconf = (struct ConfItem *)MyMalloc(sizeof(aConfItem));
  459.         listc[LC_CONF].inuse++;
  460.         c = '=';
  461.         bzero((char *)aconf, sizeof(*aconf));
  462.         }
  463.     aconf->next = NULL;
  464.     aconf->host = aconf->passwd = aconf->name = NULL;
  465.     aconf->status = CONF_ILLEGAL;
  466.     Class(aconf) = 0;
  467.     Debug((DEBUG_LIST, "make_conf() %c %#x",c , aconf));
  468.     return (aconf);
  469. }
  470.  
  471. void    free_conf(aconf)
  472. aConfItem *aconf;
  473. {
  474.     MyFree(aconf->host);
  475.     if (aconf->passwd)
  476.         bzero(aconf->passwd, strlen(aconf->passwd));
  477.     MyFree(aconf->passwd);
  478.     MyFree(aconf->name);
  479.     bzero((char *)aconf, sizeof(*aconf));
  480.     aconf->next = cofree;
  481.     cofree = aconf;
  482.     Debug((DEBUG_LIST, "free_conf(%#x)", aconf));
  483.     listc[LC_CONF].free++;
  484.     return;
  485. }
  486.  
  487. void    send_listinfo(cptr, name)
  488. aClient    *cptr;
  489. char    *name;
  490. {
  491.     static    char    *labels[] = { "Local", "Remote", "Servs", "Links",
  492.                       "Users", "Confs", "Classes", "dbufs" };
  493.     static    int    sizes[] = { CLIENT_LOCAL_SIZE, CLIENT_REMOTE_SIZE,
  494.                     sizeof(aServer), sizeof(Link),
  495.                     sizeof(anUser), sizeof(aConfItem),
  496.                     sizeof(aClass), sizeof(dbufbuf)};
  497.  
  498.     struct    liststats *ls = listc;
  499.     int    inuse = 0, mem = 0, tmp = 0, i;
  500.  
  501.     listc[LC_DBUF].inuse = dbufblocks;
  502.     listc[LC_DBUF].free = dbufblocks - dbufalloc;
  503.     for (i = 0; i < 8; i++, ls++)
  504.         {
  505.         tmp = sizes[i] * ls->inuse;
  506.         sendto_one(cptr, ":%s NOTICE %s :%s: inuse: %d(%d) free: %d",
  507.                me.name, cptr->name,
  508.                labels[i], ls->inuse, tmp, ls->free);
  509.         inuse += ls->inuse;
  510.         mem += tmp;
  511.         }
  512.  
  513.     sendto_one(cptr, ":%s NOTICE %s :Totals: inuse %d %d",
  514.            me.name, name, inuse, mem);
  515. }
  516.