1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1985 *
  6         *                                                         *
  7         *********************************************************** */
  8 
  9 /* format: off */  /* This program was formatted via emacs. */
 10 
 11 initiate_:
 12 initiate:
 13     procedure (a_dname, a_ename, a_rname, a_segsw, a_copysw, a_segptr, a_code);
 14 
 15 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 16 /*                                                                           */
 17 /* History of earlier versions of the program:                               */
 18 /* Modified on 05/74 by E Stone to call status_$long when copy made          */
 19 /*    (to get curlen and to cause a branch update)                           */
 20 /* Modified by Kobziar July 74 to call new entry in access_mode              */
 21 /*    and to add privileged initate entries                                  */
 22 /* Modified on 03/76 by R. Bratt to check mountedness of LV before okaying   */
 23 /*    makeknown                                                              */
 24 /* Modified on 06/01/76 by R. Bratt to call find_$finished                   */
 25 /* Modified on 06/02/76 by R. Bratt to cleanup a piece of trash!             */
 26 /* Modified 760317 by L. Scheffler to properly call dir_control_error        */
 27 /*    entries                                                                */
 28 /* Modified on 03/29/77 by M. Weaver to set lot fault when segment is first  */
 29 /*    initiated in ring                                                      */
 30 /* Modified on 78/02/21 by M. Weaver to call link_man$grow_lot at proper     */
 31 /*    boundary                                                               */
 32 /* Modified on 79/08/29 by Mike Grady to fix bug handling reserved segno's   */
 33 /*    and copy sw                                                            */
 34 /* Modified on 81/04/06 by J. Bongiovanni to fix max lot size check          */
 35 /* Modified May 1981 by C. Hornig to remove references to the copy switch.   */
 36 /* Modified 04/30/84 by S. Herbst to add $get_segment_ptr_path               */
 37 /* Modified 07/18/84 by Keith Loepere to use the new dc_find.                */
 38 /* Modified 10/19/84 by Keith Loepere to do the right thing for initiating   */
 39 /*    directories.                                                           */
 40 /*                                                                           */
 41 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 42 
 43 
 44 /****^  HISTORY COMMENTS:
 45   1) change(85-12-10,GDixon), approve(86-08-09,MCR7388),
 46      audit(86-09-12,Farley), install(86-09-08,MR12.0-1150):
 47      Completely rewritten to:
 48       a) improve program structure and reduce number of switches used in code;
 49       b) keep directory locked while calling makeknown_, so that the pointer to
 50          dir entry remains valid;
 51       c) use dc_find$finished for most directory unlocking.
 52                                                    END HISTORY COMMENTS */
 53 
 54 ^L
 55 /* Parameters */
 56 
 57 dcl  a_code fixed bin (35) parameter;
 58 dcl  a_copysw fixed bin (2) parameter;
 59 dcl  a_dname char (*) parameter;
 60 dcl  a_dp ptr parameter;
 61 dcl  a_ename char (*) parameter;
 62 dcl  a_rname char (*) parameter;
 63 dcl  a_count fixed bin (17);
 64 dcl  a_segptr ptr parameter;
 65 dcl  a_segsw fixed bin (1) parameter;
 66 dcl  a_uid bit (36) parameter;
 67 
 68 /* Variables */
 69 
 70 dcl  1 in aligned,                                /* copies of input parms.  */
 71        2 segp ptr,
 72        2 dirp ptr,
 73        2 dname char(168) unal,
 74        2 ename char(32) unal,
 75        2 rname char(32) varying;
 76 dcl  1 entrypoint aligned,                        /* per-entrypoint controls */
 77        2 dc_find entry (char(168), char(32), ptr, fixed bin(35)) variable,
 78        2 should_call_find_finished bit(1),
 79        2 should_unlock_dir bit(1),
 80        2 priv bit(1);
 81 dcl  1 seg aligned,                               /* intermediate data for   */
 82        2 dirp ptr,                                /* segment being initiated.*/
 83        2 entp ptr,
 84        2 directory bit(1),
 85        2 hash_bucket fixed bin(17);
 86 dcl  1 out aligned,                               /* copies of output data.  */
 87        2 segp ptr,
 88        2 bc fixed bin(24),
 89        2 uid bit(36),
 90        2 code fixed bin(35);
 91 
 92 /* External */
 93 
 94 dcl  error_table_$dirseg external fixed bin (35);
 95 dcl  error_table_$invalid_copy external fixed bin (35);
 96 dcl  error_table_$seg_unknown external fixed bin (35);
 97 dcl  error_table_$segknown external fixed bin (35);
 98 
 99 /* Entries */
100 
101 dcl  kstsrch entry (bit (36) aligned, fixed bin (17), ptr);
102 
103 /* Misc */
104 
105 dcl  (addr, baseno, baseptr, fixed, null, ptr, rtrim, unspec) builtin;
106 dcl  (FALSE init("0"b),
107       TRUE  init("1"b)) bit(1) int static options(constant);
108 ^L
109 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
110 /*                                                                           */
111 /* NAME:  initiate                                                           */
112 /*                                                                           */
113 /* This module is a primitive which calls other routines to make a segment   */
114 /* known, i.e., to assign a segment number to the segment or a copy of the   */
115 /* segment.                                                                  */
116 /*                                                                           */
117 /* ENTRY: initiate                                                           */
118 /*                                                                           */
119 /* This is the main entrypoint.  Besides making a segment identified by      */
120 /* pathname known (optionally by a given reference name), it allows the      */
121 /* caller to optionally specify the segment number by which the segment      */
122 /* will be known.  The copysw argument is obsolete; a value of 2 (always     */
123 /* make a copy of the segment in the pdir) is diagnosed as an error;         */
124 /* otherwise the switch is ignored.                                          */
125 /*                                                                           */
126 /* USAGE: call initiate (a_dname, a_ename, a_rname, a_segsw, a_copysw,       */
127 /*          a_segptr, a_code);                                               */
128 /*                                                                           */
129 /* a_dname (char(*))                                                         */
130 /*    pathname of parent directory of the segment to be initiated (Input)    */
131 /* a_ename (char(*))                                                         */
132 /*    entryname of the segment to be initiated (Input)                       */
133 /* a_rname (char(*))                                                         */
134 /*    reference name by which the segment is to be made known if this        */
135 /*    argument is of zero length, then the segment is made known by a null   */
136 /*    name (Input)                                                           */
137 /* a_segsw (fixed bin (1))                                                   */
138 /*    reserve segment switch  (Input)                                        */
139 /*    (= 0 if no segment number reserved,                                    */
140 /*     = 1 if segment number reserved)                                       */
141 /* a_copysw (fixed bin (2))                                                  */
142 /*    formerly copy switch (Input)                                           */
143 /*    (= 0 if default setting of copy switch to be used,                     */
144 /*     = 1 if segment never to be copied,                                    */
145 /*     = 2 if segment always to be copied into process dir prior to          */
146 /*         initiation. This alternative is no longer implemented.  It        */
147 /*         produces an error.)                                               */
148 /* a_segptr (pointer)                                                        */
149 /*    normally output.  If segsw = 1 then input pointer to previously known  */
150 /*    segment (used to input reserve segment number) .                       */
151 /* a_code (fixed bin (35))                                                   */
152 /*    status code (Output)                                                   */
153 /*                                                                           */
154 /* ENTRY: priv_init                                                          */
155 /*                                                                           */
156 /* This entry is identical to the initiate entrypoint, except that it        */
157 /* ignores the impact of AIM and ring brackets when determining whether the  */
158 /* user has access to initiate the segment.                                  */
159 /*                                                                           */
160 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
161 ^L
162 /* The real procedure statement is up above.  This one is useful documentation.
163 
164 initiate_:
165 initiate:
166     proc (a_dname, a_ename, a_rname, a_segsw, a_copysw, a_segptr, a_code); */
167 
168     call setup_args$initiate();
169     entrypoint.dc_find = dc_find$obj_initiate;
170     go to INITIATE_COMMON;
171 
172 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
173 
174 
175 priv_init:
176     entry (a_dname, a_ename, a_rname, a_segsw, a_copysw, a_segptr, a_code);
177 
178     call setup_args$initiate();
179     entrypoint.dc_find = dc_find$obj_initiate_raw;
180     entrypoint.priv = TRUE;
181 
182 INITIATE_COMMON:
183     if out.code = 0 then do;
184        call entrypoint.dc_find (in.dname, in.ename, seg.entp, out.code);
185        if out.code = 0 then do;
186           entrypoint.should_call_find_finished = TRUE;
187           entrypoint.should_unlock_dir = FALSE;
188           call check_entry();
189           call make_entry_known_and_unlock_dir();
190           end;
191        end;
192     a_segptr = out.segp;
193     a_code = out.code;
194     return;
195 
196 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
197 
198 
199 
200 
201 
202 setup_args$initiate:
203     proc;
204 
205 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
206 /*                                                                           */
207 /* Input Args:                                                               */
208 /* a_dname, a_ename, a_rname,                                                */
209 /* a_segsw, a_copysw, a_seg_ptr                                              */
210 /*    input parameters, to be copied and tested.  Meanings of these parms    */
211 /*    are given in entrypoint descriptions above.                            */
212 /*                                                                           */
213 /* Function:                                                                 */
214 /* 1) copy a_dname, a_ename, a_rname.                                        */
215 /* 2) copy, test and apply a_segsw to initial value of in.segp.              */
216 /* 3) initialize out.segp, out.bc out.uid & entrypoint.priv.                 */
217 /* 4) copy and test a_copysw.  Set out.code according to test results.       */
218 /*                                                                           */
219 ^L
220 /* Output Args:                                                              */
221 /* in.dname, in.ename, in.rname                                              */
222 /*    copies of input parameters.                                            */
223 /* in.segp                                                                   */
224 /*    copy of a_segptr if a_segsw is on; otherwise set to null.              */
225 /* out.segp                                                                  */
226 /*    initialized to null (default output value if error occurs).            */
227 /* out.bc                                                                    */
228 /*    set to 0 (unused return argument).                                     */
229 /* out.uid                                                                   */
230 /*    set to "0"b (unused return argument).                                  */
231 /* out.code                                                                  */
232 /*    result of test of a_copysw.                                            */
233 /* entrypoint.priv                                                           */
234 /*    set to off, assuming not entered at privileged                         */
235 /*                                                                           */
236 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
237 
238 dcl  copysw fixed bin (2);
239 dcl  segsw fixed bin (1);
240 
241     copysw = a_copysw;
242     segsw = a_segsw;
243     in.dname = a_dname;
244     in.ename = a_ename;
245     in.rname = rtrim(a_rname);
246 
247     if segsw = 0 then                             /* a_segptr can only be    */
248        in.segp = null;                            /* copied if segsw ^= 0.   */
249     else                                          /* Otherwise, it must not  */
250        in.segp = a_segptr;                        /* be touched, since its   */
251                                                   /* storage may not be in   */
252                                                   /* ptr format.             */
253     out.segp = null;
254     out.bc = 0;
255     out.uid = "0"b;
256     if copysw = 2 then
257        out.code = error_table_$invalid_copy;
258     else
259        out.code = 0;
260     entrypoint.priv = FALSE;
261 
262     end setup_args$initiate;
263 
264 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
265 ^L
266 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
267 
268 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
269 /*                                                                           */
270 /* ENTRY: initiate_count                                                     */
271 /*                                                                           */
272 /* This entry is the same as initiate except that a bit count parameter      */
273 /* replaces the a_segsw parm.                                                */
274 /*                                                                           */
275 /* USAGE: call initiate$initiate_count                                       */
276 /*          (a_dname, a_ename, a_rname, a_count, a_copysw, a_segptr, a_code);*/
277 /*                                                                           */
278 /* a_count (fixed bin(24))                                                   */
279 /*    bit count of initiated segment (Output)                                */
280 /*                                                                           */
281 /* ENTRY: priv_init_count                                                    */
282 /*                                                                           */
283 /* This entry is like initiate_count, except that it ignores the impact of   */
284 /* AIM and ring brackets when determining whether the user has access to     */
285 /* initiate the segment.                                                     */
286 /*                                                                           */
287 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
288 
289 initiate_count:
290     entry (a_dname, a_ename, a_rname, a_count, a_copysw, a_segptr, a_code);
291 
292     call setup_args$initiate_count();
293     entrypoint.dc_find = dc_find$obj_initiate;
294     go to INITIATE_COUNT_COMMON;
295 
296 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
297 
298 
299 priv_init_count:
300     entry (a_dname, a_ename, a_rname, a_count, a_copysw, a_segptr, a_code);
301 
302     call setup_args$initiate_count();
303     entrypoint.dc_find = dc_find$obj_initiate_raw;
304     entrypoint.priv = TRUE;
305 
306 INITIATE_COUNT_COMMON:
307     if out.code = 0 then do;
308        call entrypoint.dc_find (in.dname, in.ename, seg.entp, out.code);
309        if out.code = 0 then do;
310           entrypoint.should_call_find_finished = TRUE;
311           entrypoint.should_unlock_dir = FALSE;
312           call check_entry();
313           call make_entry_known_and_unlock_dir();
314           end;
315        end;
316     a_count = out.bc;
317     a_segptr = out.segp;
318     a_code = out.code;
319     return;
320 
321 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
322 ^L
323 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
324 
325 setup_args$initiate_count:
326     proc;
327 
328 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
329 /*                                                                           */
330 /* Input Args:                                                               */
331 /* a_dname, a_ename, a_rname, a_copysw                                       */
332 /*    input parameters, to be copied and tested.  Meanings of these parms    */
333 /*    are given in entrypoint descriptions above.                            */
334 /*                                                                           */
335 /* Function:                                                                 */
336 /* 1) copy a_dname, a_ename, a_rname.                                        */
337 /* 2) initialize in.segp, out.segp, out.bc, out.uid & entrypoint.priv.       */
338 /* 3) copy and test a_copysw.  Set out.code according to test results.       */
339 /*                                                                           */
340 /* Output Args:                                                              */
341 /* in.dname, in.ename, in.rname                                              */
342 /*    copies of input parameters.                                            */
343 /* in.segp                                                                   */
344 /*    set to null (no reserved segment number specified).                    */
345 /* out.segp                                                                  */
346 /*    set to null (default output value if error occurs).                    */
347 /* out.bc                                                                    */
348 /*    set to value for bit count to be output if error occurs (0).           */
349 /* out.uid                                                                   */
350 /*    set to "0"b (unused output value).                                     */
351 /* out.code                                                                  */
352 /*    result of test of a_copysw.                                            */
353 /* entrypoint.priv                                                           */
354 /*    set to off, assuming not entered at privileged entrypoint.             */
355 /*                                                                           */
356 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
357 
358 dcl  copysw fixed bin (2);
359 
360     copysw = a_copysw;
361     in.dname = a_dname;
362     in.ename = a_ename;
363     in.rname = rtrim(a_rname);
364     in.segp = null;
365 
366     out.segp = null;
367     out.bc = 0;
368     out.uid = "0"b;
369     if copysw = 2 then
370        out.code = error_table_$invalid_copy;
371     else
372        out.code = 0;
373     entrypoint.priv = FALSE;
374 
375     end setup_args$initiate_count;
376 
377 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
378 ^L
379 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
380 
381 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
382 /*                                                                           */
383 /* ENTRY: initiate_seg_count                                                 */
384 /*                                                                           */
385 /* This entry is the same as initiate_count except that it takes a           */
386 /* directory pointer instead of a directory path name.  It is used solely    */
387 /* by fs_search.                                                             */
388 /*                                                                           */
389 /* NOTE: a contract has been made that this entry can only be called by      */
390 /* fs_search.  dc_find knows this.  As such, dc_find does not do its normal  */
391 /* name lookup access check for this routine, and merely returns no_info     */
392 /* if the name doesn't exist or if the user doesn't have access.             */
393 /*                                                                           */
394 /* USAGE: call initiate$initiate_seg_count                                   */
395 /*          (a_dp, a_ename, a_rname, a_count, a_copysw, a_segptr, a_code);   */
396 /*                                                                           */
397 /* a_dp (ptr)                                                                */
398 /*    pointer to directory of entry ename. (Input)                           */
399 /*                                                                           */
400 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
401 
402 initiate_seg_count:
403     entry (a_dp, a_ename, a_rname, a_count, a_copysw, a_segptr, a_code);
404 
405     call setup_args$initiate_seg_count();
406     if out.code = 0 then do;
407 
408 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
409 /*                                                                           */
410 /* Note that dc_find$obj_initiate_for_linker_dp, knowing it is called only   */
411 /* for fs_search, does not perform its normal name lookup access checks.     */
412 /* If the entry is not found, dc_find will return no_info, as it will (for   */
413 /* this one entry only) if the user lacks access to see the object.          */
414 /*                                                                           */
415 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
416 
417        call dc_find$obj_initiate_for_linker_dp (in.dirp, in.ename, seg.entp, out.code);
418        if out.code = 0 then do;
419           if in.dirp = null then do;
420 
421 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
422 /*                                                                           */
423 /* This means ename was a link to an object in another directory besides     */
424 /* that pointed to by in.dirp.  Therefore, we cannot unlock the dir but      */
425 /* must instead tell dc_find to do it.                                       */
426 /*                                                                           */
427 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
428 
429              entrypoint.should_unlock_dir = FALSE;
430              entrypoint.should_call_find_finished = TRUE;
431              end;
432 
433           else do;
434 ^L
435 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
436 /*                                                                           */
437 /* This is the normal case, in which we can unlock in.dirp directly without  */
438 /* having to call dc_find.                                                   */
439 /*                                                                           */
440 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
441 
442              entrypoint.should_call_find_finished = FALSE;
443              entrypoint.should_unlock_dir = TRUE;
444              end;
445 
446           call check_entry();
447           call make_entry_known_and_unlock_dir();
448           end;
449        end;
450     a_count = out.bc;
451     a_segptr = out.segp;
452     a_code = out.code;
453     return;
454 
455 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
456 ^L
457 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
458 
459 setup_args$initiate_seg_count:
460     proc;
461 
462 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
463 /*                                                                           */
464 /* Input Args:                                                               */
465 /* a_dp, a_ename, a_rname,                                                   */
466 /* a_copysw                                                                  */
467 /*    input parameters, to be copied and tested.  Meanings of these parms    */
468 /*    are given in entrypoint descriptions above.                            */
469 /*                                                                           */
470 /* Function:                                                                 */
471 /* 1) copy a_dp, a_ename, a_rname.                                           */
472 /* 2) initialize in.segp, out.segp, out.bc, out.uid & entrypoint.priv.       */
473 /* 3) copy and test a_copysw.  Set out.code according to test results.       */
474 /*                                                                           */
475 /* Output Args:                                                              */
476 /* in.dirp, in.ename, in.rname                                               */
477 /*    copies of input parameters.                                            */
478 /* in.segp                                                                   */
479 /*    set to null (no reserved segment number specified).                    */
480 /* out.segp                                                                  */
481 /*    set to null (default output value if error occurs).                    */
482 /* out.bc                                                                    */
483 /*    set to value for bit count to be output if error occurs (0).           */
484 /* out.uid                                                                   */
485 /*    set to "0"b (unused output value).                                     */
486 /* out.code                                                                  */
487 /*    result of test of a_copysw.                                            */
488 /* entrypoint.priv                                                           */
489 /*    set to off, not a privileged entrypoint.                               */
490 /*                                                                           */
491 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
492 
493 dcl  copysw fixed bin (2);
494 
495     in.dirp = a_dp;
496     in.ename = a_ename;
497     in.rname = rtrim(a_rname);
498     in.segp = null;
499 
500     out.segp = null;
501     out.bc = 0;
502     out.uid = "0"b;
503     copysw = a_copysw;
504     if copysw = 2 then
505        out.code = error_table_$invalid_copy;
506     else
507        out.code = 0;
508     entrypoint.priv = FALSE;
509 
510     end setup_args$initiate_seg_count;
511 
512 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
513 ^L^L
514 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
515 
516 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
517 /*                                                                           */
518 /* ENTRY: get_segment_ptr_path                                               */
519 /*                                                                           */
520 /* This entry point returns a ptr and uid if the segment is already          */
521 /* initiated; it returns an error if the segment is not already initiated.   */
522 /*                                                                           */
523 /* USAGE: call initiate_$get_segment_ptr_path (a_dname, a_ename, a_segptr,   */
524 /*           a_uid, a_code);                                                 */
525 /*                                                                           */
526 /* a_dname (char(*))                                                         */
527 /*    parent directory. (Input)                                              */
528 /* a_ename (char(*))                                                         */
529 /*    entry name. (Input)                                                    */
530 /* a_segptr (ptr)                                                            */
531 /*    pointer to the segment, or null. (Output)                              */
532 /* a_uid (bit(36))                                                           */
533 /*    file system uid. (Output)                                              */
534 /* a_code (fixed(35))                                                        */
535 /*    zero or error_table_$seg_unknown. (Output)                             */
536 /*                                                                           */
537 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
538 
539 get_segment_ptr_path:
540     entry (a_dname, a_ename, a_segptr, a_uid, a_code);
541 
542     call setup_args$get_segment_ptr_path();
543     call dc_find$obj_initiate (in.dname, in.ename, seg.entp, out.code);
544     if out.code = 0 then do;
545        entrypoint.should_call_find_finished = TRUE;
546        entrypoint.should_unlock_dir = FALSE;
547        call check_entry();
548        if seg.directory then do;
549           out.code = error_table_$dirseg;
550           out.uid = "0"b;
551           end;
552        else do;
553           call kstsrch (out.uid, seg.hash_bucket, kstep);
554           if kstep = null then do;
555              out.code = error_table_$seg_unknown;
556              out.uid = "0"b;
557              end;
558           else
559              out.segp = baseptr (kste.segno);
560           end;
561        call unlock_dir();
562        end;
563     a_uid = out.uid;
564     a_segptr = out.segp;
565     a_code = out.code;
566     return;
567 
568 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
569 ^L
570 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
571 
572 
573 setup_args$get_segment_ptr_path:
574     proc;
575 
576 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
577 /*                                                                           */
578 /* Input Args:                                                               */
579 /* a_dname, a_ename                                                          */
580 /*    input parameters, to be copied.  Meanings of these parms are given in  */
581 /*    entrypoint descriptions above.                                         */
582 /*                                                                           */
583 /* Function:                                                                 */
584 /* 1) copy a_dname and a_ename                                               */
585 /* 2) initialize in.segp, out.segp, out.bc, out.uid, out.code and            */
586 /*    entrypoint.priv.                                                       */
587 /*                                                                           */
588 /* Output Args:                                                              */
589 /* in.dname, in.ename                                                        */
590 /*    copies of input parameters.                                            */
591 /* in.segp                                                                   */
592 /*    set to null (no reserved segment number specified).                    */
593 /* out.segp                                                                  */
594 /*    set to null (default output value if segment not known).               */
595 /* out.bc                                                                    */
596 /*    set to 0 (unused return argument).                                     */
597 /* out.uid                                                                   */
598 /*    set to uid value to output if error occurs (0).                        */
599 /* out.code                                                                  */
600 /*    set to 0.                                                              */
601 /* entrypoint.priv                                                           */
602 /*    set to off, not a privileged entrypoint.                               */
603 /*                                                                           */
604 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
605 
606     in.dname = a_dname;
607     in.ename = a_ename;
608     in.segp = null;
609 
610     out.segp = null;
611     out.bc = 0;
612     out.uid = "0"b;
613     out.code = 0;
614     entrypoint.priv = FALSE;
615 
616     end setup_args$get_segment_ptr_path;
617 
618 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
619 ^L
620 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
621 
622 check_entry:
623     proc;
624 
625 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
626 /*                                                                           */
627 /* Input Args:                                                               */
628 /* seg.entp                                                                  */
629 /*    pointer to the dir branch for the entry to be initiated.               */
630 /*                                                                           */
631 /* Function:                                                                 */
632 /* 1) Check if target entry being initiated is the root dir.  If so          */
633 /*    fabricate information.                                                 */
634 /* 2) Otherwise, extract output information from dir branch for the entry.   */
635 /*                                                                           */
636 /* Output Args:                                                              */
637 /* seg.dirp                                                                  */
638 /*    pointer to the containing dir.                                         */
639 /* seg.directory                                                             */
640 /*    on if entry being initiated is a directory.                            */
641 /* out.uid                                                                   */
642 /*    entry's unique ID                                                      */
643 /* out.bc                                                                    */
644 /*    entry's bit count                                                      */
645 /* entrypoint.should_call_find_finished,                                     */
646 /* entrypoint.should_unlock_dir                                              */
647 /*    switches controlling whether/how directory is unlocked.  These are     */
648 /*    turned off if the entry is the root dir.                               */
649 /*                                                                           */
650 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
651 
652     if seg.entp = null then do;                   /* root                    */
653        seg.dirp = null;
654        seg.directory = TRUE;
655        out.uid = "777777777777"b3;
656        out.bc = 0;
657        entrypoint.should_call_find_finished,      /* didn't lock anything    */
658           entrypoint.should_unlock_dir = FALSE;
659        end;
660     else do;
661        seg.dirp = ptr (seg.entp, 0);
662        seg.directory = seg.entp -> entry.dirsw;
663        out.uid = seg.entp -> entry.uid;
664        out.bc = seg.entp -> entry.bc;
665        end;
666     end check_entry;
667 
668 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
669 ^L
670 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
671 
672 make_entry_known_and_unlock_dir:
673     proc;
674 
675 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
676 /*                                                                           */
677 /* Input Args:                                                               */
678 /* in.segp                                                                   */
679 /*    reserved segment number to use for initiate_ entrypoint                */
680 /* in.rname                                                                  */
681 /*    name by which segment is to be referenced (for ref_name_$insert)       */
682 /* seg.dirp                                                                  */
683 /*    pointer to dir containing entry.                                       */
684 /* seg.entp                                                                  */
685 /*    pointer to entry's dir branch.                                         */
686 /* seg.directory                                                             */
687 /*    on if entry being initiated is a directory.                            */
688 /* entrypoint.priv                                                           */
689 /*    on if calling entrypoint is privileged (for call to makeknown_)        */
690 /* out.uid                                                                   */
691 /*    entry's unique ID (for call to makeknown_)                             */
692 /*                                                                           */
693 /* Function:                                                                 */
694 /* 1) Ensures disk holding target entry is mounted.                          */
695 /* 2) Makes target entry known to process.                                   */
696 /* 3) Unlocks containing directory.                                          */
697 /* 4) Adds reference name table (RNT) entry for the known segment.           */
698 /* 5) Sets LOT entry for the segment (in target ring) to lot_fault value.    */
699 /*                                                                           */
700 /* Output Args:                                                              */
701 /* out.segp                                                                  */
702 /*    pointer to initiated segment (remains unchanged if makeknown_ fails).  */
703 /* out.bc                                                                    */
704 /*    bit count (set to 0 if makeknown_ fails).                              */
705 /* out.code                                                                  */
706 /*    results from call to mountedp, makeknown_ and ref_name_$insert.        */
707 /*                                                                           */
708 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
709 
710 /* Variables */
711 dcl  ecode fixed bin (35);
712 dcl  1 mk_info aligned like makeknown_info;
713 dcl  ring fixed bin (3);
714 dcl  segno fixed bin;
715 dcl  use_count fixed bin (17);
716 
717 /* External */
718 dcl  pds$stacks (0:7) ptr ext;
719 dcl  1 pds$useable_lot aligned ext,
720        2 flags (0:7) bit (1) unal;
721 
722 /* Entries */
723 dcl  level$get entry returns (fixed bin (3));
724 dcl  link_man$grow_lot entry (fixed bin (3));
725 dcl  makeknown_ entry (ptr, fixed bin, fixed bin, fixed bin (35));
726 dcl  mountedp entry (bit (36) aligned, fixed bin (35));
727 dcl  ref_name_$insert entry (char (32) varying, fixed bin, fixed bin (35));
728 ^L
729     if ^seg.directory then do;                    /* ensure LV is mounted    */
730        call mountedp (seg.dirp -> dir.sons_lvid, out.code);
731        if out.code ^= 0 then do;
732           call unlock_dir();
733           out.bc = 0;                             /* Don't return bit count  */
734           return;                                 /* if errors occur.        */
735           end;
736        end;
737 
738     unspec (mk_info) = FALSE;
739     mk_info.uid = out.uid;
740     mk_info.entryp = seg.entp;                    /* dir locked, seg.entp    */
741                                                   /* has been validated by   */
742                                                   /*  dc_find.               */
743     mk_info.dirsw = seg.directory;
744     mk_info.priv_init = entrypoint.priv;
745     mk_info.allow_write = TRUE;
746 
747     if in.segp ^= null then do;
748        mk_info.rsw = TRUE;
749        segno = fixed (baseno (in.segp), 17);
750        end;
751     else mk_info.rsw = FALSE;
752 
753     call makeknown_ (addr (mk_info), segno, use_count, out.code);
754     call unlock_dir();                            /* The dir must stay       */
755                                                   /* locked until after      */
756     if out.code = 0 then;                         /* makeknown_ returns, as  */
757     else if out.code = error_table_$segknown then;/* per interface specs.    */
758     else do;
759        out.bc = 0;                                /* Don't return bit count  */
760        return;                                    /* if errors occur.        */
761        end;
762     out.segp = baseptr (segno);                   /* From this point on,     */
763                                                   /* makeknown_ has succeeded*/
764 
765     if in.rname ^= "" then do;                    /* Add ref name to segment.*/
766        call ref_name_$insert (in.rname, segno, ecode);
767        if ecode ^= 0 then out.code = ecode;       /* Be careful not to zero  */
768        end;                                       /* segknown code needlessly*/
769 
770     if use_count = 1 then do;                     /* Made known for first    */
771        ring = level$get ();                       /* time in a ring?         */
772        if pds$useable_lot.flags (ring) then do;   /* diddle user ring lot    */
773           if segno >= pds$stacks (ring) -> stack_header.cur_lot_size then
774              if segno < pds$stacks (ring) -> stack_header.max_lot_size then do;
775                 call link_man$grow_lot (ring);
776                 unspec (pds$stacks (ring) -> stack_header.lot_ptr -> lot.lp (segno)) = lot_fault;
777                                                   /* flag lot entry to tell  */
778                 end;                              /* run unit seg is known.  */
779              else;                                /* high segno might be OK  */
780                                                   /* if seg not linked to.   */
781           else  unspec (pds$stacks (ring) -> stack_header.lot_ptr -> lot.lp (segno)) = lot_fault;
782           end;
783        end;
784     end make_entry_known_and_unlock_dir;
785 
786 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
787 ^L
788 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
789 
790 unlock_dir:
791     proc;
792 
793 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
794 /*                                                                           */
795 /* Input Args:                                                               */
796 /* seg.dirp                                                                  */
797 /*    pointer to dir containing entry.                                       */
798 /* seg.entp                                                                  */
799 /*    pointer to entry's dir branch.                                         */
800 /* entrypoint.should_call_find_finished                                      */
801 /*    on to call dc_find$finished to unlock and unhold dir.                  */
802 /* entrypoint.should_unlock_dir                                              */
803 /*    on to call lock$unlock_dir to unlock dir.                              */
804 /*                                                                           */
805 /* Function: unlock dir containing target entry.  Normally, it was locked    */
806 /* by dc_find$obj_initiate, which also holds the directory (by incrementing  */
807 /* its usage count) to keep it from being KST-garbage-collected.  So         */
808 /* dc_find$finished must be called to undo this dir holding.                 */
809 /*                                                                           */
810 /* However, the linker calls $initiate_seg_count, which uses                 */
811 /* dc_find$obj_initiate_for_linker_dp, which does NOT hold the containing    */
812 /* dir unless ename matches a link in the containing dir and the link gets   */
813 /* chased.  If no links were chased, then the dir is NOT held and            */
814 /* lock$dir_unlock can be called directly.  If links were chased, then       */
815 /* dc_find$finished must be called to unhold the dir containing the chased   */
816 /* link target.                                                              */
817 /*                                                                           */
818 /* Finally, if the entry being initiated is the root, then there is no       */
819 /* containing directory to unlock.  The input flags are set appropriately    */
820 /* by callers to cause the correct operation to occur.                       */
821 /*                                                                           */
822 /* Output Args:                                                              */
823 /* entrypoint.should_call_find_finished,                                     */
824 /* entrypoint.should_unlock_dir                                              */
825 /*    turned off on output.                                                  */
826 /*                                                                           */
827 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
828 
829 /* Entries */
830 
831 dcl  lock$dir_unlock entry (pointer);
832 
833     if entrypoint.should_call_find_finished then
834        call dc_find$finished (seg.entp, DC_FIND_UNLOCK_DIR);
835     else if entrypoint.should_unlock_dir then
836        call lock$dir_unlock(seg.dirp);
837     entrypoint.should_call_find_finished, entrypoint.should_unlock_dir = FALSE;
838 
839     end unlock_dir;
840 
841 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *   */
842 ^L
843 %include dc_find_dcls;
844 ^L
845 %include dir_entry;
846 ^L
847 %include dir_header;
848 ^L
849 %include kst;
850 ^L
851 %include lot;
852 ^L
853 %include makeknown_info;
854 ^L
855 %include stack_header;
856      end initiate_;