home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / Portable Patmos / src / portable kernel / ncsasock / test.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-18  |  13.1 KB  |  656 lines  |  [TEXT/R*ch]

  1. /*********************************************************************
  2. File        :    GUSI                -    Grand Unified Socket Interface
  3. File        :    GUSIINETTest    -    Test unix domain sockets
  4. Author    :    Matthias Neeracher <neeri@iis.ethz.ch>
  5. Started    :    02Sep92
  6. Modified    :    08Sep92    MN    First attempt
  7.                 08Sep92    MN    Factor out common socket routines
  8.                 14Sep92    MN    Misinterpreted hostent structure
  9.                 03Mar93    MN    Added performance test
  10.                 29Jul93    MN    servent tests
  11.                 25Aug93    MN    gethostbyaddr()
  12. Last        :    25Aug93
  13. *********************************************************************/
  14.  
  15. #define Int4    long
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netdb.h>
  20. #include <ctype.h>
  21. #include <pwd.h>
  22. #include <varargs.h>
  23. #include <errno.h>
  24. #include <arpa/telnet.h>
  25. #include <netinet/in_systm.h>
  26. #include <machine/endian.h>
  27. #include <netinet/ip.h>
  28. #include <arpa/inet.h>
  29. #include <string.h>
  30. //#include <sock_ext.h>
  31. int s_select(Int4 width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  32. int sscanf(const char *, char *, ...);
  33.  
  34. #define NROFCHARS                26
  35. #define DECODE(ch)            ((ch) ? (ch) - (isupper(ch) ? 'A' : 'a') + 1 : 0)
  36. #define CMDCODE(ch1,ch2)    (DECODE(ch1)*(NROFCHARS+1)+DECODE(ch2))
  37. #define NROFCMDS                (NROFCHARS+1)*(NROFCHARS+1)
  38.  
  39. typedef void (*TestCmd)(char ch1, char ch2, const char * restcmd);
  40.  
  41. typedef struct {
  42.     TestCmd            proc;
  43.     const char *    syntax;
  44.     const char *    help;
  45. } CmdDef;
  46.  
  47. CmdDef commands[NROFCMDS];
  48.  
  49. #define DISPATCH(ch1,ch2)    commands[CMDCODE(ch1,ch2)].proc
  50. #define USAGE(ch1,ch2)         commands[CMDCODE(ch1,ch2)].syntax
  51. #define HELPMSG(ch1,ch2)     commands[CMDCODE(ch1,ch2)].help
  52.  
  53.  
  54. #ifndef       MAXHOSTNAMELEN
  55. #define       MAXHOSTNAMELEN 64
  56. #endif        MAXHOSTNAMELEN
  57.  
  58. int        inputline;
  59.  
  60. #define Boolean unsigned char
  61.  
  62. /* void COMMAND(
  63.                  char ch1, char ch2,            Command name
  64.                 TestCmd p,                        Command to be run
  65.                 char *  s,                        Arguments to command
  66.                 char *  h);                        Explanation for command
  67.  
  68.     Example:
  69.         COMMAND('m', 'd', MkDir, "directory",            "Make a new directory");
  70. */
  71.  
  72. #define COMMAND(ch1,ch2,p,s,h)    \
  73.     DISPATCH(ch1,ch2)    =    (p),        \
  74.     USAGE(ch1,ch2)     =    (s),        \
  75.     HELPMSG(ch1,ch2)    =    (h)
  76.  
  77. /* An useful macro for dumping variables.
  78.     
  79.     Example:
  80.         DUMP(statbuf.st_dev,d);
  81. */
  82.  
  83. #define DUMP(EXPR, MODE)    printf("#    %s = %"#MODE"\n", #EXPR, EXPR)
  84.  
  85. Boolean     HellHoundOnMyTrail = 1;            /* Gotta keep on moving */
  86. char        infilename[200];
  87. char *    inputfrom;
  88. int        inputline;
  89. CmdDef     commands[NROFCMDS];
  90.     
  91. void Help(char _1, char _2, const char *_3)
  92. {
  93.     char ch1,ch2;
  94.     
  95.     printf("Commands are:\n\n");
  96.     
  97.     for (ch1 = 'a'; ch1 <= 'z'; ++ch1)
  98.         for (ch2 = 0; ch2 <= 'z'; ch2 ? ++ch2 : (ch2 = 'a'))
  99.             if (HELPMSG(ch1,ch2))
  100.                 printf(
  101.                     "\t%c%c %-25s -- %s\n", 
  102.                     ch1, 
  103.                     ch2 ? ch2 : ' ', 
  104.                     USAGE(ch1,ch2), 
  105.                     HELPMSG(ch1,ch2));
  106.     
  107.     printf("\n");
  108. }
  109.  
  110. void Where()
  111. {
  112.     if (inputfrom)
  113.         printf("File '%s'; Line %d\n", inputfrom, inputline);
  114. }
  115.  
  116. void Prompt()
  117. {
  118.  
  119.     if (!inputfrom)
  120.         printf("[%d] ", inputline );
  121. }
  122.  
  123. #define CASE(code)    case code: return #code
  124.  
  125. const char * Explain()
  126. {
  127.     switch (errno) {
  128.     CASE(EPERM);
  129.     CASE(ENOENT);
  130.     CASE(ESRCH);
  131.     CASE(EINTR);
  132.     CASE(EIO);
  133.     CASE(ENXIO);
  134.     CASE(E2BIG);
  135.     CASE(ENOEXEC);
  136.     CASE(EBADF);
  137.     CASE(ECHILD);
  138.     CASE(EDEADLK);
  139.     CASE(ENOMEM);
  140.     CASE(EACCES);
  141.     CASE(EFAULT);
  142.     CASE(ENOTBLK);
  143.     CASE(EBUSY);
  144.     CASE(EEXIST);
  145.     CASE(EXDEV);
  146.     CASE(ENODEV);
  147.     CASE(ENOTDIR);
  148.     CASE(EISDIR);
  149.     CASE(EINVAL);
  150.     CASE(ENFILE);
  151.     CASE(EMFILE);
  152.     CASE(ENOTTY);
  153.     CASE(ETXTBSY);
  154.     CASE(EFBIG);
  155.     CASE(ENOSPC);
  156.     CASE(ESPIPE);
  157.     CASE(EROFS);
  158.     CASE(EMLINK);
  159.     CASE(EPIPE);
  160.     CASE(EDOM);
  161.     CASE(ERANGE);
  162.     CASE(EWOULDBLOCK);
  163.     CASE(EINPROGRESS);
  164.     CASE(EALREADY);
  165.     CASE(ENOTSOCK);
  166.     CASE(EDESTADDRREQ);
  167.     CASE(EMSGSIZE);
  168.     CASE(EPROTOTYPE);
  169.     CASE(ENOPROTOOPT);
  170.     CASE(EPROTONOSUPPORT);
  171.     CASE(ESOCKTNOSUPPORT);
  172.     CASE(EOPNOTSUPP);
  173.     CASE(EPFNOSUPPORT);
  174.     CASE(EAFNOSUPPORT);
  175.     CASE(EADDRINUSE);
  176.     CASE(EADDRNOTAVAIL);
  177.     CASE(ENETDOWN);
  178.     CASE(ENETUNREACH);
  179.     CASE(ENETRESET);
  180.     CASE(ECONNABORTED);
  181.     CASE(ECONNRESET);
  182.     CASE(ENOBUFS);
  183.     CASE(EISCONN);
  184.     CASE(ENOTCONN);
  185.     CASE(ESHUTDOWN);
  186.     CASE(ETOOMANYREFS);
  187.     CASE(ETIMEDOUT);
  188.     CASE(ECONNREFUSED);
  189.     CASE(ELOOP);
  190.     CASE(ENAMETOOLONG);
  191.     CASE(EHOSTDOWN);
  192.     CASE(EHOSTUNREACH);
  193.     CASE(ENOTEMPTY);
  194.     CASE(EPROCLIM);
  195.     CASE(EUSERS);
  196.     CASE(EDQUOT);
  197.     CASE(ESTALE);
  198.     CASE(EREMOTE);
  199.     CASE(EBADRPC);
  200.     CASE(ERPCMISMATCH);
  201.     CASE(EPROGUNAVAIL);
  202.     CASE(EPROGMISMATCH);
  203.     CASE(EPROCUNAVAIL);
  204.     CASE(ENOLCK);
  205.     CASE(ENOSYS);
  206.     default:
  207.         return "Unknown";
  208.     }        
  209. }
  210.  
  211. void Usage(char ch1, char ch2)
  212. {
  213.     printf("# Usage is: %c%c %s\n", ch1, ch2 ? ch2 : ' ', USAGE(ch1,ch2));
  214.     Where();
  215. }
  216.  
  217. void Dispatch(const char * command)
  218. {
  219.     char        ch1    =    command[0];
  220.     char        ch2    =    command[1];
  221.     TestCmd    exec;
  222.     
  223.     /* We are guaranteed to have at least one valid character */
  224.     
  225.     switch (ch1) {
  226.     case '\n':
  227.     case '#':
  228.         return;
  229.     }
  230.  
  231.     if (!ch2)
  232.         ++command;
  233.     else {
  234.         if (isspace(ch2))    {
  235.             command    +=    1;
  236.             ch2        =    0;
  237.         } else
  238.             command    +=    2;
  239.         
  240.         /* Skip rest of first word */    
  241.         for (; *command && !isspace(*command); ++command);
  242.         
  243.         /* Skip whitespace */
  244.         while (isspace(*command))
  245.             ++command;
  246.     }
  247.     
  248.     if (isalpha(ch1) && (!ch2 || isalpha(ch2)) && (exec = DISPATCH(ch1,ch2)))
  249.         exec(ch1, ch2, command);
  250.     else {
  251.         if (ch2)
  252.             printf("# Unknown command: '%c%c'\n", ch1, ch2);
  253.         else
  254.             printf("# Unknown command: '%c'\n", ch1);
  255.             
  256.         printf("# Type 'h' for a list of known commands.\n"); 
  257.         
  258.         Where();
  259.     }
  260. }
  261.  
  262. void Quit(char _1, char _2, const char *_3)
  263. {
  264.     HellHoundOnMyTrail = 0;
  265. }
  266.  
  267. void RunTest(int argc, char ** argv)
  268. {
  269.  
  270.     char         cmd[80];
  271.  
  272.     COMMAND('h',   0, Help,  "",                         "Print this list");
  273.     COMMAND('q',   0, Quit,  "",                         "End the sad existence of this program");
  274.  
  275.     if (!--argc)
  276.         Help('h', 0, "");
  277.     
  278.     do {
  279.             inputfrom    =    0;
  280.  
  281.         inputline    =    1;
  282.         
  283.         while (HellHoundOnMyTrail && (Prompt(), gets(cmd)))    {
  284.             Dispatch(cmd);
  285.             ++inputline;
  286.         }
  287.     } while (HellHoundOnMyTrail && --argc > 0);
  288.         
  289.     printf("So long, it's been good to know you.\n");
  290. }
  291.  
  292. int sock;                /* Socket to read/write to                */
  293. int accsock;            /* Socket to accept connections on     */
  294. char    addrstr[100];
  295.  
  296. void Socket(char ch1, char _2, const char *_3)
  297. {
  298.     sock    =    socket(AF_INET, (ch1 == 's') ? SOCK_STREAM : SOCK_DGRAM, 0);
  299.     
  300.     if (sock == -1)    {
  301.         printf("# socket() returned error %s\n", Explain());
  302.         Where();
  303.     }
  304. }
  305.  
  306. void Bind(char ch1, char ch2, const char * cmd)
  307. {
  308.     int                        len;
  309.     struct sockaddr_in    addr;
  310.  
  311.     if (sock == -1)    {
  312.         printf("# socket is not open\n");
  313.         Where();
  314.         
  315.         return;
  316.     }
  317.  
  318.     if (sscanf(cmd, "%s %hd", addrstr, &addr.sin_port) == 2) {
  319.         addr.sin_addr.s_addr            =    inet_addr(addrstr);
  320.         addr.sin_family        =    AF_INET;
  321.         len                        =    sizeof(struct sockaddr_in);
  322.     } else {
  323.         Usage(ch1, ch2);
  324.         return;
  325.     }
  326.     
  327.     if (bind(sock, (struct sockaddr *) &addr, len))    {
  328.         printf(
  329.             "bind(%s:%d) returned error %s\n", 
  330.             inet_ntoa(addr.sin_addr),
  331.             addr.sin_port, 
  332.             Explain());
  333.             
  334.         Where();
  335.     }
  336. }
  337.  
  338. void Accept(char _1, char _2, const char *_3)
  339. {
  340.     int                        len;
  341.     struct sockaddr_in    addr;
  342.  
  343.     if (sock == -1)    {
  344.         printf("# socket is not open\n");
  345.         Where();
  346.         
  347.         return;
  348.     }
  349.     if (accsock != -1)    {
  350.         printf("# can't accept more than one connection\n");
  351.         Where();
  352.         
  353.         return;
  354.     }
  355.  
  356.     len    =    sizeof(struct sockaddr_in);
  357.     sock    =    accept(accsock = sock, (struct sockaddr *) &addr, &len);
  358.     
  359.     if (sock < 0)    {
  360.         printf("# accept() returned error %s\n", Explain());
  361.         sock        =    accsock;
  362.         accsock    =    -1;
  363.     } else {
  364.         printf(
  365.             "# accepted connection from %s port %d\n", 
  366.             inet_ntoa(addr.sin_addr), 
  367.             addr.sin_port);
  368.     }
  369.     
  370.     Where();
  371. }
  372.     
  373. void Connect(char ch1, char ch2, const char * cmd)
  374. {
  375.     int                        len;
  376.     struct sockaddr_in    addr;
  377.  
  378.     if (sock == -1)    {
  379.         printf("# socket is not open\n");
  380.         Where();
  381.         
  382.         return;
  383.     }
  384.     
  385.     if (sscanf(cmd, "%s %hd", addrstr, &addr.sin_port) == 2) {
  386.         addr.sin_addr.s_addr            =    inet_addr(addrstr);
  387.         addr.sin_family        =    AF_INET;
  388.         len                        =    sizeof(struct sockaddr_in);
  389.     } else {
  390.         Usage(ch1, ch2);
  391.         return;
  392.     }
  393.  
  394.     if (connect(sock, (struct sockaddr *) &addr, len))    {
  395.         printf(
  396.             "connect(%s:%d) returned error %s\n", 
  397.             inet_ntoa(addr.sin_addr),
  398.             addr.sin_port, 
  399.             Explain());
  400.         Where();
  401.     }
  402. }    
  403.  
  404. #include <sys/time.h>
  405.  
  406. int ReadWhileUCan()
  407. {
  408.     int                res;
  409.     char *            outline;
  410.     fd_set            rdfds;
  411.     fd_set            exfds;
  412.     struct timeval    delay;
  413.     char                 out[500];
  414.  
  415.     for (;;) {
  416.         FD_ZERO(&rdfds);
  417.         FD_ZERO(&exfds);
  418.         
  419.         FD_SET(sock, &rdfds);
  420.         FD_SET(sock, &exfds);
  421.         
  422.         delay.tv_sec    =    1;
  423.         delay.tv_usec    =    0;
  424.         
  425.         res = select(sock+1, &rdfds, 0, &exfds, &delay);
  426.         
  427.         if (res < 0)    {
  428.             printf("# select() returned error %s\n", Explain());
  429.             
  430.             return -1;
  431.         } else if (!res)
  432.             return 0;
  433.         else if (res && FD_ISSET(sock, &exfds)) {
  434.             printf("# select() returned an exception\n");
  435.             
  436.             return -1;
  437.         } else if (res && FD_ISSET(sock, &rdfds)) {
  438.             res = read(sock, out, 500);
  439.             
  440.             if (res < 0) {
  441.                 printf("# read() returned error %s\n", Explain());
  442.             
  443.                 return -1;
  444.             }
  445.             
  446.             out[res] = 0;
  447.             
  448.             for (outline = strtok(out, "\n\r"); outline; outline = strtok(NULL, "\n\r"))
  449.                 printf("%s\n", outline);
  450.         }
  451.     }
  452. }
  453.  
  454. void Telnet(char _1, char _2, const char *_3)
  455. {
  456.     int                len;
  457.     int                 part;
  458.     int                res;
  459.     char *            line;
  460.     char *            outline;
  461.     fd_set            rdfds;
  462.     fd_set            wrfds;
  463.     fd_set            exfds;
  464.     struct timeval    delay;
  465.     char                 in[100];
  466.     char                 out[500];
  467.     
  468.     if (sock == -1)    {
  469.         printf("# socket is not open\n");
  470.         Where();
  471.             
  472.         return;
  473.     }
  474.  
  475.     printf("# Entering Poor Man's Telnet mode\n");
  476.     
  477.     for (;;) {
  478.         if (ReadWhileUCan())
  479.             break;
  480.         
  481.         Prompt();
  482.         
  483.         if (!gets(in))
  484.             break;
  485.             
  486.         ++inputline;
  487.         
  488.         if (!strcmp(in, ".\n"))
  489.             break;
  490.         
  491.         if (!strcmp(in, "?\n"))
  492.             continue;
  493.  
  494.         len             = strlen(in);
  495.         in[len++]    = '\r';
  496.         in[len]        = 0;
  497.         
  498.         for (line = in; len; len -= part, line += part) {        
  499.             part = 0;
  500.  
  501.             FD_ZERO(&rdfds);
  502.             FD_ZERO(&wrfds);
  503.             FD_ZERO(&exfds);
  504.             
  505.             FD_SET(sock, &rdfds);
  506.             FD_SET(sock, &wrfds);
  507.             FD_SET(sock, &exfds);
  508.             
  509.             delay.tv_sec    =    10;
  510.             delay.tv_usec    =    0;
  511.             
  512.             res = select(sock+1, &rdfds, &wrfds, &exfds, &delay);
  513.             
  514.             if (res < 0)    {
  515.                 printf("# select() returned error %s\n", Explain());
  516.                 
  517.                 return;
  518.             } else if (!res) {
  519.                 printf("# select() timed out\n");
  520.                 
  521.                 return;
  522.             } else if (FD_ISSET(sock, &exfds)) {
  523.                 printf("# select() returned an exception\n");
  524.                 
  525.                 return;
  526.             }
  527.             
  528.             if (FD_ISSET(sock, &rdfds)) {
  529.                 res = read(sock, out, 500);
  530.                 
  531.                 if (res < 0) {
  532.                     printf("# read() returned error %s\n", Explain());
  533.                 
  534.                     return;
  535.                 }
  536.                 
  537.                 out[res] = 0;
  538.                 
  539.                 for (outline = strtok(out, "\n\r"); outline; outline = strtok(0, "\n\r"))
  540.                     printf("%s\n", outline);
  541.             } else if (FD_ISSET(sock, &wrfds)) {
  542.                 res = write(sock, line, len);
  543.             
  544.                 if (res < 0) {
  545.                     line[strlen(line) - 2] = 0;
  546.                     printf("# write(\"%s\") returned error %s\n", line, Explain());
  547.                 
  548.                     return;
  549.                 }
  550.                 
  551.                 part = res;
  552.             }
  553.         }
  554.     }
  555.     
  556.     printf("# Leaving Poor Man's Telnet mode\n");
  557. }
  558.  
  559. void N2Addr(char ch1, char ch2, const char * cmd)
  560. {
  561.     struct in_addr        addr;
  562.     struct hostent *    ent;
  563.     
  564.     if (sscanf(cmd, "%s", addrstr) == 1)
  565.         if (ent = gethostbyname(addrstr)) {
  566.             memcpy(&addr, ent->h_addr, sizeof(struct in_addr));
  567.             printf("# gethostbyname(%s) returned %s\n", addrstr, inet_ntoa(addr));
  568.         } else
  569.             printf("# gethostbyname(%s) failed.\n", addrstr);
  570.     else
  571.         Usage(ch1, ch2);
  572. }
  573.  
  574. void A2Name(char ch1, char ch2, const char * cmd)
  575. {
  576.     struct in_addr        addr;
  577.     struct hostent *    ent;
  578.     
  579.     if (sscanf(cmd, "%s", addrstr) == 1) {
  580.         addr.s_addr = inet_addr(addrstr);
  581.         if (ent = gethostbyaddr((void *) &addr, 0, 0)) {
  582.             printf("# gethostbyaddr(%s) returned %s\n", addrstr, ent->h_name);
  583.         } else
  584.             printf("# gethostbyaddr(%s) failed.\n", addrstr);
  585.     } else
  586.         Usage(ch1, ch2);
  587. }
  588.  
  589. void PerfTest(char ch1, char ch2, const char * cmd)
  590. {
  591. }
  592.  
  593. void ServByName(char ch1, char ch2, const char * cmd)
  594. {
  595.     struct servent *    ent;
  596.     char                    proto[6];
  597.     
  598.     if (sscanf(cmd, "%s %s", addrstr, proto) == 2)
  599.         if (ent = getservbyname(addrstr, proto))
  600.             printf("# getservbyname(%s %s) returned %d\n", addrstr, proto, ent->s_port);
  601.         else
  602.             printf("# getservbyname(%s %s) failed.\n", addrstr, proto);
  603.     else if (sscanf(cmd, "%s", addrstr) == 1)
  604.         if (ent = getservbyname(addrstr, NULL))
  605.             printf("# getservbyname(%s) returned %d\n", addrstr, ent->s_port);
  606.         else
  607.             printf("# getservbyname(%s) failed.\n", addrstr);
  608.     else
  609.         Usage(ch1, ch2);
  610. }
  611.  
  612. void PrintServEnt(struct servent * ent, Boolean full)
  613. {
  614.     char    ** al;
  615.     
  616.     printf("%s", ent->s_name);
  617.     
  618.     if (full)
  619.          printf(" %d/%s", ent->s_port, ent->s_proto);
  620.         
  621.     for (al = ent->s_aliases; *al; ++al)
  622.         printf(" %s", *al);
  623.     
  624.     putchar('\n');
  625. }
  626.  
  627. void ServByPort(char ch1, char ch2, const char * cmd)
  628. {
  629. }
  630.  
  631. void ServList(char _1, char _2, const char *_3)
  632. {
  633. }
  634.  
  635. test(void)
  636. {
  637.     char *argv[] = {"test", 0};
  638.  
  639.     printf("GUSIINETTest        MN 25Aug93\n\n");
  640.  
  641.     COMMAND('s', 's', Socket,  "",                 "Create a stream socket");
  642.     COMMAND('d', 's', Socket,  "",                 "Create a datagram socket");
  643.     COMMAND('b', 'd', Bind,      "addr port",     "Bind to address");
  644.     COMMAND('c', 'o', Connect, "addr port",     "Connect to address");
  645.     COMMAND('a', 'c', Accept,  "",                 "Accept a connection");
  646.     COMMAND('t', 'n', Telnet,  "",                "Play telnet");
  647.     COMMAND('n', 'a', N2Addr,    "name",            "Convert name to address");
  648.     COMMAND('a', 'n', A2Name,    "addr",            "Convert address to name");
  649.     COMMAND('p', 't', PerfTest,"count",            "Do a performance test");
  650.     COMMAND('s', 'n', ServByName, "name",        "Convert service name to port number");
  651.     COMMAND('s', 'p', ServByPort, "port",        "Convert port number to service name");
  652.     COMMAND('s', 'l', ServList, "",                "List services");
  653.     
  654.     RunTest(1, argv);
  655. }
  656.