BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / vt / vtuser.c
CommitLineData
9319b3c3
C
1/* vtuser.c - VT user routines */
2
3#ifndef lint
4static 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
57extern char peerhost[];
58extern struct PSAPaddr ts_bound;
59static char *myservice = "terminal";
60
61static char *mycontext = "iso vt";
62static char *mypci = "iso vt pci";
63
64static char ascii_go_repertoire[] = {0x1a,0x28,0x42,0x00}; /*ESC 2/8 4/2*/
65 /*should be followed by 3 "voids" whatever that is*/
66static char full_ascii_repertoire[] = {0x1a,0x28,0x42,/*VOID*/0x1a,0x21,0x40,0x00};
67 /*Approximation to GO & CO ASCII sets*/
68
69extern char *isodeversion;
70extern char *my_displayobj;
71extern int G_Func_Units; /*Functional Units for this Association*/
72extern int vcwa; /*Collision Winner (TRUE if owned by this peer)*/
73extern int vsmd, vtok;
74extern int transparent;
75extern char na_image;
76extern char ni_image;
77extern VT_PROFILE vtp_profile;
78extern int telnet_profile;
79extern int do_break;
80extern int debug;
81
82int 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 */
97vass_req(class, acc_ri, profile)
98int class, acc_ri;
99VT_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
204vass_resp(result)
205int 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
297PE pe_buf = NULLPE;
298
299
300/************************************************************************/
301/* VRELREQ - Generate a VRELREQ to VT State Machine */
302/* */
303/* PARAMETERS - none */
304/************************************************************************/
305
306vrelreq()
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
323vrelrsp(result)
324int 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
358vrelcnf()
359{
360 if (debug)
361 advise(LLOG_DEBUG, NULLCP, "Release Confirmed");
362}
363\f
364
365vrelind()
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
376PE p_ondq = NULLPE; /* the current "ndq" being prepared for sending*/
377PE p_ovtsdi = NULLPE; /* the current "vtsdi" */
378int sdi_count = 0; /* count of "vtsdi"s in current NDQ*/
379PE p_oobjupdt = NULLPE; /* the current "object_update" */
380int obj_count = 0; /* count of "object_update"s in current "vtsdi"*/
381int updt_count = 0; /* count of updates in the current "object update"*/
382int 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
408vt_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
439send_queue(ud) /*Build NDQ with update supplied in ud structure*/
440TEXT_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
471setemode(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
493struct char_buffer {
494 int max_len, queued;
495 unsigned char *head, *tail;
496 unsigned char buf[CBUFSIZE];
497};
498
499struct 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
509int
510getch()
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
574int
575data_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
623int
624queued()
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/*************************************************************************/
636int
637putch(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
669vtsend()
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
690vtdata(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
705PE
706mkdeliver(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
726vdelreq(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
750vdelind(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
769vdatind(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
778vhdatind(pe)
779PE pe;
780{
781
782 advise(LLOG_NOTICE,NULLCP,"vhdatind(): HDQ's not supported\n");
783 pe_free(pe);
784}
785
786vudatind(pe)
787PE 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
817con_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
855read_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 */
863PE 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
1007vasscnf(pe) /*Handle ASR received from Acceptor*/
1008PE 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
1106asq(data)
1107PE 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
1196vt_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
1223long time ();
1224char *ctime ();
1225int result;
1226
1227/*PE pe;*/
1228\f
1229/*************************************************************************/
1230/* ASS_IND */
1231/*************************************************************************/
1232
1233ass_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
1281vassind(pe)
1282 PE pe;
1283{
1284 return(vass_resp(SUCCESS));
1285}
1286
1287\f
1288vbrkreq()
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
1305vbrkrsp()
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 */
1323vbrkind(brk_pe)
1324PE 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 */
1350vbrkcnf(brk_pe)
1351PE 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