DataMuseum.dk

Presents historical artifacts from the history of:

RC4000/8000/9000

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RC4000/8000/9000

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦86b8e6668⟧ TextFile

    Length: 223488 (0x36900)
    Types: TextFile
    Names: »tctxtb      «

Derivation

└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer
    └─⟦f546e193b⟧ 
        └─⟦this⟧ »tctxtb      « 

TextFile

<****************************************************************************>
<*  SW8110 Terminal Access System                                           *>
<*         Catalog and Operator Program  'tascat'                           *>
<*                                                                          *>
<*  Henning Godske      870105                                              *>
<*  A/S Regnecentralen                                                      *>
<*                                                                          *>
<*  Compiler call :tc=algol connect.no fp.yes spill.no                      *>
<****************************************************************************>

begin
<****************************************************************************>
<*  Vedligeholdelse af katalogerne, operatør kommunikation                  *>
<*  og initialisering af systemet.                                          *>
<*                                                                          *>
<*  Program skitse:                                                         *>
<*  a) Læsning af intialiserings parametre fra init fil.                    *>
<*  b) Åbning af test output filen.                                         *>
<*  c) Evt. oprettelse af nye katalogfiler ud fra catalog tekst fil         *>
<*  d) Synkronisering med Tas processen herunder overførsel af init         *>
<*     data til Tas.                                                        *>
<*  e) Opstart af korutiner: 1) Katalog vedligeholdelse og modtagelse af    *>
<*                              message fra Tas og bruger processer.        *>
<*                           2) Timecheck rutinen til evt. automatisk       *>
<*                              udlogning af brugerer.                      *>
<*                           3) Kontrol af afsendelse af tekster til        *>
<*                              terminaler via tasterm.                     *>
<*                           4) Operatør korutinerne. En for hver operatør  *>
<*                              der skal kunne 'køre' samtidig, dog altid   *>
<*                              en til brug for hovedkonsollen.             *>
<*  f) Start af kerne.                                                      *>
<*     Besvarelse af message fra tasterm-processen.                         *>
<*     Besvarelse af message fra bruger-processer.                          *>
<*     Opstart af operatør rutiner.                                         *>
<****************************************************************************>

<****************************************************************************>
<*  Revision history:                                                       *>
<*                                                                          *>
<*  87.02.01    tascat  release 1.0                                         *>
<****************************************************************************>


<*******************************>
<* Globale variable for tascat *>
<*******************************>


    integer reld;                       <* Release datoer *>
    integer relt;
    integer initver;
    integer tastermverd;
    integer tastermvert;

    integer array init_file_name(1:4);  <* Navnet på init filen *>

    integer number_of_opera;            <* Antal operatør korutiner Max. 5 *>
    integer array opera_terms(4:8,1:2); <* Beskrivelse af opr. rutiner *>
    integer language;                   <* Sprog benyttet ved bruger udskrift*>

    integer cps;                        <* Initialiserings parametre *>
    integer cls;
    integer max_sessions;
    integer max_sysmenu;
    integer max_terminals;
    integer corebufs;
    integer mclprogs;
    integer termtypes;
    integer max_users;

    boolean system_stop;                <* Systemet er ved at stoppe *>
    integer login_stat;                 <* Aktuel login status for terminaler*>
    integer fp_maxterms;                <* Maxterms angivet ved kald *>
    integer max_terms;                  <* Max. terminaler inlogget *>
    integer terms;                      <* Aktuel antal terminaler inlogget *>
    integer users;                      <* Aktuel antal brugerer inlogget *>
    integer sessions;                   <* Aktuel antal sessioner *>

    integer max_text_count;             <* Max antal udestående 'send text' *>
    integer max_user_block;             <* Max. antal user block før alarm *>
    integer max_term_block;             <* Max. antal term block før alarm *>

    integer array text_buf_reserved(1:3); <* Text buffer reserveret *>
    boolean timecheck_stat;             <* Status for timecheck *>
    integer array log_txt(0:27);        <* Logout tekst for timecheck *>
    integer array stop_txt(0:27);
    integer log_time;                   <* Logout vente tid *>

    integer array host_id(0:27);        <* host navn signon tekst *>
    integer array signon_text(0:68);    <* operator signon tekst *>

    zone head_term_zone(14,1,konsol_error);<* Hovedkonsol output zone *>
    integer array head_term_name(1:4);  <* Hovedkonsollens navn *>
    integer head_term_pda;              <* Hovedkonsol pda *>

    integer tasterm_pda;                <* Tasterm processens pda *>
    integer array tasterm_name(1:4);    <* Tasterm processens navn *>

    integer own_size;                   <* Egen proces størrelse *>
    integer own_pda;                    <* Egen proces pda *>
    integer array own_name(1:4);        <* Eget proces navn *>
    integer array prog_name(1:4);       <* Programmets navn *>

    integer struc_size;                 <* Antal blokke i login_struc *>
    integer user_list;                  <* Peger til user kæden i login_struc*>
    integer free_list;                  <* Peger til free kæden i login_struc*>

    boolean new_catalog;                <* True = nyt katalog angivet *>
    integer array cattxt_name(1:4);     <* Navnet på katalog tekst filen *>
    integer array cat_doc(1:4);         <* Katalogernes dokument navn *>
    zone cat_file(128,1,stderror);      <* Zone til læsning af katalog tekst *>

    integer array sys_bases(1:2);       <* Base par for system baser *>
    integer array cmcl_bases(1:2);      <* Base par for cmcl filer *>

    zone usercat(128,1,std_error);      <* Zone til user kataloget *>
    zone termcat(128,1,std_error);      <* Zone til terminal kataloget *>
    zone typecat(128,1,std_error);      <* Zone til terminaltype kataloget *>
    integer usercat_size;               <* Antal segmenter i user kataloget *>
    integer termcat_size;               <* Antal segmenter i terminal kat.  *>
    integer typecat_size;               <* Antal segmenter i terminaltype kat*>
    integer array field user_entry;     <* Aktuelt entry i user kat. segment *>
    integer array field term_entry;     <* Aktuelt entry i term kat. segment *>
    integer array field type_entry;     <* Aktuelt entry i type kat. segment *>
    integer user_seg;                   <* Aktuelt seg. i zone fra user kat. *>
    integer term_seg;                   <* aktuelt seg. i zone fra term kat. *>
    integer user_entry_length;          <* Længden af et entry i user kat. *>
    integer term_entry_length;          <* Længden af et entry i term kat. *>
    integer type_entry_length;          <* Længden af et entry i type kat. *>
    integer array usercat_name(1:4);    <* Bruger katalogets fil navn *>
    integer array termcat_name(1:4);    <* Terminal katalogets fil navn *>
    integer array typecat_name(1:4);    <* Terminaltype katalogets fil navn *>

    long array opr_keywords(0:20);      <* Operatør keywords i tascat *>
    integer opr_num_keys;               <* Antal keywords defineret *>
    long array cat_keywords(0:60);      <* Katalog keywords i tascat *>
    integer cat_num_keys;               <* Antal keywords defineret *>
    long array init_keywords(0:50);     <* Init keywords i tascat *>
    integer init_num_keys;              <* Antal keywords defineret *>
    integer array char_table(0:255);    <* Tegn input tabel *>

    zone copy_buf(128,1,stderror);      <* Buffer til general copy *>

    boolean killed;                     <* True = stoppet ved kill *>
    boolean test_on;                    <* Status for test output *>
    boolean sys_start;                  <* Korutine system startet *>
    zone test_out(128,1,test_out_error);<* Zone til output af test records  *>
    integer array testout_name(1:4);    <* Navnet på testout filen *>
    integer trace_type;                 <* Typen af den trace der foretages *>
    integer test_select;                <* Typen af test fra aktiviteter    *>

    integer run_alarm_cause;            <* Cause ved alarm (trap)  *>
    integer run_alarm_pos;              <* procedure nr ved alarm  *>

    integer free_sem;                   <* Semafor -4 *>
    integer delay_sem;                  <* Semafor -3 *>
    integer wait_answer_pool;           <* Semafor -2 *>
    integer wait_message;               <* Semafor -1 *>
    integer wait_message_pool;          <* Semafor  0 *>
    integer message_buf_pool;           <* Semafor  1 *>
    integer time_sem;                   <* Semafor  2 *>
    integer struc_sema;                 <* Semafor  3 *>
    integer text_write_sem;             <* Semafor  4 *>

    real t_n_l,miss_par,u_n_l,ill_val,  <* konstant tekster     *>
         ill_par,long_text,ill_time,    <*                      *>
         c_p  ;

    integer array answer(1:9);          <* Answer til modtaget mess *>
    integer array mess(1:1);            <* Reference til message   *>

    integer field sender_pda;           <* Sender pda i mess *>
    integer field reciever_pda;         <* Modtager pda i mess *>
    integer field buf_addr;             <* Buffer adresse på mess *>
    integer array field mess_array;     <* Message *>

    long array field laf;               <* work *>
    integer array field iaf;            <* work *>
    boolean array field baf;            <* work *>
    integer i;                          <* work *>

<*********************************************************>
<* Procedure til afhjælpelse af fejl i externe procedure *>
<*********************************************************>

integer procedure put_ch(dest,pos,char,rep);
long array dest;
integer pos,char,rep;
begin
  trap(local);
  put_ch:=putchar(dest,pos,char,rep);
  if false then
    local: put_ch:=-1;
end;

integer procedure put_txt(dest,pos,text,length);
long array dest,text;
integer pos,length;
begin
  trap(local);
  put_txt:=puttext(dest,pos,text,length);
  if false then
    local: put_txt:=-1;
end;

<*******************************************>
<* Generelle hjælpe procedure til TASCAT   *>
<*******************************************>

procedure claim(words);
<* 1 *>
<*------------------------------------------------------*>
<* Reserver et antal ord på stakken                     *>
<*                                                      *>
<* words (call)  : Antal ord der reserveres på stakken  *>
<*------------------------------------------------------*>
integer words;
begin
  integer array x(1:words);
end;

integer procedure send_mess(z,mess);
<* 4 *>
<*--------------------------------------------------------------------*>
<* z (call and return) : Zone åbnet med navnet på den proces der skal *>
<*                       sendes til. Share 1 benyttes til message og  *>
<*                       sharestate skal være 0 el. 1. Ved retur er   *>
<*                       sharestate lig message buffer adresse.       *>
<* mess (call)         : Integer array(1:8) indeholdede message       *>
<* Return              : Message buffer adresse                       *>
<*                       Der udføres TRAP hvis message buffer claim   *>
<*                       er overskredet                               *>
<*--------------------------------------------------------------------*>
zone z;
integer array mess;
begin
  integer array share(1:12);
  integer buf_addr,i;

  trap(alarm);
  getshare6(z,share,1);
  for i:=1 step 1 until 8 do
    share(i+3):=mess(i);
  setshare6(z,share,1);
  buf_addr:=monitor(16,z,1,share <* dummy ia *>);
  if buf_addr=0 then
    write_message(4,1,false,<:claims exceeded:>);
  send_mess:=buf_addr;
  if false then
    alarm: disable traped(4);
end;

boolean procedure wait_ans(z,mess_addr,time,wait_sem,regret);
<* 5 *>
<*---------------------------------------------------------------------*>
<* z (call and return) : Zone der blev benyttet ved send_mess          *>
<*                       Ved retur er sharestate lig 0                 *>
<* mess_addr (call)    : Adressen på message buffer fra send_mess.     *>
<* time (call)         : Tiden der skal ventes inden message fortrydes *>
<*                       sættes tiden 0 ventes uendeligt               *>
<* wait_sem (call)     : Semafor der benyttes til at vente på answer   *>
<* regret (call)       : True = regret message ved time-out            *>
<* Return              : True= answer modtaget; False=Time out         *>
<*                       Ved time out fortrydes den sendte message     *>
<*---------------------------------------------------------------------*>
zone z;
integer mess_addr,time,wait_sem;
boolean regret;
begin
  integer array answer(1:1),ia(1:1);

  trap(alarm);
  initref(answer);
  wait_select:=6;
  wait(message_buf_pool,answer);
  answer(2):=mess_addr;
  answer(3):=wait_sem;
  signal(wait_answer_pool,answer);
  wait_ans:=true;
  wait_time:=time;
  if wait(wait_sem,answer)=0 then
  begin <* time out *>
    wait_ans:=false;
    wait_select:=mess_addr;
    wait(wait_answer_pool,answer);
    if regret then
      monitor(82<* regret message *>,z,1,ia<* dummy *>);
  end;
  answer(2):=6;
  signal(message_buf_pool,answer);
  if false then
    alarm: disable traped(5);
end;

procedure write_message(from,result,cont,mess);
<* 6 *>
<*------------------------------------------------------------*>
<* Udskriver meddelelse på hovedkonsol og danner test-record  *>
<*                                                            *>
<* from   (call)    : Angiver hvorfra meddelensen kommer      *>
<* result (call)    : Angiver årsagen eller resultat til mes. *>
<* cont   (call)    : True= returner efter udskrift           *>
<*                    False= Afbryd kørslen med trap(from)    *>
<* mess   (call)    : Selve meddelelsen                       *>
<*------------------------------------------------------------*>
integer from,result;
boolean cont;
string mess;
begin
  real time;

  trap(alarm);
  if sys_start and test_on then
  begin
    prepare_test;
    test_out.iaf(1):=1030; <* message *>
    test_out.iaf(2):=abs from;
    test_out.iaf(3):=result;
  end;
  if (false add (trace_type shift (-1))) or from>=0 then
  begin
    open(head_term_zone,8,head_term_name,1 shift 9);
    write(head_term_zone,<:message Tas : :>);
    outdate(head_term_zone,round systime(5,0,time));
    write(head_term_zone,<: :>);
    outdate(head_term_zone,round time);
    write(head_term_zone,<: :>,true,30,mess,<<-dddddd>,
                         <:  :>,result,
                         <:.:>,<<zddddd>,abs from,<:<10>:>);
    close(head_term_zone,false);
  end;
  if -,cont then
    trap(from);
  if false then
    alarm: disable traped(6);
end;

procedure traped(procedure_nr);
<* 7 *>
<*--------------------------------------------------------------------*>
<* procedure_nr (call) : Nummeret på den procedure hvori kaldet står  *>
<*                                                                    *>
<*                       Der dannes test records til beskrivelse af   *>
<*                       årsagen til trap'et. Der efter fortsætte til *>
<*                       de næste ydre trap niveau. På yderste niveau *>
<*                       afbrydes programmet                          *>
<*--------------------------------------------------------------------*>
value procedure_nr;
integer procedure_nr;
begin
  integer i,cause;
  integer array ia(1:8);

  trap(alarm);
  cause:=alarmcause extract 24;
  if run_alarm_pos=0 and cause<>-13 then
  begin
    run_alarm_cause:=cause;
    run_alarm_pos:=procedure_nr;
  end;
  if cause=-9 and (alarmcause shift (-24))=8 then
    killed:=true;
  if sys_start and test_on then
  begin
    prepare_test;
    test_out.iaf(2):=procedure_nr;
    test_out.iaf(3):=alarmcause shift (-24) extract 24;
    test_out.iaf(4):=cause;
    if cause=-13 then
      test_out.iaf(1):=1028 <* Cont *>
    else
      if cause=-11 then
      begin <* Give up *>
        test_out.iaf(1):=1026; <* give up 1 *>
        test_out.iaf(5):=getalarm(ia);
        prepare_test;
        test_out.iaf(1):=1027; <* give up 2 *>
        for i:=2 step 1 until 5 do
          test_out.iaf(i):=ia(i+3);
      end
      else
        test_out.iaf(1):=1025;<* Trap *>
  end;
  if false then
    alarm: procedure_nr:=(alarmcause extract 24)-100;
  trap(0);
  trap(procedure_nr);
end;

procedure trace(p1,p2,p3,p4);
<* 8 *>
<*----------------------------------------------------------------------*>
<* p1 til p4 (call) : Integer parametre der skrives i trace test record *>
<*----------------------------------------------------------------------*>
integer p1,p2,p3,p4;
begin

  if sys_start and test_on then
  begin
    prepare_test;
    test_out.iaf(1):=1029; <* trace *>
    test_out.iaf(2):=p1;
    test_out.iaf(3):=p2;
    test_out.iaf(4):=p3;
    test_out.iaf(5):=p4;
  end;
end;

procedure close_test_out;
<* 9 *>
<*---------------------------------------*>
<* Luk test_out filen hvis det er muligt *>
<*---------------------------------------*>
begin
  if sys_start and test_on then
  begin
    write_message(-9,select_test,true,<:Test output stopped:>);
    <* Udskriv stop record *>
    prepare_test;
    close(test_out,true);
  end;
  select_test:=0;
  test_on:=false;
end;


procedure open_test(name);
<* 10 *>
<*----------------------------------------------------------------------*>
<* Åben test filen hvis det er muligt og tilladt.                       *>
<*                                                                      *>
<* name (call) : Navnet på det dokument der skal benyttes som test out  *>
<*                                                                      *>
<*----------------------------------------------------------------------*>
integer array name;
begin
  integer array tail(1:10);
  integer i,stop_result;

  trap(alarm);
  stop_result:=0;
  if test_on then
  begin
    set_cat_bases(sys_bases);
    test_on:=false;
    open(test_out,4,name,1 shift 18 <* end document *>);
    if monitor(42<* lookup entry *>,test_out,0,tail)<>0 then
      stop_result:=1
    else
      if tail(1)<2 then
        stop_result:=2
      else
      begin
        tail(6):=systime(7,0,0.0);
        i:=monitor(44,test_out,0,tail);
        i:=monitor(52,test_out,0,tail)+i;
        i:=monitor(08,test_out,0,tail)+i;
        if i<>0 then
          stop_result:=3;
      end;
    if stop_result=0 then
    begin
      <* initialiser test_out segmenterne *>
      outrec6(test_out,512);
      for i:=1 step 1 until 128 do
        test_out(i):=real <::>;
      for i:=2 step 1 until tail(1) do
        outrec6(test_out,512);
      setposition(test_out,0,0);
      write_message(-10,tail(1),true,<:Test output started:>);
      test_on:=true;
    end
    else
    begin
      test_on:=false;
      write_message(10,stop_result,true,<:Error in test out file:>);
    end;
  end;
  if -,test_on then
    close_test_out;
  if false then
    alarm: disable traped(10);
end;


procedure test_out_error(z,s,b);
<* 11 *>
<*-----------------------------------*>
<* blok procedure for test_out zonen *>
<*-----------------------------------*>
zone z;
integer s,b;
begin
  integer array ia(1:20);

  trap(alarm);
  if false add (s shift (-18)) then
  begin <* EOF Skift tilbage til segment 1 *>
    getzone6(test_out,ia);
    ia(9):=2;
    setzone6(test_out,ia);
    getshare6(test_out,ia,1);
    ia(7):=1;
    setshare6(test_out,ia,1);
    monitor(16,test_out,1,ia);
    check(test_out);
    b:=512;
  end
  else
    close_test_out;
  if false then
    alarm: disable traped(11);
end;

boolean procedure set_cat_bases(bases);
<* 12 *>
<*--------------------------------------*>
<* Sæt cat baserne til angivet base-par *>
<*                                      *>
<* bases(1) : Nedre base værdi.         *>
<* bases(2) : Øvre base værdi.          *>
<* Return   : True= baser sat           *>
<*            False= baser IKKE sat     *>
<*--------------------------------------*>
integer array bases;
begin
  zone this_proc(1,1,stderror);

  trap(alarm);
  open(this_proc,0,<::>,0);
  set_cat_bases:=
      monitor(72<* set catalog base *>,this_proc,0,bases)=0;
  if false then
    alarm: disable traped(12);
end;

integer procedure get_pda(name);
<* 13 *>
<*-----------------------------------------------------------------*>
<* Hent pda for angivet proces                                     *>
<*                                                                 *>
<* name (call) : Navnet på processen som pda skal findes for       *>
<* Return      : pda for proces hvis den findes ellers 0           *>
<*-----------------------------------------------------------------*>
integer array name;
begin
  integer array ia(1:20);
  integer i;
  zone proc(1,1,stderror);

  trap(open_trap);
  getzone6(proc,ia);
  for i:=1,2,3,4 do
    ia(i+1):=name(i);
  setzone6(proc,ia);
  get_pda:=monitor(4,proc,0,ia);
  if false then
    open_trap: get_pda:=0;
end;

boolean procedure get_proc_name(pda,name);
<* 14 *>
<*---------------------------------------------------------------------*>
<* Hent navnet på processen udpeget af proces beskriver adressen i pda *>
<*                                                                     *>
<* pda (call) : Proces beskriver adressen                              *>
<* name (ret) : Navn på proces i  integer array name(1:4)              *>
<* Return     : True  = navn fundet                                    *>
<*              False = navn IKKE fundet                               *>
<*---------------------------------------------------------------------*>
integer pda;
integer array name;
begin
  integer array ia(1:20),bases(1:2);
  integer lt,i;
  boolean ok;
  zone proc(1,1,stderror);

  trap(alarm);
  lt:=trapmode;
  trapmode:=-1;
  ok:=system(5,pda+2,name)=1;
  trap(open_trap);
  getzone6(proc,ia);
  for i:=1,2,3,4 do
    ia(i+1):=name(i);
  setzone6(proc,ia);
  ok:=ok and monitor(4,proc,0,ia)=pda;
  if false then
    open_trap: ok:=false;
  get_proc_name:=ok;
  if not ok then
    name.laf(1):=long <:No connect:>;
  trapmode:=lt;
  if false then
    alarm: disable traped(14);
end;

integer procedure cur_time;
<* 15 *>
<*-------------------------------------------*>
<* Find den aktuelle tid                     *>
<*                                           *>
<* Return   : Aktuelle tid i hel time (0-23) *>
<*-------------------------------------------*>
begin
  real time;

  trap(alarm);
  systime(5,0,time);
  cur_time:=round(time)//10000;
  if false then
    alarm: disable traped(15);
end;


integer procedure date(text);
<* 16 *>
<*-----------------------------------------------------------------------*>
<* Dan dags dato som tekst med følgende format:                          *>
<* <dags navn>  d.<dag>/<måned> 19<år>    <time>.<minut>                 *>
<*                                                                       *>
<* text (ret) : Long array indeholdende dags dato som tekst              *>
<*              Array'ets første 6 longs benyttes (36 tegn)              *>
<* Return     : Antal tegn sat i text                                    *>
<*-----------------------------------------------------------------------*>
long array text;
begin
  real time,year,hour;
  integer day,pos;

  trap(alarm);
  systime(1,0,time);
  day:=(round((time/86400)-0.5) mod 7)+1;
  pos:=1;
  text(5):=text(6):=0;
  case language of
  begin
    put_text(text,pos,case day of (<:Mandag :>,<:Tirsdag:>,
                                   <:Onsdag :>,<:Torsdag:>,
                                   <:Fredag :>,<:Lørdag :>,
                                   <:Søndag :>) ,7);
    put_text(text,pos,case day of (<:Monday   :>,<:Tuesday  :>,
                                   <:Wedensday:>,<:Thursday :>,
                                   <:Friday   :>,<:Saturday :>,
                                   <:Sunday   :>) ,9);
  end;
  put_text(text,pos,<: d.:>,3);
  year:=systime(4,time,hour);
  put_number(text,pos,<<zd>,round(year) mod 100);
  put_text(text,pos,<:/:>,1);
  put_number(text,pos,<<zd >,(round(year) mod 10000)//100);
  put_text(text,pos,<:19:>,2);
  put_number(text,pos,<<zd   >,round(year)//10000);
  put_number(text,pos,<<dd>,round(hour)//10000);
  put_text(text,pos,<:.:>,1);
  put_number(text,pos,<<zd>,(round(hour) mod 10000)//100);
  date:=pos-1;
  if false then
    alarm: disable traped(16);
end;


integer procedure data_to_copy_buf(words,mess_addr,answer);
<* 17 *>
<*------------------------------------------------------------------------*>
<* Kopier data fra anden proces til copy_buf.                             *>
<*                                                                        *>
<* words (call)     : Antal ord der kopieres (max. 256)                   *>
<* mess_addr (call) : Adressen på message der udpeger område der skal     *>
<*                    kopieres fra (2 og 3 ord i message: first,last)     *>
<* answer (ret)     : Resultatet af kopieringen:                          *>
<*                    answer(1) : Udefineret.                             *>
<*                    answer(2) : Antal HW overført                       *>
<*                    answer(3) : Antal tegn overført                     *>
<*                    answer(9) : Hvis returværdi lig 3 så 3 ellers 1     *>
<* Return           : 0 = Data kopieret til copy_buf.                     *>
<*                    2 = Anden proces stoppet.                           *>
<*                    3 = Fejl i kopieringen m.m                          *>
<*------------------------------------------------------------------------*>
integer mess_addr,words;
integer array answer;
begin
  trap(alarm);
  answer(1):=2 shift 1 + 0;
  answer(2):=2;
  answer(3):=2*words;
  answer(4):=0;
  data_to_copy_buf:=monitor(84,copy_buf,mess_addr,answer);
  answer(3):=3*(answer(2)//2);
  if false then
  begin
    alarm: answer(9):=3;
           data_to_copy_buf:=3;
  end;
end;

integer procedure data_from_copy_buf(words,mess_addr,answer);
<* 18 *>
<*------------------------------------------------------------------------*>
<* Kopier data til anden proces fra copy_buf.                             *>
<*                                                                        *>
<* words (call)     : Antal ord der kopieres (max. 256)                   *>
<* mess_addr (call) : Adressen på message der udpeger område der skal     *>
<*                    kopieres til (2 og 3 ord i message: first,last)     *>
<* answer (ret)     : Resultatet af kopieringen:                          *>
<*                    answer(1) : Udefineret.                             *>
<*                    answer(2) : Antal HW overført                       *>
<*                    answer(3) : Antal tegn overført                     *>
<*                    answer(9) : Hvis returværdi lig 3 så 3 ellers 1     *>
<* Return           : 0 = Data kopieret til anden proces                  *>
<*                    2 = Anden proces stoppet.                           *>
<*                    3 = Fejl i kopieringen m.m                          *>
<*------------------------------------------------------------------------*>
integer mess_addr,words;
integer array answer;
begin
  trap(alarm);
  answer(1):=2 shift 1 + 1;
  answer(2):=2;
  answer(3):=2*words;
  answer(4):=0;
  data_from_copy_buf:=monitor(84,copy_buf,mess_addr,answer);
  answer(3):=3*(answer(2)//2);
  if false then
  begin
    alarm: answer(9):=3;
           data_from_copy_buf:=3;
  end;
end;


procedure init_sem;
<* 19 *>
<*----------------------------------------------------*>
<* initialiser semafor navnene med nummer             *>
<* Semafor 5 og frem benyttes af operatør korutinerne *>
<*----------------------------------------------------*>
begin
  free_sem:=-4;                  <* Semafor -4 *>
  delay_sem:=-3;                 <* Semafor -3 *>
  wait_answer_pool:=-2;          <* Semafor -2 *>
  wait_message:=-1;              <* Semafor -1 *>
  wait_message_pool:=0;          <* Semafor  0 *>
  message_buf_pool:=1;           <* Semafor  1 *>
  time_sem:=2;                   <* Semafor  2 *>
  struc_sema:=3;                 <* Semafor  3 *>
  text_write_sem:=4;             <* Semafor  4 *>
end;

procedure konsol_error(z,s,b);
<* 20 *>
<*----------------------------------------------------*>
<* Block procedure for hoved_konsollen                *>
<* Ignorer alle error og give up                      *>
<*----------------------------------------------------*>
zone z;
integer s,b;
begin
end;

procedure init_bases;
<* 22 *>
<*----------------------------------------------------*>
<* Check om  mcl baser og sys baser kan benyttes      *>
<* Sæt catalog baser til sys_bases                    *>
<*----------------------------------------------------*>
begin
  integer array bases(1:6);
  integer b;

  trap(alarm);
  own_pda:=system(6,0,own_name.laf);
  if system(5,own_pda+68,bases)<>1 then
    trap(2);
  b:=0;
  if -,set_cat_bases(cmcl_bases) then
    b:=1;
  if -,set_cat_bases(sys_bases) then
    b:=2;
  if b<>0 then
    write_message(22,b,false,<:Illegal base parameter:>);
  if false then
    alarm: disable traped(22);
end;


procedure keywords_init;
<* 23 *>
<*-------------------------------------------*>
<* initialiser keywords                      *>
<*-------------------------------------------*>
begin
  integer i;

  opr_num_keys:=20;
  for i:=1 step 1 until opr_num_keys do
  begin
    opr_keywords(i):=0;
    opr_keywords(i):= long (case i of
    <*  1 *>  (<:finis:>,<:displ:>,<:messa:>,<:remov:>,<:set:>,
    <*  6 *>   <:start:>,<:stop:>,<:termi:>,<:user:>,<:on:>,
    <* 11 *>   <:off:>,<:all:>,<:signo:>,<:sessi:>,<:syste:>,
    <* 16 *>   <:login:>,<:timec:>,<:users:>,<:resou:>,<:check:>));
  end;
  cat_num_keys:=50;
  for i:=1 step 1 until cat_num_keys do
  begin
    cat_keywords(i):=0;
    cat_keywords(i):= long (case i of
    <*  1 *>  (<:end:>,<:size:>,<:user:>,<:passw:>,<:cpass:>,
    <*  6 *>   <:monda:>,<:tuesd:>,<:wedne:>,<:thurs:>,<:frida:>,
    <* 11 *>   <:satur:>,<:sunda:>,<:block:>,<:sessi:>,<:privi:>,
    <* 16 *>   <:mclna:>,<:base:>,<:group:>,<:mclte:>,<:freet:>,
    <* 21 *>   <:termi:>,<:termt:>,<:termg:>,<:bypas:>,<:type:>,
    <* 26 *>   <:scree:>,<:colum:>,<:lines:>,<:sbup:>,<:sbdow:>,
    <* 31 *>   <:sblef:>,<:sbrig:>,<:sbhom:>,<:sbdel:>,<:ceod:>,
    <* 36 *>   <:ceol:>,<:invon:>,<:invof:>,<:hlon:>,<:hloff:>,
    <* 41 *>   <:delet:>,<:inser:>,<:curso:>,<:up:>,<:down:>,
    <* 46 *>   <:left:>,<:right:>,<:home:>,<:xxxxx:>,<:init:>));
  end;
  init_num_keys:=46;
  for i:=1 step 1 until init_num_keys do
  begin
    init_keywords(i):=0;
    init_keywords(i):= long (case i of
    <*  1 *>  (<:true:>,<:false:>,<:on:>,<:off:>,<:start:>,
    <*  6 *>   <:stop:>,<:catal:>,<:termi:>,<:init:>,<:catdo:>,
    <* 11 *>   <:userc:>,<:termc:>,<:typec:>,<:ctnam:>,<:spool:>,
    <* 16 *>   <:ttnam:>,<:temna:>,<:login:>,<:userb:>,<:termb:>,
    <* 21 *>   <:timec:>,<:logti:>,<:mclba:>,<:sysba:>,<:cpool:>,
    <* 26 *>   <:clink:>,<:maxse:>,<:maxte:>,<:maxsy:>,<:coreb:>,
    <* 31 *>   <:mclpr:>,<:maxty:>,<:tbufs:>,<:spseg:>,<:maxus:>,
    <* 36 *>   <:maxop:>,<:timeo:>,<:hosti:>,<:signo:>,<:timet:>,
    <* 41 *>   <:stopt:>,<:catte:>,<:trap:>,<:termt:>,<:initv:>,
    <* 46 *>   <:reser:>));
  end;
end;

integer procedure find_keyword_value(keyword,tabel);
<* 24 *>
<*----------------------------------------------------------------*>
<* Find 'token' værdien for det angivne keyword                   *>
<*                                                                *>
<* keyword (call) : Long indeholdende op til 5 tegn af keyword    *>
<* tabel (call)   : 1=opr  2=cat  3=init  keword-tabel            *>
<* Return         : Værdien for det angivne keyword eller         *>
<*                  0 hvis keyword er ukendt                      *>
<*----------------------------------------------------------------*>
long keyword;
integer tabel;
begin
  integer i;

  trap(alarm);
  i:=case tabel of (opr_num_keys,cat_num_keys,init_num_keys)+1;
  keyword:=(keyword shift (-8)) shift 8;
  case tabel of
  begin
    for i:=i-1 while (not (keyword=opr_keywords(i))
                        and (i<>0)) do; <* nothing *>
    for i:=i-1 while (not (keyword=cat_keywords(i))
                        and (i<>0)) do; <* nothing *>
    for i:=i-1 while (not (keyword=init_keywords(i))
                        and (i<>0)) do; <* nothing *>
  end;
  find_keyword_value:=i;
  if false then
    alarm: disable traped(24);
end;


procedure init_opera_terms;
<* 25 *>
<*----------------------------------------------------*>
<* init opera_terms array'et                          *>
<*----------------------------------------------------*>
begin
  integer i;

  trap(alarm);
  for i:=4 step 1 until number_of_opera+3 do
  begin
    opera_terms(i,1):=0;
    opera_terms(i,2):=i+2
  end;
  if false then
    alarm: disable traped(25);
end;

procedure next_line(z,z_line_nr);
<* 26 *>
<*-------------------------------------------------------*>
<* Læs til starten af næste linie i fil                  *>
<* Linier der starter med ; eller er blanke overspringes *>
<* Linie tæller optælles med 1 for hver linie            *>
<*                                                       *>
<* z   (call) : Fil  der læses fra.                      *>
<* z_line_nr (call and ret) : Linie tæller for fil,      *>
<*-------------------------------------------------------*>
zone z;
integer z_line_nr;
begin
  integer i;

  trap(alarm);
  repeatchar(z);
  readchar(z,i);
  while (i<>'nl') and (i<>'em') do
    readchar(z,i);
  z_line_nr:=z_line_nr+1;
  readchar(z,i);
  if i<>'em' then
  begin
    while i=' ' do
      readchar(z,i);
    if i='nl' or i='em' or i=';' then
    begin
      next_line(z,z_line_nr);
      readchar(z,i);
    end;
  end;
  repeatchar(z);
  if false then
    alarm: disable traped(26);
end;

integer procedure read_start_key(z,t,z_line_nr);
<* 27 *>
<*-------------------------------------------------------------------*>
<* Find værdien af nøgleordet i starten af tekst linien i fil        *>
<*                                                                   *>
<* z (call) : Filen der læses fra                                    *>
<* t (call) : Keyword tabel. 1=opr  2=cat  3=init                    *>
<* Return : -1  =  Sidste linie i fil er læst                        *>
<*           0  =  Nøgleord er ikke fundet                           *>
<*          >0  =  Nøgleordets værdi                                 *>
<*-------------------------------------------------------------------*>
zone z;
integer t,z_line_nr;
begin
  long array key(1:5);
  integer i;

  trap(alarm);
  readchar(z,i);
  if i<>'em' then
  begin
    while i=' ' do
      readchar(z,i);
    if i='nl' or i='em' or i=';' then
    begin
      next_line(z,z_line_nr);
      readchar(z,i);
    end;
  end;
  repeatchar(z);
  read_start_key:=if readstring(z,key,1)>0 then
                    find_keyword_value(key(1),t)
                  else
                    -1;
  repeatchar(z);
  if false then
    alarm: disable traped(27);
end;

integer procedure read_text(z,text,max);
<* 28 *>
<*---------------------------------------------------------------------*>
<* Læs tekst fra z filen  til text til slutning af linie eller til     *>
<* maximalt antal tegn læst. Indledende blanktegn overspringes.        *>
<*                                                                     *>
<* z (call)    : File der læses fra                                    *>
<* text (ret)  : Den læste tekst                                       *>
<* max  (call) : Det maximale antal tegn der læses                     *>
<* Return      : Antal tegn læst til text                              *>
<*                                                                     *>
<* NB. Der læses altid et tegn mere fra z                              *>
<*---------------------------------------------------------------------*>
zone z;
integer max;
long array text;
begin
  integer ch,pos;
  boolean first;

  trap(alarm);
  pos:=1;
  first:=true;
  repeatchar(z);
  readchar(z,ch);
  if (ch<>'nl') and (ch<>'em') then
  begin
    readchar(z,ch);
    while ch<>'nl' and ch<>'em' and pos<=max do
    begin
      if first and (ch<>' ') then
        first:=false;
      if not first then
        put_ch(text,pos,ch,1);
      readchar(z,ch);
    end;
  end;
  read_text:=pos-1;
  if pos<=max then
    put_ch(text,pos,0,1);
  repeatchar(z);
  if false then
    alarm: disable traped(28);
end;

boolean procedure read_nr(z,nr);
<* 29 *>
<*-----------------------------------------------------------------*>
<* Læs et heltal fra fil z. Er der ikke flere tal på linien        *>
<* returneres -1 ellers det læste tal. Er der angivet ulovligt     *>
<* tal (eller andet end tal) sættes read_nr til false              *>
<*                                                                 *>
<* z (call)    : Zonen der læses fra                               *>
<* nr (ret)    : Læst tal eller -1 hvis ikke flere tal             *>
<* Return      : True = ok  False = illegalt tal                   *>
<*-----------------------------------------------------------------*>
zone z;
integer nr;
begin
  integer ch,class;

  trap(alarm);
  read_nr:=true;
  repeat
    class:=readchar(z,ch);
  until class<>7 or ch=';' ;
  if ch=';' or class=8 then
    nr:=-1
  else
    if class<2 or class>3 then
    begin
      nr:=-1;
      read_nr:=false;
    end
    else
    begin
      repeatchar(z);
      read(z,nr);
    end;
  repeatchar(z);
  if false then
    alarm: disable traped(29);
end;

boolean procedure read_name(z,name,ok);
<* 30 *>
<*---------------------------------------------------------------------*>
<* Læs et navn fra filen z til name. Resterende tegn nulstilles        *>
<* Indledende blanktegn overspringes. Der stoppes ved kommentar        *>
<*                                                                     *>
<* z (call)    : File der læses fra                                    *>
<* name (ret)  : Det læste navn i integer array name(0:3)              *>
<* ok (ret)    : True hvis første tegn er et bogstav                   *>
<* NB. Der læses altid et tegn mere fra z                              *>
<*---------------------------------------------------------------------*>
zone z;
integer array name;
boolean ok;
begin
  integer ch,pos;
  long array field laf;

  trap(alarm);
  for pos:=0,1,2,3 do
    name(pos):=0;
  pos:=1;
  laf:=-2;
  repeatchar(z);
  readchar(z,ch);
  while ch=' ' do
    readchar(z,ch);
  ok:=(ch>='a' and ch<='å');
  while ((ch>='0' and ch<='9') or (ch>='a' and ch<='å')) and pos<=11 do
  begin
    put_ch(name.laf,pos,ch,1);
    readchar(z,ch);
  end;
  repeatchar(z);
  read_name:=not name(0)=0;
  if false then
    alarm: disable traped(30);
end;


procedure open_catalogs(usercat_name,termcat_name,typecat_name);
<* 31 *>
<*-----------------------------------------------------------------*>
<* Åben kataloger og undersøg om disse er ok og kan bruges til i/o *>
<* sæt size og length for hvert katalog                            *>
<* Er newcat=true dannes nye kataloger ud fra teksten i cat_file.  *>
<* cat_doc angiver navnet på dokument hvorpå katalogerne lægges.   *>
<*                                                                 *>
<* usercat_name,                                                   *>
<* termcat_name,                                                   *>
<* typecat_name  (call) : Navnene på katalogerne                   *>
<*-----------------------------------------------------------------*>
integer array usercat_name,termcat_name,typecat_name;
begin
  integer array user_tail,term_tail,type_tail(1:10);
  integer reason,cat_line_nr;
  long array start_key(1:47);


  integer procedure init_catalogs;
  <* 32 *>
  <*----------------------------------------------------------------------*>
  <* Initialiser de 3 kataloger til tomme ud fra størrelserne læst fra    *>
  <* cat_file                                                             *>
  <*                                                                      *>
  <* Return : Reason fra initialiseringen. reason=0 er OK                 *>
  <*----------------------------------------------------------------------*>
  begin
    integer reason,i;

    trap(alarm);
    reason:=0;
    open(cat_file,4,cattxt_name,0);
    i:=read_start_key(cat_file,2,cat_line_nr);
    while i=0 do
    begin
      next_line(cat_file,cat_line_nr);
      i:=read_start_key(cat_file,2,cat_line_nr);
    end;
    if i=2 then
    begin
      read_nr(cat_file,usercat_size);
      read_nr(cat_file,termcat_size);
      read_nr(cat_file,typecat_size);
      if usercat_size<1 or termcat_size<1 or typecat_size<1 then
        reason:=16
      else
      begin
        next_line(cat_file,cat_line_nr);
        user_entry_length:=126;        <************************>
        term_entry_length:=36;         <* Antal hw i entry !!! *>
        type_entry_length:=128;        <************************>
        usercat_size:=(usercat_size-1)//(512//user_entry_length)+2;
        termcat_size:=(termcat_size-1)//(512//term_entry_length)+2;
        typecat_size:=(typecat_size-1)//(512//type_entry_length)+2;
        user_tail(1):=usercat_size;
        user_tail(2):=cat_doc(1);
        user_tail(3):=cat_doc(2);
        user_tail(4):=cat_doc(3);
        user_tail(5):=cat_doc(4);
        user_tail(6):=systime(7,0,0.0);
        user_tail(7):=0;
        user_tail(8):=0;
        user_tail(9):=11 shift 12;
        user_tail(10):=0;
      end;
      if reason=0 then
      begin
        if monitor(40<* create entry *>,usercat,0,user_tail)<>0 then
          reason:=21
        else
          if monitor(50<* permanent *>,usercat,3,user_tail)<>0 then
            reason:=22
          else
            if monitor(52<* create area proc *>,usercat,0,user_tail)<>0 then
               reason:=23
            else
              if monitor(8<* reserve proc *>,usercat,0,user_tail)<>0 then
                reason:=24;
      end;
      if reason=0 then
      begin
        term_tail(1):=termcat_size;
        term_tail(2):=cat_doc(1);
        term_tail(3):=cat_doc(2);
        term_tail(4):=cat_doc(3);
        term_tail(5):=cat_doc(4);
        term_tail(6):=systime(7,0,0.0);
        term_tail(7):=0;
        term_tail(8):=0;
        term_tail(9):=11 shift 12;
        term_tail(10):=0;
        if monitor(40<* create entry *>,termcat,0,term_tail)<>0 then
          reason:=31
        else
          if monitor(50<* permanent *>,termcat,3,term_tail)<>0 then
            reason:=32
          else
            if monitor(52<* create area proc *>,termcat,0,term_tail)<>0 then
               reason:=33
            else
              if monitor(8<* reserve proc *>,termcat,0,term_tail)<>0 then
                reason:=34;
      end;
      if reason=0 then
      begin
        type_tail(1):=typecat_size;
        type_tail(2):=cat_doc(1);
        type_tail(3):=cat_doc(2);
        type_tail(4):=cat_doc(3);
        type_tail(5):=cat_doc(4);
        type_tail(6):=systime(7,0,0.0);
        type_tail(7):=0;
        type_tail(8):=0;
        type_tail(9):=11 shift 12;
        type_tail(10):=0;
        if monitor(40<* create entry *>,typecat,0,type_tail)<>0 then
          reason:=41
        else
          if monitor(50<* permanent *>,typecat,3,type_tail)<>0 then
            reason:=42
          else
            if monitor(52<* create area proc *>,typecat,0,type_tail)<>0 then
               reason:=43
            else
              if monitor(8<* reserve proc *>,typecat,0,type_tail)<>0 then
                reason:=44;
      end;
      if reason=0 then
      begin <* initialiser katalog indholdet *>
        setposition(usercat,0,1);
        outrec6(usercat,512);
        for i:=1 step 1 until 128 do
          usercat(i):=real <::>;
        for i:=3 step 1 until usercat_size do
          outrec6(usercat,512);
        setposition(usercat,0,0);
        outrec6(usercat,512);
        usercat.iaf(1):=1; <* Bruger katalog = 1 *>
        usercat.iaf(2):=usercat_size;
        usercat.iaf(3):=user_entry_length;
        usercat.iaf(4):=systime(7,0,0.0);
        setposition(usercat,0,0);
        user_seg:=-1;
        setposition(termcat,0,1);
        outrec6(termcat,512);
        for i:=1 step 1 until 128 do
          termcat(i):=real <::>;
        for i:=3 step 1 until termcat_size do
          outrec6(termcat,512);
        setposition(termcat,0,0);
        term_seg:=-1;
        outrec6(termcat,512);
        termcat.iaf(1):=2; <* Terminal katalog = 2 *>
        termcat.iaf(2):=termcat_size;
        termcat.iaf(3):=term_entry_length;
        termcat.iaf(4):=systime(7,0,0.0);
        setposition(termcat,0,0);
        setposition(typecat,0,1);
        outrec6(typecat,512);
        for i:=1 step 1 until 128 do
          typecat(i):=real <::>;
        for i:=3 step 1 until typecat_size do
          outrec6(typecat,512);
        setposition(typecat,0,0);
        outrec6(typecat,512);
        typecat.iaf(1):=3; <* Type katalog = 3 *>
        typecat.iaf(2):=typecat_size;
        typecat.iaf(3):=type_entry_length;
        typecat.iaf(4):=systime(7,0,0.0);
        setposition(typecat,0,0);
      end;
    end
    else
      reason:=17;
    init_catalogs:=reason;
    if false then
      alarm: disable traped(32);
  end;

  integer procedure fill_catalogs;
  <* 33 *>
  <*-----------------------------------------------------*>
  <* Hent data fra cat_file og indsæt i relevant katalog *>
  <*-----------------------------------------------------*>
  begin
    integer reason,key,i,first,last,type,term_type,priv;
    integer array group,pgn,term_id,user_id(0:4);
    long array password(1:8);
    boolean ok;

    procedure clear_high(i);
    <* 32 *>
    integer i;
    begin
      i:=(i shift 12) shift (-12);
    end;

    procedure clear_low(i);
    <* 33 *>
    integer i;
    begin
      i:=(i shift (-12)) shift 12;
    end;

    trap(alarm);
    reason:=0;
    key:=read_start_key(cat_file,2,cat_line_nr);
    while (key<>1 <* end *>) and (key<>-1) and (reason=0) do
    begin
      if key=3 then
      begin <* user entry *>
        if not read_name(cat_file,user_id,ok) then
          goto ill_nr;
        if not ok then
          goto ill_nr;
        for i:=3,2,1,0 do
          user_id(i+1):=user_id(i);
        if not find_user(user_id) then
        begin
          if find_empty_user_entry(calc_hash(user_id,usercat_size)) then
          begin
            <* init entry *>
            for i:=2 step 1 until 5 do
              usercat.user_entry(i):=user_id(i-1);
            usercat.user_entry(12):=1 shift 12; <* max user index *>
            usercat.user_entry(23):=2 shift 12; <* mcl def. text *>
            usercat.user_entry(19):=1 shift 23; <* term. group 0 *>
            next_line(cat_file,cat_line_nr);
            key:=read_start_key(cat_file,2,cat_line_nr);
            while (key>=4) and (key<=20) do
            begin
              <* indsæt i entry *>
              if (key>=6) and (key<=12) then
              begin <* læs first og last for login tid *>
                if not (read_nr(cat_file,first) and
                        read_nr(cat_file,last)) then
                  goto ill_nr;
                if first<0 or first>24 or last<0 or last>24 then
                  goto ill_nr;
                type:=if first<1 and last>23 then
                        3
                      else
                        if first=last then
                          0
                        else
                          if first<last then
                            1
                          else
                            2;
              end;
              begin
                case key-3 of
                begin
                  begin <* password *>
                    for i:=1 step 1 until 8 do
                      password(i):=0;
                    usercat.user_entry(6):=0;
                    usercat.user_entry(7):=0;
                    if read_text(cat_file,password,48)>0 then
                    begin <* kod password *>
                      for last:=1 step 1 until 31 do
                      begin
                        key:=password.baf(last) extract 12;
                        for i:=last+1 step 1 until 32 do
                          password.baf(i):=false add
                            ((password.baf(i) extract 12) + key);
                      end;
                      for i:=1 step 1 until 16 do
                      begin
                        usercat.user_entry(6):=usercat.user_entry(6)+
                          password.iaf(i);
                        usercat.user_entry(7):=usercat.user_entry(7)+
                          usercat.user_entry(6);
                      end;
                    end;
                  end;
                  begin <* kodet password *>
                    read(cat_file,password(1));
                    usercat.user_entry(6):=password(1) shift (-24);
                    usercat.user_entry(7):=password(1) extract 24;
                  end;
                  begin <* monday  *>
                    clear_high(usercat.user_entry(8));
                    usercat.user_entry(8):=usercat.user_entry(8)+
                       ((first shift 7)+(last shift 2) + type) shift 12;
                  end;
                  begin <* tuesday *>
                    clear_low(usercat.user_entry(8));
                    usercat.user_entry(8):=usercat.user_entry(8)+
                       ((first shift 7)+(last shift 2) + type);
                  end;
                  begin <* wednesday *>
                    clear_high(usercat.user_entry(9));
                    usercat.user_entry(9):=usercat.user_entry(9)+
                       ((first shift 7)+(last shift 2) + type) shift 12;
                  end;
                  begin <* thursday *>
                    clear_low(usercat.user_entry(9));
                    usercat.user_entry(9):=usercat.user_entry(9)+
                       ((first shift 7)+(last shift 2) + type);
                  end;
                  begin <* friday  *>
                    clear_high(usercat.user_entry(10));
                    usercat.user_entry(10):=usercat.user_entry(10)+
                       ((first shift 7)+(last shift 2) + type) shift 12;
                  end;
                  begin <* saturday *>
                    clear_low(usercat.user_entry(10));
                    usercat.user_entry(10):=usercat.user_entry(10)+
                       ((first shift 7)+(last shift 2) + type);
                  end;
                  begin <* sunday  *>
                    clear_high(usercat.user_entry(11));
                    usercat.user_entry(11):=usercat.user_entry(11)+
                       ((first shift 7)+(last shift 2) + type) shift 12;
                  end;
                  begin <* block *>
                    clear_low(usercat.user_entry(11));
                    if not read_nr(cat_file,i) or i<0 then
                      goto ill_nr;
                    usercat.user_entry(11):=usercat.user_entry(12)+i;
                  end;
                  begin <* index *>
                    clear_high(usercat.user_entry(12));
                    if not read_nr(cat_file,i) then
                      goto ill_nr;
                    if i>9 or i<1 then
                      goto ill_nr;
                    usercat.user_entry(12):=usercat.user_entry(12)+
                       (i shift 12);
                  end;
                  begin <* privilegier *>
                    priv:=0;
                    clear_low(usercat.user_entry(12));
                    if not read_nr(cat_file,i) then
                      goto ill_nr;
                    while i>=0 do
                    begin
                      if i>11 then
                        goto ill_nr;
                      priv:=priv+(1 shift (11-i));
                      if not read_nr(cat_file,i) then
                        goto ill_nr;
                    end;
                    usercat.user_entry(12):=usercat.user_entry(12)+priv;
                  end;
                  begin <* mcl name *>
                    if not read_name(cat_file,pgn,ok) then
                      goto ill_nr;
                    if not ok then
                      goto ill_nr;
                    for i:=0 step 1 until 3 do
                      usercat.user_entry(i+13):=pgn(i);
                  end;
                  begin <* cmcl bases *>
                    if not (read_nr(cat_file,first) and
                            read_nr(cat_file,last)) then
                      goto ill_nr;
                    if first>last then
                      goto ill_nr;
                    usercat.user_entry(17):=first;
                    usercat.user_entry(18):=last;
                  end;
                  begin <* groups *>
                    for i:=1 step 1 until 4 do
                      group(i):=0;
                    if not read_nr(cat_file,i) then
                      goto ill_nr;
                    while (i>=0) and (i<=95) do
                    begin
                      first:=(i//24)+1;
                      last:=23-(i mod 24);
                      if not (false add (group(first) shift (-last))) then
                        group(first):=group(first)+(1 shift last);
                      if not read_nr(cat_file,i) then
                        goto ill_nr;
                    end;
                    for i:=1 step 1 until 4 do
                      usercat.user_entry(18+i):=group(i);
                  end;
                  begin <* mcl text *>
                    laf:=46;
                    i:=read_text(cat_file,usercat.user_entry.laf,80);
                    usercat.user_entry(23):=
                       ((((i+2)//3*2)+2) shift 12) + i;
                    laf:=0;
                  end;
                  begin <* free text *>
                    laf:=100;
                    read_text(cat_file,usercat.user_entry.laf,30);
                    laf:=0;
                  end;
                end;
              end;
              next_line(cat_file,cat_line_nr);
              key:=read_start_key(cat_file,2,cat_line_nr);
            end;
            write_user_seg;
          end
          else
            reason:=101; <* Ikke flere entries *>
        end
        else
          reason:=102; <* Entry eksisterer *>
      end
      else
        if key=21 then
        begin <* terminal entry *>
          if not read_name(cat_file,term_id,ok) then
            goto ill_nr;
          for i:=3 step (-1) until 0 do
            term_id(i+1):=term_id(i);
          if not find_term(term_id) then
          begin
            if find_empty_term_entry(calc_hash(term_id,termcat_size)) then
            begin
              <* init entry *>
              for i:=2 step 1 until 5 do
                termcat.term_entry(i):=term_id(i-1);
              termcat.term_entry(6):=1 shift 12; <* terminal type *>
              next_line(cat_file,cat_line_nr);
              key:=read_start_key(cat_file,2,cat_line_nr);
              while (key=13) or (key=20) or (key>=22 and key<=24) do
              begin
                <* indsæt i entry *>
                if key=22 then
                begin <* Terminal type *>
                  if not read_nr(cat_file,i) or i<0 or i>2047 then
                    goto ill_nr;
                  clear_high(termcat.term_entry(6));
                  termcat.term_entry(6):=termcat.term_entry(6)+
                     i shift 12;
                end;
                if key=13 then
                begin <* Block *>
                  if not read_nr(cat_file,i) or i<0 then
                    goto ill_nr;
                  clear_low(termcat.term_entry(6));
                  termcat.term_entry(6):=termcat.term_entry(6)+i;
                end;
                if key=23 then
                begin <* terminal group *>
                  if not read_nr(cat_file,i) or i<0 or i>95 then
                    goto ill_nr;
                  clear_low(termcat.term_entry(7));
                  termcat.term_entry(7):=termcat.term_entry(7)+i;
                end;
                if key=24 then
                begin <* bypass *>
                  clear_high(termcat.term_entry(7));
                  termcat.term_entry(7):=termcat.term_entry(7)+(1 shift 12);
                end;
                if key=20 then
                begin <* free text *>
                  laf:=14;
                  read_text(cat_file,termcat.term_entry.laf,30);
                  laf:=0;
                end;
                next_line(cat_file,cat_line_nr);
                key:=read_start_key(cat_file,2,cat_line_nr);
              end;
              write_term_seg;
            end
            else
              reason:=105; <* Ikke flere entries *>
          end
          else
            reason:=106; <* Entry eksisterer *>
        end
        else
          if key=25 then
          begin <* type entry *>
            if not read_nr(cat_file,term_type) or term_type<1 then
              goto ill_nr;
            if find_type_entry(term_type) then
            begin
              if typecat.type_entry(1) = 0 then
              begin
                <* init entry *>
                typecat.type_entry(1):=term_type; <* terminal type *>
                typecat.type_entry(3):=(80 shift 12)+24;
                next_line(cat_file,cat_line_nr);
                key:=read_start_key(cat_file,2,cat_line_nr);
                while (key>=26) or (key=20) do
                begin
                  <* indsæt i entry *>
                  if key=26 then
                  begin <* screen type *>
                    priv:=0;
                    if not read_nr(cat_file,i) or i>23 then
                      goto ill_nr;
                    while i>=0 do
                    begin
                      if i>23 then
                        goto ill_nr;
                      priv:=priv+(1 shift (23-i));
                      if not read_nr(cat_file,i) then
                        goto ill_nr;
                    end;
                    typecat.type_entry(2):=priv;
                  end;
                  if (key>=27) and (key<=34) then
                  begin <* 'send by' værdier *>
                    boolean array field baf;
                    baf:=0;
                    if not read_nr(cat_file,i) or i>255 or i<0 then
                      goto ill_nr;
                    typecat.type_entry.baf(key-22):=if i>0 then
                                                      false add i
                                                    else
                                                      false;
                  end;
                  if (key>=44) and (key<=49) then
                  begin <* et tegns  værdier *>
                    boolean array field baf;
                    baf:=0;
                    if not read_nr(cat_file,i) or i>255 or i<0 then
                      goto ill_nr;
                    typecat.type_entry.baf(key+7):=if i>0 then
                                                      false add i
                                                    else
                                                      false;
                  end;
                  if (key>=35) and (key<=42) then
                  begin <* 6 tegns sekevnser *>
                    if not read_nr(cat_file,i) or i>255 or i<0 then
                      goto ill_nr;
                    first:=1;
                    laf:=case (key-34) of
                         (12,16,20,24,28,32,36,40);
                    typecat.type_entry.laf(1):=0;
                    while (i<>-1) and (first<=6) do
                    begin
                      put_ch(typecat.type_entry.laf,first,i,1);
                      if first<=6 then
                      begin
                        if not read_nr(cat_file,i) or i>255 or i<(-1) then
                          goto ill_nr;
                      end;
                    end;
                    laf:=0;
                  end;
                  if key=43 then
                  begin <* cursor sekvens *>
                    if not read_nr(cat_file,i) or i>255 or i<0 then
                      goto ill_nr;
                    first:=1;
                    laf:=44;
                    while (i<>-1) and (first<=9) do
                    begin
                      put_ch(typecat.type_entry.laf,first,i,1);
                      if first<=9 then
                      begin
                        if not read_nr(cat_file,i) or i>255 or i<(-1) then
                          goto ill_nr;
                      end;
                    end;
                    laf:=0;
                  end;
                  if key=50 then
                  begin <* initialiserings sekvens *>
                    laf:=56;
                    if not read_nr(cat_file,i) or i>255 or i<0 then
                      goto ill_nr;
                    first:=1;
                    while (i<>-1) and (first<=75) do
                    begin
                      put_ch(typecat.type_entry.laf,first,i,1);
                      if first<=75 then
                      begin
                        if not read_nr(cat_file,i) or i>255 or i<(-1) then
                          goto ill_nr;
                      end;
                    end;
                    laf:=0;
                  end;
                  if key=20 then
                  begin <* free text *>
                    laf:=106;
                    read_text(cat_file,typecat.type_entry.laf,30);
                    laf:=0;
                  end;
                  next_line(cat_file,cat_line_nr);
                  key:=read_start_key(cat_file,2,cat_line_nr);
                end;
                write_type_seg;
              end
              else
                reason:=108; <* Entry eksisterer *>
            end
            else
              reason:=109; <* Illegal type *>
          end
          else
            if key<>65 then
              reason:=100; <* illegal entry key *>
    end;
    if false then
      ill_nr: reason:=110;
    fill_catalogs:=reason;
    if false then
      alarm: disable traped(33);
  end;


  <*****************************>
  <* Hoveddel af open_catalogs *>
  <*****************************>
  trap(alarm);
  cat_line_nr:=1;
  set_cat_bases(sys_bases);
  open(usercat,4,usercat_name,1 shift 9  <* passivate    *>    );
  open(termcat,4,termcat_name,1 shift 9  <* passivate    *>    );
  open(typecat,4,typecat_name,0       <* NO passivate    *>    );
  reason:=0;
  if monitor(42<* lookup *>,usercat,0,user_tail)<>0 then
    reason:=1
  else
    if new_catalog then
      monitor(48 <*remove entry*>,usercat,0,user_tail);
  if monitor(42<* lookup *>,termcat,0,term_tail)<>0 then
    reason:=2
  else
    if new_catalog then
      monitor(48 <*remove entry*>,termcat,0,term_tail);
  if monitor(42<* lookup *>,typecat,0,type_tail)<>0 then
    reason:=3
  else
    if new_catalog then
      monitor(48 <*remove entry*>,typecat,0,type_tail);
  if (not new_catalog) and (reason=0) then
  begin <* alle kataloger findes, test ydeligerer *>
    usercat_size:=user_tail(1);
    termcat_size:=term_tail(1);
    typecat_size:=type_tail(1);
    if monitor(92<* create area proc *>,usercat,0,user_tail)<>0 then
      reason:=4
    else
      if monitor(8<* reserve proc *>,usercat,0,user_tail)<>0 then
        reason:=5
      else
      begin
        user_seg:=-1;
        find_user_seg(0);
        user_entry:=0;
        if usercat.user_entry(1)<>1 then
          reason:=6
        else
          if usercat.user_entry(2)<>usercat_size then
            reason:=7
          else
            user_entry_length:=usercat.user_entry(3);
      end;
    if reason=0 then
    begin
      if monitor(92<* create area proc *>,termcat,0,term_tail)<>0 then
        reason:=8
      else
        if monitor(8<* reserve proc *>,termcat,0,term_tail)<>0 then
          reason:=9
        else
        begin
          term_seg:=-1;
          find_term_seg(0);
          term_entry:=0;
          if termcat.term_entry(1)<>2 then
            reason:=10
          else
            if termcat.term_entry(2)<>termcat_size then
              reason:=11
            else
              term_entry_length:=termcat.term_entry(3);
        end;
    end;
    if reason=0 then
    begin
      if monitor(92<* create area proc *>,typecat,0,type_tail)<>0 then
        reason:=12
      else
        if monitor(8<* reserve proc *>,typecat,0,type_tail)<>0 then
          reason:=13
        else
        begin
          setposition(typecat,0,0);
          inrec6(typecat,512);
          type_entry:=0;
          if typecat.type_entry(1)<>3 then
            reason:=14
          else
            if typecat.type_entry(2)<>typecat_size then
              reason:=15
            else
              type_entry_length:=typecat.user_entry(3);
        end;
    end;
  end
  else
    if new_catalog then
    begin <* ingen kataloger findes, opret nye *>
      write_message(31,0,true,<:Generating new catalog:>);
      reason:=init_catalogs;
      if reason=0 then
        reason:=fill_catalogs;
      close(cat_file,true);
    end;
  if reason<>0 then
    write_message(cat_line_nr,reason,false,<:Catalog error:>);
  if false then
    alarm: disable traped(31);
end;

integer procedure calc_hash(id,cat_size);
<* 34 *>
<*-----------------------------------------------------------*>
<* Beregn hash key ud fra navnet i id og kataloget størrelse *>
<*                                                           *>
<* id (call)       : Navnet som hash nøglen beregnes for     *>
<*                   navnet står i integer array id(1:4)     *>
<* cat_size (call) : Størrelsen af kataloget hvortil hash    *>
<*                   skal benyttes                           *>
<* Return          : Den beregnede hash nøgle.               *>
<*-----------------------------------------------------------*>
integer array id;
integer cat_size;
begin
  calc_hash:=1+((abs(id(1)+id(2)+id(3)+id(4))) mod (cat_size-1));
end;


procedure find_user_seg(seg_nr);
<* 35 *>
<*----------------------------------------------------------*>
<* Find segment i usercat og indlæs dette. Udskriv aktuelt  *>
<* segment, hvis wflag er sat.                              *>
<*                                                          *>
<* seg_nr (call) : Nummeret på det segment der ønskes       *>
<*----------------------------------------------------------*>
integer seg_nr;
begin
  integer array ia(1:20);

  trap(alarm);
  if seg_nr>(usercat_size-1) or seg_nr<0 then
    write_message(35,seg_nr,false,<:Illegal seg_nr in cat.:>)
  else
    if seg_nr<>user_seg then
    begin
      setposition(usercat,0,seg_nr);
      inrec6(usercat,512);
      getzone6(usercat,ia);
      ia(9):=seg_nr;
      setzone6(usercat,ia);
      user_seg:=seg_nr;
    end;
  if false then
    alarm: disable traped(35);
end;

procedure write_user_seg;
<* 36 *>
<*----------------------------------------------------------*>
<* Opdater aktuelt user segment på disken. Segmentet for-   *>
<* bliver i zone-bufferen med state: opend and positioned.  *>
<*----------------------------------------------------------*>
begin
  integer array ia(1:20);

  trap(alarm);
  setstate(usercat,6);
  if (user_seg>usercat_size-1) or (user_seg<0) then
    write_message(36,user_seg,false,<:Illegal seg_nr in cat.:>);
  setposition(usercat,0,user_seg);
  inrec6(usercat,512);
  getzone6(usercat,ia);
  ia(9):=user_seg;
  setzone6(usercat,ia);
  if false then
    alarm: disable traped(36);
end;

procedure next_user_entry;
<* 37 *>
<*----------------------------------------------------------*>
<* Find næste user_entry i katalog. Er aktuelt entry sidste *>
<* i katalog sættes næste entry til det første i kataloget  *>
<*----------------------------------------------------------*>
begin
  integer seg_nr;

  trap(alarm);
  user_entry:=user_entry+user_entry_length;
  if (511-user_entry)<user_entry_length then
  begin
    seg_nr:=if user_seg=usercat_size-1 then
              1 <* Segment 0 benyttes til katalog information *>
            else
              user_seg+1;
    find_user_seg(seg_nr);
    user_entry:=2;
  end;
  if false then
    alarm: disable traped(37);
end;

boolean procedure find_user(user_id);
<* 38 *>
<*----------------------------------------------------------*>
<* Find user_entry i katalog med key som angivet user_id    *>
<*                                                          *>
<* user_id  (call)  : Bruger navn i integer array (1:4)     *>
<* Return           : True=fundet,  False=ikke fundet       *>
<*----------------------------------------------------------*>
integer array user_id;
begin
  integer field hash_count;
  integer i,hash;
  boolean found;

  trap(alarm);
  hash:=calc_hash(user_id,usercat_size);
  find_user_seg(hash);
  hash_count:=2;
  hash_count:=usercat.hash_count;
  user_entry:=2;
  if hash_count>0 then
  begin
    repeat
      if usercat.user_entry(1)=hash then
      begin
        found:=true;
        hash_count:=hash_count-1;
        for i:=2, i+1 while (i<=5 and found) do
          if usercat.user_entry(i)<>user_id(i-1) then
            found:=false;
      end
      else
        found:=false;
      if not found then
        next_user_entry;
    until found or hash_count=0 or
          (user_seg=hash and user_entry=2);
    if not found and hash_count>0 then
      write_message(38,1,true,<:Cyclic in catalog:>);
  end
  else
    found:=false;
  find_user:=found;
  if false then
    alarm: disable traped(38);
end;

boolean procedure find_empty_user_entry(hash_key);
<* 39 *>
<*----------------------------------------------------------*>
<* Find første tomme user_entry hørende til hash_key        *>
<* Optæl hash key tæller i hash segmentet. Sæt user_entry   *>
<* til fundet entry. Hash_key indsættes i fundet segment.   *>
<* Entry SKAL udskrives på disken efter indsættelse af data *>
<*                                                          *>
<* hash_key (call)  : Hash nøglen hørende til det segment   *>
<*                    hvorfra der søges efter tomt entry    *>
<* Return           : True=Entry fundet. Sat i user_entry   *>
<*                    False=Ikke mere plads i katalog       *>
<*----------------------------------------------------------*>
integer hash_key;
begin
  boolean room;

  trap(alarm);
  find_user_seg(hash_key);
  user_entry:=0;
  usercat.user_entry(1):=usercat.user_entry(1)+1;
  setstate(usercat,6);
  user_entry:=2;
  room:=true;
  while usercat.user_entry(1)<>0 and room do
  begin
    next_user_entry;
    if (hash_key=user_seg) and (user_entry=2) then
      room:=false;
  end;
  if not room then
  begin
    find_empty_user_entry:=false;
    find_user_seg(hash_key);
    user_entry:=0;
    usercat.user_entry(1):=usercat.user_entry(1)-1;
    write_user_seg;
  end
  else
  begin
    find_empty_user_entry:=true;
    usercat.user_entry(1):=hash_key;
  end;
  if false then
    alarm: disable traped(39);
end;


procedure find_term_seg(seg_nr);
<* 40 *>
<*----------------------------------------------------------*>
<* Find segment i termcat og indlæs dette. Udskriv aktuelt  *>
<* segment, hvis wflag er sat.                              *>
<*                                                          *>
<* seg_nr (call) : Nummeret på det segment der ønskes       *>
<*----------------------------------------------------------*>
integer seg_nr;
begin
  integer array ia(1:20);

  trap(alarm);
  if seg_nr>(termcat_size-1) or seg_nr<0 then
    write_message(40,seg_nr,false,<:Illegal seg_nr in cat.:>)
  else
    if seg_nr<>term_seg then
    begin
      setposition(termcat,0,seg_nr);
      inrec6(termcat,512);
      getzone6(termcat,ia);
      ia(9):=seg_nr;
      setzone6(termcat,ia);
      term_seg:=seg_nr;
    end;
  if false then
    alarm: disable traped(40);
end;

procedure write_term_seg;
<* 41 *>
<*----------------------------------------------------------*>
<* Opdater aktuelt term segment på disken. Segmentet for-   *>
<* bliver i zone-bufferen med state: opend and positioned.  *>
<*----------------------------------------------------------*>
begin
  integer array ia(1:20);

  trap(alarm);
  setstate(termcat,6);
  if (term_seg>termcat_size-1) or (term_seg<0) then
    write_message(41,term_seg,false,<:Illegal seg_nr in cat.:>);
  setposition(termcat,0,term_seg);
  inrec6(termcat,512);
  getzone6(termcat,ia);
  ia(9):=term_seg;
  setzone6(termcat,ia);
  if false then
    alarm: disable traped(41);
end;

procedure next_term_entry;
<* 42 *>
<*----------------------------------------------------------*>
<* Find næste term_entry i katalog. Er aktuelt entry sidste *>
<* i katalog sættes næste entry til det første i kataloget  *>
<*----------------------------------------------------------*>
begin
  integer seg_nr;

  trap(alarm);
  term_entry:=term_entry+term_entry_length;
  if (511-term_entry)<term_entry_length then
  begin
    seg_nr:=if term_seg=termcat_size-1 then
              1 <* Segment 0 benyttes til katalog information *>
            else
              term_seg+1;
    find_term_seg(seg_nr);
    term_entry:=2;
  end;
  if false then
    alarm: disable traped(42);
end;

boolean procedure find_term(term_id);
<* 43 *>
<*----------------------------------------------------------*>
<* Find term_entry i katalog med key som angivet term_id    *>
<*                                                          *>
<* term_id  (call)  : Terminal navn (integer array (1:4))   *>
<* Return           : True=fundet,  False=ikke fundet       *>
<*----------------------------------------------------------*>
integer array term_id;
begin
  integer field hash_count;
  integer i,hash;
  boolean found;

  trap(alarm);
  hash:=calc_hash(term_id,termcat_size);
  find_term_seg(hash);
  hash_count:=2;
  hash_count:=termcat.hash_count;
  term_entry:=2;
  if hash_count>0 then
  begin
    repeat
      if termcat.term_entry(1)=hash then
      begin
        found:=true;
        hash_count:=hash_count-1;
        for i:=2, i+1 while (i<=5 and found) do
          if termcat.term_entry(i)<>term_id(i-1) then
            found:=false;
      end
      else
        found:=false;
      if not found then
        next_term_entry;
    until found or hash_count=0 or
          (term_seg=hash and term_entry=2);
    if not found and hash_count>0 then
      write_message(43,2,true,<:Cyclic in catalog:>);
  end
  else
    found:=false;
  find_term:=found;
  if false then
    alarm: disable traped(43);
end;

boolean procedure find_empty_term_entry(hash_key);
<* 44 *>
<*----------------------------------------------------------*>
<* Find første tomme term_entry hørende til hash_key        *>
<* Optæl hash key tæller i hash segmentet. Sæt term_entry   *>
<* til fundet entry. Hash_key indsættes i fundet segment.   *>
<* Entry SKAL udskrives på disken efter indsættelse af data *>
<*                                                          *>
<* hash_key (call)  : Hash nøglen hørende til det segment   *>
<*                    hvorfra der søges efter tomt entry    *>
<* Return           : True=Entry fundet. Sat i term_entry   *>
<*                    False=Ikke mere plads i katalog       *>
<*----------------------------------------------------------*>
integer hash_key;
begin
  boolean room;

  trap(alarm);
  find_term_seg(hash_key);
  term_entry:=0;
  termcat.term_entry(1):=termcat.term_entry(1)+1;
  setstate(termcat,6);
  term_entry:=2;
  room:=true;
  while termcat.term_entry(1)<>0 and room do
  begin
    next_term_entry;
    if (hash_key=term_seg) and (term_entry=2) then
      room:=false;
  end;
  if not room then
  begin
    find_empty_term_entry:=false;
    find_term_seg(hash_key);
    term_entry:=0;
    termcat.term_entry(1):=termcat.term_entry(1)-1;
    write_term_seg;
  end
  else
  begin
    find_empty_term_entry:=true;
    termcat.term_entry(1):=hash_key;
  end;
  if false then
    alarm: disable traped(44);
end;

boolean procedure find_type_entry(type_nr);
<* 45 *>
<*----------------------------------------------------------*>
<* Find entry hørende til angivet type. Sæt type_entry      *>
<* BEMÆRK: Benyttes parallelt i catalog, operatør og        *>
<*         timecheck korutinerne                            *>
<*                                                          *>
<* type_nr (call)  : typen af terminalen >0                 *>
<* Return          : True=Entry fundet,  False= IKKE fundet *>
<*                   field type_entry sat til entry         *>
<*----------------------------------------------------------*>
integer type_nr;
begin
  integer seg;
  integer array ia(1:20);

  trap(alarm);
  seg:=(type_nr-1)//(512//type_entry_length)+1;
  if seg > typecat_size-1 or seg<1 or type_nr<1 then
    find_type_entry:=false
  else
  begin
    type_entry:=type_entry_length*((type_nr-1) mod (512//type_entry_length));
    setposition(typecat,0,seg);
    inrec6(typecat,512);  <* NO passivate *>
    getzone6(typecat,ia);
    ia(9):=seg;
    setzone6(typecat,ia);
    find_type_entry:=true;
  end;
  if false then
    alarm: disable traped(45);
end;

procedure write_type_seg;
<* 46 *>
<*----------------------------------------------------------*>
<* Opdater aktuelt type segment på disken. Segmentet for-   *>
<* bliver i zone-bufferen med state: opend and positioned.  *>
<*----------------------------------------------------------*>
begin
  integer seg;
  integer array ia(1:20);

  trap(alarm);
  getposition(typecat,0,seg);
  setstate(typecat,6);
  setposition(typecat,0,seg);
  inrec6(typecat,512);
  getzone6(typecat,ia);
  ia(9):=seg;
  setzone6(typecat,ia);
  if false then
    alarm: disable traped(46);
end;

procedure read_param_line;
<* 47 *>
<*---------------------------------------------------------------*>
<* Læs parametre fra fp kaldet                                   *>
<* Sæt : new_catalog  /  cattxt_name                             *>
<*       init_file_name                                          *>
<*       fp_maxterms                                             *>
<*                                                               *>
<* init_file_name sættes default til: 'tasinit' men ændres       *>
<* hvis der angives init.<name> i kald                           *>
<* maxterms sættes fra kald hvis der angives terminals.<antal>   *>
<* ellers sættes maxterms fra init_file.                         *>
<* Angives catalog.<name> sættes <name> i cattxt_name og         *>
<* new_catalog sættes true                                       *>
<*---------------------------------------------------------------*>
begin
  integer j,seperator,i,key;
  real array item(1:2);

  trap(alarm);
  new_catalog:=false;
  fp_maxterms:=0;
  init_file_name.laf(1):=init_file_name.laf(2):=0;
  put_text(init_file_name.laf,1,<:tasinit:>);  <* Default init name *>
  i:=1;
  repeat
    seperator:=system(4,i,item);
    i:=i+1;
    if seperator=(4 shift 12) + 10 then
    begin
      key:=find_keyword_value(item.laf(1),3);
      seperator:=system(4,i,item);
      i:=i+1;
      if key=7 then
      begin
        if seperator=(8 shift 12) + 10 then
        begin
          new_catalog:=true;
          for j:=1,2 do
            cattxt_name.laf(j):=item.laf(j);
        end
        else
          write_message(47,i,false,<:Illegal call parameter:>);
      end
      else
        if key=9 then
        begin
          if seperator=(8 shift 12) + 10 then
          begin
            for j:=1,2 do
              init_file_name.laf(j):=item.laf(j);
          end
          else
            write_message(47,i,false,<:Illegal call parameter:>);
        end
        else
          if key=8 then
          begin
            if seperator=(8 shift 12) + 4 then
              fp_maxterms:=item(1)
            else
              write_message(47,i,false,<:Illegal call parameter:>);
          end
          else
            write_message(47,i,false,<:Unknown call parameter:>);
    end;
  until seperator=0;
  if false then
    alarm: disable traped(47);
end;

procedure init_tascat;
<* 48 *>
<*-------------------------------------------------------*>
<* Initialiser tascat variable.                          *>
<* Data hentes enten fra init fil eller der benyttes     *>
<* standard værdi. Beskrivelsen af data typer og         *>
<* standard værdier sættes i procedure init_param_arrays *>
<*-------------------------------------------------------*>
begin
  zone init_file(128,1,std_error);
  integer array val(0:45);
  integer array init_type,init_count(1:init_num_keys-9);
  integer array init_lim(1:init_num_keys-9,1:2);
  long array init_default(1:init_num_keys-9);
  integer array spoolname,ttname,temname(1:4);
  integer spseg,textbufsize,timeout,tbufsize,ttmask,reserve,i;

procedure init_param_arrays;
<* 49 *>
<*-------------------------------------------------*>
<* Initialiser arrays der beskriver data typer m.m *>
<*-------------------------------------------------*>
begin
  long f,t;
  integer i;
  integer max,min;

  <*********************************************************************>
  <* Følgende arrays initialiseres:                                    *>
  <* integer array init_type(1:???) ; Beskriver typen af data :        *>
  <*   0 = IKKE brugt                                                  *>
  <*   1 = cmcl-tekst                                                  *>
  <*   2 = navn                                                        *>
  <*   3 = heltal (integer)                                            *>
  <*   4 = logisk (boolean)                                            *>
  <*   5 = 2 heltal (integer)                                          *>
  <*                                                                   *>
  <* long array init_default(1:???) ; Standard værdi :                 *>
  <*   For type 1 : 0 til 130 iso tegn                                 *>
  <*            2 : 0 til 11 iso tegn                                  *>
  <*            3 : Heltals værdi                                      *>
  <*            4 : false add værdi (0=false , 1=true)                 *>
  <*            5 : Heltals værdi for begge værdier                    *>
  <*                                                                   *>
  <* integer array init_lim(1:???,1:2) ; Grænser for angivet værdi     *>
  <*  For type 1 : (1) = Max. antal tegn                               *>
  <*               (2) = ubrugt                                        *>
  <*           2 : (1) = ubrugt                                        *>
  <*               (2) = ubrugt                                        *>
  <*           3 : (1) = mindste værdi                                 *>
  <*               (2) = største værdi                                 *>
  <*           4 : (1) = ubrugt                                        *>
  <*               (2) = ubrugt                                        *>
  <*           5 : (1) = mindste værdi                                 *>
  <*               (2) = største værdi                                 *>
  <*                                                                   *>
  <* integer array init_count(1:???); Beskrivelse af gemning af værdi  *>
  <* Angiver antallet af ord -1, der indgår i værdien.                 *>
  <*                                                                   *>
  <* Navne på parametrerne i init_file sættes i :                      *>
  <* procedure keywords_init i array init_keywords.                    *>
  <* fra keyword 10 og frem. Keyword værdi benyttes som index til      *>
  <* init array's. Lokale værdier sættes i set_local_data              *>
  <*********************************************************************>
  trap(alarm);
  t:=1; f:=0;
  max:=8388605;  min:=-8388607;
  for i:=1 step 1 until init_num_keys-9 do
  begin
    init_type(i):=case i of
                  (2,2,2,2,2,2,2,2,4,3,
                   3,4,3,5,5,3,3,3,3,3,
                   3,3,3,3,3,3,3,3,1,1,
                   1,1,3,3,3,3,4);

    init_default(i):=case i of
                  (long <:disc:>,long <:tasusercat:>,long <:tastermcat:>,
                   long <:tastypecat:>,long <:tascattest:>,long <:tasspool:>,
                   long <:tastermtest:>, long <:tem:>,t,3,
                   3,t,5,max,max,0,0,20,10,5,
                   25,5,2,170,3,10,2,30,long <::>,long <::>,
                   long <:Afmeld !:>,long <:Afmeld !:>,412,-1,1365,0,t);

    init_count(i):=case i of
                  (3,3,3,3,3,3,3,3,0,0,
                   0,0,0,0,0,0,0,0,0,0,
                   0,0,0,0,0,0,0,0,27,45,
                   27,27,0,0,0,0,0);

    init_lim(i,1):=case i of
                  (0,0,0,0,0,0,0,0,0,0,
                   0,0,1,min,min,0,0,1,1,1,
                   3,1,1,70,1,1,1,1,80,80,
                   80,80,0,-1,0,0,0);

    init_lim(i,2):=case i of
                  (0,0,0,0,0,0,0,0,0,4095,
                   4095,0,30,max,max,max,max,max,max,max,
                   max,max,max,500,2047,max,5,max,0,0,
                   0,0,1024,0,4095,999999,0);

  end;
  if false then
    alarm: disable traped(49);
end;

procedure set_default;
<* 50 *>
<*------------------------------------------------------*>
<* Sæt standard værdierne i lokale og globale variable  *>
<*------------------------------------------------------*>
begin
  integer i,j;

  <*************************************************************************>
  <* integer array val   benyttes til midlertidig opbevaring af læst værdi *>
  <* For type 1 : (0)    = hw's shift 12 + char's                          *>
  <*              (1:45) = Teksten                                         *>
  <*          2 : (0:3)  = Navnet (udfyldt med 0)                          *>
  <*          3 : (0)    = Værdien                                         *>
  <*          4 : (0)    = (0=false , 1=true);                             *>
  <*          5 : (0),(1)= 2 værdier                                       *>
  <*************************************************************************>
  trap(alarm);
  host_id(0):=signon_text(0):=logtxt(0):=stoptxt(0):=0;
  for i:=1 step 1 until init_num_keys-9 do
  begin
    if init_type(i)>0 then
    begin
      case init_type(i) of
      begin
        begin <* 1 *>
          val(0):=puttext(val.laf,1,string init_default(i),-init_lim(i,1));
          val(0):=val(0)+1;
          put_ch(val.laf,val(0)+0,10,1);
          put_ch(val.laf,val(0)+1,0,6);
          val(0):=(((val(0)+2)//3+1)*2) shift 12 + val(0);
        end;
        begin <* 2 *>
          val.laf(1):=val.laf(2):=0;
          puttext(val.laf,1,string init_default(i),-11);
          for j:=1 step 1 until 4 do
            val(j-1):=val(j);
        end;
        begin <* 3 *>
          val(0):=init_default(i);
        end;
        begin <* 4 *>
          val(0):=init_default(i);
        end;
        begin <* 5 *>
          val(0):=init_default(i);
          val(1):=init_default(i);
        end;
      end;
      set_local_data(i);
    end;
  end;
  if false then
    alarm: disable traped(50);
end;

procedure read_init_param;
<* 51 *>
<*---------------------------------------------------*>
<* Modifiser værdier med læste værdier fra init_file *>
<*---------------------------------------------------*>
begin
  integer i,j,init_line_nr;
  boolean ok;

  trap(alarm);
  init_line_nr:=1;
  i:=read_start_key(init_file,3,init_line_nr);
  while i=0 do
  begin
    next_line(init_file,init_line_nr);
    i:=read_start_key(init_file,3,init_line_nr);
  end;
  i:=i-9;
  while i>=1 do
  begin
    if init_type(i)>0 then
    begin
      case init_type(i) of
      begin
        begin <* 1 *>
          val(0):=read_text(init_file,val.laf,init_lim(i,1));
          val(0):=val(0)+1;
          put_ch(val.laf,val(0)+0,10,1);
          put_ch(val.laf,val(0)+1,0,6);
          val(0):=(((val(0)+2)//3+1)*2) shift 12 + val(0);
        end;
        begin <* 2 *>
          read_name(init_file,val,ok);
          if not ok then
            write_message(51,init_line_nr,false,<:Illegal init value:>);
        end;
        begin <* 3 *>
          if not read_nr(init_file,val(0)) or
             (val(0)<init_lim(i,1)) or (val(0)>init_lim(i,2)) then
            write_message(51,init_line_nr,false,<:Illegal init value:>);
        end;
        begin <* 4 *>
          j:=read_start_key(init_file,3,init_line_nr);
          if j=1 <* true *> or j=3 <* on *> or j=5 <* start *> then
            val(0):=1
          else
            if j=2 <* false *> or j=4 <* off *> or j=6 <* stop *> then
              val(0):=0
            else
              write_message(51,init_line_nr,false,<:Illegal init value:>);
        end;
        begin <* 5 *>
          if not read_nr(init_file,val(0)) or
             (val(0)<init_lim(i,1)) or (val(0)>init_lim(i,2)) then
            write_message(51,init_line_nr,false,<:Illegal init value:>);
          if not read_nr(init_file,val(1)) or
             (val(1)<init_lim(i,1)) or (val(1)>init_lim(i,2)) then
            write_message(51,init_line_nr,false,<:Illegal init value:>);
        end;
      end;
      set_local_data(i);
    end;
    next_line(init_file,init_line_nr);
    i:=read_start_key(init_file,3,init_line_nr)-9;
  end;
  if i=-9 then
    write_message(51,init_line_nr,false,<:Unknown init param.:>);
  if false then
    alarm: disable traped(51);
end;

procedure set_local_data(key);
<* 52 *>
<*------------------------------------*>
<* Sæt data fra val i lokale variable *>
<*                                    *>
<* key (call) : Angiver den variable  *>
<*              der skal initialiseres*>
<*------------------------------------*>
integer key;
begin
  integer i;
  integer array st(0:68);
  
  for i:=0 step 1 until init_count(key) do
  begin
    case key of
    begin
      cat_doc(i+1):=val(i);
      usercat_name(i+1):=val(i);
      termcat_name(i+1):=val(i);
      typecat_name(i+1):=val(i);
      testout_name(i+1):=val(i);
      spoolname(i+1):=val(i);
      ttname(i+1):=val(i);
      temname(i+1):=val(i);
      login_stat:=if val(0)=0 then 0 else 96;
      max_user_block:=val(0);
      max_term_block:=val(0);
      timecheck_stat:=false add val(0);
      logtime:=val(0);
      begin
        cmclbases(1):=val(0);
        cmclbases(2):=val(1);
      end;
      begin
        sysbases(1):=val(0);
        sysbases(2):=val(1);
      end;
      cps:=val(0);
      cls:=val(0);
      max_sessions:=val(0);
      max_terminals:=val(0);
      max_sysmenu:=val(0);
      corebufs:=val(0);
      mclprogs:=val(0);
      term_types:=val(0);
      tbufsize:=val(0);
      spseg:=val(0);
      max_users:=val(0);
      number_of_opera:=val(0);
      timeout:=val(0);
      host_id(i):=val(i);
      st(i):=val(i);
      logtxt(i):=val(i);
      stoptxt(i):=val(i);
      begin
        testselect:=val(0) extract 8;
        tracetype:=val(0) shift (-8);
      end;
      trapmode:=val(0);
      ttmask:=val(0);
      initver:=val(0);
      reserve:=val(0);
    end;
  end;
  if key=30 then
  begin
    i:=signon_text(0) extract 12 + 1;
    put_txt(signon_text.laf,i,st.laf,st(0) extract 12);
    put_ch(signon_text.laf,i+0,0,6);
    signon_text(0):=(((i+1)//3)*2) shift 12 + (i-1);
  end;
end;

  trap(alarm);
  open(init_file,4,init_file_name,0);
  if monitor(42,init_file,0,val)<>0 then
    write_message(48,1,false,<:No init file:>);
  init_param_arrays;
  set_default;
  <* Set host id fra navn i monitor *>
  hostid(0):=22 shift 12 + 29;
  hostid.laf(1):=long <:    V:> add 'e';
  hostid.laf(2):=long <:lkomm:> add 'e';
  hostid.laf(3):=long <:n til:> add ' ';
  system(5,1192,val);
  for i:=0,1,2,3 do
    hostid(7+i):=val(i);
  read_init_param;
  text_buf_size:=148;
  max_text_count:=max_terminals//4;
  test_on:=true;
  language:=1;
  close(init_file,true);
  <* Sæt data i copy_buf *>
  copy_buf.iaf(1):=cps+cls+2*max_sessions+max_sysmenu; <* Antal cdescr *>
  copy_buf.iaf(2):=term_types;    <* Antal terminal type beskrivelser *>
  copy_buf.iaf(3):=max_terminals; <* Antal terminal beskrivelser *>
  copy_buf.iaf(4):=mclprogs;      <* Antal indgange i mcltable *>
  copy_buf.iaf(5):=spoolname(1);  <* Navn på spool area *>
  copy_buf.iaf(6):=spoolname(2);
  copy_buf.iaf(7):=spoolname(3);
  copy_buf.iaf(8):=spoolname(4);
  copy_buf.iaf(9):=corebufs;      <* Antal core buffere *>
  copy_buf.iaf(10):=max_sysmenu//2;<* Antal att event descr *>
  copy_buf.iaf(11):=reserve;      <* reserver terminal ved create link *>
  copy_buf.iaf(12):=cmclbases(1); <* MCL database std baser *>
  copy_buf.iaf(13):=cmclbases(2);
  copy_buf.iaf(14):=cls+max_sessions+max_sysmenu; <* Antal termina buf *>
  copy_buf.iaf(15):=tbufsize;     <* max tbuf size *>
  copy_buf.iaf(16):=spseg;        <* std seg i link spool area *>
  copy_buf.iaf(17):=2*152;        <* hw i signon buffer *>
  copy_buf.iaf(18):=sysbases(1);  <* test/spool baser *>
  copy_buf.iaf(19):=sysbases(2);
  copy_buf.iaf(20):=temname(1);   <* Navn på tem pseudo proces *>
  copy_buf.iaf(21):=temname(2);
  copy_buf.iaf(22):=temname(3);
  copy_buf.iaf(23):=temname(4);
  copy_buf.iaf(24):=ttname(1);    <* Testområde navn *>
  copy_buf.iaf(25):=ttname(2);
  copy_buf.iaf(26):=ttname(3);
  copy_buf.iaf(27):=ttname(4);
  copy_buf.iaf(28):=timeout;      <* Antal timeout på term i mcl *>
  copy_buf.iaf(29):=textbufsize;  <* Antal hw til txt i systxt buf *>
  copy_buf.iaf(30):=max_text_count;<* Antal udestående systxt mess. *>
  copy_buf.iaf(31):=ttmask;       <* testmaske *>
  copy_buf.iaf(32):=cps;          <* max pools efter create pool mess. *>
  copy_buf.iaf(33):=max_sessions; <* Max sessioner *>

  if false then
    alarm: disable traped(48);
end;

procedure wait_tasterm(error);
<* 53 *>
<*----------------------------------------------*>
<* Vent på init message fra tasterm             *>
<* Når denne kommer sendes init data til tasterm*>
<*----------------------------------------------*>
boolean error;
begin
  zone z(1,1,stderror);
  integer buf;

  trap(alarm);
  write_message(-53,0,true,if error then <:Stop tas:> else <:Synchronizing:>);
  repeat
    <* sæt tasterm_pda ud fra denne message *>
    tasterm_pda:=monitor(20,z,buf,answer);
    <* sæt tasterm_name ud fra pda *>
    if not get_proc_name(tasterm_pda,tasterm_name) then
      write_message(53,1,false,<:Sync. error:>);
    if answer(1)<>(9 shift 12 + 1) then
    begin
      write_message(53,answer(1),true,<:System not running yet:>);
      answer(9):=3;
      monitor(22,z,buf,answer);
    end;
  until answer(1)=(9 shift 12 + 1);
  tastermverd:=answer(4);
  tastermvert:=answer(5);
  write_message(answer(5),answer(4),true,<:Tasterm release:>);
  write_message(relt,reld,true,<:Tascat  release:>);
  write_message(0,initver,true,<:Init    version:>);
  <* retur init data til tasterm *>
  if data_from_copy_buf(256,buf,answer)<>0 then
    write_message(53,2,false,<:Sync. error:>);
  answer(9):=1;
  answer(1):=if error then 1 else 0;
  monitor(22,z,buf,answer);
  if false then
    alarm: disable traped(53);
end;

procedure tascat;
<* 00 *>
<*------------------------------------------*>
<*------------------------------------------*>
<* Hoved procedure for TASCAT               *>
<*------------------------------------------*>
<*------------------------------------------*>
begin
  integer array login_struc(1:4*struc_size);

<*---------------------------------------------------------------------*>
<* login_struc indeholder beskrivelse af alle tilmeldte brugere        *>
<*                                                                     *>
<*    !                                                                *>
<* bruger ----> terminal ---- session                                  *>
<*    !             !            !                                     *>
<*    !             !            V                                     *>
<*    !             !         session                                  *>
<*    !             !            .                                     *>
<*    !             V            .                                     *>
<*    !         terminal ...                                           *>
<*    V             .                                                  *>
<* bruger ...       .                                                  *>
<*    .                                                                *>
<*    .                                                                *>
<*                                                                     *>
<* login_struc er opdelt i blokke af 4 integer.                        *>
<* brugerbeskrivelse   = 2 blokke                                      *>
<* terminalbeskrivelse = 1 blok                                        *>
<* sessionsbeskrivelse = 1 blok                                        *>
<*                                                                     *>
<* brugerbeskrivelse:                                                  *>
<*                                                                     *>
<* (0) - (3) : user id                                                 *>
<*       (4) : userindex map < 12 + last login time                    *>
<*       (5) : user privilege < 12 + user status                       *>
<*       (6) : terminal pointer                                        *>
<*       (7) : next user pointer                                       *>
<*                                                                     *>
<* terminalbeskrivelse:                                                *>
<*                                                                     *>
<* (0) : terminal pda                                                  *>
<* (1) : mess < 21 + session map < 12 + terminal type                  *>
<* (2) : session pointer                                               *>
<* (3) : next terminal pointer                                         *>
<*                                                                     *>
<* sessionbeskriver                                                    *>
<*                                                                     *>
<* (0) : terminal handler cda (tasterm)                                *>
<* (1) : session nr < 12 + user index                                  *>
<* (2) : session status                                                *>
<* (3) : next session                                                  *>
<*                                                                     *>
<* free block beskriver                                                *>
<*                                                                     *>
<* (0) : 0                                                             *>
<* (1) : 0                                                             *>
<* (2) : prev. free block pointer                                      *>
<* (3) : next free block pointer                                       *>
<*                                                                     *>
<* pointer er index på første integer i blok. pointer lig 0 er tom.    *>
<*                                                                     *>
<* mess              : 0 = ingen message                               *>
<*                     bit sat angiver text buffer nr:                 *>
<*                     lsb = 1, msb = 3                                *>
<* user index map    : bit sat for hver user index benyttet            *>
<*                     index 0 lig lsb.                                *>
<* session map       : bit sat for hver session i brug                 *>
<*                     session 1 lig 1 shift 1.                        *>
<* last login time   : sidste tilmeldingstid (0 til 24)                *>
<*                     25 = ingen begrænsning (NON)                    *>
<*                     26 = under afmelding (NOW)                      *>
<*                     27 = remove mess. sendt                         *>
<*                     >100 lig næste dag.                             *>
<* user privilege    : privilegiebit fra katalog                       *>
<* user status       : bit 11 sat lig tilmelding stoppet for bruger    *>
<* session status    : bit 23 sat lig removing session                 *>
<*                                                                     *>
<*---------------------------------------------------------------------*>


procedure init_login_struc;
<* 54 *>
<*----------------------------------------------------*>
<* Initialiser login_struc                            *>
<*----------------------------------------------------*>
begin
  integer size,pos;

  trap(alarm);
  system(3,size,login_struc);
  free_list:=1;
  userlist:=0;
  login_struc(1):=login_struc(2):=login_struc(3):=0;
  login_struc(4):=5;
  for pos:=5 step 4 until size-4 do
  begin
    login_struc(pos):=login_struc(pos+1):=0;
    login_struc(pos+2):=pos-4;
    login_struc(pos+3):=pos+4;
  end;
  login_struc(pos):=login_struc(pos+1):=login_struc(pos+3):=0;
  login_struc(pos+2):=pos-4;
  if false then
    alarm: disable traped(54);
end;

integer procedure get_free_login(numbers);
<* 55 *>
<*--------------------------------------------------------------*>
<* Reserver et antal sammenhængende blokke i login strukturen.  *>
<*                                                              *>
<* numbers (call) : Det antal blokke der ønskes reserveret      *>
<* Return         : Peger til første blok der er reserveret     *>
<*                  eller nul (0) hvis det ikke var muligt      *>
<*--------------------------------------------------------------*>
integer numbers;
begin
  boolean found;
  integer free,cur,next,prev;

  trap(alarm);
  get_free_login:=0;
  found:=false;
  cur:=free_list;
  while not found and cur>0 do
  begin
    found:=true;
    free:=cur;
    while free <= cur+(numbers-2)*4 and found do
      if login_struc(free+3)=free+4 then
        free:=free+4
      else
        found:=false;
    if not found then
      cur:=login_struc(free+3);
  end;
  if found then
  begin
    get_free_login:=cur;
    next:=login_struc(free+3);
    prev:=login_struc(cur+2);
    if prev=0 then
      free_list:=next
    else
      login_struc(prev+3):=next;
    if next>0 then
      login_struc(next+2):=prev;
  end;
  if false then
    alarm: disable traped(55);
end;

procedure release_block(addr);
<* 56 *>
<*---------------------------------------------------------------*>
<* Indsæt blokken angivet ved addr i free listen direkte efter   *>
<* den forrige frie blok.                                        *>
<*                                                               *>
<* addr (call) : Adressen på den blok der skal indsættes i free  *>
<*               listen (listen udpeget af free_list)            *>
<*---------------------------------------------------------------*>
integer addr;
begin
  integer prev,next;

  trap(alarm);
  prev:=0;
  next:=free_list;
  while not (next > addr) and next>0 do
  begin
    prev:=next;
    next:=login_struc(prev+3);
  end;
  login_struc(addr):=0;
  login_struc(addr+1):=0;
  login_struc(addr+2):=prev;
  login_struc(addr+3):=next;
  if prev=0 then
    free_list:=addr
  else
    login_struc(prev+3):=addr;
  if next>0 then
    login_struc(next+2):=addr;
  if false then
    alarm: disable traped(56);
end;

integer procedure find_login_user(id,start);
<* 57 *>
<*-------------------------------------------------------------*>
<* Find bruger beskrivelse i login struktur ud fra id          *>
<* Start søgningen med beskrivelsen udpeget af start           *>
<*                                                             *>
<* id (call) : Navnet på brugeren der skal søges efter         *>
<* start (call) : Peger til første beskrivelse der søges i     *>
<* Return       : Peger til fundet beskrivelse eller nul hvis  *>
<*                beskrivelsen ikke blev fundet                *>
<*-------------------------------------------------------------*>
value start;
integer start;
integer array id;
begin
  integer i;
  boolean found;

  trap(alarm);
  find_login_user:=0;
  while start>0 do
  begin
    found:=true;
    for i:=1, i+1 while (i<=4 and found) do
      if login_struc(start+i-1)<>id(i) then
        found:=false;
    if found then
    begin
      find_login_user:=start;
      start:=0;
    end
    else
      start:=login_struc(start+7);
  end;
  if false then
    alarm: disable traped(57);
end;

integer procedure find_login_terminal(name,user_index);
<* 58 *>
<*-----------------------------------------------------------*>
<* Find terminal beskrivelse i login_struc ud fra navn       *>
<*                                                           *>
<* name (call) : Navnet på terminalen                        *>
<* user_index (ret) : Index i login_struc på terminal bruger *>
<* Return      : Index i login_struc hvis fundet ellers 0    *>
<*-----------------------------------------------------------*>
integer array name;
integer user_index;
begin
  integer pda,term_index;
  boolean found;

  trap(alarm);
  pda:=get_pda(name);
  found:=false;
  term_index:=0;
  user_index:=user_list;
  while user_index>0 and not found do
  begin
    term_index:=find_user_terminal(pda,login_struc(user_index+6));
    if term_index>0 then
      found:=true
    else
      user_index:=login_struc(user_index+7);
  end;
  find_login_terminal:=term_index;
  if false then
    alarm: disable traped(58);
end;

integer procedure find_user_terminal(pda,start);
<* 59 *>
<*-------------------------------------------------------------*>
<* Find terminal beskrivelse i login struktur ud fra pda       *>
<* Start søgningen med beskrivelsen udpeget af start           *>
<*                                                             *>
<* pda   (call) : PDA for den terminal der ledes efter         *>
<* start (call) : Peger til første beskrivelse der søges i     *>
<* Return       : Peger til fundet beskrivelse eller nul hvis  *>
<*                beskrivelsen ikke blev fundet                *>
<*-------------------------------------------------------------*>
value start;
integer pda,start;
begin
  trap(alarm);
  find_user_terminal:=0;
  while start>0 do
  begin
    if login_struc(start)=pda then
    begin
      find_user_terminal:=start;
      start:=0;
    end
    else
      start:=login_struc(start+3);
  end;
  if false then
    alarm: disable traped(59);
end;


boolean procedure check_term(term_id);
<* 60 *>
<*--------------------------------------------------------------------*>
<* Undersøg om terminal er indlogget                                  *>
<*                                                                    *>
<* term_id (call) : Navnet på terminalen (integer array (1:4)         *>
<* Return         : True = terminal indlogget                         *>
<*                  False = terminal ikke indlogget                   *>
<*--------------------------------------------------------------------*>
integer array term_id;
begin
  integer pda,next;
  integer array dummy(1:1);
  boolean found;

  trap(alarm);
  found:=false;
  pda:=get_pda(term_id);
  if pda<>0 then
  begin
    next:=user_list;
    while (next<>0) and not found do
    begin
      found:=find_user_terminal(pda,login_struc(next+6))>0;
      next:=login_struc(next+7);
    end;
  end;
  check_term:=found;
  if false then
    alarm: disable traped(60);
end;

boolean procedure check_type(type_nr);
<* 61 *>
<*--------------------------------------------------------------------*>
<* Undersøg om terminal med givet type nummer er indlogget            *>
<*                                                                    *>
<* type_nr (call) : nummeret på den type der checkes                  *>
<* Return         : True = type benyttet                              *>
<*                  False = type ikke benyttet                        *>
<*--------------------------------------------------------------------*>
integer type_nr;
begin
  integer next_user,next_term;
  boolean found;

  trap(alarm);
  found:=false;
  next_user:=user_list;
  while (next_user<>0) and not found do
  begin
    next_term:=login_struc(next_user+6);
    while (next_term<>0) and not found do
    begin
      found:=(login_struc(next_term+1) extract 12)=type_nr;
      next_term:=login_struc(next_term+3);
    end;
    next_user:=login_struc(next_user+7);
  end;
  check_type:=found;
  if false then
    alarm: disable traped(61);
end;

boolean procedure remove_sess(sess_index);
<* 62 *>
<*-----------------------------------------------------------------*>
<* Send remove message til tasterm for angivet session             *>
<* Sæt remove-status i session hvis message er sendt ok            *>
<*                                                                 *>
<* sess_index (call) : Index i login_struc til session             *>
<* Return            : True  = Message sendt og/eller status sat   *>
<*                     False = Message ikke sendt eller ikke ok    *>
<*                             Status ikke sat af denne procedure  *>
<*-----------------------------------------------------------------*>
integer sess_index;
begin
  integer array ia(1:8);
  integer i;
  zone tasterm(1,1,std_error);

  trap(alarm);
  remove_sess:=true;
  if not (false add login_struc(sess_index+2)) then
  begin
    login_struc(sess_index+2):=login_struc(sess_index+2)+1;
    ia(1):=10 shift 12 + 0;
    ia(2):=login_struc(sess_index);
    open(tasterm,0,tasterm_name,1 shift 9); <* Imp. passivate *>
    send_mess(tasterm,ia);
    i:=monitor(18,tasterm,1,ia);
    if i<>1 or ia(1)<>0 then
    begin
      remove_sess:=false;
      login_struc(sess_index+2):=login_struc(sess_index+2)-1
    end;
  end;
  if false then
    alarm: disable traped(62);
end;

integer procedure check_user(login_user,last_time,
                             user_id,term_id,password1,password2);
<* 63 *>
<*--------------------------------------------------------------------------*>
<* Check om bruger kan tilmeldes login strukturen                           *>
<*                                                                          *>
<* last_time  (ret) : Sidste indlognings tid for bruger (hvis bruger ok)    *>
<* login_user (ret) : Index til       fundet bruger i login_struc eller     *>
<*                    hvis bruger er ny er login_user lig 0                 *>
<* user_id   (call) : Navn på bruger der skal checkes (fra inlogning)       *>
<* term_id   (call) : Navn på terminal hvorfra inlogning foretages.         *>
<* password1 (call) : Første ord i kodet password (fra inlogning)           *>
<* password2 (call) : Andet ord i kodet password                            *>
<* Return           : 0 hvis check af bruger er OK ellers fejlårsag         *>
<*                                                                          *>
<* Fejlårsag:                                                               *>
<*                                                                          *>
<* 0  = User ok                                                             *>
<* 1  = inlogning stopped                                                   *>
<* 2  = max terminals inloged                                               *>
<* 3  = unknown user id                                                     *>
<* 4  = wrong password                                                      *>
<* 5  = terminal limit (illegal terminal group)                             *>
<* 6  = user blocked                                                        *>
<* 7  = terminal blocked                                                    *>
<* 8  = max sessions exceeded                                               *>
<* 9  = login time exceeded                                                 *>
<* 10 = no resources                                                        *>
<* 11 = unknown terminal                                                    *>
<* 12 = main consol                                                         *>
<*                                                                          *>
<*--------------------------------------------------------------------------*>
integer login_user,last_time;
integer array user_id,term_id;
integer password1,password2;

begin
  integer check,group,i,count;
  real time;
  integer array id(1:8);

  trap(alarm);
  check:=0; <* Bruger OK *>
  if not find_term(term_id) then
  begin <* Find default terminal *>
    integer array default(1:4);

    default(1):=<:def:> shift (-24) extract 24;
    default(2):=<:aul:> shift (-24) extract 24;
    default(3):=<:t:>   shift (-24) extract 24;
    default(4):=0;
    if not find_term(default) then
      check:=11;
  end;
  if sessions>=max_sessions then
    check:=8;
  if check=0 then
  begin
    group:=termcat.term_entry(7) extract 12;
    if group>=login_stat then
      check:=1
    else
      if max_terms<=terms then
        check:=2
      else
        if not find_user(user_id) then
        begin
          if max_term_block>0 then
            termcat.term_entry(6):=termcat.term_entry(6)+1;
          check:=3;
        end
        else
          if not ((usercat.user_entry(6)=password1) and
                (usercat.user_entry(7)=password2)) then
          begin
            check:=4;
            if ((password1<>0) or (password2<>0)) and (max_user_block>0) then
              usercat.user_entry(11):=usercat.user_entry(11)+1;
          end
          else
            if (usercat.user_entry(11) extract 12)<max_user_block or
               max_user_block=0 then
              usercat.user_entry(11):=
                 (usercat.user_entry(11) shift (-12)) shift 12;
  end;
  if check=0 then
  begin
    i:=group//24;
    group:=23-(group mod 24);
    if not (false add (usercat.user_entry(19+i) shift (-group))) then
    begin
      check:=5;
      if max_term_block>0 then
        termcat.term_entry(6):=termcat.term_entry(6)+1;
    end
    else
      if (termcat.term_entry(6) extract 12)<max_term_block or
         max_term_block=0 then
        termcat.term_entry(6):=
          (termcat.term_entry(6) shift (-12)) shift 12;
  end;
  if check=0 then
  begin
    login_user:=find_login_user(user_id,user_list);
    if login_user>0 then
    begin
      if false add (login_struc(login_user+5) extract 1) then
        check:=1
      else
      begin
        group:=login_struc(login_user+4);
        count:=0;
        for i:=-12 step (-1) until (-21) do
          if false add (group shift i) then
            count:=count+1;
        if count>=(usercat.user_entry(12) shift (-12)) then
          check:=8;
      end;
    end;
  end;
  if check=0 then
  begin <* test inlognings tid *>
    if login_user>0 then
    begin <* test i login_struc *>
      last_time:=login_struc(login_user+4) extract 12;
      if timecheck_stat and (last_time=26 or last_time=27 or last_time=0) then
        check:=9;
    end
    else <* test i katalog *>
      if not check_time(last_time) then
        check:=9
  end;
  for i:=1 step 1 until 4 do
    id(i):=logor((32 shift 16 + 32 shift 8 + 32),user_id(i));
  for i:=5 step 1 until 8 do
    id(i):=term_id(i-4);
  i:=1;
  if ((usercat.user_entry(11) extract 12)>=max_user_block) and
     (max_user_block>0) then
  begin
    check:=6;
    if ((usercat.user_entry(11) extract 12) mod 5=max_user_block) then
    begin
      write_message(63,1,true,<:Max. user block reached:>);
      write_message(63,usercat.user_entry(11) extract 12,true,
                    string id.laf(increase(i)));
    end;
  end
  else
    if ((termcat.term_entry(6) extract 12)>=max_term_block) and
       (max_term_block>0) then
    begin
      check:=7;
      if ((termcat.term_entry(6) extract 12) mod 5=max_term_block) then
      begin
        write_message(63,2,true,<:Max. terminal block reached:>);
        write_message(63,termcat.term_entry(6) extract 12,true,
                      string id.laf(increase(i)));
      end;
    end;
  write_user_seg;
  write_term_seg;
  check_user:=check;
  if false then
    alarm: disable traped(63);
end;

boolean procedure check_time(time_last);
<* 64 *>
<*----------------------------------------------------------------------*>
<* Check inlognings tidspunktet for bruger angivet i aktuelt user_entry *>
<*                                                                      *>
<* time_last (ret) : sidste indlognings tid for bruger eller 25 hvis    *>
<*                   der ikke er sat grænse                             *>
<* Return          : True hvis ok,  False hvis ikke ok                  *>
<*----------------------------------------------------------------------*>
integer time_last;
begin
  boolean field day;
  integer time_type,time_first,time_cur,new_time_last;
  real time;

  trap(alarm);
  systime(1,0,time);
  day:=(round((time/86400)-0.5) mod 7)+15;
  time_type:=usercat.user_entry.day extract 2;
  time_first:=(usercat.user_entry.day shift (-7)) extract 5;
  time_last:=(usercat.user_entry.day shift (-2)) extract 5;
  check_time:=false;
  time_cur:=cur_time;
  if time_type<>0 then
  begin
    if time_cur<time_first then
    begin
      day:=day-1;
      if day<15 then
        day:=21;
      new_time_last:=(usercat.user_entry.day shift (-2)) extract 5;
      if (usercat.user_entry.day extract 2 = 2) and
         (time_cur<new_time_last) then
      begin
        if new_time_last<time_first then
          time_last:=new_time_last;
        check_time:=true;
      end;
    end
    else
      if (time_type=3) or
         (time_last>24) or
         (time_first=0 and time_last=24) then
      begin
        time_last:=25;
        check_time:=true;
      end
      else
        if (time_type=2) then
        begin
          time_last:=time_last+100;
          check_time:=true;
        end
        else
          if (time_type=1) and
             (time_cur>=time_first) and
             (time_cur<time_last)  then
            check_time:=true;
  end
  else
    time_last:=0;
  if not timecheck_stat then
    check_time:=true;
  if false then
    alarm: disable traped(64);
end;

procedure mess_to_term(term_index,text_buf);
<* 65 *>
<*--------------------------------------------------------------------------*>
<* Sæt markering i login structure at tekst skal udskrives                  *>
<* Ved kald skal struc_sema være 'sat'                                      *>
<*                                                                          *>
<* term_index (call): Index i login_struc på terminal                       *>
<* text_buf (call)  : Nummeret på tekst buffer der skal skrives fra         *>
<*--------------------------------------------------------------------------*>
integer term_index;
integer text_buf;
begin
  trap(alarm);
  login_struc(term_index+1):=logor(loginstruc(term_index+1),
                                   1 shift (text_buf+20)     );
  if false then
    alarm: disable traped(65);
end;

integer procedure set_text_buf(text);
<* 65.1 *>
<*--------------------------------------------------------------------------*>
<* Sæt text i buffer i tasterm.                                             *>
<*                                                                          *>
<* text (call)  : Teksten der skal sættes                                   *>
<* Return       : Nummeret på den buffer teksten er sat i eller 0 hvis      *>
<*                der ingen ledig buffer er                                 *>
<*--------------------------------------------------------------------------*>
integer array text;
begin
  zone tasterm(40,1,stderror);
  integer array ia(1:20),term_id(1:4);
  integer i,hw,term_type,nr;

  trap(alarm);
  hw:=text(0) shift (-12)+4;
  nr:=0;
  for i:=1,2,3 do
    if text_buf_reserved(i)=0 then
      nr:=i;
  if hw<=148 and nr>0 then
  begin
    tasterm.iaf(1):=(7 shift 16) + (7 shift 8) +7;
    tasterm.iaf(2):=10;
    for i:=3 step 1 until (hw//2) do
      tasterm.iaf(i):=text(i-2);
    text_buf_reserved(nr):=-1;
    open(tasterm,0,tasterm_name,1 shift 9); <* Imp. passivate *>
    getzone6(tasterm,ia);
    ia(1):=11 shift 12 +0;
    ia(2):=ia(19)+1;
    ia(3):=ia(2)+hw-2;
    ia(4):=nr;
    send_mess(tasterm,ia);
    i:=monitor(18,tasterm,1,ia);
    if i<>1 then
    begin
      text_buf_reserved(nr):=0;
      nr:=0;
    end;
  end;
  set_text_buf:=nr;
  if false then
    alarm: disable traped(651);
end;

procedure send_message_text(nr);
<* 65.2 *>
<*------------------------------------------*>
<* Signalerer til write_term_text korutinen *>
<* at der er tekst til udskrift             *>
<*------------------------------------------*>
integer nr;
begin
  integer array ref(1:1);

  trap(alarm);
  initref(ref);
  wait_select:=8;
  wait(message_buf_pool,ref);
  ref(3):=nr;
  signal(text_write_sem,ref);
  if false then
    alarm: disable traped(652);
end;

boolean procedure check_user_priv(priv,result);
<* 66 *>
<*-------------------------------------------------------------------*>
<* Test om bruger givet i copy_buf er kendt, har korrekt password og *>
<* har det angivne privilegie                                        *>
<*                                                                   *>
<* priv (call)   : Privilegie der testes for (0 til 4)               *>
<* result (ret)  : 0 = Ok                                            *>
<*                 1 = Ukendt bruger                                 *>
<*                 2 = Forkert password                              *>
<*                 3 = Privilegie ikke opfyldt                       *>
<* Return        : True hvis result=0 ellers false                   *>
<*                 Er result=0 er user_entry sat til fundet bruger   *>
<*-------------------------------------------------------------------*>
integer priv,result;
begin
  trap(alarm);
  result:=1;
  if find_user(copy_buf.iaf) then
  begin <* Bruger fundet *>
    result:=2;
    if (copy_buf.iaf(5)=usercat.user_entry(6)) and
       (copy_buf.iaf(6)=usercat.user_entry(7)) then
    begin <* password ok *>
      result:=if false add (usercat.user_entry(12) shift (priv-11)) then
                0 <* privilegie ok *>
              else
                3; <* Privilegie ikke sat *>
    end;
  end;
  check_user_priv:=result=0;
  if false then
    alarm: disable traped(66);
end;

procedure catco;
<* 67 *>
<*---------------------------------------*>
<* Hoved procedure for catalog korutinen *>
<*---------------------------------------*>
begin
  zone dummy_zone(1,1,stderror);
  integer operation,
          mode,
          i;

<***********************************>
<* Procedure til katalog korutinen *>
<***********************************>

procedure attention;
<* 68 *>
<*---------------------------------------------------------------------*>
<* Start en ny operatør korutine hvis der er attention fra ny terminal *>
<*---------------------------------------------------------------------*>
begin
  integer i,head_consol;
  integer array ref(1:1);
  boolean found;
  integer array sender_name(1:4);

  trap(alarm);
  i:=4;
  answer(9):=1;
  found:=false;
  while (not found) and (i<(number_of_opera+4)) do
  begin
    found:=opera_terms(i,1)=mess.sender_pda;
    i:=i+1;
  end;
  system(5,mess.sender_pda,sender_name);
  if sender_name(1)=0 then
  begin
    answer(9):=2;
    found:=true;
  end;
  if not found then
  begin <* Ny terminal *>
    get_proc_name(mess.sender_pda,sender_name);
    i:=if (sender_name.laf(1)=head_term_name.laf(1)) and
          (sender_name.laf(2)=head_term_name.laf(2)) then
         4 else 5;
    head_consol:=i-4;
    while (not found) and (i<(number_of_opera+4)) do
    begin
      found:=opera_terms(i,1)=0;
      i:=i+1;
    end;
    if found then
    begin <* Ventende operatør korutine er fundet *>
      opera_terms(i-1,1):=mess.sender_pda;
      initref(ref);
      wait_select:=6;
      wait(message_buf_pool,ref);
      ref(3):=head_consol;
      signal(opera_terms(i-1,2),ref);
      answer(9):=1; <* Operatør er startet *>
    end
    else
    begin
      answer(9):=2; <* Ikke flere operatør rutiner *>
    end;
  end;
  if false then
    alarm: disable traped(68);
end;

procedure get_segments;
<* 69 *>
<*--------------------------------------------------*>
<* Hent segmenter fra katalogerne til bruger proces *>
<*--------------------------------------------------*>
begin
  integer seg,cat,i,size;

  trap(alarm);
  seg:=mess.mess_array(4);
  cat:=mess.mess_array(5);
  if (cat<1) or (cat>3) then
    answer(1):=1 shift 22 <* error; illegal katalog type *>
  else
  begin
    if data_to_copy_buf(6,mess.buf_addr,answer)=0 then
    begin <* data kopieret *>
      if check_user_priv(1,answer(1)) then
      begin <* operatør ok *>
        case cat of
        begin
          begin <* bruger katalog *>
            if usercat_size>seg then
            begin
              size:=usercat_size;
              find_user_seg(seg);
              for i:=1 step 1 until 128 do
                copy_buf(i):=usercat(i);
            end
            else
              answer(1):=1 shift 18; <* end of catalog *>
          end;
          begin <* terminal katalog *>
            if termcat_size>seg then
            begin
              size:=termcat_size;
              find_term_seg(seg);
              for i:=1 step 1 until 128 do
                copy_buf(i):=termcat(i);
            end
            else
              answer(1):=1 shift 18; <* end of catalog *>
          end;
          begin <* type katalog *>
            if typecat_size>seg then
            begin
              size:=typecat_size;
              setposition(typecat,0,seg);
              write_type_seg;
              for i:=1 step 1 until 128 do
                copy_buf(i):=typecat(i);
            end
            else
              answer(1):=1 shift 18; <* end of catalog *>
          end;
        end; <* case *>
        if answer(1)=0 then
        begin
          answer(1):=if data_from_copy_buf(256,mess.buf_addr,answer)<>0 then
                       1 shift 23 <* fejl i kopiering *>
                     else
                       0; <* alt ok *>
          answer(4):=size;
        end;
      end
      else
        if answer(1)=3 then
          answer(1):=1 shift 11 <* ingen privilegie *>
        else
          answer(1):=1 shift 10; <* illegal bruger (operatør) *>
    end
    else
      answer(1):=1 shift 23; <* bruger proces stoppet *>
  end;
  answer(9):=1;
  if false then
    alarm: disable traped(69);
end;


procedure tasterm_mess;
<* 70 *>
<*-------------------------------*>
<* Behandling af message fra TAS *>
<*-------------------------------*>
begin
  <******************************>
  <* Procedure til tasterm_mess *>
  <******************************>

procedure sign_on;
<* 71 *>
<*------------------------------------------------*>
<* Undersøg inlognings muligheden og hvis ok      *>
<* dan signon tekst til brug for TAS              *>
<*------------------------------------------------*>
begin
  integer term_type,width,pos,date_width;
  integer array term_id(1:4);
  long array date_text(1:6);
  boolean term_found,def;

  trap(alarm);
  def:=false;
  get_proc_name(mess.mess_array(4),term_id);
  if (term_id.laf(1)=head_term_name.laf(1)) and
     (term_id.laf(2)=head_term_name.laf(2)) then
    <* Hovedkonsollen *>
    answer(1):=12
  else
    if terms<max_terms then
    begin <* Ikke maximalt antal terminaler tilmeldt *>
      answer(1):=11;
      if get_proc_name(mess.mess_array(4),term_id) then
      begin <* terminal id fundet *>
        term_found:=find_term(term_id);
        if not term_found then
        begin <* Find default terminal *>
          integer array default(1:4);

          default(1):=<:def:> shift (-24) extract 24;
          default(2):=<:aul:> shift (-24) extract 24;
          default(3):=<:t:>   shift (-24) extract 24;
          default(4):=0;
          def:=true;
          term_found:=find_term(default);
        end;
        if term_found then
        begin <* Terminal kendt i katalog *>
          if (termcat.term_entry(7) extract 12)>=login_stat then
            answer(1):=1;
          term_type:=termcat.term_entry(6) shift (-12);
          if answer(1)<>1 and find_type_entry(term_type) then
          begin
            if typecat.type_entry(1)>0 then
            begin <* Term type fundet i katalog *>
              width:=typecat.type_entry(3) shift (-12);
              date_width:=date(date_text);
              copy_buf.iaf(1):=((termcat.term_entry(7) shift (-12))
                                shift 12)+term_type;
              <* sæt signon text i copy_buf *>
              pos:=7; <* Første tegn i copy_buf i position 7 *>
              laf:=56;
              <* Sæt init data i tekst *>
              put_text(copy_buf,pos,char_table,typecat.type_entry.laf,-75);
              laf:=0;
              <* Sæt signon tekst *>
              put_char(copy_buf,pos,10,2);
              put_char(copy_buf,pos,32,(width-(host_id(0) extract 12))//2);
              put_text(copy_buf,pos,host_id.laf,host_id(0) extract 12);
              put_char(copy_buf,pos,10,2);
              put_char(copy_buf,pos,32,(width-date_width)//2);
              put_text(copy_buf,pos,date_text,date_width);
              put_char(copy_buf,pos,10,2);
              put_text(copy_buf,pos,signon_text.laf,
                                signon_text(0) extract 12);
              put_char(copy_buf,pos,10,2);
              if def then
              begin
                puttext(copy_buf,pos,<:<10>Terminal :>,10);
                puttext(copy_buf,pos,term_id.laf,-12);
                puttext(copy_buf,pos,<: er ikke i katalog<10>:>,19);
              end;
              copy_buf.iaf(2):=(2*((pos-5)//3+1) shift 12) + (pos-7);
              put_char(copy_buf,pos,0,3);
              <* Kopier data til TAS *>
              if data_from_copy_buf(152,mess.buf_addr,answer)<>0 then
                write_message(71,1,true,string c_p  );
              answer(1):=0;
            end;
          end;
        end;
      end;
    end
    else
      answer(1):=2;
  if false then
    alarm: disable traped(71);
end;

procedure include_user;
<* 72 *>
<*---------------------------------*>
<* Inkluder ny bruger og terminal  *>
<*---------------------------------*>
begin
  integer user_index,term_index,sess_index,last_time,i,ui;
  integer array user_id,term_id(1:4);
  integer array struc_ref(1:1);
  boolean term_found;

  procedure init_term;
  <* 73 *>
  <* initialiser term i login_struc *>
  begin
    login_struc(term_index):=copy_buf.iaf(1);
    <* bemærk: term_entry sat af find_term *>
    login_struc(term_index+1):=
                (1 shift 13)+(termcat.term_entry(6) shift (-12));
    login_struc(term_index+2):=sess_index;
    login_struc(term_index+3):=login_struc(user_index+6);
    login_struc(user_index+6):=term_index;
    terms:=terms+1;
  end;


  procedure init_sess;
  <* 74 *>
  <* initialiser sess i login_struc *>
  begin
    login_struc(sess_index):=copy_buf.iaf(2);
    ui:=0;
    while false add (login_struc(user_index+4) shift (-ui-12)) do
      ui:=ui+1;
    <* Sæt ny userindex bit *>
    login_struc(user_index+4):=login_struc(user_index+4)+(1 shift (12+ui));
    login_struc(sess_index+1):=(1 shift 12)+ui; <* session 1, user-index ui *>
    login_struc(sess_index+2):=0;
    login_struc(sess_index+3):=0;
    sessions:=sessions+1;
  end;


  trap(alarm);
  initref(struc_ref);
  wait(struc_sema,struc_ref);
  answer(1):=0;
  user_index:=term_index:=sess_index:=0;
  if data_to_copy_buf(8,mess.buf_addr,answer)=0 then
  begin <* Data kopieret *>
    if answer(2)=16 then
    begin <* alt kopieret *>
      answer(1):=0;
      for i:=1 step 1 until 4 do
        user_id(i):=copy_buf.iaf(i+2);
      if get_proc_name(copy_buf.iaf(1),term_id) then
      begin <* Terminal navn fundet *>
        term_found:=find_term(term_id);
        if not term_found then
        begin <* Find default terminal *>
          integer array default(1:4);
          default(1):=<:def:> shift (-24) extract 24;
          default(2):=<:aul:> shift (-24) extract 24;
          default(3):=<:t:>   shift (-24) extract 24;
          default(4):=0;
          term_found:=find_term(default);
        end;
        if term_found then
        begin <* Terminal fundet i katalog *>
          answer(1):=check_user(user_index,last_time,
                           user_id,term_id,copy_buf.iaf(7),copy_buf.iaf(8));
          if answer(1)=0 then
          begin <* user ok *>
            if user_index=0 then
            begin <* Ny bruger *>
              term_index:=sess_index:=0;
              user_index:=get_free_login(4);
              if user_index>0 then
              begin
                term_index:=user_index+8;
                sess_index:=user_index+12;
              end
              else
              begin
                user_index:=get_free_login(2);
                if user_index>0 then
                begin
                  term_index:=get_free_login(2);
                  if term_index>0 then
                    sess_index:=term_index+4
                  else
                  begin
                    term_index:=get_free_login(1);
                    if term_index>0 then
                      sess_index:=get_free_login(1);
                  end;
                end;
              end;
              if term_index=0 then
              begin
                release_block(user_index);
                release_block(user_index+4);
                user_index:=0;
              end
              else
                if sess_index=0 then
                begin
                  release_block(user_index);
                  release_block(user_index+4);
                  release_block(term_index);
                  user_index:=term_index:=0;
                end;
              if user_index>0 then
              begin <* Initialiser ny user, term og sess *>
                for i:=1 step 1 until 4 do
                  login_struc(user_index+i-1):=user_id(i);
                login_struc(user_index+4):=last_time;
                <* bemærk: user_entry sat af check_user *>
                login_struc(user_index+5):=usercat.user_entry(12) shift 12;
                login_struc(user_index+6):=0;
                <* indsæt ny user først i user liste *>
                login_struc(user_index+7):=user_list;
                user_list:=user_index;
                init_term;
                init_sess;
                users:=users+1;
              end;
            end <* Ny bruger indsat, hvis user_index>0 *>
            else
            begin <* Bruger kendt, ny terminal og session *>
              term_index:=get_free_login(2);
              if term_index>0 then
                sess_index:=term_index+4
              else
              begin
                term_index:=get_free_login(1);
                if term_index>0 then
                  sess_index:=get_free_login(1);
              end;
              if sess_index=0 then
              begin
                release_block(term_index);
                term_index:=0;
              end;
              if term_index>0 then
              begin <* Initialiser term og sess *>
                init_term;
                init_sess;
              end;
            end; <* Ny terminal og session indsat, hvis term_index>0 *>
          end; <* user ok *>
        end <* terminal navn fundet *>
        else <* pda ukendt *>
          answer(1):=11;
      end
      else <* terminal ukendt *>
        answer(1):=11;
      if answer(1)=0 then
      begin
        if (user_index>0) and (term_index>0) then
        begin
          copy_buf.iaf(1):=user_index;
          for i:=2 step 1 until 7 do
            copy_buf.iaf(i):=usercat.user_entry(i+11);
          copy_buf.iaf(8):=1;
          copy_buf.iaf(9):=(4 shift 12)+1;
          copy_buf.iaf(10):=(ui+48) shift 16;
          copy_buf.iaf(11):=(4 shift 12)+1;
          copy_buf.iaf(12):=49 shift 16;
          for i:=13 step 1 until 40 do
            copy_buf.iaf(i):=usercat.user_entry(i+10);
          if data_from_copy_buf(40,mess.buf_addr,answer)<>0 then
            write_message(74,1,true,string c_p  );
          answer(1):=0;
        end
        else
          answer(1):=10;
      end;
    end <* alt kopiret *>
    else
      answer(9):=3;
  end <* data kopieret *>
  else
    write_message(74,2,true,string c_p  );
  signal(struc_sema,struc_ref);
  if false then
    alarm: disable traped(74);
end;

procedure start_sess;
<* 75 *>
<*--------------------------------------------------*>
<* Start en ny session hos kendt bruger og terminal *>
<*--------------------------------------------------*>
begin
  integer user_index,term_index,sess_index,i,ui,sess_nr,map,count;
  integer array user_id(1:4);
  integer array struc_ref(1:1);

  trap(alarm);
  initref(struc_ref);
  wait(struc_sema,struc_ref);
  user_index:=term_index:=sess_index:=0;
  if data_to_copy_buf(3,mess.buf_addr,answer)=0 then
  begin <* data kopieret *>
    if answer(2)=6 then
    begin
      answer(1):=0;
      user_index:=copy_buf.iaf(3);
      if (user_index>0) and (user_index<=(4*struc_size-7)) then
      begin
        for i:=1 step 1 until 4 do
          user_id(i):=login_struc(user_index+i-1);
        if find_user(user_id) then
        begin <* bruger kendt *>
          if (login_stat>0) and not (false add login_struc(user_index+5)) then
          begin <* bruger login ok *>
            map:=login_struc(user_index+4) shift (-12);
            count:=0;
            for i:=0 step (-1) until (-9) do
              if false add (map shift i) then
                count:=count+1;
            if (count<(usercat.user_entry(12) shift (-12))) and
               (sessions<max_sessions) then
            begin <* ledige sessioner *>
              if cur_time<(login_struc(user_index+4) extract 12) then
              begin <* tid ok *>
                term_index:=find_user_terminal(copy_buf.iaf(1),
                                                login_struc(user_index+6));
                if term_index>0 then
                begin <* terminal kendt *>
                  sess_index:=get_free_login(1);
                  if sess_index>0 then
                  begin <* resourcer ok *>
                    login_struc(sess_index+3):=login_struc(term_index+2);
                    login_struc(term_index+2):=sess_index;
                    login_struc(sess_index):=copy_buf.iaf(2);
                    login_struc(sess_index+2):=0;
                    ui:=0;
                    while false add
                          (login_struc(user_index+4) shift (-ui-12)) do
                      ui:=ui+1;
                    <* Sæt ny userindex bit *>
                    login_struc(user_index+4):=
                          login_struc(user_index+4)+(1 shift (12+ui));
                    sess_nr:=1;
                    sessions:=sessions+1;
                    while false add (login_struc(term_index+1) shift
                                                       (-sess_nr-12)) do
                      sess_nr:=sess_nr+1;
                    <* Sæt ny sessions nummer bit *>
                    login_struc(term_index+1):=
                          login_struc(term_index+1)+(1 shift (12+sess_nr));
                    login_struc(sess_index+1):=
                          (sess_nr shift 12)+ui; <* session nr, user-index *>
                  end <* initialiser *>
                  else
                    answer(1):=10;
                end
                else
                  answer(1):=11;
              end
              else
                answer(1):=9;
            end
            else
              answer(1):=8;
          end
          else
            answer(1):=1;
        end
        else
          answer(1):=3;
      end
      else
        answer(1):=3;
      if answer(1)=0 then
      begin
        <* sæt returdata i copy_buf *>
        copy_buf.iaf(1):=user_index;
        for i:=2 step 1 until 7 do
          copy_buf.iaf(i):=usercat.user_entry(i+11);
        copy_buf.iaf(8):=sess_nr;
        copy_buf.iaf(9):=(4 shift 12)+1;
        copy_buf.iaf(10):=(ui+48) shift 16;
        copy_buf.iaf(11):=(4 shift 12)+1;
        copy_buf.iaf(12):=(sess_nr+48) shift 16;
        for i:=13 step 1 until 40 do
          copy_buf.iaf(i):=usercat.user_entry(i+10);
        if data_from_copy_buf(40,mess.buf_addr,answer)<>0 then
          write_message(75,1,true,string c_p  );
        answer(1):=0;
      end;
    end
    else
      answer(9):=3;
  end
  else
    write_message(75,2,true,string c_p  );
  signal(struc_sema,struc_ref);
  if false then
    alarm: disable traped(75);
end;

procedure end_sess;
<* 76 *>
<*-------------------------------------------------------------------------*>
<* Nedlæg en sessions beskrivelse                                          *>
<* Er det sidste session på terminalen, nedlægges terminal beskrivelsen    *>
<* Er det sidste terminal på bruger, nedlægges bruger beskrivelsen         *>
<*-------------------------------------------------------------------------*>
begin
  integer user_index,term_index,sess_index;
  integer prev_user_index,prev_term_index,prev_sess_index;
  integer next_user_index;
  integer array struc_ref(1:1);
  boolean found;

  trap(alarm);
  initref(struc_ref);
  wait(struc_sema,struc_ref);
  user_index:=mess.mess_array(4);
  if (user_index>0) and (user_index<=(4*struc_size-7)) then
  begin
    found:=false;
    prev_term_index:=0;
    term_index:=login_struc(user_index+6);
    while term_index>0 and not found do
    begin <* find terminal beskrivelse *>
      if login_struc(term_index)=mess.mess_array(2) then
        found:=true
      else
      begin
        prev_term_index:=term_index;
        term_index:=login_struc(term_index+3);
      end;
    end;
    if found then
    begin <* terminal fundet *>
      found:=false;
      prev_sess_index:=0;
      sess_index:=login_struc(term_index+2);
      while sess_index>0 and not found do
      begin <* find sessions beskrivelse *>
        if login_struc(sess_index)=mess.mess_array(3) then
          found:=true
        else
        begin
          prev_sess_index:=sess_index;
          sess_index:=login_struc(sess_index+3);
        end;
      end;
      if found then
      begin <* session fundet *>
        if (prev_sess_index=0) and (login_struc(sess_index+3)=0) then
        begin <* sidste session på denne terminal *>
          if (prev_term_index=0) and (login_struc(term_index+3)=0) then
          begin <* sidste terminal for denne bruger *>
            <* nedlæg bruger *>
            prev_user_index:=0;
            next_user_index:=user_list;
            while user_index<>next_user_index do
            begin
              prev_user_index:=next_user_index;
              next_user_index:=login_struc(next_user_index+7);
            end;
            if prev_user_index=0 then
              user_list:=login_struc(user_index+7)
            else
              login_struc(prev_user_index+7):=login_struc(user_index+7);
            release_block(user_index);
            release_block(user_index+4);
            release_block(term_index);
            release_block(sess_index);
            terms:=terms-1;
            users:=users-1;
            sessions:=sessions-1;
            answer(1):=2;
          end
          else
          begin
            <* nedlæg terminal *>
            <* nulstil userindex bit for session i map *>
            login_struc(user_index+4):=login_struc(user_index+4) -
                  (1 shift ((login_struc(sess_index+1) extract 12)+12));
            if prev_term_index=0 then
              login_struc(user_index+6):=login_struc(term_index+3)
            else
              login_struc(prev_term_index+3):=login_struc(term_index+3);
            release_block(term_index);
            release_block(sess_index);
            terms:=terms-1;
            sessions:=sessions-1;
            answer(1):=1;
          end;
        end
        else
        begin
          <* nedlæg session *>
          <* nulstil userindex bit for session i map *>
          login_struc(user_index+4):=login_struc(user_index+4) -
             (1 shift ((login_struc(sess_index+1) extract 12)+12));
          <* nulstil sessions nr bit for session i map *>
          login_struc(term_index+1):=login_struc(term_index+1) -
             (1 shift ((login_struc(sess_index+1) shift (-12))+12));
          if prev_sess_index=0 then
            login_struc(term_index+2):=login_struc(sess_index+3)
          else
            login_struc(prev_sess_index+3):=login_struc(sess_index+3);
          release_block(sess_index);
          sessions:=sessions-1;
          answer(1):=0;
        end;
      end
      else
        answer(1):=3; <* session ikke fundet *>
    end
    else
      answer(1):=3; <* terminal ikke fundet *>
  end
  else
    answer(1):=3; <* Ukendt bruger *>
  signal(struc_sema,struc_ref);
  if false then
    alarm: disable traped(76);
end;

procedure modify_pass;
<* 77 *>
<*--------------------------------------*>
<* Sæt nyt password for inlogget bruger *>
<*--------------------------------------*>
begin
  integer user_index;
  integer array field user_id;
  integer array struc_ref(1:1);

  trap(alarm);
  initref(struc_ref);
  wait(struc_sema,struc_ref);
  if data_to_copy_buf(5,mess.buf_addr,answer)=0 then
  begin <* data læst *>
    if answer(2)=10 then
    begin <* al data læst *>
      answer(1):=1;
      user_index:=copy_buf.iaf(1);
      if (user_index>0) and (user_index<=(4*struc_size-7)) then
      begin <* User ident ok *>
        user_id:=(user_index-1)*2;
        if find_user(login_struc.user_id) then
        begin <* bruger fundet i katalog *>
          if (usercat.user_entry(6)=copy_buf.iaf(2)) and
             (usercat.user_entry(7)=copy_buf.iaf(3)) then
          begin <* old password ok *>
            usercat.user_entry(6):=copy_buf.iaf(4);
            usercat.user_entry(7):=copy_buf.iaf(5);
            usercat.user_entry(61):=usercat.user_entry(61)+1;
            write_user_seg;
            answer(1):=0;
          end;
        end;
      end;
    end
    else
      answer(9):=3;
  end
  else
    write_message(77,3,true,string c_p  );
  signal(struc_sema,struc_ref);
  if false then
    alarm: disable traped(77);
end;

procedure get_term_data;
<* 78 *>
<*---------------------------------*>
<* Hent terminal type data til TAS *>
<*---------------------------------*>
begin
  integer i;

  trap(alarm);
  answer(1):=1;
  if find_type_entry(mess.mess_array(4)) then
  begin
    if typecat.type_entry(1)>0 then
    begin <* type entry fundet *>
      for i:=1 step 1 until 53 do <* Kopier data *>
        copy_buf.iaf(i):=typecat.type_entry(i);
      if data_from_copy_buf(53,mess.buf_addr,answer)<>0 then
        write_message(78,1,true,string c_p  );
      answer(1):=0;
    end;
  end;
  if false then
    alarm: disable traped (78);
end;

  <**************************************>
  <* Hoveddel af procedure tasterm_mess *>
  <**************************************>
  trap(alarm);
  if (mode<2) or (mode>7) or (mess.sender_pda<>tasterm_pda) then
    <* Ukendt mode i message eller illegal sender *>
    answer(9):=3
  else
  begin
    answer(9):=1;
    case mode-1 of
    begin
      sign_on;
      include_user;
      start_sess;
      end_sess;
      modify_pass;
      get_term_data;
    end;
  end;
  if false then
    alarm: disable traped(70);
end;

procedure modify_entry;
<* 79 *>
<*-----------------------------------------------*>
<* Behandling af modify_entry message fra bruger *>
<*-----------------------------------------------*>
begin

procedure modify_user_entry;
<* 80 *>
<*------------------------------------------------*>
<* Hent, sæt eller modifiser data i brugerkatalog *>
<*------------------------------------------------*>
begin
  integer array field user_id,liaf;
  boolean user_exist;
  integer func,i;

  trap(alarm);
  user_id:=12;
  func:=mess.mess_array(4)+1;
  if (func<1) or (func>4) then
    answer(9):=3
  else
  begin
    if data_to_copy_buf((case func of (10,66,66,10)),
                        mess.buf_addr,answer)=0 then
    begin <* data kopieret *>
      if check_user_priv(1,answer(1)) then
      begin <* operatør ok *>
        user_exist:=find_user(copy_buf.user_id);
        liaf:=10;
        case func of
        begin
        <* Get data *>
          if user_exist then
          begin
            for i:=2 step 1 until 61 do
              copy_buf.liaf(i):=usercat.user_entry(i);
            answer(1):=if data_from_copy_buf(66,mess.buf_addr,answer)=0 then
                         0 <* ok *>
                       else
                         8; <* process stopped *>
          end
          else
            answer(1):=2; <* entry not found *>
        <* Modify data *>
          if user_exist then
          begin
            if find_login_user(copy_buf.user_id,user_list)=0 then
            begin <* bruger er ikke logget ind *>
              if copy_buf.liaf(61)=usercat.user_entry(61) then
              begin <* time stamp's ens *>
                for i:=2 step 1 until 60 do
                  usercat.user_entry(i):=copy_buf.liaf(i);
                <* sæt ny time stamp *>
                usercat.user_entry(61):=usercat.user_entry(61)+1;
                write_user_seg;
                answer(1):=0;
              end
              else
                answer(1):=7; <* Data changed since last get-data *>
            end
            else
              answer(1):=1; <* entry in use *>
          end
          else
            answer(1):=2; <* entry not found *>
        <* Set new data *>
          if not user_exist then
          begin
            if find_empty_user_entry(
                    calc_hash(copy_buf.user_id,usercat_size)) then
            begin <* tomt entry fundet *>
              for i:=2 step 1 until 60 do
                usercat.user_entry(i):=copy_buf.liaf(i);
              <* sæt ny time stamp *>
              usercat.user_entry(61):=0;
              write_user_seg;
              answer(1):=0;
            end
            else
              answer(1):=6; <* catalog full *>
          end
          else
            answer(1):=3; <* entry exist *>
        <* Delete data *>
          if user_exist then
          begin
            if find_login_user(copy_buf.user_id,user_list)=0 then
            begin <* bruger ikke logget ind *>
              usercat.user_entry(1):=0;
              setstate(usercat,6);
              find_user_seg(calc_hash(copy_buf.user_id,usercat_size));
              user_entry:=0;
              <* nedtæl hash-nøgle tæller *>
              usercat.user_entry(1):=usercat.user_entry(1)-1;
              write_user_seg;
              answer(1):=0;
            end
            else
              answer(1):=1; <* entry in use *>
          end
          else
            answer(1):=2; <* entry not found *>
        end;
      end
      else
        answer(1):=if answer(1)=3 then
                     4 <* ingen privilegie *>
                   else
                     13; <* illegal bruger (operatør) *>
    end
    else
      answer(1):=8; <* bruger proces stoppet *>
  end;
  if false then
    alarm: disable traped(80);
end;

procedure modify_term_entry;
<* 81 *>
<*--------------------------------------------------*>
<* Hent, sæt eller modificer data i terminalkatalog *>
<*--------------------------------------------------*>
begin
  integer array field term_id,liaf;
  boolean term_exist;
  integer func,i;

  trap(alarm);
  term_id:=12;
  func:=mess.mess_array(4)+1;
  if (func<1) or (func>4) then
    answer(9):=3
  else
  begin
    if data_to_copy_buf((case func of (10,23,23,10)),
                        mess.buf_addr,answer)=0 then
    begin <* data kopieret *>
      if check_user_priv(1,answer(1)) then
      begin <* operatør ok *>
        term_exist:=find_term(copy_buf.term_id);
        liaf:=10;
        case func of
        begin
        <* Get data *>
          if term_exist then
          begin
            for i:=2 step 1 until 18 do
              copy_buf.liaf(i):=termcat.term_entry(i);
            answer(1):=if data_from_copy_buf(23,mess.buf_addr,answer)=0 then
                         0 <* ok *>
                       else
                         8; <* process stopped *>
          end
          else
            answer(1):=2; <* entry not found *>
        <* Modify data *>
          if term_exist then
          begin
            if not check_term(copy_buf.term_id) then
            begin <* terminal ikke logget ind *>
              if copy_buf.liaf(18)=termcat.term_entry(18) then
              begin <* time stamp's ens *>
                for i:=2 step 1 until 17 do
                  termcat.term_entry(i):=copy_buf.liaf(i);
                <* sæt ny time stamp *>
                termcat.term_entry(18):=termcat.term_entry(18)+1;
                write_term_seg;
                answer(1):=0;
              end
              else
                answer(1):=7; <* Data changed since last get-data *>
            end
            else
              answer(1):=1; <* entry in use *>
          end
          else
            answer(1):=2; <* entry not found *>
        <* Set new data *>
          if not term_exist then
          begin
            if find_empty_term_entry(
                    calc_hash(copy_buf.term_id,termcat_size)) then
            begin <* tomt entry fundet *>
              for i:=2 step 1 until 17 do
                termcat.term_entry(i):=copy_buf.liaf(i);
              <* sæt ny time stamp *>
              termcat.term_entry(18):=0;
              write_term_seg;
              answer(1):=0;
            end
            else
              answer(1):=6; <* catalog full *>
          end
          else
            answer(1):=3; <* entry exist *>
        <* Delete data *>
          if term_exist then
          begin
            if not check_term(copy_buf.term_id) then
            begin <* terminal ikke logget ind *>
              termcat.term_entry(1):=0;
              setstate(termcat,6);
              find_term_seg(calc_hash(copy_buf.term_id,termcat_size));
              term_entry:=0;
              <* nedtæl hash-nøgle tæller *>
              termcat.term_entry(1):=termcat.term_entry(1)-1;
              write_term_seg;
              answer(1):=0;
            end
            else
              answer(1):=1; <* entry in use *>
          end
          else
            answer(1):=2; <* entry not found *>
        end;
      end
      else
        answer(1):=if answer(1)=3 then
                     4 <* ingen privilegie *>
                   else
                     13; <* illegal bruger (operatør) *>
    end
    else
      answer(1):=8; <* bruger proces stoppet *>
  end;
  if false then
    alarm: disable traped(81);
end;

procedure modify_type_entry;
<* 82 *>
<*----------------------------------------------*>
<* Hent, sæt eller modificer data i typekatalog *>
<*----------------------------------------------*>
begin
  integer array field liaf;
  boolean type_exist;
  integer func,i;
  integer field type_nr;

  trap(alarm);
  type_nr:=14;
  func:=mess.mess_array(4)+1;
  if (func<1) or (func>4) then
    answer(9):=3
  else
  begin
    if data_to_copy_buf((case func of (7,70,70,7)),
                        mess.buf_addr,answer)=0 then
    begin <* data kopieret *>
      if check_user_priv(1,answer(1)) then
      begin <* operatør ok *>
        type_exist:=false;
        if find_type_entry(copy_buf.type_nr) then
          type_exist:=typecat.type_entry(1)<>0;
        liaf:=12;
        case func of
        begin
        <* Get data *>
          if type_exist then
          begin
            for i:=1 step 1 until 64 do
              copy_buf.liaf(i):=typecat.type_entry(i);
            answer(1):=if data_from_copy_buf(70,mess.buf_addr,answer)=0 then
                         0 <* ok *>
                       else
                         8; <* process stopped *>
          end
          else
            answer(1):=2; <* entry not found *>
        <* Modify data *>
          if type_exist then
          begin
            if not check_type(copy_buf.type_nr) then
            begin <* type er ikke i login terminaler *>
              if copy_buf.liaf(64)=typecat.type_entry(64) then
              begin <* time stamp's ens *>
                for i:=1 step 1 until 63 do
                  typecat.type_entry(i):=copy_buf.liaf(i);
                <* sæt ny time stamp *>
                typecat.type_entry(64):=typecat.type_entry(64)+1;
                write_type_seg;
                answer(1):=0;
              end
              else
                answer(1):=7; <* Data changed since last get-data *>
            end
            else
              answer(1):=1; <* entry in use *>
          end
          else
            answer(1):=2; <* entry not found *>
        <* Set new data *>
          if not type_exist then
          begin
            if find_type_entry(copy_buf.type_nr) then
            begin <* tomt entry fundet *>
              for i:=1 step 1 until 63 do
                typecat.type_entry(i):=copy_buf.liaf(i);
              <* sæt ny time stamp *>
              typecat.type_entry(64):=0;
              write_type_seg;
              answer(1):=0;
            end
            else
              answer(1):=6; <* illegal type *>
          end
          else
            answer(1):=3; <* entry exist *>
        <* Delete data *>
          if type_exist then
          begin
            if not check_type(copy_buf.type_nr) then
            begin <* type benyttes ikke i indlogget terminal *>
              typecat.type_entry(1):=0;
              write_type_seg;
              answer(1):=0;
            end
            else
              answer(1):=1; <* entry in use *>
          end
          else
            answer(1):=2; <* entry not found *>
        end;
        answer(4):=(typecat_size-1)*(512//type_entry_length);
      end
      else
        answer(1):=if answer(1)=3 then
                     4 <* ingen privilegie *>
                   else
                     13; <* illegal bruger (operatør) *>
    end
    else
      answer(1):=8; <* bruger proces stoppet *>
  end;
  if false then
    alarm: disable traped(82);
end;

  <*****************************>
  <* Hoved del af modify_entry *>
  <*****************************>
  trap(alarm);
  if (mode<1) or (mode>3) then
    answer(9):=3
  else
  begin
    answer(9):=1;
    case mode of
    begin
      modify_user_entry;
      modify_term_entry;
      modify_type_entry;
    end;
  end;
  if false then
    alarm: disable traped(79);
end;

procedure send_text;
<* 83 *>
<*--------------------------------------------------------------------*>
<* Behandling af message fra bruger, med tekst til udskrift på anden  *>
<* terminal tilknyttet TAS                                            *>
<*--------------------------------------------------------------------*>
begin
  integer array id(1:4);
  integer i,user_index,term_index,t,nr;
  integer array field liaf;
  integer array struc_ref(1:1);

  trap(alarm);
  initref(struc_ref);
  answer(9):=1;
  if data_to_copy_buf(256,mess.buf_addr,answer)=0 then
  begin <* data kopieret *>
    if check_user_priv(3,answer(1)) then
    begin <* operatør ok *>
      liaf:=14;
      t:=0;
      answer(1):=0;
      for i:=1 step 1 until 4 do
        id(i):=mess.mess_array(i+3);
      if id(1)<>0 then
      begin
        user_index:=find_login_user(id,user_list);
        if user_index>0 then
        begin
          nr:=set_text_buf(copy_buf.liaf);
          if nr>0 then
          begin
            term_index:=login_struc(user_index+6);
            wait(struc_sema,struc_ref);
            while term_index>0 do
            begin
              mess_to_term(term_index,nr);
              t:=t+1;
              term_index:=login_struc(term_index+3);
            end;
            signal(struc_sema,struc_ref);
            send_message_text(nr);
          end
          else
            answer(1):=4;
        end
        else
          answer(1):=1;
      end
      else
      begin
        nr:=set_text_buf(copy_buf.liaf);
        if nr>0 then
        begin
          wait(struc_sema,struc_ref);
          user_index:=user_list;
          while user_index>0 do
          begin
            term_index:=login_struc(user_index+6);
            while term_index>0 do
            begin
              mess_to_term(term_index,nr);
              t:=t+1;
              term_index:=login_struc(term_index+3);
            end;
            user_index:=login_struc(user_index+7);
          end;
          signal(struc_sema,struc_ref);
          send_message_text(nr);
        end
        else
          answer(1):=4;
      end;
      answer(4):=t;
    end
    else
      answer(1):=if answer(1)=3 then
                   2
                 else
                   13;
  end
  else
    answer(1):=3;
  if false then
    alarm: disable traped(83);
end;

procedure move_mcl;
<* 84 *>
<*-------------------------------------------------------*>
<* Behandling af message til flytning af cmcl programmer *>
<*-------------------------------------------------------*>
begin
  integer array ia(1:17),name(1:4),user_bases(1:2);
  zone z(1,1,stderror);
  integer i,result;

  trap(alarm);
  if (mode<0) or (mode>2) then
    answer(9):=3 <* error; illegal mode *>
  else
  begin
    answer(9):=1;
    if data_to_copy_buf(12,mess.buf_addr,answer)=0 then
    begin <* data kopieret *>
      if check_user_priv(2,result) then
      begin <* operatør ok *>
        result:=0;
        for i:=1 step 1 until 4 do
          name(i):=copy_buf.iaf(i+6);
        open(z,0,name,0);
        user_bases(1):=copy_buf.iaf(11);
        user_bases(2):=copy_buf.iaf(12);
        if mode=0 then
        begin <* Lookup file *>
          set_cat_bases(cmcl_bases);
          if monitor(42,z,0,ia)<>0 or
             ia(9)<>(29 shift 12)  then
            result:=1
          else
          begin
            for i:=2,3,4,5 do
              copy_buf.iaf(i+5):=ia(i);
            copy_buf.iaf(11):=ia(6);
            copy_buf.iaf(12):=ia(10);
            result:=if data_from_copy_buf(12,mess.buf_addr,answer)=0 then
                      result
                    else
                      8;
          end;
        end
        else
          if mode=1 then
          begin <* move to tascat *>
            set_cat_bases(user_bases);
            i:=monitor(76,z,0,ia);
            if monitor(76,z,0,ia)=0 then
            begin
              if (ia(8)>0) and
                 (ia(16) shift (-12) = 29) and
                 (ia(1) extract 3 = 3) then
              begin
                result:=monitor(74,z,0,cmcl_bases);
                if result=7 then
                  result:=2;
              end
              else
                result:=9;
            end
            else
              result:=1;
          end
          else
            if mode=2 then
            begin <* move to user *>
              set_cat_bases(cmcl_bases);
              if monitor(42,z,0,ia)=0 then
              begin
                result:=monitor(74,z,0,user_bases);
                if result=7 then
                  result:=2;
              end
              else
                result:=1;
            end;
        answer(1):=result;
        answer(4):=cmcl_bases(1);
        answer(5):=cmcl_bases(2);
        set_cat_bases(sys_bases);
      end
      else
        answer(1):=if result=3 then
                     7 <* ingen privilegie *>
                   else
                     13; <* illegal bruger (operatør) *>
    end
    else
      answer(1):=8; <* bruger proces stoppet *>
  end;
  if false then
    alarm: disable traped(84);
end;

<**********************************>
<* Hoved del af catalog korutinen *>
<**********************************>
  trap(alarm);
  claim(600); <* Reserver plads på stakken *>
  <* Hent buffer til message *>
  initref(mess);
  wait_select:=22;
  wait(message_buf_pool,mess);
  <* sæt den i wait message pool *>
  signal(wait_message_pool,mess);
  while true do
  begin
    <* vent på næste message til TASCAT *>
    <* Der behandles kun 1 mess af gangen *>
    wait_time:=0;
    wait_select:=0;
    wait(wait_message,mess);
    for i:=1 step 1 until 8 do
      answer(i):=0;
    answer(9):=3;
    operation:=mess.mess_array(1) shift (-12);
    mode:=mess.mess_array(1) extract 12;
    if false add trace_type then
      trace(61,1,operation,mode);
    if operation=0 then
      attention
    else
      if operation=3 then
        get_segments
      else
        if operation=9 then
          tasterm_mess
        else
          if operation=11 then
            modify_entry
          else
            if operation=13 then
              send_text
            else
              if operation=15 then
                move_mcl;
    <* send answer sat af procedure der behandlede message *>
    <* answer(9) er sat til answer-result, mens answer(1)  *>
    <* til answer(8) indeholder svaret (hvis answer(9)=1)  *>
    monitor(22,dummy_zone,mess.buf_addr,answer);
    <* sæt besked buffer i pool så der kan ventes på næste message *>
    signal(wait_message_pool,mess);
  end;
  if false then
    alarm: disable traped(67);
end;

<***********************************************>
<***********************************************>
<* Hoved procedurerne for operatør korutinerne *>
<***********************************************>
<***********************************************>

procedure operator(cor_nr);
<* 85 *>
<*------------------------------------------*>
<* Hoved procedure for operator korutinerne *>
<*                                          *>
<* cor_nr (call) : Denne korutines nummer   *>
<*------------------------------------------*>
value cor_nr;
integer cor_nr;
begin
  zone term_in(13,1,in_error),
       term_out(13,1,out_error);
  integer i,
          head_consol,
          buf,
          command_value,
          command_keyword,
          user_ident;
  boolean priv,
          break,
          finis,
          out_stop;
  integer array term_name(1:4),
                command_name(1:4),
                ref(1:1),
                ia(1:20),
                user_id(1:4);
  long password;

<**************************************>
<**************************************>
<* Operatør korutine hjælpe procedure *>
<**************************************>
<**************************************>



boolean procedure read_param(term_in,text_param,num_param);
<* 86 *>
<*--------------------------------------------------------------------------*>
<* Læs en parameter fra input fra terminal                                  *>
<*                                                                          *>
<* text_param (ret) : Den læste parameter (max 11 tegn) konverteret til     *>
<*                    små bogstaver og efterstillet med nul                 *>
<* num_par    (ret) : Den læste parameter omregnet til integer              *>
<* Return           : True  = parameter læst til text_param og num_param    *>
<*                    False = ikke flere parametre (retur param. nulstillet)*>
<*--------------------------------------------------------------------------*>
zone term_in;
integer num_param;
integer array text_param;
begin
  integer text_pos,char_class,ch;
  long array field laf;
  boolean neg;

  trap(alarm);
  neg:=false;
  char_class:=7;
  while char_class=7 do
    char_class:=readchar(term_in,ch);
  laf:=0;
  text_pos:=1;
  num_param:=0;
  text_param.laf(1):=text_param.laf(2):=0;
  if (ch=0) or (char_class>=8) then
    read_param:=false
  else
  begin
    read_param:=true;
    if ch='-' then
      neg:=true;
    while char_class<7 do
    begin
      num_param:=if char_class=2 then
                   (num_param*10)+(ch-48)
                 else
                   0;
      if (text_pos<12) and (char_class>1) then
        put_char(text_param.laf,text_pos,ch);
      char_class:=readchar(term_in,ch);
    end;
  end;
  if neg then
    num_param:= -num_param;
  repeatchar(term_in);
  if false then
    alarm: disable traped(86);
end;

procedure out_error(z,s,b);
<* 87 *>
<*--------------------------------------------------------------*>
<* Blok procedure for zonen term_out                            *>
<* Sæt out_stop true hvis der sættes attention status på output *>
<* Sæt break ved fejl                                           *>
<*--------------------------------------------------------------*>
zone z;
integer s,b;
begin
  out_stop:=true;
  if not (false add (s shift (-16))) then
  begin
    <* Ikke attention status men give_up eller error *>
    break:=true;
    b:=0;
  end;
end;

procedure in_error(z,s,b);
<* 88 *>
<*-------------------------------------*>
<* Blok procedure for zonen term_in    *>
<* Sæt break ved fejl og returner da   *>
<* 'em' i input                        *>
<*-------------------------------------*>
zone z;
integer s,b;
begin
  <* Give_up eller error *>
  break:=true;
  b:=2;
  z(1):= real <:<'em'><'em'><'em'>:>;
end;

procedure show_sess(sess_index);
<* 89 *>
<*---------------------------------------------------------------------*>
<* Udskriv en linie på skærmen indeholde data for den angivne sesseion *>
<*                                                                     *>
<* sess_index (call) : Index i login_struc for sessionen               *>
<*---------------------------------------------------------------------*>
integer sess_index;
begin
begin
  zone tasterm(1,1,stderror);
  integer array ia(1:8),name(1:4);
  integer buf;
  boolean ok;

  trap(alarm);
  ok:=false;
  open(tasterm,0,tasterm_name,1 shift 9);
  ia(1):=12 shift 12 + 0;
  ia(2):=login_struc(sess_index);
  buf:=send_mess(tasterm,ia);
  if wait_ans(tasterm,buf,100,opera_terms(cor_nr,2),true) then
  begin
    if monitor(18,tasterm,1,ia)=1 then
    begin
      if ia(1)=0 then
      begin
        name(1):=ia(5);
        name(2):=ia(6);
        name(3):=name(4):=0;
        write(term_out,<:Id  =:>,true,6,name.laf,
                               <:  Index=:>,<<d>,
                               login_struc(sess_index+1) extract 12);
        if ia(2)>0 then
        begin
          get_proc_name(ia(2),name);
          write(term_out,<:  Sess.Term=:>,true,11,name.laf);
        end
        else
          write(term_out," ",23);
        if ia(3)>0 then
        begin
          get_proc_name(ia(3),name);
          write(term_out,<:  User=:>,true,11,name.laf);
        end
        else
          write(term_out," ",18);
        if false add login_struc(sess_index+2) then
          write(term_out,<: Removing:>)
        else
        begin
          write(term_out,if false add (ia(4) shift (-1)) then
                            <:       :> else <: Active:>);
          write(term_out,if false add ia(4) then
                            <: Direct:> else <::>);
        end;
        ok:=true;
      end;
    end;
  end;
  if not ok then
    write(term_out,string c_p  ,<:<10>:>);
  if false then
    alarm: disable traped(89);
end;
end;

procedure show_term(user_index,term_index);
<* 90 *>
<*---------------------------------------------------------------*>
<* Udskriv oplysninger om en inlogget terminal og dens sessioner *>
<*                                                               *>
<* user_index (call) : Index i login_struc til den user          *>
<*                     der benytter terminalen                   *>
<* term_index (call) : Index i login_struc til ønsket terminal   *>
<*---------------------------------------------------------------*>
integer user_index,term_index;
begin
begin
  integer array user_id,term_id(1:4);
  integer i,sess_index;

  trap(alarm);
  for i:=1 step 1 until 4 do
    user_id(i):=login_struc(user_index-1+i);
  get_proc_name(login_struc(term_index),term_id);
  i:=login_struc(user_index+4) extract 12;
  write(term_out,<:<10>User=:>,true,11,user_id.laf,
                 <:      Terminal =:>,true,11,term_id.laf,
                 <:  Logout :>);
  if i>=100 then
    i:=i-100;
  if i=25 then
    write(term_out,<:disabled for user:>)
  else
    if timecheck_stat then
    begin
      write(term_out,if i>25 or i=0 then
                       <:now:> else <:time :>);
      if i<25 and i>0 then
        write(term_out,<<dd>,i);
    end
    else
    begin
      write(term_out,<:disabled (:>);
      if i>25 or i=0 then
        write(term_out,<:now):>)
      else
        write(term_out,<<dd>,i,<:):>);
    end;
  write(term_out,<:<10>:>);
  sess_index:=login_struc(term_index+2);
  while sess_index>0 do
  begin
    show_sess(sess_index);
    write(term_out,<:<10>:>);
    sess_index:=login_struc(sess_index+3);
  end;
  if false then
    alarm: disable traped(90);
end;
end;

boolean procedure check_priv(priv_nr);
<* 91 *>
<*--------------------------------------------------------*>
<* Check privilegie for bruger, udskriv fejl hvis ikke ok *>
<*                                                        *>
<* priv_nr (call) : Privilegie nummeret der checkes       *>
<*--------------------------------------------------------*>
integer priv_nr;
begin
  trap(alarm);
  if false add ((priv extract 12) shift (priv_nr-11)) then
    check_priv:=true
  else
  begin
    check_priv:=false;
    write(term_out,<:*** no privilege<10>:>);
  end;
  if false then
    alarm: disable traped(91);
end;


procedure opr_finis;
<* 92 *>
<*-------------------------------------------*>
<* Stop udførelsen af operatør kommandoer og *>
<* send continue message til terminal hvis   *>
<* denne ikke er hovedterminalen             *>
<*-------------------------------------------*>
begin

  trap(alarm);
  write(term_out,<:Operator finis<10>:>);
  finis:=true;
  setposition(term_out,0,0);
    if cor_nr<>4 then
  begin
    <* Send continue message til terminal *>
    ia(1):=128 shift 12 + 0;
    ia(2):=0;
    ia(3):=8 shift 12 + 8;
    ia(4):=<:ope:> shift (-24) extract 24;
    ia(5):=<:rat:> shift (-24) extract 24;
    ia(6):=<:or:> shift (-24) extract 24;
    buf:=send_mess(term_in,ia);
    wait_ans(term_in,buf,100,opera_terms(cor_nr,2),true);
  end;
  if false then
    alarm: disable traped(92);
end;

procedure opr_disp;
<* 93 *>
<*---------------------------------------------------*>
<* Udskriv oplysninger om bruger / terminal / system *>
<*---------------------------------------------------*>
begin
  zone tasterm(1,1,stderror);
  long array text(1:6);
  integer user_index,term_index;
  integer array ia(1:8);
  integer array struc_ref(1:1);
  boolean ok;

  trap(alarm);
  initref(struc_ref);
  if read_param(term_in,command_name,0) then
  begin
    command_keyword:=find_keyword_value(command_name.laf(1),1);
    if command_keyword=8 then
    begin <* terminal *>
      if check_priv(4) then
      begin
        wait(struc_sema,struc_ref);
        if read_param(term_in,command_name,0) then
        begin
          term_index:=find_login_terminal(command_name,user_index);
          if term_index>0 then
            show_term(user_index,term_index)
          else
            write(term_out,string t_n_l);
        end
        else
          opr_terminal;
        signal(struc_sema,struc_ref);
      end;
    end
    else
      if command_keyword=9 or command_keyword=18 then
      begin <* user *>
        if check_priv(4) then
        begin
          wait(struc_sema,struc_ref);
          if read_param(term_in,command_name,0) then
          begin
            user_index:=find_login_user(command_name,user_list);
            if user_index>0 then
            begin
              term_index:=login_struc(user_index+6);
              while term_index>0 and not out_stop do
              begin
                show_term(user_index,term_index);
                term_index:=login_struc(term_index+3);
              end;
            end
            else
              write(term_out,string u_n_l);
          end
          else
            opr_user;
          signal(struc_sema,struc_ref);
        end;
      end
      else
        if command_keyword=15 then
        begin <* system *>
          if system_stop then
            write(term_out,<:<10>System is stopping:>);
          write(term_out,<:<10>--- Sign on ---:>);
          write(term_out,<:<10>:>,host_id.laf);
          date(text);
          write(term_out,<:<10>:>,text);
          write(term_out,<:<10>:>,signon_text.laf);
          write(term_out,<:<10>--- Status ---:>);
          write(term_out,<< dddd     >,<:<10>Users     : :>,users,
                <:Free::>,maxterminals-terms);
          write(term_out,<< dddd     >,<:<10>Terminals : :>,terms,
                <:Max ::>,max_terms);
          write(term_out,<< dddd     >,<:<10>Sessions  : :>,sessions);
          write(term_out,<:<10>Timecheck : :>,if timecheck_stat then
                                                <:activ:>
                                              else
                                                <:passiv:>,
                         <:<10>Login     : :>);
          if login_stat=96 then
            write(term_out,<:enabled:>)
          else
            if login_stat=0 then
              write(term_out,<:disabled:>)
            else
              write(term_out,<:disabled from terminal group :>,login_stat);
          write(term_out,<:<10><10>--- Release dates ---:>);
          write(term_out,<:<10>Tasterm   : :>,<<dddddd >,
                         tastermverd,tastermvert);
          write(term_out,<:<10>Tascat    : :>,<<dddddd >,reld,relt);
          write(term_out,<:<10>Init      : :>,<<dddddd >,initver);
        end
        else
          if command_keyword=19 then
          begin <* Resources *>
            ok:=false;
            open(tasterm,0,tasterm_name,1 shift 9);
            ia(1):=18 shift 12;
            if wait_ans(tasterm,send_mess(tasterm,ia),
                                100,operaterms(cor_nr,2),true) then
            begin
              if monitor(18,tasterm,1,ia)=1 then
              begin
                ok:=true;
                write(term_out,<:<10>Resource         Maximum:>,
                      <:     Used       % Used<10>:>,
                      <:<10>Create pools     :>,
                      <<dddd       >,cps,cps-ia(1),
                      <<ddd>,if cps=0 then 0 else (cps-ia(1))/cps*100,
                      <:<10>Create links     :>,
                      <<dddd       >,cls,ia(2),
                      <<ddd>,if cls=0 then 0 else ia(2)/cls*100,
                      <:<10>Sessions         :>,
                      <<dddd       >,maxsessions,sessions,
                      <<ddd>,sessions/maxsessions*100,
                      <:<10>Terminals        :>,
                      <<dddd       >,maxterminals,terms,
                      <<ddd>,terms/maxterminals*100,
                      <:<10>Users            :>,
                      <<dddd       >,maxusers,users,
                      <<ddd>,users/maxusers*100,
                      <:<10>System menues    :>,
                      <<dddd       >,maxsysmenu,ia(3),
                      <<ddd>,ia(3)/maxsysmenu*100,
                      <:<10>Terminal types   :>,
                      <<dddd       >,termtypes,termtypes-ia(6),
                      <<ddd>,(termtypes-ia(6))/termtypes*100,
                      <:<10>Mcl programs     :>,
                      <<dddd       >,mclprogs,mclprogs-ia(5),
                      <<ddd>,(mclprogs-ia(5))/mclprogs*100,
                      <:<10>Core buffers     :>,
                      <<dddd       >,corebufs,corebufs-ia(4),
                      <<ddd>,(corebufs-ia(4))/corebufs*100,
                      <:<10>Spool segments   :>,
                      <<dddd       >,ia(7),ia(7)-ia(8),
                      <<ddd>,(ia(7)-ia(8))/ia(7)*100);
              end;
            end;
            if not ok then
              write(term_out,string c_p,<:<10>:>);
          end
          else
            write(term_out,string ill_par,command_name.laf);
  end
  else
    write(term_out,string miss_par);
  write(term_out,<:<10>:>);
  if false then
    alarm: disable traped(93);
end;

procedure opr_message;
<* 94 *>
<*---------------------------------------------------*>
<* Send meddelelser til bruger og terminal           *>
<*---------------------------------------------------*>
begin
  long array text(0:34);
  integer i,t,user_index,term_index,nr;
  integer array struc_ref(1:1);

  boolean procedure read_term_text(text);
  <* 95 *>
  <*--------------------------------------------------------------*>
  <* Læs tekst fra terminal til text i mcl-format                 *>
  <* prompt for hver linie. Afslut ved '.' først på linie         *>
  <*                                                              *>
  <* text (ret) : Den læste tekst i mcl-format                    *>
  <* Return     : True = Tekst læst, False = Fejl ved læsning     *>
  <*--------------------------------------------------------------*>
  long array text;
  begin
    long array line(1:14);
    integer i,pos;

    trap(alarm);
    pos:=1;
    repeat
      i:=read_line(line);
      if i>0 then
        i:=put_txt(text,pos,line,i);
    until i<1;
    if i=0 then
    begin
      put_ch(text,pos,0,3);
      put_ch(text,200,0,3);
      pos:=pos-4;
      text(0):=((((pos+2)//3)*2+1) shift 12) + pos;
      read_term_text:=true;
    end
    else
      read_term_text:=false;
    if false then
      alarm: disable traped(95);
  end;

  integer procedure read_line(line);
  <* 96 *>
  <*--------------------------------------------------------------------*>
  <* Læs en linie fra terminal                                          *>
  <*                                                                    *>
  <* line (ret) : Den læste linie                                       *>
  <* Return     : Antal tegn læst ink. 'nl' (0 = '.' først på linie)    *>
  <*--------------------------------------------------------------------*>
  long array line;
  begin
    integer ch,i,pos;

    trap(alarm);
    write(term_out,<:>:>);
    setposition(term_out,0,0);
    setposition(term_in,0,0);
    pos:=1;
    repeat
      readchar(term_in,ch);
      i:=put_ch(line,pos,ch,1);
    until (ch='nl') or (i<1) or (((ch='.') or (ch='/')) and (pos=2));
    if ch='nl' then
      read_line:=pos-1
    else
      if ch='/' then
        read_line:=-1
      else
        read_line:=pos-2;
    if false then
      alarm: disable traped(96);
  end;

  trap(alarm);
  initref(struc_ref);
  if read_param(term_in,command_name,0) then
  begin
    command_keyword:=find_keyword_value(command_name.laf(1),1);
    if command_keyword=16 then
    begin <* login *>
      if check_priv(0) then
      begin
        t:=0;
        if read_term_text(text) then
        begin
          nr:=set_text_buf(text.iaf);
          if nr>0 then
          begin
            wait(struc_sema,struc_ref);
            user_index:=user_list;
            while user_index>0 do
            begin
              term_index:=login_struc(user_index+6);
              while term_index>0 do
              begin
                mess_to_term(term_index,nr);
                t:=t+1;
                term_index:=login_struc(term_index+3);
              end;
              user_index:=login_struc(user_index+7);
            end;
            signal(struc_sema,struc_ref);
            send_message_text(nr);
          end
          else
            write(term_out,<:No free text buffer<10>:>);
        end
        else
          write(term_out,string long_text);
        write(term_out,<<d>,<:Message sent to :>,t,<: terminal:>,
                         if t<>1 then <:s:> else <::>);
      end;
    end
    else
      if command_keyword=13 then
      begin <* sign on *>
        if check_priv(0) then
        begin
          if read_term_text(text) then
          begin
            signon_text(0):=text(0) extract 24;
            for i:=1 step 1 until 34 do
              signon_text.laf(i):=text(i);
          end
          else
            write(term_out,string long_text);
        end;
      end
      else
        if command_keyword=12 then
        begin <* all *>
          if check_priv(0) then
          begin
            t:=0;
            if read_term_text(text) then
            begin
              signon_text(0):=text(0) extract 24;
              for i:=1 step 1 until 34 do
                signon_text.laf(i):=text(i);
              nr:=set_text_buf(text.iaf);
              if nr>0 then
              begin
                wait(struc_sema,struc_ref);
                user_index:=user_list;
                while user_index>0 do
                begin
                  term_index:=login_struc(user_index+6);
                  while term_index>0 do
                  begin
                    mess_to_term(term_index,nr);
                    t:=t+1;
                    term_index:=login_struc(term_index+3);
                  end;
                  user_index:=login_struc(user_index+7);
                end;
                signal(struc_sema,struc_ref);
                send_message_text(nr);
              end
              else
                write(term_out,<:No free text buffer<10>:>);
            end
            else
              write(term_out,string long_text);
            write(term_out,<<d>,<:Message sent to :>,t,<: terminal:>,
                                if t<>1 then <:s:> else <::>);
          end;
        end
        else
          if command_keyword=9 then
          begin <* user *>
            if read_param(term_in,command_name,0) then
            begin
              if check_priv(3) then
              begin
                t:=0;
                user_index:=find_login_user(command_name,user_list);
                if user_index>0 then
                begin
                  if read_term_text(text) then
                  begin
                    nr:=set_text_buf(text.iaf);
                    if nr>0 then
                    begin
                      wait(struc_sema,struc_ref);
                      user_index:=find_login_user(command_name,user_list);
                      if user_index>0 then
                        term_index:=login_struc(user_index+6)
                      else
                        term_index:=0;
                      while term_index>0 do
                      begin
                        mess_to_term(term_index,nr);
                        t:=t+1;
                        term_index:=login_struc(term_index+3);
                      end;
                      signal(struc_sema,struc_ref);
                      send_message_text(nr);
                    end
                    else
                      write(term_out,<:No free text buffer<10>:>);
                    write(term_out,<<d>,<:Message sent to :>,t,<: terminal:>,
                                        if t<>1 then <:s:> else <::>);
                  end
                  else
                    write(term_out,string long_text);
                end
                else
                  write(term_out,string u_n_l);
              end;
            end
            else
              write(term_out, string miss_par);
          end
          else
            if command_keyword=8 then
            begin <* terminal *>
              if read_param(term_in,command_name,0) then
              begin
                if check_priv(3) then
                begin
                  term_index:=find_login_terminal(command_name,0);
                  if term_index>0 then
                  begin
                    if read_term_text(text) then
                    begin
                      nr:=set_text_buf(text.iaf);
                      if nr>0 then
                      begin
                        wait(struc_sema,struc_ref);
                        term_index:=find_login_terminal(command_name,0);
                        if term_index>0 then
                          mess_to_term(term_index,nr);
                        signal(struc_sema,struc_ref);
                        send_message_text(nr);
                      end
                      else
                        write(term_out,<:No free text buffer<10>:>);
                    end
                    else
                      write(term_out,string long_text);
                  end
                  else
                    write(term_out,string t_n_l);
                end;
              end
              else
                write(term_out, string miss_par);
            end
            else
              write(term_out,string ill_par,command_name.laf);
  end
  else
    write(term_out,string miss_par);
  write(term_out,<:<10>:>);
  if false then
    alarm: disable traped(94);
end;

procedure opr_remove;
<* 97 *>
<*---------------------------------------------------*>
<* Nedlæg session, terminal eller bruger             *>
<*---------------------------------------------------*>
begin
  integer array user_id,term_id(1:4);
  integer index,user_index,term_index,sess_index,t;
  integer array struc_ref(1:1);
  boolean found;

  trap(alarm);
  initref(struc_ref);
  if read_param(term_in,command_name,0) then
  begin
    if check_priv(0) then
    begin
      command_keyword:=find_keyword_value(command_name.laf(1),1);
      if command_keyword=14 then
      begin <* session *>
        if read_param(term_in,user_id,0) and
           read_param(term_in,command_name,index) then
        begin
          wait(struc_sema,struc_ref);
          user_index:=find_login_user(user_id,user_list);
          if user_index>0 then
          begin
            if false add (login_struc(user_index+4) shift (-12-index)) then
            begin
              found:=false;
              term_index:=login_struc(user_index+6);
              while not found and term_index>0 do
              begin
                sess_index:=login_struc(term_index+2);
                while not found and sess_index>0 do
                begin
                  if (login_struc(sess_index+1) extract 12)=index then
                    found:=true
                  else
                    sess_index:=login_struc(sess_index+3);
                end;
                term_index:=login_struc(term_index+3);
              end;
              if not remove_sess(sess_index) then
                write(term_out,<:*** session not removed:>);
            end
            else
              write(term_out,<:*** unknow user index:>);
          end
          else
            write(term_out,string u_n_l);
          signal(struc_sema,struc_ref);
        end
        else
          write(term_out,string miss_par);
      end
      else
        if command_keyword=9 then
        begin <* user *>
          if read_param(term_in,user_id,0) then
          begin
            t:=0;
            wait(struc_sema,struc_ref);
            user_index:=find_login_user(user_id,user_list);
            if user_index>0 then
            begin
              term_index:=login_struc(user_index+6);
              while term_index>0 do
              begin
                sess_index:=login_struc(term_index+2);
                while sess_index>0 do
                begin
                  if remove_sess(sess_index) then
                    t:=t+1;
                  sess_index:=login_struc(sess_index+3);
                end;
                term_index:=login_struc(term_index+3);
              end;
            end
            else
              write(term_out,string u_n_l);
            signal(struc_sema,struc_ref);
            write(term_out,<<dd >,t,<:session:>,if t<>1 then <:s:> else <::>,
                                    <: removed:>);
          end
          else
            write(term_out,string miss_par);
        end
        else
          if command_keyword=8 then
          begin <* terminal *>
            if read_param(term_in,term_id,0) then
            begin
              t:=0;
              wait(struc_sema,struc_ref);
              term_index:=find_login_terminal(term_id,0);
              if term_index>0 then
              begin
                sess_index:=login_struc(term_index+2);
                while sess_index>0 do
                begin
                  if remove_sess(sess_index) then
                    t:=t+1;
                  sess_index:=login_struc(sess_index+3);
                end;
                term_index:=login_struc(term_index+3);
              end
              else
                write(term_out,string t_n_l);
              signal(struc_sema,struc_ref);
              write(term_out,<<dd >,t,<:session:>,if t<>1 then <:s:> else <::>,
                                      <: removed:>);
            end
            else
              write(term_out,string miss_par);
          end
          else
            write(term_out,string ill_par,command_name.laf);
    end;
  end
  else
    write(term_out,string miss_par);
  write(term_out,<:<10>:>);
  if false then
    alarm: disable traped(97);
end;

procedure opr_set;
<* 98 *>
<*---------------------------------------------------*>
<* Sæt værdi for timecheck eller antal terminaler    *>
<*---------------------------------------------------*>
begin
  integer user_index;
  integer array user_id(1:4),ref(1:1),struc_ref(1:1);

  trap(alarm);
  initref(struc_ref);
  if read_param(term_in,command_name,0) then
  begin
    if check_priv(0) then
    begin
      command_keyword:=find_keyword_value(command_name.laf(1),1);
      if command_keyword=8 then
      begin <* terminal *>
        if read_param(term_in,command_name,command_value) then
        begin
          if command_value<=maxterminals then
            max_terms:=command_value
          else
            write(term_out,<:*** not enough resources<10>:>);
        end
        else
          write(term_out,string miss_par);
      end
      else
        if command_keyword=17 then
        begin <* timecheck *>
          if read_param(term_in,command_name,0) then
          begin
            command_keyword:=find_keyword_value(command_name.laf(1),1);
            if command_keyword=10 or command_keyword=11 then
            begin <* on/off *>
              timecheck_stat:=if command_keyword=10 then
                                true
                              else
                                false;
            end
            else
              if command_keyword=9 then
              begin <* user *>
                if read_param(term_in,user_id,0) then
                begin
                  if read_param(term_in,command_name,command_value) then
                  begin
                    if find_keyword_value(command_name.laf(1),1)=11 then
                      command_value:=25;
                    if command_value<=25 and command_value>=0 then
                    begin
                      wait(struc_sema,struc_ref);
                      user_index:=find_login_user(user_id,user_list);
                      if user_index>0 then
                        login_struc(user_index+4):=
                           ((login_struc(user_index+4) shift (-12)) shift 12)+
                           command_value
                      else
                        write(term_out,string u_n_l);
                      signal(struc_sema,struc_ref);
                    end
                    else
                      write(term_out,string ill_time);
                  end
                  else
                    write(term_out, string miss_par);
                end
                else
                  write(term_out,string miss_par);
              end
              else
                write(term_out,string ill_par,command_name.laf,<:<10>:>);
          end;
          <* start time check *>
          initref(ref);
          wait_select:=6;
          wait(message_buf_pool,ref);
          signal(time_sem,ref);
        end
        else
          write(term_out,string ill_par,command_name.laf,<:<10>:>);
    end;
  end
  else
    write(term_out,string miss_par);
  if false then
    alarm: disable traped(98);
end;

procedure opr_start;
<* 99 *>
<*---------------------------------------------------*>
<* Start inlogning til systemet                      *>
<*---------------------------------------------------*>
begin
  integer array ref(1:1);

  trap(alarm);
  if read_param(term_in,command_name,0) then
  begin
    if check_priv(0) then
    begin
      command_keyword:=find_keyword_value(command_name.laf(1),1);
      if command_keyword=16 then
      begin <* login *>
        login_stat:=96;
      end
      else
        if command_keyword=15 then
        begin <* system *>
          if system_stop then
          begin
            initref(ref);
            wait_select:=6;
            wait(message_buf_pool,ref);
            signal(free_sem,ref);
            write(term_out,<:System restarted<10>:>);
          end
          else
            write(term_out,<:*** System not stoped<10>:>);
        end
        else
          write(term_out,string ill_par,command_name.laf,<:<10>:>);
    end;
  end
  else
    write(term_out,string miss_par);
  if false then
    alarm: disable traped(99);
end;

procedure opr_stop;
<* 100 *>
<*---------------------------------------------------*>
<* Stop inlogning eller hele systemet                *>
<*---------------------------------------------------*>
begin
  zone z(4,1,stderror);
  integer array ia(1:8);
  integer array dummy(1:1);
  integer user_index,i,stop_time;

  trap(alarm);
  initref(dummy);
  if read_param(term_in,command_name,0) then
  begin
    if check_priv(4) then
    begin
      command_keyword:=find_keyword_value(command_name.laf(1),1);
      if command_keyword=15 then
      begin <* system *>
        if read_param(term_in,command_name,stop_time) then
        begin
          if stop_time=0 then
          begin
            command_keyword:=find_keyword_value(command_name.laf(1),1);
            if command_keyword=20 then
            begin <* check *>
              stop_time:=8388606;
              write(term_out,<:System stopping after check<10>:>);
            end
            else
              if command_name.laf(1)<> long <:0:> then
              begin
                write(term_out,string ill_par,command_name.laf,<:<10>:>);
                goto start;
              end;
          end
          else
            write(term_out,<:System stopping<10>:>);
          setposition(term_out,0,0);
          opera_terms(cor_nr,1):=1;
          login_stat:=0;
          system_stop:=true;
          timecheck_stat:=false;
          write_message(-100,if stop_time<>8388606 then stop_time
                             else -1,true,<:Operator system stop:>);
          for i:=1 step 1 until stop_time do
          begin
            if (stop_time=8388606) and (sessions=0) then
              goto stop_sys;
            notis_users(stop_txt);
            if i<stop_time then
            begin
              wait(struc_sema,dummy);
              user_index:=user_list;
              while user_index>0 do
              begin
                if login_struc(user_index+4) extract 12 = 26 then
                  login_struc(user_index+4):=
                          (login_struc(user_index+4) shift (-12)) shift 12 ;
                user_index:=login_struc(user_index+7);
              end;
              signal(struc_sema,dummy);
            end;
            wait_time:=600;
            if wait(free_sem,dummy)>0 then
            begin
              signal(message_buf_pool,dummy);
              system_stop:=false;
              finis:=true;
              if head_consol=1 then
                write(term_out,<:System restarted<10>:>);
              head_consol:=1;
              wait(struc_sema,dummy);
              user_index:=user_list;
              while user_index>0 do
              begin
                login_struc(user_index+4):=
                     ((login_struc(user_index+4) shift (-12)) shift 12) + 25;
                user_index:=login_struc(user_index+7);
              end;
              signal(struc_sema,dummy);
              goto start;
            end;
          end;
          stop_sys:
          <* Send stop message til tasterm *>
          ia(1):=14 shift 12 + 0;
          ia(2):=0;
          open(z,0,tasterm_name,0);
          send_mess(z,ia);
          monitor(18,z,1,ia);
          goto stop;
        end
        else
          write(term_out,string miss_par);
      end
      else
        if command_keyword=16 then
        begin <* login *>
          read_param(term_in,command_name,i);
          if i<0 or i>95 then
            write(term_out,string ill_val)
          else
            login_stat:=i;
         end
        else
          write(term_out,string ill_par,command_name.laf,<:<10>:>);
    end;
  end
  else
    write(term_out,string miss_par);
start:
  if false then
    alarm: disable traped(100);
end;

procedure opr_terminal;
<* 101 *>
<*---------------------------------------------------*>
<* Udskriv alle terminaler der er inlogget           *>
<*---------------------------------------------------*>
begin
  integer user_index,term_index,t,i;
  integer array term_id,user_id(1:4);

  trap(alarm);
  t:=0;
  user_index:=user_list;
  while user_index>0 and not out_stop do
  begin
    for i:=0 step 1 until 3 do
      user_id(i+1):=login_struc(user_index+i);
    term_index:=login_struc(user_index+6);
    while term_index>0 and not out_stop do
    begin
      get_proc_name(login_struc(term_index),term_id);
      write(term_out,<:<10>:>,true,20,term_id.laf,true,11,user_id.laf);
      term_index:=login_struc(term_index+3);
      t:=t+1;
    end;
    user_index:=login_struc(user_index+7);
  end;
  write(term_out,<:<10><10>Terminals = :>,t);
  if false then
    alarm: disable traped(101);
end;

procedure opr_user;
<* 102 *>
<*---------------------------------------------------*>
<* Udskriv alle brugerer der er tilmeldt             *>
<*---------------------------------------------------*>
begin
  integer user_index,t,i;
  integer array user_id(1:4);

  trap(alarm);
  t:=0;
  user_index:=user_list;
  while user_index>0 and not out_stop do
  begin
    for i:=0 step 1 until 3 do
      user_id(i+1):=login_struc(user_index+i);
    write(term_out,<:<10>:>,true,11,user_id.laf);
    t:=t+1;
    user_index:=login_struc(user_index+7);
  end;
  write(term_out,<:<10><10>Users = :>,t);
  if false then
    alarm: disable traped(102);
end;


  <****************************************>
  <* Hoved rutinen for operatør korutinen *>
  <****************************************>
  trap(alarm);
  claim(600); <* Reserver plads på stakken *>
  initref(ref);
  wait_time:=0;
  wait_select:=0;
  while true do
  begin
    break:=false;
    finis:=false;
    wait(opera_terms(cor_nr,2),ref);
    head_consol:=ref(3);
    <* sæt uændret besked buffer tilbage i pool *>
    signal(message_buf_pool,ref);
    if get_proc_name(opera_terms(cor_nr,1),term_name) then
    begin
      open(term_out,8,term_name,1 shift 16 + 1 shift 9);
      open(term_in,8,term_name,1 shift 9);
      if head_consol=1 then
      begin <* Ikke hoved terminalen *>
        <* Hent user id fra terminal *>
        getzone6(term_in,ia);
        ia(1):=131 shift 12 + 0; <* get user id *>
        ia(2):=ia(19)+1;  <* first address *>
        ia(3):=ia(19)+11; <* last address  *>
        buf:=send_mess(term_in,ia);
        if buf=0 then
          break:=true
        else
        begin
          if not wait_ans(term_in,buf,100,opera_terms(cor_nr,2),false) then
            break:=true <* Der blev ikke svaret inden 10 sek. *>
          else
          begin
            if monitor(18,term_in,1,ia)<>1 then
              break:=true
            else
              if ia(1)<>0 then
                break:=true
              else
              begin
                close(term_in,false);
                for i:=1,2 do
                  user_id.laf(i):=term_in.laf(i);
                password:=term_in.laf(3);
                open(term_in,8,term_name,1 shift 9);
                <* Find privilegier i login_struc *>
                user_ident:=find_login_user(user_id,user_list);
                if user_ident=0 then
                  break:=true <* Bruger ikke login *>
                else
                  priv:=false add (login_struc(user_ident+5) shift (-12));
              end;
          end;
        end;
      end
      else
        priv:=true; <* alle privilegier *>
      if not break then
        write(term_out,<:<10>Operator ready<10>:>)
      else
      begin
        write(term_out,
              <:Tas operatør-adgang ikke tilladt fra denne terminal<10>:>);
        setposition(term_out,0,0);
        monitor(64,term_out,0,command_name <*dummy*>);
      end;
      while not (finis or break) do
      begin <* Udfør operatør kommunikation *>
        setposition(term_out,0,0);
        write(term_out,<:$ :>);<* Prompt *>
        setposition(term_out,0,0);
        setposition(term_in,0,0); <* Slet input buffer *>
        if read_param(term_in,command_name,0) then
        begin
          if not break then <* break evt. sat af write el. read_param *>
          begin
            <* fortolk kommando i commandline *>
            command_keyword:=find_keyword_value(command_name.laf(1),1);
            if command_keyword>7 or command_keyword=0 then
            begin
              write(term_out,<:*** unknown command: :>,
                    command_name.laf,<:<10>:>);
              setposition(term_out,0,0);
            end
            else
            begin
              out_stop:=false;
              case command_keyword of
              begin
                <* Udfør kommando                                   *>
                <* Test for out_stop ved hver setposition på output *>
                <* er denne true stoppes evt ydeligerer udskrift    *>
                <* Test for break efter hver i/o, er denne true     *>
                <* stoppes udførelsen af kommandoen                 *>
                opr_finis;
                opr_disp;
                opr_message;
                opr_remove;
                opr_set;
                opr_start;
                opr_stop;
              end;
            end;
          end;
        end;
        if head_consol=0 then
        begin
          write(term_out,<:ok<10>:>);
          finis:=true; <* Hoved terminal *>
        end;
      end; <* session *>
    end;
    close(term_in,true);
    close(term_out,true);
    opera_terms(cor_nr,1):=0;
  end; <* while true *>
stop:
  if false then
    alarm: disable traped(85);
end; <* Operatør korutine *>

<**************************************>
<**************************************>
<* Procedure til time ckeck korutinen *>
<**************************************>
<**************************************>

integer procedure next_hour;
<* 103 *>
<*------------------------------------------------------------*>
<* Beregn ventetiden til næste hele klokkeslet i              *>
<* 0.1 sek enheder                                            *>
<*                                                            *>
<* Return : Tiden til næste hele klokkeslet i 0.1 sek enheder *>
<*------------------------------------------------------------*>
begin
  real r;
  long t;

  systime(1,0,r);
  t:=r;
  next_hour:=round(3600-t+t//3600*3600)*10;
end;

procedure notis_users(txt);
<* 104 *>
<*--------------------------------------------------------------------*>
<* Find bruger der har overskredet tiden eller alle hvis stop         *>
<* Send log_txt  og mærk tiden med 26                                 *>
<* Gentag for alle brugere                                            *>
<*--------------------------------------------------------------------*>
integer array txt;
begin
  integer user_index,term_index,map,ut,nr;
  boolean found;
  integer array ref(1:1),struc_ref(1:1);

  trap(alarm);
  initref(ref);
  initref(struc_ref);
  found:=true;
  repeat
    nr:=set_text_buf(txt);
    if nr=0 then
    begin
      wait_time:=100;
      wait(delay_sem,ref);
    end;
  until nr>0;
  while found do
  begin
    wait(struc_sema,struc_ref);
    found:=false;
    user_index:=user_list;
    while user_index>0 and not found do
    begin
      ut:=login_struc(user_index+4) extract 12;
      found:=(ut<=cur_time) or (system_stop and (ut<>26));
      if not found then
        user_index:=login_struc(user_index+7);
    end;
    if found then
    begin
      map:=login_struc(user_index+4) shift (-12);
      login_struc(user_index+4):=(map shift 12)+26;
      term_index:=login_struc(user_index+6);
      while term_index>0 do
      begin
        mess_to_term(term_index,nr);
        term_index:=login_struc(term_index+3);
      end;
    end;
    signal(struc_sema,struc_ref);
    send_message_text(nr);
  end;
  if false then
    alarm: disable traped(104);
end;

procedure remove_users;
<* 105 *>
<*--------------------------------------------------------------------*>
<* Find første bruger der har 26 sat i tid                            *>
<* Send remove session message til TAS og sæt tid 27                  *>
<*  Gentag for alle                                                   *>
<*--------------------------------------------------------------------*>
begin
  integer user_index,term_index,sess_index,map;
  boolean found;
  integer array struc_ref(1:1);

  trap(alarm);
  initref(struc_ref);
  found:=true;
  while found do
  begin
    wait(struc_sema,struc_ref);
    found:=false;
    user_index:=user_list;
    while user_index>0 and not found do
    begin
      found:=(login_struc(user_index+4) extract 12)=26;
      if not found then
        user_index:=login_struc(user_index+7);
    end;
    if found then
    begin
      map:=login_struc(user_index+4) shift (-12);
      login_struc(user_index+4):=(map shift 12)+27;
      term_index:=login_struc(user_index+6);
      while term_index>0 do
      begin
        sess_index:=login_struc(term_index+2);
        while sess_index>0 do
        begin
          remove_sess(sess_index);
          sess_index:=login_struc(sess_index+3);
        end;
        term_index:=login_struc(term_index+3);
      end;
    end;
    signal(struc_sema,struc_ref);
  end;
  if false then
    alarm: disable traped(105);
end;

procedure timeco;
<* 106 *>
<*--------------------------------------------*>
<* Hoved procedure for check time korutinen   *>
<*--------------------------------------------*>
begin
  integer array dummy(1:1);
  integer user_index,i,last_time;
  integer array id(1:4);

  trap(alarm);
  claim(500);
  initref(dummy);
  while true do
  begin
    wait_time:=next_hour;
    if wait(time_sem,dummy)>0 then
      signal(message_buf_pool,dummy);
    if cur_time=0 then
    begin
      wait(struc_sema,dummy);
      user_index:=user_list;
      while user_index>0 do
      begin
        for i:=0,1,2,3 do
          id(i+1):=login_struc(user_index+i);
        find_user(id);
        last_time:=if check_time(last_time) then
                     last_time
                   else
                     0;
        login_struc(user_index+4):=
            ((login_struc(user_index+4) shift (-12)) shift 12) + last_time;
        user_index:=login_struc(user_index+7);
      end;
      signal(struc_sema,dummy);
    end;
    for i:=1 step 1 until log_time do
    begin
      if timecheck_stat then
      begin
        notis_users(log_txt);
        if i<log_time then
        begin
          wait(struc_sema,dummy);
          user_index:=user_list;
          while user_index>0 do
          begin
            if login_struc(user_index+4) extract 12 = 26 then
              login_struc(user_index+4):=
                  (login_struc(user_index+4) shift (-12)) shift 12 ;
            user_index:=login_struc(user_index+7);
          end;
          signal(struc_sema,dummy);
        end;
        wait_time:=600;
        if wait(time_sem,dummy)>0 then
           signal(message_buf_pool,dummy);
      end;
    end;
    if timecheck_stat then
      remove_users;
  end;
  if false then
    alarm: disable traped(106);
end;

procedure write_term_text; <* Korutine *>
<* 107 *>
<*---------------------------------------------------------------*>
<* Gemmenløb alle terminaler for at udskrive en evt tekst der er *>
<* markeret i login_struc. Start gennemløb ved signalering fra   *>
<* send_text proceduren. Efter udskrift frigives text-buffer     *>
<*                                                               *>
<* Formater af sem-message:                                      *>
<*                                                               *>
<* Ved send_text:    (1)  buf nr.                                *>
<*                   (2)  message_buf_addr                       *>
<*                   (3)  text_write_sem                         *>
<*                   (4)  zone array index                       *>
<*                                                               *>
<* Ved signal   :    (1)  0                                      *>
<*                   (2)  8                                      *>
<*                   (3)  text buf. nr.                          *>
<*                   (4)  0                                      *>
<*                                                               *>
<*---------------------------------------------------------------*>
begin
  integer array ref(1:1),answer(1:8);
  integer out_count,i,buf_nr;
  boolean finis;
  zone array z(max_text_count,1,1,stderror);

boolean procedure write_next_term;
<* 108 *>
<*-----------------------------------------------------*>
<* Udskriv text på en terminal (den første der findes) *>
<*-----------------------------------------------------*>
begin
  integer array ref(1:1),share(1:12);
  integer user_index,term_index,bufs,nr,i,buf_addr;
  integer array struc_ref(1:1);
  boolean found;

  trap(alarm);
  initref(ref);
  initref(struc_ref);
  wait(struc_sema,struc_ref);
  found:=false;
  user_index:=user_list;
  while (user_index>0) and (not found) do
  begin
    term_index:=login_struc(user_index+6);
    while term_index>0 and not found do
    begin
      bufs:=login_struc(term_index+1) shift (-21);
      if bufs<>0 then
      begin
        found:=true;
        nr:=0;
        while not (false add (bufs shift (-nr))) do
          nr:=nr+1;
        nr:=nr+1;
        login_struc(term_index+1):=login_struc(term_index+1)-
                                   (1 shift (20+nr));
        i:=1;
        repeat
          getshare6(z(i),share,1);
          i:=i+1;
        until share(1)<2;
        i:=i-1;
        share(4):=16 shift 12;
        share(5):=nr;
        share(6):=login_struc(term_index);
        setshare6(z(i),share,1);
        buf_addr:=monitor(16,z(i),1,share);
        if buf_addr=0 then
          write_message(998,1,false,<:Claims exceeded:>);
        text_buf_reserved(nr):=if text_buf_reserved(nr)=-1 then
                                 1
                               else
                                 text_buf_reserved(nr)+1;
        wait_select:=8;
        wait(message_buf_pool,ref);
        ref(1):=nr;
        ref(2):=buf_addr;
        ref(3):=text_write_sem;
        ref(4):=i;
        signal(wait_answer_pool,ref);
      end
      else
        term_index:=login_struc(term_index+3);
    end;
    user_index:=login_struc(user_index+7);
  end;
  write_next_term:=not found;
  signal(struc_sema,struc_ref);
  if false then
    alarm: disable traped(108);
end; <* write_next_text *>


  trap(alarm);   <* main write_term_text *>
  claim(500);
  initref(ref);
  out_count:=0;
  for i:=1,2,3 do
    text_buf_reserved(i):=0;
  for i:=1 step 1 until max_text_count do
    open(z(i),0,tasterm_name,1 shift 9);
  while true do
  begin
    wait(text_write_sem,ref);
    if ref(1)<>0 then
    begin
      <* answer *>
      monitor(18,z(ref(4)),1,answer);
      text_buf_reserved(ref(1)):=text_buf_reserved(ref(1))-1;
      ref(1):=0;
      ref(2):=8;
      signal(message_buf_pool,ref);
      out_count:=out_count-1;
    end
    else
    begin
      <* Ny tekst *>
      buf_nr:=ref(3);
      signal(message_buf_pool,ref);
      finis:=false;
      while not finis do
      begin
        if out_count=max_text_count then
        begin
          wait_select:=-1;
          wait(text_write_sem,ref);
          monitor(18,z(ref(4)),1,answer);
          text_buf_reserved(ref(1)):=text_buf_reserved(ref(1))-1;
          ref(1):=0;
          ref(2):=8;
          signal(message_buf_pool,ref);
          out_count:=out_count-1;
        end;
        finis:=write_next_term;
        if not finis then
          out_count:=out_count+1;
      end;
      if text_buf_reserved(buf_nr)=-1 then
        text_buf_reserved(buf_nr):=0;
    end;
  end;
  if false then
  alarm: disable traped(107);
end;


<*************************************************>
<* Start af tascat og initialisering af korutiner*>
<*************************************************>

    trap(alarm);
    <* Initialiser login_struc *>
    init_login_struc;
    <* Opret korutinerne og semafor beskrivelserne *>
    activity(3+number_of_opera);
    coroutines(5+number_of_opera,test_out);
    sys_start:=true;
    <***********************************************************>
    <* Alloker alle besked buffere på stakken og signaler dem  *>
    <* til semaforen message_buf_pool                          *>
    <* En buffer kan hentes fra poolen på følgende måde:       *>
    <*  wait_selct:= 'besked buffer størrelse';                *>
    <*  wait(message_buf_pool,ref);                            *>
    <*                                                         *>
    <* Når bufferen ikke skal benyttes mere sættes den tilbage *>
    <*  ref(1):=0;                                             *>
    <*  ref(2):='besked buffer størrelse';                     *>
    <*  signal(message_buf_pool,ref);                          *>
    <***********************************************************>
    for i:=1 step 1 until (2*number_of_opera) do
      allocate(message_buf_pool,6,0);
    for i:=1 step 1 until (3 + max_text_count) do
      allocate(message_buf_pool,8,0);
    allocate(message_buf_pool,22,0);
    allocate(struc_sema,6,0);
    select_test:=test_select;
    <* Vent på synkronisering med tasterm *>
    wait_tasterm(false);
    <* Start korutinerne *>
    new_activity(1,0,catco);     <* Katalog hovedrutinen *>
    new_activity(2,0,timeco);    <* Time check rutinen *>
    new_activity(3,0,write_term_text);
    for i:=4 step 1 until number_of_opera+3 do
      new_activity(i,0,operator,i); <* Operatør rutinerne *>

    <* Start kerne, Udskriv version *>
    write_message(struc_size,number_of_opera,true,<:Tas version 1.0 ready:>);
    i:=kernel(traped);

    answer(4):= <:ok :> shift (-24) extract 24;
    answer(5):= <:   :> shift (-24) extract 24;
    if not system_stop then
    begin
alarm:traped(0);
      write_message(run_alarm_pos,run_alarm_cause,true,<:Run error:>);
      answer(4):= <:err:> shift (-24) extract 24;
      answer(5):= <:or :> shift (-24) extract 24;
    end;
    close(usercat,true);
    close(termcat,true);
    close(typecat,true);
    close_test_out;
    sys_start:=false;
  end; <* TASCAT *>


  <******************************************>
  <* Program start og initialisering        *>
  <******************************************>

  <* Sæt global trap lable *>
  trap(init_alarm);

  <* sæt fields *>
  sender_pda:=2;
  reciever_pda:=4;
  buf_addr:=6;
  mess_array:=6;
  laf:=iaf:=baf:=0;

  <* sæt status *>
  trap_mode:=-1;
  sys_start:=false;
  system_stop:=false;
  test_on:=false;
  killed:=false;
  users:=
  sessions:=
  terms:=0;

  run_alarm_pos:=
  run_alarm_cause:=0;

  <* initialiser konstant tekster *>
  ill_par:=   real <:*** illegal parameter: :>;
  miss_par:=  real <:*** missing parameter<10>:>;
  ill_val:=   real <:*** illegal value<10>:>;
  long_text:= real <:*** text too long or input terminated by /<10>:>;
  t_n_l:=     real <:*** terminal not login<10>:>;
  u_n_l:=     real <:*** user not login<10>:>;
  ill_time:=  real <:*** illegal login time<10>:>;
  c_p  :=     real <:*** communication problems<10>:>;

  <* Fjern fp area proces og in zonen *>
  open(test_out,4,<:fp:>,0);
  close(test_out,true);
  close(in,true);
  <* Fjern c og v entry *>
  open(copy_buf,0,<:c:>,0);
  monitor(48,copy_buf,i,log_txt);
  close(copy_buf,true);
  open(copy_buf,0,<:v:>,0);
  monitor(48,copy_buf,i,log_txt);
  close(copy_buf,true);

  isotable(char_table);
  for i:=0 step 1 until 127 do
    char_table(i+128):=char_table(i)+128;
  char_table(46):=7 shift 12 + 46;
  intable(char_table);

  <* Initialiser hovedterminalen *>
  head_term_pda:=system(7,i,head_term_name.laf);

  <* initialiser keywords *>
  keywords_init;

  <* Læs fp parametre *>
  read_param_line;

  <* Sæt konstant værdier m.m fra init fil *>
  init_tascat;

  <* Åben test output filen *>
  open_test(testout_name);

  <* initialiser semafor navnene med nummer             *>
  init_sem;

  <* Test og initialiser baserne for processen *>
  init_bases;

  <* init opera_terms array'et *>
  init_opera_terms;

  <* Beregn struc_size og test processens størrelse *>
  struc_size:=2*max_users+max_terminals+max_sessions;
  max_terms:=if fp_maxterms>0 then
               fp_maxterms
             else
               max_terminals;
  system(2,own_size,prog_name.laf);
  <* Hent oversættelses dato og tid for tascat *>
  begin
    integer segm,rel;
    integer array tail(1:10);
    zone z(128,1,stderror);
    open(z,4,prog_name,0);
    monitor(42,z,0,tail);
    segm:=tail(7) shift (-12);
    rel:=tail(7) extract 12;
    setposition(z,0,segm);
    inrec6(z,rel-4);
    inrec6(z,4);
    reld:=z(1) shift (-24) extract 24;
    relt:=z(1) extract 24;
    close(z,true);
  end;

  if struc_size>(own_size-5000-number_of_opera*1500)//8 then
    write_message(own_size,25000+number_of_opera*1500+struc_size*8,
                            false,<:Process too small:>)
  else
  begin
    <* Åben katalogerne *>
    open_catalogs(usercat_name,termcat_name,typecat_name);

    <* test buffer claims *>
    system(5,own_pda+26,testout_name <* work array *>);
    if (testout_name(1) shift (-12))<(max_text_count+3+ number_of_opera) then
      write_message(testout_name(1) shift (-12)+2,
                    max_text_count+5+number_of_opera,
                    false,<:Not enough buffers:>);

    if false then
    begin <* trap i initialiseringen *>
init_alarm: traped(0);
      write_message(run_alarm_pos,run_alarm_cause,true,<:Initiation error:>);
      wait_tasterm(true);
      answer(4):= <:err:> shift (-24) extract 24;
      answer(5):= <:or :> shift (-24) extract 24;
    end
    else

    <* start hovedproceduren *>
      tascat;

    if killed then
      write_message(0,3,true,<:System breaked:>)
    else
      write_message(0,4,true,<:System stopped:>);
    system(11,i,log_txt);
    sys_bases(1):=log_txt(1);
    sys_bases(2):=log_txt(2);
    set_cat_bases(sys_bases);
    answer(1):=2 shift 12 + 1;
    answer(2):= <: st:> shift (-24) extract 24;
    answer(3):= <:op :> shift (-24) extract 24;
    for i:=6,7,8 do
      answer(i):=0;
    system(10,0,answer);
  end;
end;
▶EOF◀