Commit | Line | Data |
---|---|---|
9319b3c3 C |
1 | /* vtuser.c - VT user routines */ |
2 | ||
3 | #ifndef lint | |
4 | static char *rcsid = "$Header: /f/osi/vt/RCS/vtuser.c,v 7.5 91/02/22 09:48:34 mrose Interim $"; | |
5 | #endif | |
6 | ||
7 | /* | |
8 | * $Header: /f/osi/vt/RCS/vtuser.c,v 7.5 91/02/22 09:48:34 mrose Interim $ | |
9 | * | |
10 | * | |
11 | * $Log: vtuser.c,v $ | |
12 | * Revision 7.5 91/02/22 09:48:34 mrose | |
13 | * Interim 6.8 | |
14 | * | |
15 | * Revision 7.4 90/12/11 10:53:12 mrose | |
16 | * lock-and-load | |
17 | * | |
18 | * Revision 7.3 90/10/23 20:44:48 mrose | |
19 | * update | |
20 | * | |
21 | * Revision 7.2 90/07/09 14:52:10 mrose | |
22 | * sync | |
23 | * | |
24 | * Revision 7.1 89/11/30 23:51:45 mrose | |
25 | * pa2str | |
26 | * | |
27 | * Revision 7.0 89/11/23 22:32:00 mrose | |
28 | * Release 6.0 | |
29 | * | |
30 | */ | |
31 | ||
32 | /* | |
33 | * NOTICE | |
34 | * | |
35 | * Acquisition, use, and distribution of this module and related | |
36 | * materials are subject to the restrictions of a license agreement. | |
37 | * Consult the Preface in the User's Manual for the full terms of | |
38 | * this agreement. | |
39 | * | |
40 | */ | |
41 | ||
42 | ||
43 | #include "vtpm.h" | |
44 | #include "sector1.h" | |
45 | #include "sector5.h" | |
46 | #include <sys/ioctl.h> | |
47 | ||
48 | #undef PTYBUG /*When testing Break and demon not started from rc.local, | |
49 | this turns off resetting local echo so ioctl to pty | |
50 | will not cause demon to hang up. | |
51 | */ | |
52 | ||
53 | #undef PEPYPARM | |
54 | #define PEPYPARM int * | |
55 | ||
56 | ||
57 | extern char peerhost[]; | |
58 | extern struct PSAPaddr ts_bound; | |
59 | static char *myservice = "terminal"; | |
60 | ||
61 | static char *mycontext = "iso vt"; | |
62 | static char *mypci = "iso vt pci"; | |
63 | ||
64 | static char ascii_go_repertoire[] = {0x1a,0x28,0x42,0x00}; /*ESC 2/8 4/2*/ | |
65 | /*should be followed by 3 "voids" whatever that is*/ | |
66 | static char full_ascii_repertoire[] = {0x1a,0x28,0x42,/*VOID*/0x1a,0x21,0x40,0x00}; | |
67 | /*Approximation to GO & CO ASCII sets*/ | |
68 | ||
69 | extern char *isodeversion; | |
70 | extern char *my_displayobj; | |
71 | extern int G_Func_Units; /*Functional Units for this Association*/ | |
72 | extern int vcwa; /*Collision Winner (TRUE if owned by this peer)*/ | |
73 | extern int vsmd, vtok; | |
74 | extern int transparent; | |
75 | extern char na_image; | |
76 | extern char ni_image; | |
77 | extern VT_PROFILE vtp_profile; | |
78 | extern int telnet_profile; | |
79 | extern int do_break; | |
80 | extern int debug; | |
81 | ||
82 | int default_rep_flag = 0; | |
83 | ||
84 | /*************************************************************************/ | |
85 | /* VASS_REQ - create an ASQ PDU and generate a VASSreq event to */ | |
86 | /* send it. */ | |
87 | /* */ | |
88 | /* PARAMETERS - */ | |
89 | /* */ | |
90 | /* CLASS - class of VTP service (only BASIC supported) */ | |
91 | /* */ | |
92 | /* ACC_RI - access rights */ | |
93 | /* */ | |
94 | /* PROFILE - designator of the VT profile to request */ | |
95 | /*************************************************************************/ | |
96 | /* ARGSUSED */ | |
97 | vass_req(class, acc_ri, profile) | |
98 | int class, acc_ri; | |
99 | VT_PROFILE *profile; | |
100 | { | |
101 | PE a_req; | |
102 | ASQ_MSG ud; | |
103 | char my_version, my_fu; | |
104 | OID p_oid; | |
105 | int i; | |
106 | ||
107 | my_version = 0x01; | |
108 | if(do_break) my_fu = destBreak; | |
109 | else my_fu = 0x00; | |
110 | ||
111 | bzero ((char *) &ud, sizeof ud); | |
112 | ud.class = class; | |
113 | ud.valid_imp = 0; | |
114 | ud.coll_winner = ACHOICE; | |
115 | ud.valid_coll = 1; | |
116 | ud.version.bitstring = my_version; | |
117 | ud.version.bitcount = 1; | |
118 | if( !strcmp(profile->profile_name,"telnet") ) | |
119 | { | |
120 | ud.valid_prof = 1; | |
121 | ud.asq_profile.oid_true = 1; | |
122 | if((p_oid = ode2oid(profile->profile_name)) == NULLOID) | |
123 | adios(NULLCP,"%s: unknown profile", profile->profile_name); | |
124 | ud.asq_profile.prof_oid = p_oid; | |
125 | ||
126 | ud.asq_profile.num_sp_param = 0; | |
127 | ud.asq_profile.num_cds_objects = 0; | |
128 | ud.asq_profile.num_css_objects = 0; | |
129 | ud.asq_profile.num_dev_objects = 0; | |
130 | ud.asq_profile.del_ctrl.bitcount = 0; | |
131 | ||
132 | ud.asq_profile.num_cds_objects = 1; | |
133 | ud.asq_profile.cds_offer_list[0].obj_name = "D"; | |
134 | for(i=0; i<ud.asq_profile.num_cds_objects; i++) | |
135 | { | |
136 | ud.asq_profile.cds_offer_list[i].valid_x_dim = 0; | |
137 | ud.asq_profile.cds_offer_list[i].valid_y_dim= 0; | |
138 | ud.asq_profile.cds_offer_list[i].valid_z_dim = 0; | |
139 | ud.asq_profile.cds_offer_list[i].erasure.bitcount = 0; | |
140 | ud.asq_profile.cds_offer_list[i].valid_emp_list = 0; | |
141 | ud.asq_profile.cds_offer_list[i].valid_fore_color = 0; | |
142 | ud.asq_profile.cds_offer_list[i].valid_back_color = 0; | |
143 | ud.asq_profile.cds_offer_list[i].access_right.bitcount = 0; | |
144 | ud.asq_profile.cds_offer_list[i].valid_rep_list = 0; | |
145 | } | |
146 | if(!vtp_profile.arg_val.tel_arg_list.full_ascii) | |
147 | { | |
148 | ud.asq_profile.cds_offer_list[0].valid_rep_list = 1; | |
149 | ud.asq_profile.cds_offer_list[0].rep_offer.valid_cap = 1; | |
150 | ud.asq_profile.cds_offer_list[0].rep_offer.capability.type = 0; | |
151 | ud.asq_profile.cds_offer_list[0].rep_offer.capability.value = 1; | |
152 | ud.asq_profile.cds_offer_list[0].rep_offer.num_reps = 1; | |
153 | ud.asq_profile.cds_offer_list[0].rep_offer.repertoire[0].rep_type = 2; | |
154 | ud.asq_profile.cds_offer_list[0].rep_offer.repertoire[0].valid_font_cap = 0; | |
155 | ud.asq_profile.cds_offer_list[0].rep_offer.repertoire[0].num_fonts = 0; | |
156 | ud.asq_profile.cds_offer_list[0].rep_offer.repertoire[0].rep_assign = | |
157 | ascii_go_repertoire; | |
158 | } | |
159 | ||
160 | ud.asq_profile.cds_offer_list[0].valid_x_dim = 1; | |
161 | ud.asq_profile.cds_offer_list[0].x_dim.bound_type = 0; | |
162 | ud.asq_profile.cds_offer_list[0].x_dim.addressing.bitcount = 0; | |
163 | ud.asq_profile.cds_offer_list[0].x_dim.absolute.bitcount = 0; | |
164 | ud.asq_profile.cds_offer_list[0].x_dim.window_type = 2; | |
165 | ud.asq_profile.cds_offer_list[0].x_dim.window.type = 0; | |
166 | ud.asq_profile.cds_offer_list[0].x_dim.window.value = | |
167 | vtp_profile.arg_val.tel_arg_list.x_window; | |
168 | ||
169 | vtok = 1; | |
170 | vsmd = 0; | |
171 | } | |
172 | else if( !strcmp(profile->profile_name,"default") ) | |
173 | { | |
174 | ud.valid_prof = 0; | |
175 | ud.asq_profile.oid_true = 0; | |
176 | ud.asq_profile.num_sp_param = 0; | |
177 | ud.asq_profile.num_cds_objects = 0; | |
178 | ud.asq_profile.num_css_objects = 0; | |
179 | ud.asq_profile.num_dev_objects = 0; | |
180 | vtok = 1; | |
181 | vsmd = 0; | |
182 | } | |
183 | else | |
184 | adios(NULLCP, "%s: unsupported profile", profile->profile_name); | |
185 | ||
186 | ud.func_units.bitstring = my_fu; | |
187 | ud.func_units.bitcount = 5; | |
188 | ||
189 | if(build_ASQPDU_ASQpdu(&a_req,1,NULL,NULLCP,(PEPYPARM)&ud) == NOTOK) | |
190 | adios(NULLCP, "ASQ build failure (%s)", PY_pepy); | |
191 | ||
192 | (void)do_event(VASSreq, a_req); | |
193 | } | |
194 | ||
195 | \f | |
196 | /******************************************************************************/ | |
197 | /* VASS_RESP - create an ASR PDU and generate a VASSRSP event to send it.*/ | |
198 | /* */ | |
199 | /* PARAMETERS - */ | |
200 | /* */ | |
201 | /* RESULT - SUCCESS or FAILURE */ | |
202 | /******************************************************************************/ | |
203 | ||
204 | vass_resp(result) | |
205 | int result; | |
206 | { | |
207 | PE a_resp; | |
208 | char my_version, my_fu; | |
209 | ASR_MSG ud; | |
210 | int i; | |
211 | ||
212 | my_version = 0x01; | |
213 | if(G_Func_Units & destBreak) do_break = 1; | |
214 | else do_break = 0; | |
215 | my_fu = G_Func_Units & destBreak; /*VT-Break is only Functional Unit | |
216 | we will accept*/ | |
217 | bzero ((char *) &ud, sizeof ud); | |
218 | ud.valid_reason = 0; | |
219 | ud.result = result; | |
220 | ud.valid_imp = 0; | |
221 | ud.valid_coll = 1; | |
222 | if(vcwa == TRUE) ud.coll_winner = ACCEPTOR; | |
223 | else ud.coll_winner = INITIATOR; | |
224 | ud.version.bitstring = my_version; | |
225 | ud.version.bitcount = 1; | |
226 | if( !strcmp(vtp_profile.profile_name,"telnet") ) | |
227 | { | |
228 | ud.valid_arg_list = 1; | |
229 | ud.arg_list.num_css_objects = 0; | |
230 | ud.arg_list.num_dev_objects = 0; | |
231 | ud.arg_list.num_cds_objects = 1; | |
232 | ||
233 | ud.arg_list.cds_val[0].obj_name = "D"; | |
234 | for(i=0; i<ud.arg_list.num_cds_objects; i++) | |
235 | { | |
236 | ud.arg_list.cds_val[i].dimensions = 0; | |
237 | ud.arg_list.cds_val[i].valid_x_dim = 0; | |
238 | ud.arg_list.cds_val[i].valid_y_dim = 0; | |
239 | ud.arg_list.cds_val[i].valid_z_dim = 0; | |
240 | ud.arg_list.cds_val[i].valid_erasure= 0; | |
241 | ud.arg_list.cds_val[i].valid_emp_list = 0; | |
242 | ud.arg_list.cds_val[i].valid_fore_color = 0; | |
243 | ud.arg_list.cds_val[i].valid_back_color = 0; | |
244 | ud.arg_list.cds_val[i].valid_access_right = 0; | |
245 | ud.arg_list.cds_val[i].valid_rep_list = 0; | |
246 | ud.arg_list.cds_val[i].rep_value.repertoire[0].valid_font_cap = 0; | |
247 | ud.arg_list.cds_val[i].rep_value.repertoire[0].num_fonts = 0; | |
248 | } | |
249 | if( !default_rep_flag) | |
250 | { | |
251 | ud.arg_list.cds_val[0].valid_rep_list = 1; | |
252 | ud.arg_list.cds_val[0].rep_value.valid_cap = 1; | |
253 | ud.arg_list.cds_val[0].rep_value.capability = 1; | |
254 | ud.arg_list.cds_val[0].rep_value.num_reps = 1; | |
255 | ud.arg_list.cds_val[0].rep_value.repertoire[0].rep_type = 2; | |
256 | ud.arg_list.cds_val[0].rep_value.repertoire[0].rep_assign = | |
257 | vtp_profile.arg_val.tel_arg_list.full_ascii ? | |
258 | full_ascii_repertoire : ascii_go_repertoire; | |
259 | } | |
260 | ud.arg_list.num_sp_param = 0; | |
261 | ud.arg_list.cds_val[0].valid_x_dim = 1; | |
262 | ud.arg_list.cds_val[0].x_dim.bound_type = 0; | |
263 | ud.arg_list.cds_val[0].x_dim.valid_addr = 0; | |
264 | ud.arg_list.cds_val[0].x_dim.valid_abs = 0; | |
265 | ud.arg_list.cds_val[0].x_dim.window_type = 2; | |
266 | ud.arg_list.cds_val[0].x_dim.window = | |
267 | vtp_profile.arg_val.tel_arg_list.x_window; | |
268 | ||
269 | } | |
270 | else if( !strcmp(vtp_profile.profile_name,"default") ) | |
271 | { | |
272 | ud.valid_arg_list = 0; | |
273 | ud.arg_list.num_sp_param = 0; | |
274 | ud.arg_list.num_cds_objects = 0; | |
275 | ud.arg_list.num_css_objects = 0; | |
276 | ud.arg_list.num_dev_objects = 0; | |
277 | } | |
278 | else | |
279 | adios (NULLCP, "invalid profile stored"); | |
280 | ud.func_units.bitstring = my_fu; | |
281 | ud.func_units.bitcount = 5; | |
282 | ||
283 | if(build_ASRPDU_ASRpdu((PE *)&a_resp,1,NULL,NULLCP,(PEPYPARM)&ud) == NOTOK) | |
284 | advise(LLOG_NOTICE,NULLCP, "ASR build failure (%s) -- continuing", | |
285 | PY_pepy); | |
286 | return(do_event(VASSrsp, a_resp)); | |
287 | } | |
288 | ||
289 | \f | |
290 | /*************************************************************************/ | |
291 | /* "pe" will be to store NDQ contents that could not be mapped to */ | |
292 | /* the cbuf because of lack of buffer space. There is only one, */ | |
293 | /* because a new NDQ can be combined with "pe" rather than creating */ | |
294 | /* a queue of PEs */ | |
295 | /*************************************************************************/ | |
296 | ||
297 | PE pe_buf = NULLPE; | |
298 | ||
299 | ||
300 | /************************************************************************/ | |
301 | /* VRELREQ - Generate a VRELREQ to VT State Machine */ | |
302 | /* */ | |
303 | /* PARAMETERS - none */ | |
304 | /************************************************************************/ | |
305 | ||
306 | vrelreq() | |
307 | { | |
308 | PE r_req; | |
309 | ||
310 | r_req = NULLPE; | |
311 | (void)do_event(VRELreq,r_req); | |
312 | } | |
313 | \f | |
314 | /*************************************************************************/ | |
315 | /* VRELRSP - create an RLR PDU and send it and generate a VRELRSP-S */ | |
316 | /* */ | |
317 | /* PARAMETERS - */ | |
318 | /* */ | |
319 | /* RESULT - success or failure */ | |
320 | /* */ | |
321 | /*************************************************************************/ | |
322 | ||
323 | vrelrsp(result) | |
324 | int result; | |
325 | { | |
326 | ||
327 | int offset = 0; | |
328 | PE r_rsp, r_result, r_coll; | |
329 | ||
330 | if ((r_rsp = pe_alloc(PE_CLASS_CONT, PE_FORM_CONS, RLR_PDU)) == NULLPE) | |
331 | adios (NULLCP, "RLR build failure (out of memory)"); | |
332 | ||
333 | if ((r_result = num2prim((integer)result,PE_CLASS_CONT,0)) == NULLPE) | |
334 | adios (NULLCP, "RLR build failure (out of memory)"); | |
335 | ||
336 | if (seq_add(r_rsp,r_result,offset) == NOTOK) | |
337 | adios (NULLCP, "RLR build failure (%s)", pe_error(r_rsp -> pe_errno)); | |
338 | ||
339 | if(result == COLL_DET) | |
340 | { | |
341 | if((r_coll = num2prim((integer)0,PE_CLASS_CONT,2)) == NULLPE) | |
342 | adios (NULLCP, "RLR build failure (out of memory)"); | |
343 | if (seq_add(r_rsp,r_coll,++offset) == NOTOK) | |
344 | adios (NULLCP, "RLR build failure (%s)", | |
345 | pe_error(r_rsp -> pe_errno)); | |
346 | } | |
347 | if (seq2prim(r_rsp) == NULLPE) | |
348 | adios(NULLCP, "RLR encode error, seq2prim: (%s)", PY_pepy); | |
349 | (void)do_event(VRELrsp,r_rsp); | |
350 | ||
351 | pe_free(r_coll); | |
352 | pe_free(r_result); | |
353 | pe_free(r_rsp); | |
354 | ||
355 | } | |
356 | \f | |
357 | ||
358 | vrelcnf() | |
359 | { | |
360 | if (debug) | |
361 | advise(LLOG_DEBUG, NULLCP, "Release Confirmed"); | |
362 | } | |
363 | \f | |
364 | ||
365 | vrelind() | |
366 | { | |
367 | if (AcFINISHser(sd,pf,aci) == NOTOK) | |
368 | acs_adios (&aci->aci_abort, "A-RELEASE.INDICATION"); | |
369 | ||
370 | vrelrsp(SUCCESS); | |
371 | return(OK); | |
372 | } | |
373 | ||
374 | \f | |
375 | ||
376 | PE p_ondq = NULLPE; /* the current "ndq" being prepared for sending*/ | |
377 | PE p_ovtsdi = NULLPE; /* the current "vtsdi" */ | |
378 | int sdi_count = 0; /* count of "vtsdi"s in current NDQ*/ | |
379 | PE p_oobjupdt = NULLPE; /* the current "object_update" */ | |
380 | int obj_count = 0; /* count of "object_update"s in current "vtsdi"*/ | |
381 | int updt_count = 0; /* count of updates in the current "object update"*/ | |
382 | int cur_emode = NOT_ECHO_NOW; /* echo mode (ECHO_NOW or NOT_ECHO_NOW)*/ | |
383 | ||
384 | /*************************************************************************/ | |
385 | /* VT_TEXT - Add a text update to the PE that represents */ | |
386 | /* an NDQ of buffered updates awaiting delivery. */ | |
387 | /* */ | |
388 | /* When we do a control object update, the current buffer of */ | |
389 | /* display object updates is terminated and a new one will be */ | |
390 | /* started next time a display object update is queued. */ | |
391 | /* (this is so we can synchronize control updates with */ | |
392 | /* display updates.) */ | |
393 | /* */ | |
394 | /* Likewise, whenever we queue a display object update, we */ | |
395 | /* terminate the current sequence of control object updates. */ | |
396 | /* */ | |
397 | /* Whenever we change echo mode (ECHO_NOW or NOT_ECHO_NOW) */ | |
398 | /* we have to start a new "vtsdi". */ | |
399 | /* This requires that we terminate the current buffers of */ | |
400 | /* display object and control object updates. */ | |
401 | /* */ | |
402 | /* PARAMETERS - */ | |
403 | /* */ | |
404 | /* STR - the character string to be added to the NDQ PDU. */ | |
405 | /* LEN - Number of characters in the string. */ | |
406 | /*************************************************************************/ | |
407 | ||
408 | vt_text(str, len) | |
409 | char *str; | |
410 | int len; | |
411 | { | |
412 | TEXT_UPDATE ud; | |
413 | ||
414 | if (debug > 6) | |
415 | { | |
416 | int i; | |
417 | ||
418 | (void)ll_log(vt_log, LLOG_DEBUG, NULLCP, ("vt_text sending")); | |
419 | (void)ll_printf (vt_log, "<<"); | |
420 | for(i=0; i<len; i++) | |
421 | (void)ll_printf (vt_log, "%02x ", *(str+i)); | |
422 | (void)ll_printf (vt_log, ">>\n"); | |
423 | (void)ll_sync (vt_log); | |
424 | } | |
425 | ||
426 | bzero ((char *) &ud, sizeof ud); | |
427 | ud.echo_sw = cur_emode; | |
428 | ud.type_sw = 0; /*Display object*/ | |
429 | ud.updates.do_list.do_name = my_displayobj; | |
430 | ud.updates.do_list.do_type = DO_TEXT; /*Text*/ | |
431 | ud.updates.do_list.do_cmd.text_ud.text_ptr = str; | |
432 | ud.updates.do_list.do_cmd.text_ud.text_count = len; | |
433 | send_queue(ud); | |
434 | ||
435 | return(OK); | |
436 | } | |
437 | \f | |
438 | ||
439 | send_queue(ud) /*Build NDQ with update supplied in ud structure*/ | |
440 | TEXT_UPDATE ud; | |
441 | { | |
442 | ||
443 | PE vtsdip; | |
444 | ||
445 | if(p_ondq == NULLPE) /*Nothing waiting to be sent*/ | |
446 | { | |
447 | if(build_NDQPDU_NDQpdu(&p_ondq,1,NULL,NULLCP,(PEPYPARM)&ud) == NOTOK) | |
448 | adios(NULLCP,"NDQ build failure (%s)", PY_pepy); | |
449 | p_ondq->pe_context = 1; | |
450 | } | |
451 | else | |
452 | { | |
453 | if(build_NDQPDU_VTsdi(&vtsdip,1,NULL,NULLCP,(int *)&ud) == NOTOK) | |
454 | adios(NULLCP,"VTsdi build failure (%s)", PY_pepy); | |
455 | vtsdip->pe_context = 1; | |
456 | if(seq_add(p_ondq,vtsdip,-1) == NOTOK) | |
457 | adios(NULLCP,"NDQ build failure (%s)", | |
458 | pe_error(p_ondq->pe_errno)); | |
459 | } | |
460 | } | |
461 | ||
462 | \f | |
463 | ||
464 | /* SETEMODE - set echo mode | |
465 | ||
466 | PARAMETERS - | |
467 | ||
468 | MODE - ECHO_NOW or NOT_ECHO_NOW | |
469 | */ | |
470 | ||
471 | setemode(mode) | |
472 | int mode; | |
473 | { | |
474 | if (mode != ECHO_NOW && mode != NOT_ECHO_NOW) | |
475 | return(NOTOK); | |
476 | if (cur_emode != mode) { | |
477 | p_ovtsdi = NULLPE; | |
478 | sdi_count = 0; | |
479 | p_oobjupdt = NULLPE; | |
480 | obj_count = 0; | |
481 | cur_emode = mode; | |
482 | } | |
483 | return(OK); | |
484 | } | |
485 | \f | |
486 | ||
487 | /* this data structure will buffer character output | |
488 | that is ready to be read by the application or terminal. | |
489 | */ | |
490 | ||
491 | #define CBUFSIZE 10240 | |
492 | ||
493 | struct char_buffer { | |
494 | int max_len, queued; | |
495 | unsigned char *head, *tail; | |
496 | unsigned char buf[CBUFSIZE]; | |
497 | }; | |
498 | ||
499 | struct char_buffer cbuf = { CBUFSIZE, 0 }; | |
500 | ||
501 | /************************************************************************/ | |
502 | /* GETCH - get a character from the buffer waiting to */ | |
503 | /* be read by the application */ | |
504 | /* */ | |
505 | /* RETURNS - the character, NOTOK if no data, or an error code (<0)*/ | |
506 | /************************************************************************/ | |
507 | ||
508 | ||
509 | int | |
510 | getch() | |
511 | { | |
512 | int c; | |
513 | ||
514 | if (data_pending() == FALSE) { | |
515 | if (!connected) | |
516 | return(E_EOF); | |
517 | else | |
518 | return(WOULDBLOCK); | |
519 | } | |
520 | c = *cbuf.head; | |
521 | if (++cbuf.head >= cbuf.buf + CBUFSIZE) | |
522 | cbuf.head = cbuf.buf; | |
523 | cbuf.queued--; | |
524 | if (debug > 1) | |
525 | advise(LLOG_DEBUG, NULLCP, "normal return from getch, c is %c,queued is %d", c,cbuf.queued); | |
526 | return(c); | |
527 | } | |
528 | ||
529 | /* at some point we need to use the async. interface to the network | |
530 | so that at any time when data becomes available, we trap to a vtpm | |
531 | function to handle it. This function will examine the type of | |
532 | network event and act accordingly. Each time the function is invoked | |
533 | it should completely process the data received and free the PSAPdata | |
534 | structure for use in processing the next network event. | |
535 | If it is an expedited | |
536 | data request, for instance, it is treated differently from a P-DATA. | |
537 | If an NDQ is | |
538 | received all the data should be read from the PSAPread structure and | |
539 | mapped to the cbuf. | |
540 | If the cbuf fills up in the process of doing this, the PE containing the | |
541 | remaining updates should be put in a queue of pending PEs. | |
542 | */ | |
543 | \f | |
544 | ||
545 | /* This macro does the same thing as PXFREE except it does not free | |
546 | the PEs in the px_info array. We will use this instead of PXFREE | |
547 | because we need to free the data PEs one at a time as they are | |
548 | processed. | |
549 | Any unprocessed (pending) PEs are maintained in a queue | |
550 | by the VTPM. If some of the PEs received from a PDATArequest are in | |
551 | this queue a call to PXFREE would free the | |
552 | data and leave dangling references in the queue. | |
553 | ||
554 | Note that the vtuser may have at most one unprocessed or partially | |
555 | processed PE. The VTPM can potentially have any number of unprocessed | |
556 | PEs in its queue. | |
557 | */ | |
558 | ||
559 | #define PFIN(px) \ | |
560 | { \ | |
561 | register int PXI; \ | |
562 | \ | |
563 | if ((px) -> px_realinfo) \ | |
564 | pe_free ((px) -> px_realinfo), (px) -> px_realinfo = NULLPE; \ | |
565 | else { \ | |
566 | for (PXI = (px) -> px_ninfo - 1; PXI >= 0; PXI--) \ | |
567 | if ((px) -> px_info[PXI]) \ | |
568 | (px) -> px_info[PXI] = NULLPE; \ | |
569 | (px) -> px_ninfo = 0; \ | |
570 | } \ | |
571 | } | |
572 | \f | |
573 | ||
574 | int | |
575 | data_pending() | |
576 | { | |
577 | int result; | |
578 | PE *peptr = NULLPEP; | |
579 | ||
580 | if (queued()) | |
581 | return(TRUE); | |
582 | ||
583 | /* something was already in the cbuf | |
584 | */ | |
585 | ||
586 | if (pe_buf != NULLPE) { | |
587 | ||
588 | /* there seems to be something to map | |
589 | */ | |
590 | ||
591 | map(pe_buf); | |
592 | if (queued()) | |
593 | return(TRUE); | |
594 | } | |
595 | result = get_event(sd, peptr); | |
596 | ||
597 | /* if there was no network event | |
598 | */ | |
599 | if (result == NOTOK) | |
600 | return(FALSE); | |
601 | ||
602 | /* get_event may have resulted in data being read and mapped to the | |
603 | cbuf | |
604 | */ | |
605 | ||
606 | if (queued()) | |
607 | return(TRUE); | |
608 | ||
609 | /* if there is no data left and get_event resulted in the association | |
610 | being released | |
611 | */ | |
612 | if (!connected) { | |
613 | (void)putch(EOF); | |
614 | return(TRUE); | |
615 | } | |
616 | ||
617 | /* there's nothing to read right now, but we're still connected | |
618 | */ | |
619 | return(FALSE); | |
620 | } | |
621 | \f | |
622 | ||
623 | int | |
624 | queued() | |
625 | { | |
626 | return(cbuf.queued); | |
627 | } | |
628 | ||
629 | \f | |
630 | /*************************************************************************/ | |
631 | /* PUTCH - put a character on the buffer to be read by the */ | |
632 | /* application */ | |
633 | /* */ | |
634 | /* RETURNS - OK on success, NOTOK otherwise */ | |
635 | /*************************************************************************/ | |
636 | int | |
637 | putch(c) | |
638 | char c; | |
639 | { | |
640 | if (debug > 1) { | |
641 | advise(LLOG_DEBUG, NULLCP, "in putch, queued is %d, c is %c", cbuf.queued, c); | |
642 | advise(LLOG_DEBUG, NULLCP, "cbuf.buf is %d, cbuf.head is %d, cbuf.tail is %d", (int)cbuf.buf, (int)cbuf.head, (int)cbuf.tail); | |
643 | advise(LLOG_DEBUG, NULLCP, "cbuf.max_len is %d", (int)cbuf.max_len); | |
644 | } | |
645 | if (cbuf.queued >= CBUFSIZE) { | |
646 | if (debug > 1) | |
647 | advise(LLOG_DEBUG, NULLCP, "***********************\nputch: queued exceeds CBUFSIZE ***************"); | |
648 | return(NOTOK); | |
649 | } | |
650 | if (cbuf.queued <= 0) { | |
651 | cbuf.tail = cbuf.head = cbuf.buf; | |
652 | cbuf.queued = 0; | |
653 | if (debug) | |
654 | advise(LLOG_DEBUG, NULLCP, "tail and head set to %d", (int)cbuf.buf); | |
655 | } | |
656 | *(cbuf.tail) = c; | |
657 | if (++(cbuf.tail) > cbuf.buf + CBUFSIZE) | |
658 | cbuf.tail = cbuf.buf; | |
659 | cbuf.queued++; | |
660 | return(OK); | |
661 | } | |
662 | ||
663 | \f | |
664 | /*************************************************************************/ | |
665 | /* VTSEND - send the updates that have been put into the PE */ | |
666 | /* called "p_ondq". */ | |
667 | /*************************************************************************/ | |
668 | ||
669 | vtsend() | |
670 | { | |
671 | if(p_ondq == NULLPE) return; | |
672 | vtdata(p_ondq); | |
673 | pe_free(p_ondq); | |
674 | p_ondq = NULLPE; | |
675 | p_ovtsdi = NULLPE; | |
676 | sdi_count = 0; | |
677 | p_oobjupdt = NULLPE; | |
678 | obj_count = 0; | |
679 | updt_count = 0; | |
680 | } | |
681 | \f | |
682 | /************************************************************************/ | |
683 | /* VTDATA - generate a VDATREQ event to send an NDQ */ | |
684 | /* */ | |
685 | /* PARAMETERS */ | |
686 | /* */ | |
687 | /* NDQ - a presentation element containing an NDQ. */ | |
688 | /************************************************************************/ | |
689 | ||
690 | vtdata(ndq) | |
691 | PE ndq; | |
692 | { | |
693 | if (ndq == NULLPE) | |
694 | return; | |
695 | ||
696 | (void)do_event(VDATreq_n,ndq); | |
697 | } | |
698 | ||
699 | \f | |
700 | /************************************************************************/ | |
701 | /* MKDELIVER - create a DLQ. Requests for an acknowlegement are not */ | |
702 | /* allowed at this time. */ | |
703 | /************************************************************************/ | |
704 | ||
705 | PE | |
706 | mkdeliver(ack) | |
707 | int ack; | |
708 | { | |
709 | PE p_dlq; | |
710 | ||
711 | if (ack != FALSE) | |
712 | adios(NULLCP, "DLQ PDUs can only be sent without an ACK request"); | |
713 | if ((p_dlq = bool2prim(ack)) == NULLPE) | |
714 | adios (NULLCP, "DLQ build failure (out of memory)"); | |
715 | p_dlq->pe_id = DLQ_PDU; | |
716 | p_dlq->pe_class = PE_CLASS_CONT; | |
717 | p_dlq->pe_context = 1; | |
718 | return(p_dlq); | |
719 | } | |
720 | \f | |
721 | /**************************************************************************/ | |
722 | /* VDELREQ - create a deliver request PE and generate a VDELreq */ | |
723 | /* event to send it. */ | |
724 | /**************************************************************************/ | |
725 | ||
726 | vdelreq(ack) | |
727 | int ack; | |
728 | { | |
729 | PE p_dlq; | |
730 | ||
731 | if (ack) | |
732 | adios(NULLCP, | |
733 | "ACK requests in deliver PDUs not supported at this time"); | |
734 | p_dlq = mkdeliver(FALSE); | |
735 | ||
736 | (void)do_event(VDELreq,p_dlq); | |
737 | } | |
738 | ||
739 | \f | |
740 | /**************************************************************************/ | |
741 | /* VDELIND - we queue up data to go to the terminal when the NDQ */ | |
742 | /* is received, so there's really nothing */ | |
743 | /* to do when we get a VDELIND */ | |
744 | /* */ | |
745 | /* PARAMETERS: */ | |
746 | /* ACK - TRUE or FALSE according to whether */ | |
747 | /* acknowledgement is requested or not. */ | |
748 | /**************************************************************************/ | |
749 | ||
750 | vdelind(del_pe,ack) | |
751 | PE del_pe; | |
752 | int ack; | |
753 | { | |
754 | if (ack) { | |
755 | if (debug) | |
756 | advise(LLOG_DEBUG, NULLCP, "vdelind with ack requested not implemented!"); | |
757 | } | |
758 | pe_free(del_pe); | |
759 | } | |
760 | \f | |
761 | /************************************************************************/ | |
762 | /* VDATIND - On receiving a data indication we will go ahead and */ | |
763 | /* map the contents onto the character buffer to go to the terminal */ | |
764 | /* */ | |
765 | /* PARAMETERS - "type" can be SEQUENCED or NONSEQUENCED */ | |
766 | /* only SEQUENCED is implemented now */ | |
767 | /************************************************************************/ | |
768 | ||
769 | vdatind(type, pe) | |
770 | int type; | |
771 | PE pe; | |
772 | { | |
773 | if (type != SEQUENCED) | |
774 | adios(NULLCP, "unimplemented NDQ type %d", type); | |
775 | map(pe); | |
776 | } | |
777 | ||
778 | vhdatind(pe) | |
779 | PE pe; | |
780 | { | |
781 | ||
782 | advise(LLOG_NOTICE,NULLCP,"vhdatind(): HDQ's not supported\n"); | |
783 | pe_free(pe); | |
784 | } | |
785 | ||
786 | vudatind(pe) | |
787 | PE pe; | |
788 | { | |
789 | ||
790 | TEXT_UPDATE ud; | |
791 | ||
792 | if(unbuild_UDQPDU_UDQpdu(pe,1,NULLIP,NULLVP,(PEPYPARM) &ud) == NOTOK) | |
793 | { | |
794 | advise(LLOG_NOTICE,NULLCP,"UDQ parse failure\n"); | |
795 | } | |
796 | else | |
797 | { | |
798 | control_ud((CO_UPDATE *) &(ud.updates.co_list) ); | |
799 | free( (char *)ud.updates.co_list.co_name); | |
800 | pe_free(pe); | |
801 | } | |
802 | } | |
803 | \f | |
804 | /*****************************************************************************/ | |
805 | /* Connect_request: */ | |
806 | /* */ | |
807 | /* Sends an ASQ, waits for a confirm. */ | |
808 | /* */ | |
809 | /* Returns the file descriptor that corresponds to the network socket */ | |
810 | /* for the association, or NOTOK if the association failed. */ | |
811 | /* */ | |
812 | /* The assumption is made that the acs_sd data element of the AcSAPstart*/ | |
813 | /* structure is same as the file descriptor for the network socket used */ | |
814 | /* by the association. */ | |
815 | /*****************************************************************************/ | |
816 | ||
817 | con_req() | |
818 | { | |
819 | int uevent; | |
820 | ||
821 | if (debug) | |
822 | advise(LLOG_DEBUG, NULLCP, "in con_req"); | |
823 | ||
824 | vass_req(1,WACI_WACA,&vtp_profile); | |
825 | if (acc->acc_result != ACS_ACCEPT) { | |
826 | advise(LLOG_NOTICE,NULLCP, "association rejected: [%s]", | |
827 | AcErrString (acc -> acc_result)); | |
828 | state = S1_01; | |
829 | return NOTOK; | |
830 | } | |
831 | ||
832 | if (debug) { | |
833 | advise(LLOG_DEBUG, NULLCP, "got associate confirm event, sd is %d", acc->acc_sd); | |
834 | advise(LLOG_DEBUG, NULLCP, "acc_ninfo is %d", acc->acc_ninfo); | |
835 | advise(LLOG_DEBUG, NULLCP, "pe_id is %d", acc->acc_info[0]->pe_id); | |
836 | advise(LLOG_DEBUG, NULLCP, "pe_class is %d", acc->acc_info[0]->pe_class); | |
837 | advise(LLOG_DEBUG, NULLCP, "pe_form is %d", acc->acc_info[0]->pe_form); | |
838 | } | |
839 | ||
840 | if (acc->acc_ninfo < 1) | |
841 | adios(NULLCP, "no ASQ PDU sent with the associate confirm"); | |
842 | ||
843 | sd = acc->acc_sd; | |
844 | uevent = do_event(ASR,acc->acc_info[0]); | |
845 | ||
846 | if (debug) | |
847 | advise(LLOG_DEBUG, NULLCP, "got user event %d", uevent); | |
848 | ||
849 | if(uevent == SUCCESS) return(sd); | |
850 | else return(-1); | |
851 | } | |
852 | ||
853 | \f | |
854 | ||
855 | read_asq(pe) /*Unwrap ASQ PDU. Use information it contains to fill in | |
856 | some global values (profile_id,G_Func_Units,vcwa). | |
857 | Return 0 if ASQ is improperly formatted or missing a | |
858 | required field. For now, only the more obvious fields are | |
859 | checked and only transparent and telnet profiles | |
860 | are handled. Return PROFILE_NG if profile is not | |
861 | supported. Return 1 if ASQ is valid. | |
862 | */ | |
863 | PE pe; | |
864 | { | |
865 | ||
866 | int i,n, D; | |
867 | ASQ_MSG ud; | |
868 | ||
869 | bzero ((char *) &ud, sizeof ud); | |
870 | if(unbuild_ASQPDU_ASQpdu(pe,1,NULLIP,NULLVP,(PEPYPARM)&ud) == NOTOK) | |
871 | { | |
872 | advise(LLOG_NOTICE,NULLCP, "ASQ parse failure (%s)", PY_pepy); | |
873 | return(0); | |
874 | } | |
875 | ||
876 | ||
877 | if(!ud.class) | |
878 | { | |
879 | advise(LLOG_DEBUG, NULLCP, "ASQ without Class"); | |
880 | return(0); | |
881 | } | |
882 | if(ud.valid_coll) | |
883 | { | |
884 | if(ud.coll_winner == INITIATOR) vcwa = FALSE; | |
885 | else vcwa = TRUE; | |
886 | } | |
887 | G_Func_Units = ud.func_units.bitstring & 0x1f; | |
888 | if( (!ud.valid_prof) || (!ud.asq_profile.oid_true) || | |
889 | !oid_cmp(ud.asq_profile.prof_oid,ode2oid("default")) ) | |
890 | { | |
891 | vtp_profile.profile_name = "default"; | |
892 | my_displayobj = "DISPLAY-OBJECT-1"; | |
893 | telnet_profile = 0; | |
894 | return(1); | |
895 | } | |
896 | if( !oid_cmp(ud.asq_profile.prof_oid,ode2oid("telnet")) ) | |
897 | { | |
898 | vtp_profile.profile_name = "telnet"; | |
899 | vtp_profile.arg_val.tel_arg_list.full_ascii = 0xff; | |
900 | vtp_profile.arg_val.tel_arg_list.x_window = -1; | |
901 | ||
902 | D = -1; | |
903 | for(n=0; n<ud.asq_profile.num_cds_objects; n++) | |
904 | { | |
905 | if( *ud.asq_profile.cds_offer_list[n].obj_name == 'D') | |
906 | { | |
907 | D = n; | |
908 | break; | |
909 | } | |
910 | } | |
911 | if(D < 0) | |
912 | { | |
913 | advise(LLOG_DEBUG, NULLCP, "ASQ with no D Display Object"); | |
914 | return(0); | |
915 | } | |
916 | ||
917 | if( !ud.asq_profile.cds_offer_list[D].valid_rep_list ) | |
918 | { | |
919 | vtp_profile.arg_val.tel_arg_list.full_ascii = 1; | |
920 | default_rep_flag = 1; | |
921 | } | |
922 | else /*Repertoire specified*/ | |
923 | { | |
924 | if(ud.asq_profile.cds_offer_list[D].rep_offer.num_reps | |
925 | > MAXREPS) | |
926 | { | |
927 | advise(LLOG_DEBUG, NULLCP, "ASQ with too many repertoires"); | |
928 | return(0); | |
929 | } | |
930 | for(i=0; i< ud.asq_profile.cds_offer_list[D].rep_offer.num_reps; | |
931 | i++) | |
932 | { | |
933 | if(ud.asq_profile.cds_offer_list[D].rep_offer.repertoire[i].rep_type != 2) | |
934 | continue; | |
935 | if(!strncmp(ud.asq_profile.cds_offer_list[D].rep_offer.repertoire[i].rep_assign, | |
936 | ascii_go_repertoire,sizeof(ascii_go_repertoire))) | |
937 | { | |
938 | vtp_profile.arg_val.tel_arg_list.full_ascii = 0; | |
939 | advise(LLOG_DEBUG, NULLCP, "Using ASCII GO Repertoire."); | |
940 | break; | |
941 | } | |
942 | if(!strncmp(ud.asq_profile.cds_offer_list[D].rep_offer.repertoire[i].rep_assign, | |
943 | full_ascii_repertoire,sizeof(full_ascii_repertoire))) | |
944 | { | |
945 | vtp_profile.arg_val.tel_arg_list.full_ascii = 1; | |
946 | break; | |
947 | } | |
948 | } | |
949 | if(vtp_profile.arg_val.tel_arg_list.full_ascii < 0) return(0); | |
950 | } | |
951 | transparent = 0; | |
952 | ||
953 | if(ud.asq_profile.cds_offer_list[D].valid_x_dim == 0) | |
954 | { | |
955 | advise(LLOG_DEBUG, NULLCP, "ASQ with no X-Window"); | |
956 | return(0); | |
957 | } | |
958 | if(ud.asq_profile.cds_offer_list[D].x_dim.window_type != 2) | |
959 | /*If not integer type window field*/ | |
960 | { | |
961 | advise(LLOG_DEBUG, NULLCP, "ASQ with invalid X-Window"); | |
962 | return(0); | |
963 | } | |
964 | if(ud.asq_profile.cds_offer_list[D].x_dim.window.type | |
965 | == 0) /*If single value*/ | |
966 | { | |
967 | vtp_profile.arg_val.tel_arg_list.x_window = | |
968 | ud.asq_profile.cds_offer_list[D].x_dim.window.value; | |
969 | } | |
970 | else if(ud.asq_profile.cds_offer_list[D].x_dim.window.type == 1) | |
971 | /*If range*/ | |
972 | { | |
973 | if((ud.asq_profile.cds_offer_list[D].x_dim.window.min_val | |
974 | <= 80) && | |
975 | (ud.asq_profile.cds_offer_list[D].x_dim.window.max_val | |
976 | >= 80)) | |
977 | { | |
978 | vtp_profile.arg_val.tel_arg_list.x_window = 80; | |
979 | } | |
980 | else | |
981 | { | |
982 | vtp_profile.arg_val.tel_arg_list.x_window = | |
983 | ud.asq_profile.cds_offer_list[D].x_dim.window.min_val; | |
984 | } | |
985 | ||
986 | } | |
987 | if(vtp_profile.arg_val.tel_arg_list.x_window < 0) | |
988 | { | |
989 | advise(LLOG_DEBUG, NULLCP, "ASQ without x-window"); | |
990 | return(0); | |
991 | } | |
992 | if(vtp_profile.arg_val.tel_arg_list.full_ascii < 0) | |
993 | { | |
994 | advise(LLOG_DEBUG, NULLCP, "Using Default for ASCII repertoire (Full ASCII)"); | |
995 | vtp_profile.arg_val.tel_arg_list.full_ascii = 1; | |
996 | } | |
997 | } | |
998 | else | |
999 | { | |
1000 | advise(LLOG_DEBUG, NULLCP, "Unknown Profile Requested"); | |
1001 | return(PROFILE_NG); | |
1002 | } | |
1003 | ||
1004 | return(1); | |
1005 | } | |
1006 | \f | |
1007 | vasscnf(pe) /*Handle ASR received from Acceptor*/ | |
1008 | PE pe; | |
1009 | { | |
1010 | ||
1011 | ASR_MSG udr; | |
1012 | int rep, n; | |
1013 | int window_flag = 0; | |
1014 | int rep_flag = 0; | |
1015 | ||
1016 | bzero ((char *) &udr, sizeof udr); | |
1017 | if(unbuild_ASRPDU_ASRpdu(pe,1,NULLIP,NULLVP,(PEPYPARM)&udr) == NOTOK) | |
1018 | { | |
1019 | advise (LLOG_NOTICE,NULLCP, "ASR parse failure (%s)", PY_pepy); | |
1020 | return(NOTOK); | |
1021 | } | |
1022 | if(udr.result != SUCCESS) | |
1023 | { | |
1024 | advise(LLOG_NOTICE,NULLCP, "Association rejected by Peer VT"); | |
1025 | return(NOTOK); | |
1026 | } | |
1027 | if(udr.valid_coll) vcwa = udr.coll_winner; | |
1028 | else | |
1029 | advise(LLOG_DEBUG, NULLCP, "Received ASR with no collision winner"); | |
1030 | if(!strcmp(vtp_profile.profile_name,"transparent")) | |
1031 | { | |
1032 | if(!udr.arg_list.cds_val[0].valid_rep_list) /*No repertoires*/ | |
1033 | { | |
1034 | if(strcmp(vtp_profile.arg_val.tr_arg_list.cur_rep, | |
1035 | TRANSPARENT)) | |
1036 | /*If don't want default for this profile*/ | |
1037 | { | |
1038 | advise(LLOG_DEBUG, NULLCP, "ASR with no repertoire"); | |
1039 | return(NOTOK); | |
1040 | } | |
1041 | } | |
1042 | if(strcmp(vtp_profile.arg_val.tr_arg_list.cur_rep, | |
1043 | udr.arg_list.cds_val[0].rep_value.repertoire[0].rep_assign)) | |
1044 | /*Only support 1 repertoire in transparent*/ | |
1045 | { | |
1046 | advise(LLOG_DEBUG, NULLCP, "ASR--Invalid repertoire for transparent profile"); | |
1047 | return(NOTOK); | |
1048 | } | |
1049 | } | |
1050 | else if(!strcmp(vtp_profile.profile_name,"telnet")) | |
1051 | { | |
1052 | if(udr.arg_list.num_sp_param < 1) | |
1053 | { | |
1054 | advise(LLOG_DEBUG, NULLCP, "ASR without enough Special Arguments"); | |
1055 | return(0); | |
1056 | } | |
1057 | for(n=0; n<udr.arg_list.num_sp_param; n++) | |
1058 | { | |
1059 | if(udr.arg_list.sp_val[n].param_num == 1) | |
1060 | { | |
1061 | if(udr.arg_list.sp_val[n].param_type == 1) | |
1062 | /*If integer type*/ | |
1063 | { | |
1064 | if(vtp_profile.arg_val.tel_arg_list.x_window != | |
1065 | udr.arg_list.sp_val[n].args.int_arg) | |
1066 | { | |
1067 | advise(LLOG_DEBUG, NULLCP, "ASR with invalid X-Window"); | |
1068 | return(NOTOK); | |
1069 | } | |
1070 | else ++window_flag; | |
1071 | } | |
1072 | } | |
1073 | else if(udr.arg_list.sp_val[n].param_num == 2) | |
1074 | /*ASCII Repertoire type*/ | |
1075 | { | |
1076 | if(udr.arg_list.sp_val[n].param_type == 0) | |
1077 | /*If Boolean*/ | |
1078 | { | |
1079 | if(vtp_profile.arg_val.tel_arg_list.full_ascii) | |
1080 | rep = 1; | |
1081 | else rep = 0; | |
1082 | if(udr.arg_list.sp_val[n].args.bool_arg != rep) | |
1083 | { | |
1084 | advise(LLOG_DEBUG, NULLCP, "ASR with invalid Repertoire"); | |
1085 | return(NOTOK); | |
1086 | } | |
1087 | ++rep_flag; | |
1088 | } | |
1089 | } | |
1090 | } /*End for loop*/ | |
1091 | if(!window_flag) | |
1092 | { | |
1093 | advise(LLOG_DEBUG, NULLCP, "ASR without x-window"); | |
1094 | return(NOTOK); | |
1095 | } | |
1096 | if(!rep_flag) | |
1097 | { | |
1098 | advise(LLOG_DEBUG, NULLCP, "ASR with no repertoire"); | |
1099 | return(NOTOK); | |
1100 | } | |
1101 | } | |
1102 | return(OK); | |
1103 | } | |
1104 | \f | |
1105 | ||
1106 | asq(data) | |
1107 | PE data; | |
1108 | { | |
1109 | int srequirements; | |
1110 | struct PSAPctxlist vclist; | |
1111 | OID vt_asn; | |
1112 | struct QOStype qos; | |
1113 | ||
1114 | qos.qos_reliability = HIGH_QUALITY; | |
1115 | qos.qos_sversion = 2; | |
1116 | ||
1117 | if (debug) | |
1118 | advise(LLOG_DEBUG, NULLCP, "in asq"); | |
1119 | ||
1120 | acc = &accs; | |
1121 | acr = &acrs; | |
1122 | aci = &acis; | |
1123 | ||
1124 | /* I'm relying on "peerhost" being an external char * that | |
1125 | has the name of the host we want to connect to | |
1126 | */ | |
1127 | if ((aei = _str2aei (peerhost, myservice, "iso vt", 1, NULLCP, NULLCP)) | |
1128 | == NULLAEI) | |
1129 | adios (NULLCP, "unable to resolve service: %s", PY_pepy); | |
1130 | if ((pa = aei2addr (aei)) == NULLPA) | |
1131 | adios (NULLCP, "address translation failed"); | |
1132 | ||
1133 | if ((ctx = ode2oid (mycontext)) == NULLOID) | |
1134 | adios (NULLCP, "%s: unknown object descriptor", mycontext); | |
1135 | if ((ctx = oid_cpy (ctx)) == NULLOID) | |
1136 | adios (NULLCP, "out of memory"); | |
1137 | if ((pci = ode2oid (mypci)) == NULLOID) | |
1138 | adios (NULLCP, "%s: unknown object descriptor", mypci); | |
1139 | if ((pci = oid_cpy (pci)) == NULLOID) | |
1140 | adios (NULLCP, "out of memory"); | |
1141 | ||
1142 | if ((sf = addr2ref (PLocalHostName ())) == NULL) { | |
1143 | sf = &sfs; | |
1144 | (void) bzero ((char *) sf, sizeof *sf); | |
1145 | } | |
1146 | ||
1147 | PLOG (vt_log, print_VT_PDUs, data, NULLCP, 0); | |
1148 | aca = &aci->aci_abort; | |
1149 | srequirements = SR_DUPLEX | SR_RESYNC | SR_TYPEDATA; | |
1150 | srequirements &= ~SR_RLS_EXISTS; | |
1151 | ||
1152 | if((vt_asn = oid_cpy (pci)) == NULLOID) | |
1153 | adios (NULLCP, "out of memory"); | |
1154 | vclist.pc_nctx = 1; | |
1155 | vclist.pc_ctx[0].pc_id = 1; | |
1156 | vclist.pc_ctx[0].pc_asn = vt_asn; | |
1157 | vclist.pc_ctx[0].pc_atn = NULLOID; | |
1158 | data -> pe_context = 1; | |
1159 | ||
1160 | if (AcAssocRequest (ctx, NULLAEI, aei, NULLPA, pa, | |
1161 | &vclist, pci, | |
1162 | 0, srequirements, SERIAL_MIN, 0, sf, &data, 1, &qos, | |
1163 | acc, aci) == NOTOK) | |
1164 | acs_adios (aca, "A-ASSOCIATE.REQUEST"); | |
1165 | ||
1166 | if (acc -> acc_result != ACS_ACCEPT) | |
1167 | return; | |
1168 | ||
1169 | sd = acc->acc_sd; | |
1170 | ts_bound = acc -> acc_connect.pc_responding; /* struct copy */ | |
1171 | #ifdef DEBUG | |
1172 | { | |
1173 | register int i; | |
1174 | register struct PSAPconnect *pc = &acc -> acc_connect; | |
1175 | register struct PSAPctxlist *pl = &pc -> pc_ctxlist; | |
1176 | ||
1177 | advise (LLOG_DEBUG, NULLCP, "context: %s", | |
1178 | oid2ode (acc -> acc_context)); | |
1179 | ||
1180 | advise (LLOG_DEBUG, NULLCP, | |
1181 | "responding AE title: %s, responding PSAP address: %s", | |
1182 | sprintaei (&acc -> acc_respondtitle), | |
1183 | paddr2str (&pc -> pc_responding, NULLNA)); | |
1184 | ||
1185 | for (i = 0; i < pl -> pc_nctx; i++) | |
1186 | advise (LLOG_DEBUG, NULLCP, "ctx %d: 0x%x 0x%x %d", | |
1187 | pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn, | |
1188 | pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result); | |
1189 | advise (LLOG_DEBUG, NULLCP, "default %d", pc -> pc_defctxresult); | |
1190 | advise (LLOG_DEBUG, NULLCP, "p/s requirements 0x%x/0x%x", | |
1191 | pc -> pc_prequirements, pc -> pc_srequirements); | |
1192 | } | |
1193 | #endif | |
1194 | } | |
1195 | ||
1196 | vt_disconnect() | |
1197 | { | |
1198 | if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) | |
1199 | == NOTOK) | |
1200 | acs_adios (aca, "A-RELEASE.REQUEST"); | |
1201 | if(acr->acr_affirmative) { | |
1202 | connected = FALSE; | |
1203 | (void) do_event (RLR, acr -> acr_info[0]); | |
1204 | } | |
1205 | ||
1206 | ACRFREE (acr); | |
1207 | ||
1208 | } | |
1209 | ||
1210 | \f | |
1211 | ||
1212 | #define ASYNC 0 | |
1213 | ||
1214 | #define RMASK \ | |
1215 | "\020\01HALFDUPLEX\02DUPLEX\03EXPEDITED\04MINORSYNC\05MAJORSYNC\06RESYNC\ | |
1216 | \07ACTIVITY\010NEGOTIATED\011CAPABILITY\012EXCEPTIONS\013TYPEDATA" | |
1217 | ||
1218 | #define PMASK \ | |
1219 | "\020\01MANAGEMENT\02RESTORATION" | |
1220 | ||
1221 | /* \f DATA */ | |
1222 | ||
1223 | long time (); | |
1224 | char *ctime (); | |
1225 | int result; | |
1226 | ||
1227 | /*PE pe;*/ | |
1228 | \f | |
1229 | /*************************************************************************/ | |
1230 | /* ASS_IND */ | |
1231 | /*************************************************************************/ | |
1232 | ||
1233 | ass_ind (argc, argv) | |
1234 | int argc; | |
1235 | char **argv; | |
1236 | { | |
1237 | register struct PSAPctxlist *pl; | |
1238 | ||
1239 | ||
1240 | aca = &aci->aci_abort; | |
1241 | ps = &acs->acs_start; | |
1242 | pl = &ps -> ps_ctxlist; | |
1243 | ||
1244 | if (AcInit (argc, argv, acs, aci) == NOTOK) | |
1245 | acs_adios (aca, "initialization fails"); | |
1246 | ||
1247 | advise (LLOG_NOTICE,NULLCP, | |
1248 | "A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>", | |
1249 | acs -> acs_sd, oid2ode (acs -> acs_context), | |
1250 | sprintaei (&acs -> acs_callingtitle), | |
1251 | sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo); | |
1252 | ||
1253 | advise (LLOG_NOTICE,NULLCP, | |
1254 | "PSAP: <%d, %s, %s, %d, %s,", | |
1255 | ps -> ps_sd, | |
1256 | paddr2str (&ps -> ps_calling, NULLNA), | |
1257 | paddr2str (&ps -> ps_called, NULLNA), | |
1258 | pl -> pc_nctx, sprintb (ps -> ps_prequirements, PMASK)); | |
1259 | advise (LLOG_NOTICE,NULLCP, | |
1260 | " %s, %d, %d>", | |
1261 | sprintb (ps -> ps_srequirements, RMASK), ps -> ps_isn, | |
1262 | ps -> ps_ssdusize); | |
1263 | ||
1264 | (void) strcpy (peerhost, | |
1265 | na2str (ps -> ps_calling.pa_addr.sa_addr.ta_addrs)); | |
1266 | ||
1267 | sd = acs->acs_sd; | |
1268 | ||
1269 | /* ACSFREE(acs); | |
1270 | */ | |
1271 | ||
1272 | PLOG (vt_log, print_VT_PDUs, acs -> acs_info[0], NULLCP, 1); | |
1273 | ||
1274 | return( do_event(ASQ,acs->acs_info[0]) ); | |
1275 | } | |
1276 | ||
1277 | \f | |
1278 | ||
1279 | /* ARGSUSED */ | |
1280 | ||
1281 | vassind(pe) | |
1282 | PE pe; | |
1283 | { | |
1284 | return(vass_resp(SUCCESS)); | |
1285 | } | |
1286 | ||
1287 | \f | |
1288 | vbrkreq() | |
1289 | { | |
1290 | PE brk_pe; | |
1291 | BRcnt brk; | |
1292 | ||
1293 | bzero ((char *) &brk, sizeof brk); | |
1294 | brk.BKQcont.token_val = NOBKTOK; | |
1295 | brk.BKQcont.ExplPtr.xval = 0; | |
1296 | brk.BKQcont.ExplPtr.yval = 0; | |
1297 | brk.BKQcont.ExplPtr.zval = NULLCOORD; | |
1298 | if ((build_VT_BKQ__pdu(&brk_pe,1,NULL,NULLCP,(PEPYPARM)&brk)) == NOTOK) | |
1299 | adios (NULLCP, "BKQ build failed (%s)", PY_pepy); | |
1300 | brk_pe->pe_context = 1; | |
1301 | flushbufs(); /* flush local buffers */ | |
1302 | (void)do_event(VBRKreq,brk_pe); | |
1303 | } | |
1304 | \f | |
1305 | vbrkrsp() | |
1306 | { | |
1307 | PE brk_pe; | |
1308 | BRcnt brk; | |
1309 | ||
1310 | bzero ((char *) &brk, sizeof brk); | |
1311 | brk.BKRcont.token_val = NOBKTOK; | |
1312 | brk.BKRcont.ExplPtr.xval = 0; | |
1313 | brk.BKRcont.ExplPtr.yval = 0; | |
1314 | brk.BKRcont.ExplPtr.zval = NULLCOORD; | |
1315 | if ((build_VT_BKR__pdu(&brk_pe,1,NULL,NULLCP,(int *)&brk)) == NOTOK) | |
1316 | adios (NULLCP, "BKR build failed (%s)", PY_pepy); | |
1317 | brk_pe->pe_context = 1; | |
1318 | (void)do_event(VBRKrsp,brk_pe); | |
1319 | } | |
1320 | ||
1321 | \f | |
1322 | /* ARGSUSED */ | |
1323 | vbrkind(brk_pe) | |
1324 | PE brk_pe; | |
1325 | { | |
1326 | flushbufs(); | |
1327 | vtok = 1; /* got tokens from peer */ | |
1328 | advise(LLOG_DEBUG, NULLCP, "Received VT-BREAK"); | |
1329 | vt_clr_obj(); /*Initialize Control Objects*/ | |
1330 | vbrkrsp(); | |
1331 | if(telnet_profile) | |
1332 | { | |
1333 | #ifndef PTYBUG | |
1334 | #ifdef BSD44 | |
1335 | ptyecho(0); | |
1336 | #else | |
1337 | setmode(0,ECHO); /*Return to Local Echo. This call is not | |
1338 | the same for user (vtp) and server (vtpd) so for | |
1339 | now, VT-BREAK can only be requested at user side.*/ | |
1340 | #endif | |
1341 | vt_rem_echo(&na_image); | |
1342 | #endif | |
1343 | vt_sup_ga(&na_image); | |
1344 | kill_proc(); | |
1345 | } | |
1346 | /*Re-Negotiate Remote Echo and Suppress Go Ahead*/ | |
1347 | } | |
1348 | \f | |
1349 | /*ARGSUSED */ | |
1350 | vbrkcnf(brk_pe) | |
1351 | PE brk_pe; | |
1352 | { | |
1353 | (void)printf("\r\n[break]\r\n"); | |
1354 | if(telnet_profile) | |
1355 | { | |
1356 | #ifndef PTYBUG | |
1357 | vt_rem_echo(&ni_image); | |
1358 | #endif | |
1359 | vt_sup_ga(&ni_image); | |
1360 | } | |
1361 | } | |
1362 |