|
|
1 /* 2 * Example NetBIOS server 3 */4 #include <stdio.h> 5 #include <signal.h> 6 #include <stropts.h> 7 #include <xti.h> 8 #include <fcntl.h> 9 #include <sys/nb/nbtpi.h>
10 #define SRV_NAME "NB-XTI-DEMO-SERV" 11 #define RFCNBPATH "/dev/nbcots" 12 #define NBEPATH "/dev/netbeui" 13 #define DISCONNECT -1
14 extern int t_errno; 15 void run_server(int); 16 int conn_fd; 17 char *netpath = RFCNBPATH;
18 main(int argc, char *argv[]) 19 { 20 int listen_fd; 21 struct t_bind *bind; 22 struct t_call *call; 23 struct nbaddr srv_addr; 24 struct nbaddr client_addr;
25 /* ensure child processes do not become zombies */
26 signal(SIGCHLD, SIG_IGN);
27 if ((listen_fd = 28 t_open(netpath, O_RDWR, (struct t_info *) NULL)) < 0) { 29 t_error("t_open failed for listen_fd"); 30 exit(1); 31 }
32 if ((bind = (struct t_bind *)t_alloc(listen_fd, T_BIND, T_ADDR)) 33 == NULL) { 34 t_error("t_alloc of t_bind structure failed"); 35 exit(2); 36 }
37 bind->qlen = 5; 38 bind->addr.len = sizeof(srv_addr); 39 bind->addr.buf = (char *)&srv_addr;
40 srv_addr.nb_type = NB_UNIQUE; 41 memcpy(srv_addr.nb_name, SRV_NAME, NB_NAMELEN);
42 if (t_bind(listen_fd, bind, bind) < 0) { 43 t_error("t_bind failed for listen_fd"); 44 exit(3); 45 }
46 if (memcmp(srv_addr.nb_name, SRV_NAME, NB_NAMELEN) != 0) { 47 fprintf(stderr, "t_bind bound wrong address\n"); 48 exit(4); 49 }
50 if ((call = (struct t_call *)t_alloc(listen_fd, T_CALL, T_ADDR)) 51 == NULL) { 52 t_error("t_alloc failed"); 53 exit(5); 54 } 55 call->addr.len = sizeof(srv_addr); 56 call->addr.buf = (char *)&client_addr;
57 while (1) { 58 if (t_listen(listen_fd, call) < 0) { 59 t_error("t_listen failed for listen_fd"); 60 exit(6); 61 } 62 if ((conn_fd = accept_call(listen_fd, call)) != DISCONNECT) 63 run_server(listen_fd); 64 } 65 }
66 int 67 accept_call(int listen_fd, struct t_call *call) 68 { 69 int resfd;
70 if ((resfd = t_open(netpath, O_RDWR, (struct t_info *) NULL)) 71 < 0) { 72 t_error("t_open for responding fd failed"); 73 exit(7); 74 }
75 if (t_bind(resfd, (struct t_bind *) NULL, 76 (struct t_bind *) NULL) < 0) { 77 t_error("t_bind for responding fd failed"); 78 exit(8); 79 }
80 if (t_accept(listen_fd, resfd, call) < 0) { 81 if (t_errno == TLOOK) { 82 if (t_rcvdis(listen_fd, (struct t_discon *) NULL) < 0) { 83 t_error("t_rcvdis failed for listen_fd"); 84 exit(9); 85 } 86 if (t_close(resfd) < 0) { 87 t_error("t_close failed for responding fd"); 88 exit(10); 89 } 90 return(DISCONNECT); 91 } 92 t_error("t_accept failed"); 93 exit(11); 94 }
95 return(resfd); 96 }
97 connrelease() 98 { 99 exit(0); 100 }
101 void 102 run_server(int listen_fd) 103 { 104 int nbytes; 105 FILE *logfp;
106 struct { 107 unsigned short length; 108 char buf[1024]; 109 } msg;
110 switch (fork()) {
111 case -1: 112 perror("fork failed"); 113 exit(12);
114 default: /* parent */ 115 /* close conn_fd and go up to listen again */ 116 if (t_close(conn_fd) < 0) { 117 t_error("t_close failed for conn_fd"); 118 exit(13); 119 } 120 return;
121 case 0: /* child */ 122 /* close listen_fd and do service */ 123 if (t_close(listen_fd) < 0) { 124 t_error("t_close failed for listen_fd"); 125 exit(14); 126 } 127 if ((logfp = fopen("logfile", "r")) == NULL) { 128 perror("cannot open logfile"); 129 exit(15); 130 }
131 signal(SIGPOLL, connrelease);
132 if (ioctl(conn_fd, I_SETSIG, S_INPUT) < 0) { 133 perror("ioctl I_SETSIG failed"); 134 exit(16); 135 }
136 if (t_look(conn_fd) != 0) { 137 fprintf(stderr, "t_look returned unexpected event"); 138 exit(17); 139 }
140 while ((nbytes = fread(msg.buf, 1, 1024, logfp)) > 0) { 141 msg.length = nbytes; 142 if (t_snd(conn_fd, &msg, nbytes + 143 sizeof(msg.length), 0) < 0) { 144 t_error("t_snd failed"); 145 exit(18); 146 } 147 }
148 msg.length = 0;
149 if (t_snd(conn_fd, &msg, 2, 0) < 0) { 150 t_error("can't send 0 bytes"); 151 exit(19); 152 }
153 pause(); /* until disconnect indication arrives */ 154 } 155 }
addr.buf
to the
NetBIOS name structure.
->qlen
the
actual value of the connection request queue length it can support,
if that is less than the requested value.
->add.buf
will point to the name of the
client trying to connect to the server. This value will be
filled in by the call to t_listen on line 58.
An alternative is to call t_look after line 81 to determine precisely what asynchronous event has occurred. The server can then respond appropriately. See the manual page for t_look for a description of the asynchronous events returned by this function.