#include <stdio.h>
#include <stdlib.h>   /* for abs() */
#include <time.h>
#include <string.h>
#include <ctype.h>	


#include "global.h"
#include "custom.h"		/* for date FORMAT strings */

#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_person_list.h"   /* for build_option_person_list() */
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_translate_url.h"
#include "manhat-lib/shared_access.h"
#include "manhat-lib/shared_msg_line.h"

#define GATHER_ALL "_all_"
#define GATHER_UNREAD "_unread_"
#define GATHER_FLAGGED "_flagged_"
#define GATHER_LAST   "_last_"


typedef enum gather_type { UNREAD, FLAGGED, ALL, USERNAME,  LAST } GATHER_TYPE;

typedef struct gather_struct
{
  int target_topic;           /* this is read from an optional parameter sent to this CGI program
                                 if an 'topic' parameter is sent, it will contain the topic_id that
                                 needs to be sent to the "assign_fac_expand" program when the user clicks
                                 the 'Back' button.  If the 'topic' parameter is not sent, this will
                                 be set to -1, and the 'Back' button will return to the NEWS_TOPIC program
                               */

  long topic_offset;         /* if this is -1, then the optional 'loc' parameter was not sent to this CGI 
  				program.  We will be looking at ALL of the Assignments.  If this is not -1,
  		               then it means the 'loc' parameter was received by the CGI.  We will be looking
  	                       at only the topic referred to by this offset.
                              */

  char username[MAX_USERNAME + 1];
  char realname[MAX_NAME + 1];
  GATHER_TYPE target;
  time_t time_read;     /* if GATHER_TYPE is 'UNREAD', then this contains the time the messages were read via this gather program */
}	
GATHER_STRUCT;


/* these are declared globally to reduce overhead
** for a recursive function in this program
**/

GATHER_STRUCT global_gather_criteria;  /* declared globally to reduce overhead on a recursive function */
time_t global_current_time;


SESSION global_user;
CONFIG_STRUCT global_conf;		/* the configuration read from config file */

MSG_TREE_NODE *global_topic_ptr;        /* should always point to the topic (assignment) we are working with */

char global_course[MAX_PATH + 1];	/* from crs=? command line */
char global_key[MAX_KEY + 1];	        /* from id=? command line */
int global_can_write;                   /* can this user write to this course? */

char global_topic_subject[MAX_SUBJECT + 1];
int global_topic_teacher_hidden;              /* did the teacher hide the topic */
int global_topic_read_only;                   /* did the teacher mark the topic READ-ONLY? */
char global_username[MAX_USERNAME + 1] = "";
char global_realname[MAX_NAME + 1] = "";
int global_teacher_search;                    /* are we searching for msgs by an individual who is FACULTY ? */
int global_indent = 0;

ATTACHMENT_NODE *global_attachment_head = (ATTACHMENT_NODE *) 0;
P_NODE *global_person_head = (P_NODE *) 0;


static void
read_parameters (char *course,  char *key, char *gather,
		  int *del_link, int *topic, long *loc,
		  	  int *printer_friendly, int *fixed_font)
{
  char tmp[MAX_FILENAME + 1];	/* scratch variable */


  cs_get_required_parameter ("crs", course, MAX_PATH);
  cs_get_required_parameter ("id", key, MAX_KEY);
  
  cs_get_optional_parameter ("gather", gather, MAX_PATH);
  if(strlen(gather) ==0)
      strncpy (gather, GATHER_LAST, MAX_PATH + 1);

  cs_get_optional_parameter("loc", tmp, MAX_FILENAME);
  if(!strlen(tmp))
     *loc = -1;           /* loc parameter not sent */
  else
     *loc = atol(tmp);   
  
   /* topic parameter is optional, but if it is provided, the 
      'loc' parameter must also exist.  Both the 'topic' and
       the 'loc' parameter are sent from the assign_fac_expand program
       When gathering a single assignment from the NEWS_TOPIC program,
       (by clicking on the 'G' next to the assignment) only the loc is
       sent.
     */
 
  cs_get_optional_parameter("topic", tmp, MAX_FILENAME);
  if(strlen(tmp))
     {
      if(*loc == -1)
         cs_critical_error(ERR_PARAM_MISSING, "loc");
      *topic = atoi(tmp);
      }  
    else
        *topic = -1;
               
  
  /* just check if the "del_link" parameter is there */
    cs_get_optional_parameter("del_link", tmp, 5);
   *del_link = strlen(tmp);	/* shared_cgi_util.c */


    /* provide printer-friendly version? */
  cs_get_optional_parameter ("print", tmp, 5);              /* shared_cs_util.c */
  *printer_friendly = *tmp? (atoi(tmp)? 1 : 0) :  0;


  /* provide preformatted text (instead of proportional) ? */
  cs_get_optional_parameter ("fixed", tmp, 5);              /* shared_cs_util.c */
  *fixed_font = *tmp? (atoi(tmp)? 1 : 0) :  0;

}





static void
parse_gather_string (char *gather_string, int target_topic, long topic_offset)
{
  char *ptr;

  global_gather_criteria.topic_offset = topic_offset;
  global_gather_criteria.target_topic = target_topic;
  *global_gather_criteria.username = '\0';
  *global_gather_criteria.realname = '\0';
  global_gather_criteria.time_read = 0;
  
  if (!strcmp (gather_string, GATHER_ALL))
    global_gather_criteria.target = ALL;
  else if (!strcmp (gather_string, GATHER_UNREAD))
    global_gather_criteria.target = UNREAD;
  else if (!strcmp (gather_string, GATHER_FLAGGED))
    global_gather_criteria.target = FLAGGED;
  else if (!strcmp (gather_string, GATHER_LAST))
    global_gather_criteria.target = LAST;
  else
    {
      ptr = strchr (gather_string, ':');
      if (ptr)
	{
	  *ptr = '\0';
	  strncpy (global_gather_criteria.username, gather_string, MAX_USERNAME);
	  strncpy (global_gather_criteria.realname, ptr + 1, MAX_NAME);
	  *ptr = ':';
	  global_gather_criteria.target = USERNAME;
	}
      else
	    cs_critical_error (ERR_GATHER_PARSE_ERROR, "");
    }
}




static void
last_io_error ()
{
  cs_critical_error (ERR_LAST_FILE_IO_ERROR, "");
}



static void
free_attachment_list()
{
 ATTACHMENT_NODE *ptr;
 while(global_attachment_head)
  {
   ptr = global_attachment_head;
   global_attachment_head = global_attachment_head -> next;
   free(ptr);
  }
}   




static void
read_last_criteria ()
{
  char last_path[MAX_PATH + 1];
  FILE *fp;

  snprintf (last_path, MAX_PATH + 1, "%s%s", discussion_path, GATHER_LAST_FNAME);
  fp = fopen (last_path, "r");
  if (!fp)
    last_io_error ();
  if (fread (&global_gather_criteria, sizeof (GATHER_STRUCT), 1, fp) != 1)
    last_io_error ();

  fclose (fp);
}






static void
write_last_criteria ()
{
  char last_path[MAX_PATH + 1];
  FILE *fp;

  if( (global_gather_criteria.target == UNREAD) && !global_gather_criteria.time_read )
      global_gather_criteria.time_read = global_current_time;
  snprintf (last_path, MAX_PATH + 1, "%s%s", discussion_path, GATHER_LAST_FNAME);
  fp = fopen (last_path, "w");
  if (!fp)
    last_io_error ();
  if (fwrite (&global_gather_criteria, sizeof (GATHER_STRUCT), 1, fp) != 1)
    last_io_error ();

  fclose (fp);
}





static void
set_basic_values ()
{
  char timestring[MAX_TIMESTRING + 1];
  char url[MAX_PATH +1];

  cs_set_current_time();

  /* put in the BACK button */
  if (global_gather_criteria.target_topic != -1)  /* then return to "assign_fac_expand" */
   {
    snprintf (url, MAX_PATH + 1, "%s?crs=%s&amp;id=%s&amp;topic=%d&amp;loc=%ld",
	    "assign_fac_expand", global_course, global_key, 
             global_gather_criteria.target_topic,global_gather_criteria.topic_offset);
    cs_set_value("back_url", url);
   }
  else
   {
    snprintf (url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;grp=%d",
	    "news_topic", global_course, global_key, ASSIGNMENTS);
    cs_set_value("back_url", url);
   }


  
  cs_set_value("gather_from_assignment_list", global_gather_criteria.target_topic == -1 ? "1" : "0");
  cs_set_value("gather_one_assignment", global_gather_criteria.topic_offset == -1? "0": "1");    
  switch(global_gather_criteria.target)
   {
     case UNREAD:  cs_set_value("gather_target", "UNREAD");
                   break;
                
     case FLAGGED: cs_set_value("gather_target", "FLAGGED");
                   break;   
  
     case ALL:     cs_set_value("gather_target", "ALL");
                   break;
                   
     case USERNAME:   cs_set_value("gather_target", "USERNAME");
                      cs_set_value("gather_target_realname", global_gather_criteria.realname);
                      cs_set_value("gather_target_username", global_gather_criteria.username);
                      cs_set_value("gather_target_is_teacher", global_teacher_search? "1": "0");
                      
                     break;

     default:   break;

   }
  


  strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,
	    localtime (&global_current_time));
  cs_set_value("global_time", timestring);

}







static void
set_flag_reply_info_urls ( const char *name_prefix, MSG_TREE_NODE *msg_ptr)
{
  #define MAX_TMP_NAME 50
  static char from_string[MAX_PATH + 1];	/* how to get back to THIS page... passed
                                                ** to the NEWS_NEW_MEMO program
						*/
  char name[MAX_TMP_NAME];
  char url[MAX_PATH *2+1];

    
  snprintf (from_string, MAX_PATH + 1,
	    "from=%s%ccrs%c%s%cid%c%s%cgather%c_last_%c%ld",
	    "assign_gather", QMARK_SUB, EQUAL_SUB, global_course,
	    AMP_SUB, EQUAL_SUB, global_key,  AMP_SUB,
	    EQUAL_SUB, POUND_SUB, msg_ptr->offset);



  /** set flag value and url */
  snprintf(name, MAX_TMP_NAME, "%s.flagged", name_prefix);
  cs_set_int_value(name, msg_ptr->user_data.flagged? 1:0);

  snprintf(url, 
       MAX_PATH * 2, "%s?crs=%s&amp;id=%s&amp;grp=%d&amp;msg_id=%d&amp;%s",
        "news_flag", global_course, global_key, ASSIGNMENTS, msg_ptr->data.info.msg_id, from_string);
  snprintf(name, MAX_TMP_NAME, "%s.flag_url", name_prefix);        
  cs_set_value(name, url);  


    
  /*** REPLY button only if msg was sent by a student
  **** button is disabled if this user doesn't have write access 
  ***/
  
  if(!strcmp(msg_ptr->data.info.sender, msg_ptr->data.info.receiver_username))
    {
     if(global_can_write)
      {
	snprintf(name, MAX_TMP_NAME, "%s.reply_url", name_prefix);
        snprintf (url, MAX_PATH *2 +1,"%s?crs=%s&amp;id=%s&amp;grp=%d&amp;topic=%d&amp;loc=%ld&amp;reply_to=%d&amp;to=%s&amp;%s",
           "news_new_memo", global_course, global_key, ASSIGNMENTS, msg_ptr->data.info.topic_id, msg_ptr->offset, 
                                            msg_ptr->data.info.msg_id,
                                             msg_ptr->data.info.sender, from_string);
        cs_set_value(name, url); 
   
      }
    }
    
      
  
/**** Always provide an INFO button ***/

  snprintf(name, MAX_TMP_NAME, "%s.info_url", name_prefix);
  snprintf (url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;loc=%ld&amp;grp=%d",
	  "news_info", global_course, global_key, msg_ptr->offset, ASSIGNMENTS);
  cs_set_value(name, url); 
  
  #undef MAX_TMP_NAME 
}












int gather_msg_should_display(MSG_TREE_NODE *msg_ptr, char *username)
{

 /* always show the assignment */
 if(msg_ptr->data.info.reply_to == -1)
     return 1;
switch(global_gather_criteria.target)
 {
  case USERNAME:
  case ALL: return (!strcmp(msg_ptr->data.info.sender, username) ||
                    !strcmp(msg_ptr->data.info.receiver_username, username) );
            break;

             
  case FLAGGED: return msg_ptr->user_data.flagged;
                break;
           
  case UNREAD:  return (global_gather_criteria.time_read == msg_ptr->user_data.time_read);
                break;

     
  default: return 0;          /* this should never happen */
           break;
 }
}                                         
                  




static void
process_msg_node (MSG_TREE_NODE *msg_ptr, int *website_attached)
{
  FILE *fp;
  int fd;
  
  char infopath[MAX_PATH + 1];
  int i;
  NEWS_INFO infofile_info;
  ATTACHMENT_NODE *aptr = 0;

  if(!msg_ptr->user_data.time_read && (global_conf.access != ACCESS_CAPTURE))   /* if msg is unread and not in capture mode */
   {
          mark_msg_as_read(&(msg_ptr->data),&global_conf,&global_user);   /*shared_news_util.c */
   }    



  /*** if there are attachments, read the info file to 
  **** build the attachment list
  ***/

 *website_attached = 0;  /* assume this to start */
 if(msg_ptr->data.info.attachments)
 {
   snprintf(infopath,MAX_PATH + 1,"%s%s/%s/%s/%s",global_conf.course_path,PEOPLE_DIR,
                            msg_ptr->data.info.sender,discussion_fname,msg_ptr->data.info_fname);
  
  fp = fopen(infopath,"r");
  if(!fp)
     cs_critical_error (ERR_FOPEN_READ_FAILED, infopath);

  fd = fileno(fp);   
  get_shared_lock(fd, 1);                      /* shared_lock.c */    

  if(fread( &infofile_info, sizeof(NEWS_INFO), 1, fp) != 1)
   cs_critical_error (ERR_FREAD_FAILED, infopath); 


  /* process attachments, build linked list */
  *website_attached = (infofile_info.attachments == -1);
     
  if (*website_attached)
    infofile_info.attachments = 1;	/* since we have to pick up the dirname */

  for (i = 1; i <= infofile_info.attachments; i++)
    {
      if (!global_attachment_head)
	{
	  global_attachment_head =
	    (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE));
	  if (!global_attachment_head)
	    cs_critical_error (ERR_MALLOC_FAILED, infopath);
	  aptr = global_attachment_head;
	}
      else
	{
	  aptr->next = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE));
	  if (!aptr->next)
	    cs_critical_error (ERR_MALLOC_FAILED, infopath);
	  aptr = aptr->next;
	}

      if (fread(&aptr->data, sizeof (ATTACHMENT), 1, fp) != 1)
	 cs_critical_error (ERR_FREAD_FAILED, infopath); 
      aptr->next = 0;
    }				/* for .. */

  release_lock(fd);   /* shared_lock.c */
  fclose (fp);
 } /* if attachments */ 
}





static void
print_message(MSG_TREE_NODE *msg_ptr, char *username, char *realname)
{

#define MAX_TMP_NAME 50 


static int last_topic = -1;
static char last_username[MAX_USERNAME + 1] = "";
static int topic_number = -1;
static int msg_number = -1;
static int student_number = -1;

char name_prefix[MAX_TMP_NAME + 1];
char name[MAX_TMP_NAME + 1];
int website_attached;
char msg_path[MAX_PATH + 1];

 if(gather_msg_should_display(msg_ptr, username))
  {

   /* if the topic has changed since the last time this was called,
   ** adjust the counts
   */
   if(msg_ptr->data.info.topic_id != last_topic)
      {
       last_topic = msg_ptr->data.info.topic_id;
       topic_number++;
       msg_number = -1;
       student_number = -1;
       *last_username = '\0';
      }

   if((msg_ptr->data.info.reply_to != -1)  && strcmp(username, last_username))
     {
         strncpy(last_username, username, MAX_USERNAME + 1);
         student_number++;
         msg_number = -1;
     }  
   
   
   if(msg_ptr->data.info.reply_to == -1) /* if this is a topic */
       snprintf(name_prefix,MAX_TMP_NAME + 1, "topic.%d", topic_number);
   else
       snprintf(name_prefix,MAX_TMP_NAME + 1, "topic.%d.student.%d.msg.%d", topic_number, student_number, ++msg_number);
       
   set_flag_reply_info_urls (name_prefix, msg_ptr);

   /* shared_news_util.c */
   set_assign_read_heading_data (msg_ptr,  name_prefix, global_topic_ptr,  global_course,  global_key,       
                                    &global_conf, global_topic_teacher_hidden, global_can_write, global_topic_read_only);


   /* the above call does not know about the real name of the person we are working with, so
   ** we'll set it 'manually' here
   **/
   snprintf(name, MAX_TMP_NAME, "%s.receiver_realname", name_prefix);
   cs_set_value(name, realname);
   
   
   snprintf(name, MAX_TMP_NAME, "%s.indent", name_prefix);
   cs_set_int_value(name, global_gather_criteria.target != UNREAD? global_indent: 0);
   
   process_msg_node (msg_ptr, &website_attached);

    /* shared_news_util.c */
   set_news_attachment_data (msg_ptr, 
                         global_topic_ptr->data.info.subject, 
                         global_course, 
                         global_key, 
                         ASSIGNMENTS,  
                         website_attached,
                         "assign_read", 
                         global_user.team,    /* but it doesn't really matter */
                         0,             /* is_fac_teamteach */
                         last_username,          /* THIS MAY BE WRONG! - checked only quickly */
                         &global_conf, 
                         0,                  /* attachments locked, should be 0 because there's a teacher running this */
			 global_user.username,  
			 global_attachment_head, 
			 name_prefix);          /* name prefix is blank */


   free_attachment_list();
  
   snprintf (msg_path, MAX_PATH + 1, "%s%s/%s/%s/%s",
	    global_conf.course_path, PEOPLE_DIR, 
	    msg_ptr->data.info.sender, discussion_fname, msg_ptr->data.info.msg_fname);


   strcat(name_prefix, ".");  /* stupid, because next expects a dot after the prefix */
   set_msg_body_data(msg_path, name_prefix, "");   /* shared_msg_line.c */
  
  }
    
#undef MAX_TMP_NAME  

}  




static void
gather_subtree (MSG_TREE_NODE *root, int indent)
{

 if(!root)
    return;
    
 if(indent)
    global_indent++;
    
  print_message(root, global_username, global_realname);
   
 if(root->reply)
    gather_subtree(root->reply, 1);
 if(root->next) 
    gather_subtree(root->next, 0);

 if(indent)
     global_indent--; 

  
}



P_NODE *build_user_list()
{
 
 P_NODE *p_head, *p_ptr;
 
  /* if we are looking for msgs by a particular person, 
  ** just put that one person in the list
  */
  if(global_gather_criteria.target == USERNAME)
   {
    p_head = (P_NODE *) malloc (sizeof (P_NODE));
    if (!p_head)
	cs_critical_error (ERR_MALLOC_FAILED, "");
    strncpy(p_head->data.username,global_gather_criteria.username, MAX_USERNAME + 1);
    strncpy(p_head->data.realname,global_gather_criteria.realname, MAX_NAME + 1);

    global_person_head = build_option_person_list(&global_conf);   /* shared_person_list.c */
   
    /* look for the username in the password file */
    for(p_ptr=global_person_head; p_ptr && strcmp(p_ptr->data.username, global_gather_criteria.username); 
                            p_ptr=p_ptr->next);
                            
    if(!p_ptr) /* for some reason, user wasn't in the password file - give bogus values */
     {                        
      *(p_head->data.id) = '\0';
      p_head->data.team = 'Z';
      p_head->data.group = STUDENT;
     }
    else
     {
      strncpy(p_head->data.id, p_ptr->data.id, MAX_ID + 1);
      p_head->data.team = p_ptr->data.team;
      p_head->data.group = p_ptr->data.group;
     }
      p_head->next = (P_NODE *) 0;
  }   
 else    
  /* for all other targets, build a complete list of users */
    p_head = build_option_person_list(&global_conf);  /* shared_person_list.c */    
   
 return (p_head);
 
 /* for complete correctness, we should add to the list created by build_option_person_list
 ** those students who posted something to ASSIGNMENTS, but have since been removed from the
 ** course.  That is, gathering 'all' will NOT show msgs by those deleted students.
 ** maybe an enhancement?
 */   

}





static void
gather_news_msg ( char *gather_string, int target_topic, long topic_offset)
{

  MSG_TREE_NODE *msg_ptr, *msg_ptr2;
  MSG_TREE_NODE *topic, *msg;
  int msg_count;
  P_NODE *person_head, *p_ptr;


  parse_gather_string (gather_string, target_topic, topic_offset);
  if (global_gather_criteria.target == LAST)
      read_last_criteria();
      
  if(global_gather_criteria.topic_offset == -1) /* if we are looking at ALL assignments (instead of just one) */
    build_msg_tree(&global_user, ASSIGNMENTS, 0, 1, &global_current_time);   /* shared_news_util.c */
  else 
   {
     build_one_topic_tree(&global_user, ASSIGNMENTS, global_gather_criteria.topic_offset,   /* shared_news_util.c */
                             &msg, &topic, &msg_count, 
                             0, 1, &global_current_time);
   
     /* the above call must be completely successful */
     if( (!tree_head || !msg) || (msg != topic) )
         cs_critical_error(ERR_CANT_FIND_THIS_OFFSET, "");
       
   }
  

  person_head = build_user_list();   /* build a list of people to search for */

  /*are we looking for a teacher's posts? */
  global_teacher_search = ((global_gather_criteria.target == USERNAME) &&
                                    (person_head && person_head->data.group == FACULTY) );
                                    
  set_basic_values ();


  for(msg_ptr=tree_head; msg_ptr; msg_ptr=msg_ptr->next)  /* for each assignment */
     {
      global_indent = 0;
      global_topic_ptr = msg_ptr;
      /* copy the topic subject to the global variable */
      strncpy(global_topic_subject,msg_ptr->data.info.subject, MAX_SUBJECT + 1);
      global_topic_teacher_hidden = is_teacher_hidden (msg_ptr->data.status, msg_ptr->data.release_time,   /* shared_news_util.c */
                                                        msg_ptr->data.unrelease_time, global_current_time ); 
      global_topic_read_only = BASIC_STATUS(msg_ptr->data.status) == READ_ONLY? 1 : 0;                                             
       

      if(global_teacher_search)   /* special case - we are looking for msgs posted by a teacher */
       {
         /* copy names to global variables */
         strncpy(global_username, person_head->data.username, MAX_USERNAME + 1);
         strncpy(global_realname, person_head->data.realname, MAX_NAME + 1);

         if(!strcmp(msg_ptr->data.info.sender,global_username))
              print_message(msg_ptr,"","");     /* print the assignment if it was posted by the teacher we 
                                                ** are targeting
                                                */

         gather_subtree(msg_ptr->reply, 1);
         
       }
      else /* not a global_teacher_search */
       {

       /* Show the assignment when 
       ** You're searching for anything but UNREAD or FLAGGED messages OR
       ** You're searching for UNREAD msgs, and the assignment is unread OR
       ** You're searching for FLAGGED msgs, and the assignment is flagged.
       */
       
       if(   ((global_gather_criteria.target != UNREAD)  && (global_gather_criteria.target != FLAGGED)) ||
               ( ((global_gather_criteria.target == UNREAD) && (!msg_ptr->user_data.time_read)) || 
                 ((global_gather_criteria.target == FLAGGED) && (msg_ptr->user_data.flagged)) )   )
            {   
                print_message(msg_ptr,"","");    
            }    
             
             
             
             
       
       for(p_ptr = person_head; p_ptr; p_ptr = p_ptr->next)  /* for each person on the list */
         {
           /* copy names to global variables */
           strncpy(global_username, p_ptr->data.username, MAX_USERNAME + 1);
           strncpy(global_realname, p_ptr->data.realname, MAX_NAME + 1);

           for(msg_ptr2 = msg_ptr->reply; msg_ptr2; msg_ptr2 = msg_ptr2->next)
            {

              if(!strcmp(msg_ptr2->data.info.receiver_username, p_ptr->data.username))
               {
                    print_message(msg_ptr2, p_ptr->data.username, p_ptr->data.realname);
                    gather_subtree(msg_ptr2->reply, 1);
               }
            }
        }          

       }   /* else not a global_teacher_search */
     }   /* for each assignment */




  free_option_person_list(person_head);	         /* shared_person_list.c */
  free_option_person_list(global_person_head);   /* shared_person_list.c */
  free_msg_tree (tree_head);                     /* shared_news_util.c */
  write_last_criteria();

}




int
main (void)
{

  int del_link;			/* from del_link=?command line  do we need to rm a symbolic link
  			        ** to an attached web page?
				*/

  int target_topic;		/* from optional topic=? command line */  
  
  long topic_offset;            /* from optional loc=? command line */
  
  char gather_string[MAX_PATH + 1];  

  int printer_friendly;         /* from print=? command line  provide "printer friendly" version? */				 
  int fixed_font;               /* from fixed=? command line  print body as fixed font? */				 



  cs_cgi_init();  
  read_parameters (global_course,global_key, gather_string, &del_link, &target_topic, &topic_offset,
                      &printer_friendly, &fixed_font);
  read_configuration_file (global_course, &global_conf);	/* shared_util.c */
  validate_key (global_key, &global_user, &global_conf);	/* shared_util.c */

  if(global_user.group != FACULTY)    /* only teachers can run this program */
    cs_critical_error(ERR_REQUEST_DENIED, "");

  cs_set_value("is_faculty","1");   

  if(global_conf.access == ACCESS_CAPTURE)
      cs_set_value("capture_mode", "1");        /* shared_cs_util.h */

  cs_set_int_value("printer_friendly", printer_friendly);
  cs_set_int_value("fixed_font", fixed_font);

  global_can_write = has_write_permission(&global_user, &global_conf);   /* shared_access.c */
  if(global_can_write)
      cs_set_value("can_write", "1");
 
  cs_set_course_info(&global_conf);     /* shared_cs_util.c */
  

  
  cs_set_value("crs", global_course);
  cs_set_int_value("grp", ASSIGNMENTS);
  cs_set_value("key", global_key);
  cs_set_value("username",global_user.username);  
     
   
  set_discussion_names (global_conf.course_path, global_user.username, ASSIGNMENTS);	/* shared_news_util.c */

  gather_news_msg ( gather_string, target_topic, topic_offset);
  
  if (del_link)
    remove_stale_symlinks (global_user.username, global_course, global_conf.access);  /* shared_news_util.c */

  /* NOTE: this program uses the same lang file as news_read.c **/
  cs_load_lang("news_read");
  cs_cgi_display("assign_gather", 0);
  
  cs_cgi_destroy();

  return 0;
}

