source: trunk/athena/bin/olc/server/olcd/data_utils.c @ 2074

Revision 2074, 25.5 KB checked in by tjcoppet, 35 years ago (diff)
Line 
1/*
2 * This file is part of the OLC On-Line Consulting System.
3 * It contains functions for manipulating OLC data structures.
4 *
5 *      Win Treese
6 *      Dan Morgan
7 *      Bill Saphir
8 *      MIT Project Athena
9 *
10 *      Ken Raeburn
11 *      MIT Information Systems
12 *
13 *      Tom Coppeto
14 *      MIT Project Athena
15 *
16 *      Copyright (c) 1988 by the Massachusetts Institute of Technology
17 *
18 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/olc/server/olcd/data_utils.c,v $
19 *      $Author: tjcoppet $
20 */
21
22#ifndef lint
23static char rcsid[]= "$Header: /afs/dev.mit.edu/source/repository/athena/bin/olc/server/olcd/data_utils.c,v 1.3 1989-08-22 14:02:02 tjcoppet Exp $";
24#endif
25
26
27#include <olc/olc.h>
28#include <olcd.h>
29
30#include <ctype.h>
31#include <sys/types.h>   
32#include <sys/time.h>
33
34extern PROC         Proc_List[];
35
36/* Contents:
37 *
38 *           create_user()
39 *           create_knuckle()
40 *           insert_knuckle()
41 *           insert_knuckle_in_user()
42 *           insert_topic()
43 *           delete_user()
44 *           delete_knuckle()
45 *           init_user()
46 *           init_question()
47 *           get_knuckle()
48 *           find_knuckle()
49 *           assign_instance()
50 *           connect_knuckles()
51 *           match_maker()
52 *           new_message()
53 *           get_status_info()
54 *           verify_topic()
55 *           is_specialty()
56 */
57
58
59
60/*
61 * Function:    create_user()
62 * Arguments:   REQUEST *request:       The request from olc.
63 * Returns:     A pointer to the first knuckle structure, or NULL if an error
64 *              occurs
65 * Notes:
66 *     First, allocate memory space for a new user structure and zero it
67 *     out.  Then create a knuckle which inserts the knuckle into the user
68 *     structure and into the Knuckle List.
69 *     Next order of business is to load info from the database, like
70 *     acls, specialties and such.
71 */
72
73KNUCKLE *
74create_user(person)
75     PERSON *person;
76{
77  KNUCKLE *knuckle;           /* Ptr. to new user struct. */
78  USER *user;                 /* Ptr. to another new struct */
79
80  /*
81   * create user
82   */
83
84  if((user = (USER *) malloc(sizeof(USER))) == (USER *) NULL)
85    {
86      log_error("create_user: out of memory");
87      return((KNUCKLE *) NULL);
88    }
89  bzero((char *) user, sizeof(USER));
90
91  user->knuckles = (KNUCKLE **) NULL;
92
93  /*
94   * create knuckle
95   */
96
97  if ((knuckle = create_knuckle(user)) == (KNUCKLE *) NULL)
98    {
99      log_error("add_user: could not create knuckle");
100      return((KNUCKLE *) NULL);
101    }
102
103
104
105  /*
106   * allocate and get db info
107   */
108
109  init_user(knuckle,person);
110
111#ifdef TEST
112  printf("create_user: %s (%d) \n",
113         knuckle->user->username, knuckle->instance);
114#endif TEST
115
116
117  return(knuckle);
118}
119
120
121
122
123
124
125/*
126 * Function:    create_knuckle()
127 * Arguments:   USER *user   
128 * Returns:     A pointer to the newknuckle structure, or NULL if an error
129 *              occurs
130 * Notes:
131 *     First, allocate memory space for a new knuckle structure and zero it
132 *     out.  Hook up the knuckle with the user and assign it an instance id.
133 *     Initialize the connected and question pointers.
134 */
135
136KNUCKLE *
137create_knuckle(user)
138     USER *user;
139{
140  KNUCKLE *k, **k_ptr;
141
142  /*
143   * first let's see if we already have one
144   */
145
146  if(user->knuckles != (KNUCKLE **) NULL)
147    for (k_ptr = user->knuckles; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
148      if(!is_active((*k_ptr)))
149        return((*k_ptr));
150
151  /*
152   * Make room for daddy
153   */
154
155  k = (KNUCKLE *) malloc(sizeof(KNUCKLE));
156  if(k == (KNUCKLE *) NULL)
157    {
158      log_error("create_knuckle: out of memory");
159      return((KNUCKLE *) NULL);
160    } 
161  bzero((char *) k, sizeof(KNUCKLE));
162
163  /*
164   * insert knuckle in Knuckle List
165   */
166
167  if (insert_knuckle(k) != SUCCESS)
168    {
169      free((char *) k);
170      return((KNUCKLE *) NULL);
171    }
172
173  /*
174   * initialize knuckle and insert in User Knuckle List
175   */
176
177  k->user = user;
178  k->instance = assign_instance(user);
179
180  if(insert_knuckle_in_user(k,user) != SUCCESS)
181    {
182      free((char *) k);
183      return((KNUCKLE *) NULL);
184    }
185
186  k->user->no_knuckles++;
187  k->question = (QUESTION *) NULL;
188  k->connected = (KNUCKLE *)  NULL;
189  k->status = 0;
190  strcpy(k->title,k->user->title2);
191
192#ifdef TEST
193  printf("create_knuckle: %s (%d)\n",user->username, k->instance);
194#endif TEST
195
196  return(k);
197}
198 
199
200
201
202/*
203 * Function:    insert_knuckle()
204 * Arguments:   KNUCKLE *knuckle:       Knuckle to be inserted.
205 * Returns:     Zero on success, non-zero otherwise.
206 * Notes:       
207 *          Inserts a knuckle to the Knuckle List.
208 */
209
210insert_knuckle(knuckle)
211     KNUCKLE *knuckle;
212{
213  KNUCKLE **k_ptr;
214  int n_knuckles=0;
215  int n_inactive=0;
216  static struct timeval time;
217
218  /*
219   * Start off knuckle list
220   */
221 
222  if (Knuckle_List == (KNUCKLE **) NULL)
223    {
224      Knuckle_List = (KNUCKLE **) malloc(sizeof(KNUCKLE *));
225      if (Knuckle_List == (KNUCKLE **) NULL)
226        {
227          perror("malloc(insert_knuckle)");
228          return(ERROR);
229        }
230      *Knuckle_List = (KNUCKLE *) NULL;
231    }
232 
233
234  /*
235   * How many do we have, really
236   */
237
238
239  for (k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
240    {
241      ++n_knuckles;
242      if(!is_active((*k_ptr)))
243        ++n_inactive;
244    }
245
246  if(n_inactive < MAX_CACHE_SIZE)
247    {
248      n_knuckles++;
249     
250      /*
251       * reallocate Knuckle List and add new knuckle
252       */
253     
254      Knuckle_List = (KNUCKLE **) realloc((char *) Knuckle_List, (unsigned)
255                                          (n_knuckles+1) * sizeof(KNUCKLE *));
256      Knuckle_List[n_knuckles]   = (KNUCKLE *) NULL;
257      Knuckle_List[n_knuckles-1] = knuckle;
258      return(SUCCESS);
259    }
260  else
261    {
262      for(k_ptr = Knuckle_List;*k_ptr != (KNUCKLE *) NULL; k_ptr++)
263        {
264          if(!is_active((*k_ptr)))
265            {
266              delete_knuckle((*k_ptr),1);
267              Knuckle_List[n_knuckles-1] = knuckle;
268              Knuckle_List[n_knuckles]   = (KNUCKLE *) NULL;
269              return(SUCCESS);
270            }
271        }
272    }
273  return(ERROR);
274}
275
276
277
278/*
279 * Function:    insert_knuckle_in_user()
280 * Arguments:   KNUCKLE *knuckle:       Knuckle to be inserted.
281 * Returns:     Zero on success, non-zero otherwise.
282 * Notes:       
283 *          Inserts a knuckle to the User list.
284 */
285
286insert_knuckle_in_user(knuckle, user)
287     KNUCKLE *knuckle;
288     USER *user;
289{
290  int n_knuckles;
291
292  /*
293   * Allocate first knuckle, if needed
294   */
295
296  if (user->knuckles == (KNUCKLE **) NULL)
297    {
298      user->knuckles = (KNUCKLE **) malloc(sizeof(KNUCKLE *));
299      if (user->knuckles == (KNUCKLE **) NULL)
300        {
301          perror("malloc(insert_knuckle)");
302          return(ERROR);
303        }
304      *(user->knuckles) = (KNUCKLE *) NULL;
305    }
306
307  /*
308   * count knuckles
309   */
310
311  for (n_knuckles = 0; user->knuckles[n_knuckles] !=
312       (KNUCKLE *) NULL; n_knuckles++);
313   
314  n_knuckles++;
315
316  /*
317   * reallocate user kncukle list and insert knuckle
318   */
319
320  user->knuckles = (KNUCKLE **) realloc((char *) user->knuckles, (unsigned)
321                                      ((n_knuckles+1) * sizeof(KNUCKLE *)));
322  user->knuckles[n_knuckles]   = (KNUCKLE *) NULL;
323  user->knuckles[n_knuckles-1] = knuckle;
324  return(SUCCESS);
325}
326
327
328
329
330/*
331 * Function:    insert_topic()
332 * Arguments:   TOPIC *t   Topic structure
333 * Returns:     Zero on success, non-zero otherwise.
334 * Notes:       
335 *          Inserts a Topic into the Topic List. The Topic List is useful
336 *          to cache topic information so we donb't have to keep scanning
337 *          the database. The List manipulation is the same.
338 */
339
340insert_topic(t)
341     TOPIC *t;
342{
343  int n_topics;
344 
345  /*
346   * Allocate first Topic
347   */
348
349  if (Topic_List == (TOPIC **) NULL)
350    {
351      Topic_List = (TOPIC **) malloc(sizeof(TOPIC *));
352      if (Topic_List == (TOPIC **) NULL)
353        {
354          perror("malloc(insert_topic)");
355          return(1); /* I'll get back to this */
356        }
357      *Topic_List = (TOPIC *) NULL;
358    }
359 
360  /*
361   * count topics
362   */
363
364  for (n_topics = 0; Topic_List[n_topics] !=
365       (TOPIC *) NULL; n_topics++);
366   
367  n_topics++;
368
369  /*
370   * reallocate Topic List and insert new topic
371   */
372
373  Topic_List = (TOPIC **) realloc((char *) Topic_List, (unsigned)
374                                      ((n_topics+1) * sizeof(TOPIC *)));
375  Topic_List[n_topics]   = (TOPIC *) NULL;
376  Topic_List[n_topics-1] = t;
377  return(SUCCESS);
378}
379
380   
381
382/*
383 * Function:    delete_user()
384 * Arguments:   USER *user:     Ptr. to user structure to be deleted.
385 * Returns:     Nothing.
386 * Notes:
387 *        Delete every knuckle in the user list. Delete_knuckle() will
388 *        take care of the user structure.   
389 */
390
391void
392delete_user(user)
393     USER *user;
394{
395  KNUCKLE *k;
396  int i;
397 
398  k = *(user->knuckles);
399
400  for(i=0; i< user->no_knuckles; i++)
401    delete_knuckle((k+i),0);
402}
403
404
405/*
406 * Function:    delete_knuckle() removes a knuckle from the Knuckle List.
407 * Arguments:   KNUCKLE *knuckle:      Ptr. to user structure to be deleted.
408 * Returns:     Nothing.
409 * Notes:
410 *      Find the entry that matches the Knuckle, and copy the last entry
411 *      in the list into that slot.  (This is a no-op if the user is at
412 *      the end of the list.)  Then put a NULL into the last slot, and
413 *      free the KNUCKLE structure. The user is deleted if it is the last
414 *      knuckle in the User List.
415 */
416
417void
418delete_knuckle(knuckle,cont)
419     KNUCKLE *knuckle;
420     int cont;
421{
422  int n_knuckles, knuckle_idx;
423  char msgbuf[BUFSIZ];
424  KNUCKLE **k_ptr;
425  int i;
426
427  /* maintain continuity in the master knuckle list */
428  /* linked lists anybody? */
429
430  for (n_knuckles=0; Knuckle_List[n_knuckles] != (KNUCKLE *)NULL; n_knuckles++)
431    if (Knuckle_List[n_knuckles] == knuckle)
432      knuckle_idx = n_knuckles;
433
434  Knuckle_List[knuckle_idx]  = Knuckle_List[n_knuckles-1];
435  Knuckle_List[n_knuckles-1] = (KNUCKLE *) NULL;
436
437  if(!cont)
438    Knuckle_List = (KNUCKLE **) realloc(Knuckle_List,
439                                        sizeof(KNUCKLE *) * (n_knuckles-1));
440     
441
442  /* maintain continuity in the user knuckle list */
443  k_ptr = knuckle->user->knuckles;
444  for(i=0;i<knuckle->user->no_knuckles;i++)
445    if(knuckle == *(k_ptr+i))
446      break;
447 
448  *(k_ptr+i) = *(k_ptr+(knuckle->user->no_knuckles-1));
449  *(k_ptr+(knuckle->user->no_knuckles-1)) = (KNUCKLE *) NULL;
450 
451
452  /* delete user if last knuckle */
453  if(knuckle->user->no_knuckles == 1)
454    free((char *) knuckle->user);
455  else
456    knuckle->user->no_knuckles -= 1;
457
458  /* free question */
459  if(knuckle->question != (QUESTION *) NULL)
460    free((char *) knuckle->question);
461     
462  /* free new messages */
463  if(knuckle->new_messages !=  (char *) NULL)
464    free((char *) knuckle->new_messages);
465     
466  /* log it */
467  (void) sprintf(msgbuf, "Deleting knuckle %s (%d)",
468          knuckle->user->username, knuckle->instance);
469  log_status(msgbuf);
470
471  /* free it */
472  free((char *)knuckle);
473}
474
475
476deactivate_knuckle(knuckle)
477     KNUCKLE *knuckle;
478{
479  if(knuckle->instance > 0)
480    delete_knuckle(knuckle);
481  else
482    knuckle->status = 0;
483 
484  return(SUCCESS);
485}
486
487
488void
489init_user(knuckle,person)
490     KNUCKLE *knuckle;
491     PERSON *person;
492{
493
494  (void) strncpy(knuckle->user->realname,person->realname, NAME_LENGTH);
495  (void) strncpy(knuckle->user->username,person->username, LOGIN_SIZE);
496  (void) strncpy(knuckle->user->machine,person->machine,NAME_LENGTH);
497  (void) strncpy(knuckle->user->realm,person->realm,REALM_SZ);
498  (void) strcpy(knuckle->user->title1, DEFAULT_TITLE);
499  (void) strcpy(knuckle->user->title2, DEFAULT_TITLE2);
500  knuckle->user->max_ask = 1;
501  knuckle->user->max_answer = 2;
502  knuckle->status = 0;
503  knuckle->user->specialties[0] = UNKNOWN_TOPIC;
504  load_user(knuckle->user);
505  (void) strcpy(knuckle->title,knuckle->user->title1);
506}
507
508
509
510init_question(k,topic,text)
511     KNUCKLE *k;
512     char *topic;
513     char *text;
514{
515  k->question = (QUESTION *) malloc(sizeof(QUESTION));
516  if(k->question == (QUESTION *) NULL)
517    {
518      perror("init_question");
519      return(ERROR);
520    }
521
522  k->question->owner = k;
523  k->queue = ACTIVE_Q;
524  k->question->nseen = 0;
525  k->question->note[0] = '\0';
526  k->question->comment[0] = '\0';
527  k->question->topic_code = verify_topic(topic);
528  (void) strcpy(k->title,k->user->title1);
529  (void) strcpy(k->question->topic,topic);
530  init_log(k,text);
531 
532  return(SUCCESS);
533}
534
535
536/*
537 * Function:    get_knuckle() finds a k  structure in the ring given an id.
538 * Arguments:   id: id of desired node
539 * Returns:     A pointer to the desired user, or NULL if the user is not
540 *              in the ring.
541 * Notes:
542 *      Loop through the user ring, comparing the name with the ids of
543 *      nodes in the ring.  If a match is found, return a pointer to the
544 *      appropriate user structure.  Otherwise, return NULL. Only the number
545 *      of characters to uniquely define the name is necessary.
546 */
547
548int
549get_knuckle(name,instance,knuckle)
550     char *name;
551     int instance;
552     KNUCKLE **knuckle;
553{
554  KNUCKLE **k_ptr; 
555  int status = 0;
556
557#ifdef TEST
558  printf("get_knuckle: %s %d...\n",name,instance);
559#endif TEST
560
561  if (Knuckle_List == (KNUCKLE **) NULL)
562    return(EMPTY_LIST);
563 
564  for (k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
565    if(string_eq((*k_ptr)->user->username,name))
566      {
567
568#ifdef TEST
569        printf("get_knuckle: matched on %s (%d)\n",
570               (*k_ptr)->user->username,
571               (*k_ptr)->instance);
572#endif TEST
573
574        if(((*k_ptr)->instance == instance) && !(!is_active((*k_ptr)) &&
575                                                 (*k_ptr)->instance > 0))
576          {
577            *knuckle = *k_ptr;
578            return(SUCCESS);
579          }
580
581        status=1;
582      }
583
584#ifdef TEST
585  printf("get_knuckle: matched on %s, incomplete instance %d\n",name,status);
586#endif TEST
587
588  if(status)
589    return(INSTANCE_NOT_FOUND);
590
591#ifdef TEST
592  printf("get_knuckle: no match for %s\n",name);
593#endif TEST
594
595  return(USER_NOT_FOUND);
596}       
597
598
599int
600match_knuckle(name,instance,knuckle)
601     char *name;
602     int instance;
603     KNUCKLE **knuckle;
604{
605  KNUCKLE **k_ptr,*store_ptr;
606  int status;
607
608  status = get_knuckle(name,instance,knuckle);
609  if(status != USER_NOT_FOUND)
610    return(status);
611
612  status = 0;
613  store_ptr = (KNUCKLE *) NULL;
614
615#ifdef TEST
616  printf("get_knuckle: %s %d...\n",name,instance);
617#endif TEST
618
619  if (Knuckle_List == (KNUCKLE **) NULL)
620    return(EMPTY_LIST);
621 
622  for (k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
623    if(string_equiv(name,(*k_ptr)->user->username,strlen(name)) &&
624       is_active((*k_ptr)))
625      {
626
627#ifdef TEST
628        printf("match_knuckle: matched on %s (%d)\n",
629               (*k_ptr)->user->username,
630               (*k_ptr)->instance);
631#endif TEST
632
633        if((*k_ptr)->instance == instance)
634          {
635            if(store_ptr != (KNUCKLE *) NULL)
636              {
637                if(store_ptr->instance == (*k_ptr)->instance)
638                  return(NAME_NOT_UNIQUE);
639              }
640            else
641              store_ptr = *k_ptr;
642          }
643        else
644          status=1;
645      }
646
647  if(store_ptr != (KNUCKLE *) NULL)
648    {
649      *knuckle = store_ptr;
650      return(SUCCESS);
651    }
652
653#ifdef TEST
654  printf("match_knuckle: matched on %s, incomplete instance %d\n",name,status);
655#endif TEST
656
657  if(status)
658    return(INSTANCE_NOT_FOUND);
659
660#ifdef TEST
661  printf("get_knuckle: no match for %s\n",name);
662#endif TEST
663
664  return(USER_NOT_FOUND);
665}       
666
667
668int
669find_knuckle(person,knuckle)
670     PERSON *person;
671     KNUCKLE **knuckle;
672{
673  int status;
674
675  status = get_knuckle(person->username, person->instance,knuckle);
676  if(status == USER_NOT_FOUND || status == EMPTY_LIST)
677    {
678      *knuckle = create_user(person);
679      if(*knuckle != (KNUCKLE *) NULL)
680        {
681          (*knuckle)->user->status = ACTIVE;
682          return(SUCCESS);
683        }
684      else
685        return(ERROR);
686    }
687  else
688    if(status == SUCCESS)
689      {
690        strcpy((*knuckle)->user->machine,person->machine);
691        (*knuckle)->user->status = ACTIVE;
692      }
693
694  return(status);
695}
696 
697
698get_instance(user,instance)
699     char *user;
700     int *instance;
701{
702  KNUCKLE **k_ptr;
703  KNUCKLE *k_save = (KNUCKLE *) NULL;
704
705  for (k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
706    if(string_eq(user,(*k_ptr)->user->username) &&
707      is_active((*k_ptr)))
708      {
709        if(k_save != (KNUCKLE *) NULL)
710          {
711            if(((*k_ptr)->instance < k_save->instance))
712            k_save = *k_ptr;
713          }
714        else
715          k_save = *k_ptr;
716      }
717
718  if(k_save != (KNUCKLE *) NULL)
719    *instance = k_save->instance;
720  else
721    *instance = 0;
722 
723  return(SUCCESS);
724}
725
726
727verify_instance(knuckle,instance)
728     KNUCKLE *knuckle;
729     int instance;
730{
731  KNUCKLE **k;
732  int i;
733
734  if(instance == 0)
735    return(SUCCESS);
736
737  k = knuckle->user->knuckles;
738   
739  for(i=0; i<= knuckle->user->no_knuckles; i++)
740    if(((*(k+i))->instance == instance) && is_active((*(k+i))))
741      return(SUCCESS);
742  return(FAILURE);
743}
744     
745int
746assign_instance(user)
747     USER *user;
748{
749  KNUCKLE **k;
750  int match;
751  int i,j;
752
753  k = user->knuckles;
754 
755  for(i=0; i<= user->no_knuckles; i++)
756    {
757      match = 0;
758      for(j=0; j < user->no_knuckles; j++)
759        {
760          if( (*(k+j))->instance == i)
761            {
762
763#ifdef TEST
764              printf("assign_instance: match on %d, no = %d\n",i,
765                     user->no_knuckles);
766#endif TEST
767
768              match = 1;
769              break;
770            }
771        }
772      if(!match)
773        return(i);
774    }
775  return(ERROR);
776}
777
778/*
779 * Function:    connect_users() connects a user and a user.
780 * Arguments:   a:              User to be connected.
781 *              b:              User to be connected.
782 * Returns:     Nothing.
783 * Notes:
784 */
785
786connect_knuckles(a,b)
787     KNUCKLE *a, *b;
788{
789  char msg[BUFSIZ];
790
791  if(is_connected(a) || is_connected(b))
792    {
793      log_error("connect: users already connected");
794      return(FAILURE);
795    }
796
797  if(a->question == (QUESTION *) NULL)
798    {
799      if(b->question == (QUESTION *) NULL)
800        {
801          log_error("connect: connectee has no question");
802          return(ERROR);
803        }
804      a->question = b->question;
805      strcpy(a->title,a->user->title2);
806      strcpy(b->title,b->user->title1);
807    }
808  else
809    {
810      if(b->question != (QUESTION *) NULL)
811        {
812          log_error("connect: connectee already has question");
813          return(ERROR);
814        }
815      b->question = a->question;
816      strcpy(a->title,a->user->title1);
817      strcpy(b->title,b->user->title2);
818    }
819 
820  a->connected = b;
821  (void) strcpy(a->cusername,b->user->username);
822  a->cinstance = b->instance;
823  b->connected = a;
824  (void) strcpy(b->cusername,a->user->username);
825  b->cinstance = a->instance;
826
827  (void) sprintf(msg,"You are connected to %s %s.\n",
828          a->title, a->user->realname);
829  if(write_message_to_user(b,msg,0)!=SUCCESS)
830    {
831/*      a->connected = (KNUCKLE *) NULL;
832      b->connected = (KNUCKLE *) NULL;
833      return(FAILURE);*/
834    }
835     
836  (void) sprintf(msg,"You are connected to %s %s.\n",
837          b->title, b->user->realname);
838  if((write_message_to_user(a,msg,0) != SUCCESS) &&  (!is_signed_on(b)))
839    {
840/*      sprintf(msg,"Oops, he just logged out. Will try to find another...");
841      write_message_to_user(b,msg,0);
842      a->connected = (KNUCKLE *) NULL;
843      b->connected = (KNUCKLE *) NULL;
844      return(FAILURE);*/
845    }
846
847  a->question->nseen++;
848  return(SUCCESS);
849}
850
851
852
853/*
854 * Function:    find_available_consultant() finds an available consultant in
855 *                      the list.
856 * Arguments:   user:   Ptr. to user structure for user needing a consultant.
857 * Returns:     SUCCESS or FAILURE;
858 * Notes:
859 */
860
861match_maker(knuckle)
862     KNUCKLE *knuckle;
863{
864  KNUCKLE **k_ptr, *temp = (KNUCKLE *) NULL;   
865  int priority, queue, foo;
866  long t = 0;
867  char msgbuf[BUFSIZ];
868  int status;
869 
870  if(!has_question(knuckle))
871    {
872      if(is_logout(knuckle) ||
873         is_connected(knuckle) ||
874         !is_signed_on(knuckle))
875        return(FAILURE);
876
877      priority = CANCEL;   /* lowest connectable priority */
878     
879#ifdef TEST
880      printf("match_maker: %s (%d) has no question\n",
881             knuckle->user->username, knuckle->instance);
882#endif TEST
883
884      for(k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
885        {
886
887#ifdef TEST
888          printf("match_maker: status: %d   %d queue: %d   ts:  %d\n",
889                 (*k_ptr)->status, (*k_ptr)->user->status,
890                 (*k_ptr)->queue, (*k_ptr)->timestamp);
891          printf("match_maker: status: %d   %d queue: %d   ts:  %d\n",
892                 knuckle->status, knuckle->user->status,
893                 knuckle->queue, knuckle->timestamp);
894#endif TEST
895         
896          if(!has_question((*k_ptr)))
897            continue;
898          if(is_connected((*k_ptr)))
899            continue;
900          if(is_logout((*k_ptr)))
901            continue;
902          if((*k_ptr)->status > QUESTION_STATUS)
903            continue;
904          if((*k_ptr) == knuckle)
905            continue;
906          else
907            if(((*k_ptr)->status & QUESTION_STATUS) > priority)
908              continue;
909            else
910              if(((*k_ptr)->timestamp < t) &&
911                 ((*k_ptr)->status == priority))
912                continue;
913                 
914          switch(knuckle->status & SIGNED_ON)
915            {
916            case FIRST:
917            case SECOND:
918              if(is_specialty(knuckle->user,(*k_ptr)->question->topic_code))
919                {
920                  temp = *k_ptr;
921                  t = (*k_ptr)->timestamp;
922                  priority = (*k_ptr)->status;
923                }
924              break;
925            case DUTY:
926            case URGENT:
927              if(is_specialty(knuckle->user,(*k_ptr)->question->topic_code))
928                {
929                  temp = *k_ptr;
930                  t = (*k_ptr)->timestamp;
931                  foo = DUTY;
932                  priority = (*k_ptr)->status;
933                }
934              else
935                if(foo != DUTY)
936                  {
937#ifdef TEST
938                    printf("match_maker: assigning to %s\n",
939                           (*k_ptr)->user->username);
940#endif TEST
941                    temp = *k_ptr;
942                    t = (*k_ptr)->timestamp;
943                    priority = (*k_ptr)->status;
944                  }
945              break;
946            default:
947              break;
948            }
949        }
950    }
951  else
952    {
953      if(is_logout(knuckle) ||
954         is_pitted(knuckle) ||
955         is_connected(knuckle) ||
956         (knuckle->status > QUESTION_STATUS))
957        return(FAILURE);
958     
959      for(k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
960        {
961          if((*k_ptr) == knuckle)
962            continue;
963          if(is_logout((*k_ptr)))
964            continue;
965          if(is_connected((*k_ptr)))
966            continue;
967          if(priority < (*k_ptr)->status & SIGNED_ON)
968             continue;
969          if((priority == is_signed_on((*k_ptr))) &&
970             t <= (*k_ptr)->timestamp)
971             continue;
972
973          switch((*k_ptr)->status & SIGNED_ON)
974            {
975            case FIRST:
976            case SECOND:
977              if(!is_specialty((*k_ptr)->user,knuckle->question->topic_code))
978                break;
979              priority = (*k_ptr)->status & SIGNED_ON;
980              t = (*k_ptr)->timestamp;
981              temp = *k_ptr;
982              break;
983            case DUTY:
984            case URGENT:
985              if(is_specialty((*k_ptr)->user,(knuckle)->question->topic_code))
986                {
987                  temp = *k_ptr;
988                  t = (*k_ptr)->timestamp;
989                  foo = DUTY;
990                  priority = (*k_ptr)->status & SIGNED_ON;
991                }
992              else
993                if(foo != DUTY)
994                  {
995                    temp = *k_ptr;
996                    t = (*k_ptr)->timestamp;
997                    priority = (*k_ptr)->status & SIGNED_ON;
998                  }
999              break;
1000            default:
1001              break;
1002            }
1003        }
1004    }
1005   
1006  if(temp != (KNUCKLE *) NULL)
1007    {
1008      status = connect_knuckles(temp,knuckle);
1009      if(status == SUCCESS)
1010        {
1011          (void) sprintf(msgbuf,"Connected to %s %s (%d) %s@%s",
1012                         temp->title,
1013                         temp->user->realname,
1014                         temp->instance,
1015                         temp->user->username,
1016                         temp->user->machine);
1017
1018          log_daemon(temp,msgbuf);
1019          return(SUCCESS);
1020        }
1021      else
1022        if(status == FAILURE)
1023          return(match_maker(knuckle));
1024        else
1025          return(ERROR);
1026    }
1027  else
1028    return(FAILURE); 
1029}
1030
1031
1032/*
1033 * Function:    new_message() takes a new message for a user or a consultant
1034 *                      and stores it in the messages field of the
1035 *                      appropriate structure.
1036 * Arguments:   msg_field:      A pointer to the message field for the
1037 *                              appropriate structure.
1038 *              message:        The new message.
1039 * Returns:     Nothing.
1040 * Notes:
1041 *      First, we allocate space for the new message string, which is then
1042 *      formed by concatenating the old messages, the date and time, and
1043 *      the new message, with some newlines to handle spacing.
1044 *      Then we free the old message memory and change the msg_field
1045 *      to point at the right string.
1046 */
1047
1048new_message(msg_field, message)
1049     char **msg_field;  /* Place to store the new message. */
1050     char *message;             /* Message string. */
1051{
1052  int curr_length;              /* Length of current message. */
1053  int msg_length;               /* Length of the new message. */
1054  int time_length;              /* Length of time string. */
1055  char *new_message;            /* Ptr. to constructed new message. */
1056  char timebuf[TIME_SIZE];      /* Current time. */
1057 
1058  time_now(timebuf);
1059  time_length = strlen(timebuf);
1060 
1061  if (*msg_field == (char *) NULL)
1062    curr_length = 0;
1063  else
1064    curr_length = strlen(*msg_field);
1065 
1066  msg_length = strlen(message);
1067  new_message = malloc((unsigned) curr_length + msg_length + time_length + 10);
1068  if (new_message == (char *)NULL)
1069    {
1070      log_error("new_message: malloc failed");
1071      return;
1072    }
1073
1074  new_message[0] = '\0';
1075  if (*msg_field != (char *) NULL)
1076    {
1077      (void) strcpy(new_message, *msg_field);
1078      (void) strcat(new_message, "\n");
1079    }
1080  (void) strcat(new_message, "time: ");
1081  (void) strcat(new_message, timebuf);
1082  (void) strcat(new_message, "\n");
1083  (void) strcat(new_message, message);
1084
1085printf("message: %s\n",new_message);
1086 
1087  if (*msg_field != (char *)NULL)
1088    free(*msg_field);
1089  *msg_field = new_message;
1090}
1091
1092
1093
1094/*
1095 * Function:    get_status_info() returns some status information.
1096 * Arguments:   None.
1097 * Returns:     Nothing.
1098 * Notes:
1099 *      The status information is returned in a static structure.
1100 */
1101
1102QUEUE_STATUS *
1103get_status_info()
1104{
1105  static QUEUE_STATUS status;   /* Static status structure. */
1106  KNUCKLE **k_ptr;      /* Current consultant. */
1107
1108  status.consultants = 0;
1109  status.busy = 0;
1110  status.waiting = 0;
1111
1112  if (Knuckle_List != (KNUCKLE **) NULL)
1113    {
1114      for (k_ptr = Knuckle_List; *k_ptr != (KNUCKLE *) NULL; k_ptr++)
1115        {
1116          if ((*k_ptr)->question == (QUESTION *) NULL)
1117            {
1118              if((*k_ptr)->connected != (KNUCKLE *) NULL)
1119                status.busy++;
1120              status.consultants++;
1121            }
1122          else
1123            if((*k_ptr)->connected == (KNUCKLE *) NULL)
1124              status.waiting++;
1125        }
1126    }
1127  return(&status);
1128}
1129
1130/*
1131 * Function:    verify_topic() checks to make sure that a topic is legitimate.
1132 * Arguments:   topic:  topic to be checked.
1133 * Returns:     SUCCESS, FAILURE, or ERROR.
1134 * Notes:
1135 *      Scan through the topics file, matching each line against the given
1136 *      topic.  If a match is found, return SUCCESS; otherwise return FAILURE.
1137 */
1138
1139
1140
1141int
1142verify_topic(topic)
1143     char *topic;
1144{
1145  TOPIC **t_ptr;
1146
1147  if (strlen(topic) == 0)
1148    return(FAILURE);
1149 
1150  for(t_ptr = Topic_List; *t_ptr != (TOPIC *) NULL; t_ptr++)
1151    if(string_eq(topic,(*t_ptr)->name))
1152      return((*t_ptr)->value);
1153
1154  return(FAILURE);
1155}
1156
1157
1158 
1159owns_question(knuckle)
1160     KNUCKLE *knuckle;
1161{
1162  if(!has_question(knuckle))
1163    return(FALSE);
1164
1165  if(knuckle->question->owner == knuckle)
1166    return(TRUE);
1167  else
1168    return(FALSE);
1169}
1170
1171
1172is_topic(topics,code)
1173     int *topics;
1174     int code;
1175{
1176  while(topics != (int *) NULL)
1177    {
1178      if(*topics == code)
1179        return(TRUE);
1180      ++topics;
1181      if((*topics == UNKNOWN_TOPIC) || (*topics <= 0))
1182        break;
1183    }
1184  return(FALSE);
1185}
1186
Note: See TracBrowser for help on using the repository browser.