home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / ka9q_src.arc / AX25CMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-07-28  |  11.8 KB  |  596 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "ax25.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "lapb.h"
  8. #include "cmdparse.h"
  9. #include "session.h"
  10. #include "st.h"            /* DG2KK */
  11.  
  12. extern struct tcb;
  13. #define NULLTCB (struct tcb *)0
  14.  
  15. #ifdef FLOW
  16. extern  int ttyflow;        /* DG2KK (output flowcontrol) */
  17. #endif
  18.  
  19. char *ax25states[] = {
  20.     "Disconnected",
  21.     "Conn pending",
  22.     "Disc pending",
  23.     "Connected",
  24.     "Frame Reject",
  25. };
  26.  
  27. int domycall(),dodigipeat(),doaxstat(),dot1(),dot2(),dot3(),domaxframe(),
  28.     doaxwindow(),dopaclen(),don2(),doaxreset(),doconok();    /* DG2KK */
  29.  
  30. static struct cmds axcmds[] = {
  31.     "conok",    doconok,    0, NULLCHAR,    NULLCHAR, /* DG2KK */
  32.     "digipeat",    dodigipeat,    0, NULLCHAR,    NULLCHAR,
  33.     "maxframe",    domaxframe,    0, NULLCHAR,    NULLCHAR,
  34.     "mycall",    domycall,    0, NULLCHAR,    NULLCHAR,
  35.     "paclen",    dopaclen,    0, NULLCHAR,    NULLCHAR,
  36.     "reset",    doaxreset,    2, "ax25 reset <axcb>", NULLCHAR,
  37.     "retry",    don2,        0, NULLCHAR,    NULLCHAR,
  38.     "status",    doaxstat,    0, NULLCHAR,    NULLCHAR,
  39.     "t1",        dot1,        0, NULLCHAR,    NULLCHAR,
  40.     "t2",        dot2,        0, NULLCHAR,    NULLCHAR,
  41.     "t3",        dot3,        0, NULLCHAR,    NULLCHAR,
  42.     "window",    doaxwindow,    0, NULLCHAR,    NULLCHAR,
  43.     NULLCHAR,    NULLFP,        0, "ax25 subcommands: digipeat maxframe mycall paclen reset retry status\n\tt1 t2 t3 window",    NULLCHAR,
  44. };
  45. /* Multiplexer for top-level ax25 command */
  46. doax25(argc,argv)
  47. int argc;
  48. char *argv[];
  49. {
  50.     return subcmd(axcmds,argc,argv);
  51. }
  52.  
  53. static
  54. doaxreset(argc,argv)
  55. int argc;
  56. char *argv[];
  57. {
  58.     struct ax25_cb *axp;
  59.     extern char notval[];
  60.     long htol();
  61.  
  62.     axp = (struct ax25_cb *)htol(argv[1]);
  63.     if(!ax25val(axp)){
  64.         printf(notval);
  65.         return 1;
  66.     }
  67.     reset_ax25(axp);
  68.     return 0;
  69. }
  70.  
  71. /* Display AX.25 link level control blocks */
  72. static
  73. doaxstat(argc,argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.     register int i;
  78.     register struct ax25_cb *axp;
  79.     char tmp[10];
  80.     extern char notval[];
  81.     long htol();
  82.  
  83.     if(argc < 2){
  84.         printf("    &AXB IF   Snd-Q   Rcv-Q   Remote    State\n");
  85.         for(i=0;i<NHASH;i++){
  86.             for(axp = ax25_cb[i];axp != NULLAX25; axp = axp->next){
  87.                 pax25(tmp,&axp->addr.dest);
  88.                 printf("%8lx %-5s%-8d%-8d%-10s%s\n",
  89.                     (long)axp,axp->interface->name,
  90.                     len_q(axp->txq),len_mbuf(axp->rxq),
  91.                     tmp,ax25states[axp->state]);
  92.             }
  93.         }
  94.         return 0;
  95.     }
  96.     axp = (struct ax25_cb *)htol(argv[1]);
  97.     if(!ax25val(axp)){
  98.         printf(notval);
  99.         return 1;
  100.     }
  101.     dumpstat(axp);
  102.     return 0;
  103. }
  104. /* Dump one control block */
  105. static
  106. dumpstat(axp)
  107. register struct ax25_cb *axp;
  108. {
  109.     char tmp[10];
  110.     int i;
  111.  
  112.     if(axp == NULLAX25 || axp->interface == NULLIF)
  113.         return;
  114.     /* DG2KK: changed "&AXB IF..." to " &AXB IF..." (Atari has 5 digit addr. */
  115.     printf(" &AXB IF   Remote   RBW V(S) V(R) Unack P Retry   T1    T2    T3  State\n");
  116.     pax25(tmp,&axp->addr.dest);
  117.     printf("%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
  118.     putchar(axp->rejsent ? 'R' : ' ');
  119.     putchar(axp->remotebusy ? 'B' : ' ');
  120.     putchar(axp->waitack ? 'W' : ' ');
  121.     printf(" %4d %4d",axp->vs,axp->vr);
  122.     printf(" %02d/%02d %d",axp->unack,axp->maxframe,axp->proto);
  123.     printf(" %02d/%02d",axp->retries,axp->n2);
  124.     if(run_timer(&axp->t1))
  125.         printf(" %02d/%02d",axp->t1.start - axp->t1.count,
  126.          axp->t1.start);
  127.     else
  128.         printf("   /%02d",axp->t1.start);
  129.  
  130.     if(run_timer(&axp->t2))
  131.         printf(" %02d/%02d",axp->t2.start - axp->t2.count,
  132.          axp->t2.start);
  133.     else
  134.         printf("   /%02d",axp->t2.start);
  135.  
  136.     if(run_timer(&axp->t3))
  137.         printf(" %02d/%02d",axp->t3.start - axp->t3.count,
  138.          axp->t3.start);
  139.     else
  140.         printf("   /%02d",axp->t3.start);
  141.  
  142.     printf(" %s\n",ax25states[axp->state]);
  143.     if(axp->addr.ndigis == 0)
  144.         return;
  145.     printf("Digipeaters:");
  146.     for(i=0;i<axp->addr.ndigis;i++){
  147.         pax25(tmp,&axp->addr.digis[i]);
  148.         printf(" %s",tmp);
  149.     }
  150.     printf("\n");
  151. }
  152.  
  153. /* Display or change our AX.25 address */
  154. static
  155. domycall(argc,argv)
  156. int argc;
  157. char *argv[];
  158. {
  159.     char buf[15];
  160.  
  161.     if(argc < 2){
  162.         pax25(buf,&mycall);
  163.         printf("%s\n",buf);
  164.         return 0;
  165.     }
  166.     if(setcall(&mycall,argv[1]) == -1)
  167.         return -1;
  168.     mycall.ssid |= E;
  169.     return 0;
  170. }
  171.  
  172. /* Control AX.25 digipeating */
  173. static
  174. dodigipeat(argc,argv)
  175. int argc;
  176. char *argv[];
  177. {
  178.     extern int digipeat;
  179.  
  180.     if(argc == 1) {
  181.         printf("digipeat %s\n",digipeat ? "on" : "off");
  182.     } else {
  183.         if(strcmp(argv[1],"on") == 0)
  184.             digipeat = 1;
  185.         else
  186.             digipeat = 0;
  187.     }
  188. }
  189.  
  190. /* Set retransmission timer */
  191. static
  192. dot1(argc,argv)
  193. int argc;
  194. char *argv[];
  195. {
  196.     extern int16 t1init;
  197.  
  198.     if(argc == 1) {
  199.         printf("T1 %d\n",t1init);
  200.     } else {
  201.         t1init = atoi(argv[1]);
  202.     }
  203. }
  204.  
  205. /* Set acknowledgement delay timer */
  206. static
  207. dot2(argc,argv)
  208. int argc;
  209. char *argv[];
  210. {
  211.     extern int16 t2init;
  212.  
  213.     if(argc == 1) {
  214.         printf("T2 %d\n",t2init);
  215.     } else {
  216.         t2init = atoi(argv[1]);
  217.     }
  218. }
  219.  
  220. /* Set idle timer */
  221. static
  222. dot3(argc,argv)
  223. int argc;
  224. char *argv[];
  225. {
  226.     extern int16 t3init;
  227.  
  228.     if(argc == 1) {
  229.         printf("T3 %d\n",t3init);
  230.     } else {
  231.         t3init = atoi(argv[1]);
  232.     }
  233. }
  234.  
  235. /* Set retry limit count */
  236. static
  237. don2(argc,argv)
  238. int argc;
  239. char *argv[];
  240. {
  241.     extern int16 n2;
  242.  
  243.     if(argc == 1) {
  244.         printf("Retry %d\n",n2);
  245.     } else {
  246.         n2 = atoi(argv[1]);
  247.     }
  248. }
  249.  
  250. /* Set maximum number of frames that will be allowed in flight */
  251. static
  252. domaxframe(argc,argv)
  253. int argc;
  254. char *argv[];
  255. {
  256.     extern int16 maxframe;
  257.  
  258.     if(argc == 1) {
  259.         printf("Maxframe %d\n",maxframe);
  260.     } else {
  261.         maxframe = atoi(argv[1]);
  262.     }
  263. }
  264.  
  265. /* Set maximum length of I-frame data field */
  266. static
  267. dopaclen(argc,argv)
  268. int argc;
  269. char *argv[];
  270. {
  271.     extern int16 paclen;
  272.  
  273.     if(argc == 1) {
  274.         printf("Paclen %d\n",paclen);
  275.     } else {
  276.         paclen = atoi(argv[1]);
  277.     }
  278. }
  279.  
  280. /* Set high water mark on receive queue that triggers RNR */
  281. static
  282. doaxwindow(argc,argv)
  283. int argc;
  284. char *argv[];
  285. {
  286.     extern int16 axwindow;
  287.  
  288.     if(argc == 1) {
  289.         printf("Axwindow %d\n",axwindow);
  290.     } else {
  291.         axwindow = atoi(argv[1]);
  292.     }
  293. }
  294. /* End of ax25 subcommands */
  295.  
  296. /* Initiate interactive AX.25 connect to remote station */
  297. doconnect(argc,argv)
  298. int argc;
  299. char *argv[];
  300.  {
  301.     void ax_rx(),ax_tx(),ax_state();
  302.     int ax_parse();
  303.     struct ax25_addr dest;
  304.     struct ax25 addr;
  305.     struct ax25_cb *open_ax25();
  306.     struct interface *ifp;
  307.     struct session *s;
  308.     extern int16 axwindow;
  309.     int i;
  310.  
  311.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  312.         if(strcmp(argv[1],ifp->name) == 0)
  313.             break;
  314.  
  315.     if(ifp == NULLIF){
  316.         printf("Interface %s unknown\n",argv[1]);
  317.         return 1;
  318.     }
  319.     setcall(&dest,argv[2]);
  320.     /* See if a session already exists */
  321.     for(s = sessions; s < &sessions[nsessions]; s++){
  322.         if(s->type == AX25TNC
  323.          && addreq(&s->cb.ax25_cb->addr.dest,&dest)){
  324. #if ( MAC || AMIGA )
  325.             printf("Session %lu to %s already exists\n",
  326. #else
  327.             printf("Session %u to %s already exists\n",
  328. #endif
  329.                 s - sessions,argv[2]);
  330.             return 1;
  331.         }
  332.     }
  333.     /* Allocate a session descriptor */
  334.     if((s = newsession()) == NULLSESSION){
  335.         printf("Too many sessions\n");
  336.         return 1;
  337.     }
  338.     if((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
  339.         strcpy(s->name,argv[2]);
  340.     s->type = AX25TNC;
  341.     s->parse = ax_parse;
  342.     current = s;
  343.     ASSIGN(addr.source,mycall);    /* DG2KK: should be changed */
  344.     setcall(&addr.dest,argv[2]);
  345.     for(i=3; i < argc; i++)
  346.         setcall(&addr.digis[i-3],argv[i]);
  347.  
  348.     addr.ndigis = i - 3;
  349.     s->cb.ax25_cb = open_ax25(&addr,axwindow,ax_rx,ax_tx,ax_state,ifp,(char *)s);
  350.     go();
  351.     return 0;
  352. }
  353.  
  354.  
  355. /* Display changes in AX.25 state */
  356. void
  357. ax_state(axp,old,new)
  358. struct ax25_cb *axp;
  359. int old,new;
  360. {
  361.     struct session *s;
  362.     char remote[10];        /* DG2KK */
  363.  
  364.     s = (struct session *)axp->user;
  365.  
  366.     if(current != NULLSESSION && current->type == AX25TNC && current == s){
  367.         printf("%s\n",ax25states[new]);
  368.  
  369.         /* added to enable a 'bell' when state is connected */
  370. /* ---- DG2KK: AX25 logging ---- */
  371.         if(new == CONNECTED) {
  372.             printf("\007");
  373.             pax25(remote,&axp->addr.dest);
  374.             log(NULLTCB,"Connected to %s",remote);
  375.         }
  376.  
  377.         if(new == DISCONNECTED) {
  378.             pax25(remote,&axp->addr.dest);
  379.             log(NULLTCB,"Disconnected from %s",remote);
  380.             cmdmode();
  381.         }
  382. /* ----- */
  383.         fflush(stdout);
  384.     }
  385.     if(new == DISCONNECTED){
  386.         axp->user = NULLCHAR;
  387.         freesession(s);
  388.     }
  389. }
  390. /* Handle typed characters on AX.25 connection */
  391. int
  392. ax_parse(buf,cnt)
  393. char *buf;
  394. int16 cnt;
  395. {
  396.     struct mbuf *bp;
  397.     register char *cp;
  398.     char c;
  399.  
  400.     if(current == NULLSESSION || current->type != AX25TNC)
  401.         return;    /* "can't happen" */
  402.  
  403.     /* If recording is on, record outgoing stuff too */
  404.     if(current->record != NULLFILE)
  405.         fwrite(buf,1,cnt,current->record);
  406.  
  407.     /* Allocate buffer and start it with the PID */
  408.     bp = alloc_mbuf(cnt+1);
  409.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
  410.     bp->cnt++;
  411.  
  412.     /* Copy keyboard buffer to output, stripping line feeds */
  413.     cp = bp->data + 1;
  414.     while(cnt-- != 0){
  415.         c = *buf++;
  416.         if(c != '\n'){
  417.             *cp++ = c;
  418.             bp->cnt++;
  419.         }
  420.     }
  421.     send_ax25(current->cb.ax25_cb,bp);
  422. }
  423.  
  424. /* This is the default receive upcall function, used when
  425.  * someone else connects to us.
  426.  */
  427. void
  428. ax_incom(axp,cnt)
  429. register struct ax25_cb *axp;
  430. int16 cnt;
  431. {
  432.     /* temporary hack - replace with a switch */
  433.     mbx_incom(axp,cnt);
  434.     return;
  435. }
  436.  
  437. /* This function sets up an ax25 chat session.
  438.  * (Formerly ax_incom())!
  439.  * Handle new incoming terminal sessions
  440.  * This is the default receive upcall function, used when
  441.  * someone else connects to us
  442.  */
  443. void
  444. ax_session(axp,cnt)        /* DG2KK: was ax_income() */
  445. register struct ax25_cb *axp;
  446. int16 cnt;
  447. {
  448.     struct session *s;
  449.     char remote[10];
  450.     void ax_rx(),ax_state();
  451.  
  452.     pax25(remote,&axp->addr.dest);
  453.     if((s = newsession()) == NULLSESSION){
  454.         /* Out of sessions */
  455.         disc_ax25(axp);
  456.         return;
  457.     }
  458.     s->type = AX25TNC;
  459.     s->name = malloc((int16)strlen(remote)+1);
  460.     s->cb.ax25_cb = axp;
  461.     s->parse = ax_parse;
  462.     strcpy(s->name,remote);
  463.     axp->r_upcall = ax_rx;
  464.     axp->s_upcall = ax_state;
  465.     axp->user = (char *)s;
  466. #if ( MAC || AMIGA ) /* was: (defined(MAC) || defined(AMIGA)) DG2KK */
  467.     printf("\007Incoming AX25 session %lu from %s\n",s - sessions,remote);
  468. #else
  469.     printf("\007Incoming AX25 session %u from %s\n",s - sessions,remote);
  470. #endif
  471.     fflush(stdout);
  472. }
  473.  
  474. /* Handle incoming terminal traffic */
  475. void
  476. ax_rx(axp,cnt)
  477. struct ax25_cb *axp;
  478. int16 cnt;
  479. {
  480.     register struct mbuf *bp;
  481.     struct mbuf *recv_ax25();
  482.     char c;
  483.  
  484.     /* Hold output if we're not the current session */
  485.     if(mode != CONV_MODE || current == NULLSESSION
  486.      || current->type != AX25TNC || current->cb.ax25_cb != axp)
  487.         return;
  488.  
  489. #ifdef FLOW
  490.     if (ttyflow == 0)    /* DG2KK */
  491.         return;
  492. #endif FLOW
  493.  
  494.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)
  495.         return;
  496.  
  497.     /* Display received characters, translating CR's to CR/LF */
  498.     while(bp != NULLBUF){
  499.         while(bp->cnt-- != 0){
  500.             c = *bp->data++;
  501.             putc(c,stdout);
  502.             if(current->record){
  503.                 fputc(c,current->record);
  504.                 if(c == '\r')
  505.                     fputc('\n',current->record);
  506.             }
  507.             if(c == '\r')
  508.                 putc('\n',stdout);
  509.         }
  510.         bp = free_mbuf(bp);
  511.     }
  512.     if(current->record)
  513.         fflush(current->record);
  514.     fflush(stdout);
  515. }
  516. /* Handle transmit upcalls. Used only for file uploading */
  517. void
  518. ax_tx(axp,cnt)
  519. struct ax25_cb *axp;
  520. int16 cnt;
  521. {
  522.     register char *cp;
  523.     struct session *s;
  524.     register struct mbuf *bp;
  525.     int16 size;
  526.     int c;
  527.  
  528.     if((s = (struct session *)axp->user) == NULLSESSION
  529.      || s->upload == NULLFILE)
  530.         return;
  531.     while(cnt != 0){
  532.         size = min(cnt,axp->paclen+1);
  533.         if((bp = alloc_mbuf(size)) == NULLBUF)
  534.             break;
  535.         cp = bp->data;
  536.         /* Start with the PID */
  537.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  538.         bp->cnt++;
  539.  
  540.         /* Now send data characters, translating between local
  541.          * keyboard end-of-line sequences and the (unwritten)
  542.          * AX.25 convention, which is carriage-return only
  543.          */
  544.         while(bp->cnt < size){
  545.             if((c = getc(s->upload)) == EOF)
  546.                 break;
  547. #ifdef    MSDOS
  548.             /* MS-DOS gives cr-lf */
  549.             if(c == '\n')
  550.                 continue;
  551. #endif
  552. #if (UNIX || MAC || AMIGA) /*(defined(UNIX) || defined(MAC) || defined(AMIGA))*/
  553.             /* These give lf only */
  554.             if(c == '\n')
  555.                 c = '\r';
  556. #endif
  557.             *cp++ = c;
  558.             bp->cnt++;
  559.         }    
  560.         if(bp->cnt > 1) {
  561.             send_ax25(axp,bp);
  562.         } else {
  563.             /* Empty frame, don't bother sending */
  564.             free_p(bp);
  565.             break;
  566.         }
  567.         cnt -= bp->cnt;
  568.     }
  569.     if(cnt != 0){
  570.         /* Error or end-of-file */
  571.         fclose(s->upload);
  572.         s->upload = NULLFILE;
  573.         free(s->ufile);
  574.         s->ufile = NULLCHAR;
  575.     }
  576. }
  577.  
  578. /* Control AX.25 connects (DG2KK) */
  579. static
  580. doconok(argc,argv)
  581. int argc;
  582. char *argv[];
  583. {
  584.     extern int conok;
  585.  
  586.     if(argc == 1) {
  587.         printf("conok %s\n",conok ? "on" : "off");
  588.     } else {
  589.         if(strcmp(argv[1],"on") == 0)
  590.             conok = 1;
  591.         else
  592.             conok = 0;
  593.     }
  594. }
  595.  
  596.