/****************************************/ /* */ /* Author: */ /* */ /* Ira Winston */ /* Computer Science Department */ /* University of Pennsylvania */ /* */ /****************************************/ Notice: Procedure Options(Main); /* Subroutines */ %Include Add_to_Index; %Include Lib$day; %Include Locked_Record; %Include Sys$Asctim; %Include Lib_Day_to_time; %Include Sys$Getjpi; %Include Read_line; %Include Scan_Index; Declare Null Builtin; /* Data Structure Definitions */ %Include $Stsdef; %Include indexdef; %Include reptypes; /* File Definitions */ %Replace message_filename By 'SYS$SYSDISK:[SYSMGR]MESSAGE.DAT'; Declare Message_File_input File Input Record Keyed Environment (Shared_read,Shared_write, Maximum_record_size(2048), Multibuffer_count(5)); Declare messfptr pointer, 1 messf Based(messfptr), 2 timestamp bit(64) aligned, 2 sequence_no fixed binary(7), 2 start_date fixed binary(31), 2 termination_date fixed binary(31), 2 repetition_type fixed binary(7), 2 number_of_terminals fixed binary(15), 2 terminals(messf.number_of_terminals) character(5), 2 number_of_users fixed binary(15), 2 users(messf.number_of_users) character(12); Declare messfkey character(9) Based(messfptr), messfseckey character(1) Defined(messf.sequence_no); Declare textfptr Pointer, 1 textf Based(textfptr), 2 timestamp Bit(64) Aligned, 2 sequence_no Fixed Binary(7), 2 text_length Fixed Binary(15), 2 text Character(textf.text_length); Declare 1 Key_Record, 2 timestamp Bit(64) Aligned, 2 sequence_no Fixed Binary(7), messkey Character(9) Based(Addr(Key_Record)); %Replace user_filename By 'SYS$SYSDISK:[SYSMGR]USER.DAT'; Declare User_File_update File Update Record Keyed Environment (Shared_read,Shared_write, Maximum_record_size(2048), Multibuffer_count(5)); Declare User_File_input File Input Record Keyed Environment (Shared_read,Shared_write, Maximum_record_size(2048), Multibuffer_count(5)); Declare userfptr pointer, 1 userf Based(userfptr), 2 name character(12), 2 number_of_messages fixed binary(15), 2 messages(userf.number_of_messages), 3 timestamp bit(64) aligned, 3 start_date fixed binary(31), 3 termination_date fixed binary(31), 3 repetition_type fixed binary(7), 3 date_last_read fixed binary(31), 3 access_count fixed binary(15); Declare usernptr pointer, ext_number_of_messages fixed binary(15), 1 usern Based(usernptr), 2 name character(12), 2 number_of_messages fixed binary(15), 2 messages(ext_number_of_messages), 3 timestamp bit(64) aligned, 3 start_date fixed binary(31), 3 termination_date fixed binary(31), 3 repetition_type fixed binary(7), 3 date_last_read fixed binary(31), 3 access_count fixed binary(15); /* Variables */ Declare Line_count Fixed Binary(31) Initial(0); Declare input_buffer Character(255) Varying; Declare 1 Jpi_List, 2 Jpi_Username, 3 Jpi_Length Fixed Binary(15) Init(12), 3 Code Fixed Binary(15) Init(Jpi$_Username), 3 Address Pointer Init(addr(username)), 3 Return_length Pointer Init(null), 2 Jpi_Terminal, 3 Jpi_Length Fixed Binary(15) Init(6), 3 Code Fixed Binary(15) Init(Jpi$_Terminal), 3 Address Pointer Init(addr(terminal)), 3 Return_length Pointer Init(null), 2 Jpi_listend Fixed Binary(31) Init(Jpi$C_listend); Declare username Character(12) Static, terminal Character(6) Static; Declare new_user Bit(1) Init('0'b), (current_day,current_time) Fixed Binary(31), reptype Fixed Binary(7), retries Fixed Binary(31), (i,j) Fixed Binary, display Bit(1), count Fixed Binary(31), message_applies Bit(1), message_file_empty Bit(1), message_tree Pointer Init(Null); /* Main program */ Sts$Value = Sys$Getjpi(,,,Jpi_list,,,); If terminal = ' ' Then Stop; /* Stop if not interactive job */ terminal = Substr(terminal,1,Index(terminal,':')-1); /* Open message and user files */ Open File(user_file_input) Title(user_filename); Open File(message_file_input) Title(message_filename); /* Try to get user record */ Open File(user_file_update) Title(user_filename); On error Begin; If Locked_record(retries,oncode()) Then Goto retry; Else Call Resignal(); End; On Key(user_file_update) new_user = '1'b; retries = 0; Retry: Read File(user_file_update) Set(userfptr) Key(username); Revert Error; /* Process new user */ If new_user Then Do; ext_number_of_messages = 100; /* Maximum number of messages that can be put into a user record */ Allocate usern Set(usernptr); usern.name = username; message_file_empty = '0'b; usern.number_of_messages = 0; On Error Begin; If locked_record(retries,oncode()) Then Goto retry3; Else Call Resignal(); End; On Key(message_file_input) message_file_empty = '1'b; retries = 0; Retry3: Read File(message_file_input) Set(messfptr) Key(Byte(0)) Options(Index_number(1)); Revert Key(message_file_input); If ^message_file_empty Then Do; On Error Begin; If Locked_record(retries,oncode()) Then Goto retry4; Else Call Resignal(); End; Do While(messf.sequence_no = 0); If messf.repetition_type ^= rpt_marked_for_delete Then Do; message_applies = '0'b; If messf.number_of_users = 0 Then message_applies = '1'b; Else Do; Do i = 1 To messf.number_of_users; If messf.users(i) = username Then message_applies = '1'b; End; End; If message_applies Then Do; usern.number_of_messages = usern.number_of_messages + 1; usern.messages(usern.number_of_messages).timestamp = messf.timestamp; usern.messages(usern.number_of_messages).start_date = messf.start_date; usern.messages(usern.number_of_messages).termination_date = messf.termination_date; usern.messages(usern.number_of_messages).repetition_type = messf.repetition_type; usern.messages(usern.number_of_messages).date_last_read = 0; usern.messages(usern.number_of_messages).access_count = 0; End; End; retries = 0; Retry4: Read File(message_file_input) Set(messfptr); End; /* once for each message */ End; /* message file not empty */ ext_number_of_messages = usern.number_of_messages; On Key(user_file_update) ; Write File(user_file_update) From(usern) Keyfrom(username); Revert Key(user_file_update); ext_number_of_messages = 100; Free usern; Close File(message_file_input); /* Rewind to change keys */ Open File(message_file_input) Title(message_filename); On Error Begin; If Locked_record(retries,oncode()) Then Goto Retry5; Else Call Resignal(); End; retries = 0; Retry5: Read File(user_file_update) Set(userfptr) Key(username); Revert Error; End; message_tree = Null; Call Lib$Day(current_day,,current_time); /* If it is before 4AM use yesterday's date */ If current_time < 1440000 Then current_day = current_day - 1; count = 0; Do i = 1 to userf.Number_of_messages; If current_day >= userf.messages(i).start_date & current_day <= userf.messages(i).termination_date Then Do; reptype = abs(userf.messages(i).repetition_type); If reptype > rpt_remind_offset Then reptype = reptype - rpt_remind_offset; display = '0'b; If reptype = rpt_once_except_last_day Then If current_day = userf.messages(i).termination_date Then reptype = rpt_always; Else reptype = rpt_once; If reptype = rpt_daily_except_last_day Then If current_day = userf.messages(i).termination_date Then reptype = rpt_always; Else reptype = rpt_daily; If reptype = rpt_once Then Do; If userf.messages(i).date_last_read = 0 Then display = '1'b; End; Else If reptype = rpt_daily Then Do; If userf.messages(i).date_last_read ^= current_day Then display = '1'b; End; Else If reptype = rpt_always Then display = '1'b; /* check terminal list */ If userf.messages(i).repetition_type < 0 & display Then Do; On Error Begin; If Locked_record(retries,oncode()) Then Goto retry2; Else Call Resignal(); End; On Key(message_file_input) display = '0'b; key_record.timestamp = userf.messages(i).timestamp; key_record.sequence_no = 0; retries = 0; Retry2: Read File(message_file_input) Set(messfptr) Key(messkey); Revert Error; Revert Key(message_file_input); If display Then Do; display = '0'b; If messf.repetition_type ^= rpt_marked_for_delete Then Do; Do j = 1 To messf.number_of_terminals; If messf.terminals(j) = terminal Then display = '1'b; End; End; End; End; /* check terminal list */ If display Then Do; userf.messages(i).date_last_read = current_day; userf.messages(i).access_count = userf.messages(i).access_count + 1; Rewrite File(user_file_update) From(userf); Call add_to_index(message_tree,userf.messages(i).timestamp,count); End; End; /* In active period */ End; /* For each message in users message list */ Close File(User_file_update); count = 0; Call Scan_Index(message_tree,display_notice,count); Close File(user_file_input); Close File(message_file_input); Display_notice: Procedure (message,count); Declare message Pointer, count Fixed Binary(31); Declare buffer Character(255) Varying, len Fixed Binary(31), ind Fixed Binary(7), result Bit(1), datbuf Character(11); On Error Begin; If Locked_record(retries,oncode()) Then Goto retry; Else Call Resignal(); End; On Key(message_file_input) messfptr = Null; Key_record.timestamp = message->index_entry.timestamp; Key_record.sequence_no = 0; retries = 0; Retry: Read File(message_file_input) Set(messfptr) Key(messkey); If messfptr ^= Null Then If messf.repetition_type = rpt_marked_for_delete Then messfptr = Null; If messfptr ^= Null Then Do; Sts$Value = sys$asctim(,datbuf,messf.timestamp,0); line_count = line_count + 2; Put Skip Edit(datbuf) (A) Options(Cancel_Control_O); Put Skip; ind = 1; buffer = get_text(messf.timestamp,ind); Do While(buffer ^= Byte(26)); len = divide(length(buffer)+1,80,31)+1; If line_count + len > 22 Then Do; result = Read_line('Hit return when ready: ',input_buffer,cvt2upper); line_count = len; End; Else line_count = line_count + len; Put Skip Edit(buffer) (A); ind = ind + 1; buffer = get_text(messf.timestamp,ind); End; /* Do While */ line_count = line_count + 1; Put Skip; End; End Display_notice; Get_text: Procedure (timestamp,sequence_no) Returns(Character(*)); Declare timestamp Bit(64) Aligned, sequence_no Fixed Binary(7); Declare retries Fixed Binary(31); key_record.timestamp = timestamp; key_record.sequence_no = sequence_no; On Key(message_file_input) Goto text_gone; On Error Begin; If Locked_record(retries,oncode()) Then Goto retry; Else Call Resignal(); End; retries = 0; retry: Read File(message_file_input) Set(textfptr) Key(messkey); Revert Error; Return(textf.text); text_gone: Return(Byte(26)); End Get_text; End Notice;