inndchannel.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:16k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. #include "innbbsconf.h"
  2. #include "daemon.h"
  3. #include "bbslib.h"
  4. #include "version.h"
  5. #ifndef MAXCLIENT
  6. #define MAXCLIENT 10
  7. #endif
  8. #ifndef ChannelSize
  9. #define ChannelSize 4096
  10. #endif
  11. #ifndef ReadSize
  12. #define ReadSize 1024
  13. #endif
  14. #ifndef DefaultINNBBSPort
  15. #define DefaultINNBBSPort "7777"
  16. #endif
  17. #ifndef HIS_MAINT
  18. #define HIS_MAINT
  19. #define HIS_MAINT_HOUR 5
  20. #define HIS_MAINT_MIN  30
  21. #endif
  22. int     Maxclient = MAXCLIENT;
  23. ClientType *Channel = NULL;
  24. ClientType INNBBSD_STAT;
  25. int     Max_Art_Size = MAX_ART_SIZE;
  26. int     inetdstart = 0;
  27. int     Junkhistory = 0;
  28. char   *REMOTEUSERNAME, *REMOTEHOSTNAME;
  29. static fd_set rfd, wfd, efd, orfd, owfd, oefd;
  30. clearfdset(fd)
  31. int     fd;
  32. {
  33. FD_CLR(fd, &rfd);
  34. }
  35. static
  36. channelcreate(client)
  37. ClientType *client;
  38. {
  39. buffer_t *in, *out;
  40. in = &client->in;
  41. out = &client->out;
  42. if (in->data != NULL)
  43. free(in->data);
  44. in->data = (char *) mymalloc(ChannelSize);
  45. in->left = ChannelSize;
  46. in->used = 0;
  47. if (out->data != NULL)
  48. free(out->data);
  49. out->data = (char *) mymalloc(ChannelSize);
  50. out->used = 0;
  51. out->left = ChannelSize;
  52. client->ihavecount = 0;
  53. client->ihaveduplicate = 0;
  54. client->ihavefail = 0;
  55. client->ihavesize = 0;
  56. client->statcount = 0;
  57. client->statfail = 0;
  58. client->begin = time(NULL);
  59. client->filter_buffer = NULL;
  60. }
  61. channeldestroy(client)
  62. ClientType *client;
  63. {
  64. if (client->in.data != NULL) {
  65. free(client->in.data);
  66. client->in.data = NULL;
  67. }
  68. if (client->out.data != NULL) {
  69. free(client->out.data);
  70. client->out.data = NULL;
  71. }
  72. if (client->filter_buffer != NULL) {
  73. free(client->filter_buffer);
  74. client->filter_buffer = NULL;
  75. }
  76. #if !defined(PowerBBS) && !defined(DBZSERVER)
  77. if (client->ihavecount > 0 || client->statcount > 0) {
  78. bbslog("%s@%s rec: %d dup: %d fail: %d size: %d, stat rec: %d fail: %d, time sec: %dn",
  79. client->username, client->hostname, client->ihavecount,
  80. client->ihaveduplicate, client->ihavefail, client->ihavesize,
  81. client->statcount, client->statfail, time(NULL) - client->begin);
  82. INNBBSD_STAT.ihavecount += client->ihavecount;
  83. INNBBSD_STAT.ihaveduplicate += client->ihaveduplicate;
  84. INNBBSD_STAT.ihavefail += client->ihavefail;
  85. INNBBSD_STAT.ihavesize += client->ihavesize;
  86. INNBBSD_STAT.statcount += client->statcount;
  87. INNBBSD_STAT.statfail += client->statfail;
  88. }
  89. #endif
  90. }
  91. inndchannel(port, path)
  92. char   *port, *path;
  93. {
  94. time_t  tvec;
  95. int     i;
  96. int     bbsinnd;
  97. int     localbbsinnd;
  98. char    obuf[4096];
  99. struct timeval tout;
  100. ClientType *client = (ClientType *) mymalloc(sizeof(ClientType) * Maxclient);
  101. int     localdaemonready = 0;
  102. Channel = client;
  103. bbsinnd = pmain(port);
  104. if (bbsinnd < 0) {
  105. perror("pmain, existing");
  106. docompletehalt();
  107. return (-1);
  108. }
  109. FD_ZERO(&rfd);
  110. FD_ZERO(&wfd);
  111. FD_ZERO(&efd);
  112. localbbsinnd = p_unix_main(path);
  113. if (localbbsinnd < 0) {
  114. perror("local pmain, existing");
  115. if (!inetdstart)
  116. fprintf(stderr, "if no other innbbsd running, try to remove %sn", path);
  117. close(bbsinnd);
  118. return (-1);
  119. } else {
  120. FD_SET(localbbsinnd, &rfd);
  121. localdaemonready = 1;
  122. }
  123. FD_SET(bbsinnd, &rfd);
  124. tvec = time((time_t *) 0);
  125. for (i = 0; i < Maxclient; ++i) {
  126. client[i].fd = -1;
  127. client[i].access = 0;
  128. client[i].buffer[0] = '';
  129. client[i].mode = 0;
  130. client[i].in.left = 0;
  131. client[i].in.used = 0;
  132. client[i].in.data = NULL;
  133. client[i].out.left = 0;
  134. client[i].out.used = 0;
  135. client[i].out.data = NULL;
  136. client[i].midcheck = 1;
  137. }
  138. for (;;) {
  139. int     nsel, i;
  140. /*
  141.           When to maintain history files.
  142. */
  143. time_t  now;
  144. static int maint = 0;
  145. struct tm *local;
  146. if (INNBBSDshutdown()) {
  147. HISclose();
  148. bbslog(" Shutdown Complete n");
  149. docompletehalt();
  150. exit(0);
  151. }
  152. time(&now);
  153. local = localtime(&now);
  154. if (local != NULL & local->tm_hour == His_Maint_Hour &&
  155. local->tm_min >= His_Maint_Min) {
  156. if (!maint) {
  157. bbslog(":Maint: start (%d:%d).n", local->tm_hour, local->tm_min);
  158. HISmaint();
  159. time(&now);
  160. local = localtime(&now);
  161. if (local != NULL)
  162. bbslog(":Maint: end (%d:%d).n", local->tm_hour, local->tm_min);
  163. maint = 1;
  164. }
  165. } else {
  166. maint = 0;
  167. }
  168. /*
  169. */
  170. /*
  171. in order to maintain history, timeout every 60 seconds in case
  172. no connections
  173. */
  174. tout.tv_sec = 60;
  175. tout.tv_usec = 0;
  176. orfd = rfd;
  177. if ((nsel = select(FD_SETSIZE, &orfd, NULL, NULL, &tout)) < 0) {
  178. continue;
  179. }
  180. if (localdaemonready && FD_ISSET(localbbsinnd, &orfd)) {
  181. int     ns, length;
  182. int     cc;
  183. ns = tryaccept(localbbsinnd);
  184. if (ns < 0)
  185. continue;
  186. for (i = 0; i < Maxclient; ++i) {
  187. if (client[i].fd == -1)
  188. break;
  189. }
  190. if (i == Maxclient) {
  191. static char msg[] = "502 no free descriptorsrn";
  192. printf("%s", msg);
  193. write(ns, msg, sizeof(msg));
  194. close(ns);
  195. continue;
  196. }
  197. client[i].fd = ns;
  198. client[i].buffer[0] = '';
  199. client[i].mode = 0;
  200. client[i].midcheck = 1;
  201. channelcreate(&client[i]);
  202. FD_SET(ns, &rfd); /* FD_SET(ns,&wfd); */
  203. {
  204. strncpy(client[i].username, "localuser", 20);
  205. strncpy(client[i].hostname, "localhost", 128);
  206. client[i].Argv.in = fdopen(ns, "r");
  207. client[i].Argv.out = fdopen(ns, "w");
  208. #if !defined(PowerBBS) && !defined(DBZSERVER)
  209. bbslog("connected from (%s@%s).n", client[i].username, client[i].hostname);
  210. #endif
  211. #ifdef INNBBSDEBUG
  212. printf("connected from (%s@%s).n", client[i].username, client[i].hostname);
  213. #endif
  214. #ifdef DBZSERVER
  215. fprintf(client[i].Argv.out, "200 %s InterNetNews DBZSERVER server %s (%s@%s).rn", MYBBSID, VERSION, client[i].username, client[i].hostname);
  216. #else
  217. fprintf(client[i].Argv.out, "200 %s InterNetNews INNBBSD server %s (%s@%s).rn", MYBBSID, VERSION, client[i].username, client[i].hostname);
  218. #endif
  219. fflush(client[i].Argv.out);
  220. verboselog("UNIX Connect from %s@%sn", client[i].username, client[i].hostname);
  221. }
  222. }
  223. if (FD_ISSET(bbsinnd, &orfd)) {
  224. int     ns = tryaccept(bbsinnd), length;
  225. struct sockaddr_in there;
  226. char   *name;
  227. struct hostent *hp;
  228. int     cc;
  229. if (ns < 0)
  230. continue;
  231. for (i = 0; i < Maxclient; ++i) {
  232. if (client[i].fd == -1)
  233. break;
  234. }
  235. if (i == Maxclient) {
  236. static char msg[] = "502 no free descriptorsrn";
  237. printf("%s", msg);
  238. write(ns, msg, sizeof(msg));
  239. close(ns);
  240. continue;
  241. }
  242. client[i].fd = ns;
  243. client[i].buffer[0] = '';
  244. client[i].mode = 0;
  245. client[i].midcheck = 1;
  246. channelcreate(&client[i]);
  247. FD_SET(ns, &rfd); /* FD_SET(ns,&wfd); */
  248. length = sizeof(there);
  249. if (getpeername(ns, (struct sockaddr *) & there, &length) >= 0) {
  250. time_t  now = time((time_t *) 0);
  251. name = (char *) my_rfc931_name(ns, &there);
  252. strncpy(client[i].username, name, 20);
  253. hp = (struct hostent *) gethostbyaddr((char *) &there.sin_addr, sizeof(struct in_addr), there.sin_family);
  254. if (hp)
  255. strncpy(client[i].hostname, hp->h_name, 128);
  256. else
  257. strncpy(client[i].hostname, (char *) inet_ntoa(there.sin_addr), 128);
  258. client[i].Argv.in = fdopen(ns, "r");
  259. client[i].Argv.out = fdopen(ns, "w");
  260. if ((char *) search_nodelist(client[i].hostname, client[i].username) == NULL) {
  261. bbslog(":Err: invalid connection (%s@%s).n", client[i].username, client[i].hostname);
  262. fprintf(client[i].Argv.out, "502 You are not in my access file. (%s@%s)rn", client[i].username, client[i].hostname);
  263. fflush(client[i].Argv.out);
  264. fclose(client[i].Argv.in);
  265. fclose(client[i].Argv.out);
  266. close(client[i].fd);
  267. FD_CLR(client[i].fd, &rfd);
  268. client[i].fd = -1;
  269. continue;
  270. }
  271. bbslog("connected from (%s@%s).n", client[i].username, client[i].hostname);
  272. if (isPause()) {
  273. fprintf(client[i].Argv.out, "400 Server Paused. (%s@%s)rn", client[i].username, client[i].hostname);
  274. fflush(client[i].Argv.out);
  275. fclose(client[i].Argv.in);
  276. fclose(client[i].Argv.out);
  277. close(client[i].fd);
  278. FD_CLR(client[i].fd, &rfd);
  279. client[i].fd = -1;
  280. continue;
  281. }
  282. #ifdef INNBBSDEBUG
  283. printf("connected from (%s@%s).n", client[i].username, client[i].hostname);
  284. #endif
  285. #ifdef DBZSERVER
  286. fprintf(client[i].Argv.out, "200 %s InterNetNews DBZSERVER server %s (%s@%s).rn", MYBBSID, VERSION, client[i].username, client[i].hostname);
  287. #else
  288. fprintf(client[i].Argv.out, "200 %s InterNetNews INNBBSD server %s (%s@%s).rn", MYBBSID, VERSION, client[i].username, client[i].hostname);
  289. #endif
  290. fflush(client[i].Argv.out);
  291. verboselog("INET Connect from %s@%sn", client[i].username, client[i].hostname);
  292. } else {
  293. }
  294. }
  295. for (i = 0; i < Maxclient; ++i) {
  296. int     fd = client[i].fd;
  297. if (fd < 0) {
  298. continue;
  299. }
  300. if (FD_ISSET(fd, &orfd)) {
  301. int     nr;
  302. #ifdef DEBUG
  303. printf("before read i %d in.used %d in.left %dn", i, client[i].in.used, client[i].in.left);
  304. #endif
  305. nr = channelreader(client + i);
  306. #ifdef DEBUG
  307. printf("after read i %d in.used %d in.left %dn", i, client[i].in.used, client[i].in.left);
  308. #endif
  309. /* int nr=read(fd,client[i].buffer,1024); */
  310. if (nr <= 0) {
  311. FD_CLR(fd, &rfd);
  312. fclose(client[i].Argv.in);
  313. fclose(client[i].Argv.out);
  314. close(fd);
  315. client[i].fd = -1;
  316. channeldestroy(client + i);
  317. continue;
  318. }
  319. #ifdef DEBUG
  320. printf("nr %d %.*s", nr, nr, client[i].buffer);
  321. #endif
  322. if (client[i].access == 0) {
  323. continue;
  324. }
  325. }
  326. }
  327. }
  328. }
  329. int 
  330. channelreader(client)
  331. ClientType *client;
  332. {
  333. int     len, clientlen;
  334. char    buffer1[8192], buffer2[4096];
  335. char   *ptr;
  336. buffer_t *in = &client->in;
  337. if (in->left < ReadSize + 3) {
  338. int     need = in->used + in->left + ReadSize + 3;
  339. need += need / 5;
  340. in->data = (char *) myrealloc(in->data, need);
  341. in->left = need - in->used;
  342. verboselog("channelreader realloc %dn", need);
  343. }
  344. len = read(client->fd, in->data + in->used, ReadSize);
  345. if (len <= 0)
  346. return len;
  347. in->data[len + in->used] = '';
  348. in->lastread = len;
  349. #ifdef DEBUG
  350. printf("after read lastread %dn", in->lastread);
  351. printf("len %d client %dn", len, strlen(in->data + in->used));
  352. #endif
  353. REMOTEHOSTNAME = client->hostname;
  354. REMOTEUSERNAME = client->username;
  355. if (client->mode == 0) {
  356. if ((ptr = (char *) strchr(in->data, 'n')) != NULL) {
  357. if (in->data[0] != 'r')
  358. commandparse(client);
  359. }
  360. } else {
  361. commandparse(client);
  362. }
  363. return len;
  364. }
  365. commandparse(client)
  366. ClientType *client;
  367. {
  368. char   *ptr, *lastend;
  369. argv_t *Argv = &client->Argv;
  370. int     (*Main) ();
  371. char   *buffer = client->in.data;
  372. int     fd = client->fd;
  373. buffer_t *in = &client->in;
  374. int     dataused;
  375. int     dataleft;
  376. #ifdef DEBUG
  377. printf("%s %s buffer %s", client->username, client->hostname, buffer);
  378. #endif
  379. ptr = (char *) strchr(in->data + in->used, 'n');
  380. if (client->mode == 0) {
  381. if (ptr == NULL) {
  382. in->used += in->lastread;
  383. in->left -= in->lastread;
  384. return;
  385. } else {
  386. dataused = ptr - (in->data + in->used) + 1;
  387. dataleft = in->lastread - dataused;
  388. lastend = ptr + 1;
  389. }
  390. } else {
  391. if (in->used >= 5) {
  392. ptr = (char *) strstr(in->data + in->used - 5, "rn.rn");
  393. } else if (strncmp(in->data, ".rn", 3) == 0) {
  394. ptr = in->data;
  395. } else {
  396. ptr = (char *) strstr(in->data + in->used, "rn.rn");
  397. }
  398. if (ptr == NULL) {
  399. in->used += in->lastread;
  400. in->left -= in->lastread;
  401. return;
  402. } else {
  403. ptr[2] = '';
  404. if (strncmp(in->data, ".rn", 3) == 0)
  405. dataused = 3;
  406. else
  407. dataused = ptr - (in->data + in->used) + 5;
  408. dataleft = in->lastread - dataused;
  409. lastend = ptr + 5;
  410. verboselog("Get: %s@%s end of data . size %dn", client->username, client->hostname, in->used + dataused);
  411. client->ihavesize += in->used + dataused;
  412. }
  413. }
  414. if (client->mode == 0) {
  415. struct Daemoncmd *dp;
  416. Argv->argc = 0, Argv->argv = NULL,
  417. Argv->inputline = buffer;
  418. if (ptr != NULL)
  419. *ptr = '';
  420. verboselog("Get: %sn", Argv->inputline);
  421. Argv->argc = argify(in->data + in->used, &Argv->argv);
  422. if (ptr != NULL)
  423. *ptr = 'n';
  424. dp = (struct Daemoncmd *) searchcmd(Argv->argv[0]);
  425. Argv->dc = dp;
  426. if (Argv->dc) {
  427. #ifdef DEBUG
  428. printf("enter command %sn", Argv->argv[0]);
  429. #endif
  430. if (Argv->argc < dp->argc) {
  431. fprintf(Argv->out, "%d Usage: %srn", dp->errorcode, dp->usage);
  432. fflush(Argv->out);
  433. verboselog("Put: %d Usage: %sn", dp->errorcode, dp->usage);
  434. } else if (dp->argno != 0 && Argv->argc > dp->argno) {
  435. fprintf(Argv->out, "%d Usage: %srn", dp->errorcode, dp->usage);
  436. fflush(Argv->out);
  437. verboselog("Put: %d Usage: %sn", dp->errorcode, dp->usage);
  438. } else {
  439. Main = Argv->dc->main;
  440. if (Main) {
  441. fflush(stdout);
  442. (*Main) (client);
  443. }
  444. }
  445. } else {
  446. fprintf(Argv->out, "500 Syntax error or bad commandrn");
  447. fflush(Argv->out);
  448. verboselog("Put: 500 Syntax error or bad commandrn");
  449. }
  450. deargify(&Argv->argv);
  451. } else {
  452. if (Argv->dc) {
  453. #ifdef DEBUG
  454. printf("enter data moden");
  455. #endif
  456. Main = Argv->dc->main;
  457. if (Main) {
  458. fflush(stdout);
  459. (*Main) (client);
  460. }
  461. }
  462. }
  463. if (client->mode == 0) {
  464. if (dataleft > 0) {
  465. strncpy(in->data, lastend, dataleft);
  466. #ifdef INNBBSDEBUG
  467. printf("***** try to copy %x %x %d bytesn", in->data, lastend, dataleft);
  468. #endif
  469. } else {
  470. dataleft = 0;
  471. }
  472. in->left += in->used - dataleft;
  473. in->used = dataleft;
  474. }
  475. }
  476. do_command()
  477. {
  478. }
  479. void 
  480. dopipesig(s)
  481. int     s;
  482. {
  483. printf("catch sigpipen");
  484. signal(SIGPIPE, dopipesig);
  485. }
  486. int 
  487. standaloneinit(port)
  488. char   *port;
  489. {
  490. int     ndescriptors;
  491. FILE   *pf;
  492. char    pidfile[24];
  493. ndescriptors = getdtablesize();
  494. /*#ifndef NOFORK*/
  495. if (!inetdstart)
  496. if (fork())
  497. exit(0);
  498. /*#endif*/
  499. sprintf(pidfile, "/usr/tmp/innbbsd-%s.pid", port);
  500. if (!inetdstart)
  501. fprintf(stderr, "PID file is in %sn", pidfile);
  502. {
  503. int     s;
  504. for (s = 3; s < ndescriptors; s++)
  505. (void) close(s);
  506. }
  507. pf = fopen(pidfile, "w");
  508. if (pf != NULL) {
  509. fprintf(pf, "%dn", getpid());
  510. fclose(pf);
  511. }
  512. }
  513. extern char *optarg;
  514. extern int opterr, optind;
  515. innbbsusage(name)
  516. char   *name;
  517. {
  518. fprintf(stderr, "Usage: %s   [options] [port [path]]n", name);
  519. fprintf(stderr, "   -v   (verbose log)n");
  520. fprintf(stderr, "   -h|? (help)n");
  521. fprintf(stderr, "   -n   (not to use in core dbz)n");
  522. fprintf(stderr, "   -i   (start from inetd with wait option)n");
  523. fprintf(stderr, "   -c   connections  (maximum number of connections accepted)n");
  524. fprintf(stderr, "        default=%dn", Maxclient);
  525. fprintf(stderr, "   -j   (keep history of junk article, default=none)n");
  526. }
  527. #ifdef DEBUGNGSPLIT
  528. main()
  529. {
  530. char  **ngptr;
  531. char    buf[1024];
  532. gets(buf);
  533. ngptr = (char **) BNGsplit(buf);
  534. printf("line %sn", buf);
  535. while (*ngptr != NULL) {
  536. printf("%sn", *ngptr);
  537. ngptr++;
  538. }
  539. }
  540. #endif
  541. static time_t INNBBSDstartup;
  542. innbbsdstartup()
  543. {
  544. return INNBBSDstartup;
  545. }
  546. main(argc, argv)
  547. int     argc;
  548. char  **argv;
  549. {
  550. char   *port, *path;
  551. int     c, errflag = 0;
  552. extern  INNBBSDhalt();
  553. #if !defined(DBZSERVER)
  554. initial_lang();
  555. #endif
  556. port = DefaultINNBBSPort;
  557. path = LOCALDAEMON;
  558. Junkhistory = 0;
  559. time(&INNBBSDstartup);
  560. openlog("innbbsd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
  561. while ((c = getopt(argc, argv, "c:f:s:vhidn?j")) != -1)
  562. switch (c) {
  563. case 'j':
  564. Junkhistory = 1;
  565. break;
  566. case 'v':
  567. verboseon("innbbsd.log");
  568. break;
  569. case 'n':
  570. hisincore(0);
  571. break;
  572. case 'c':
  573. Maxclient = atoi(optarg);
  574. if (Maxclient < 0)
  575. Maxclient = 0;
  576. break;
  577. case 'i':{
  578. struct sockaddr_in there;
  579. int     len = sizeof(there);
  580. int     rel;
  581. if ((rel = getsockname(0, (struct sockaddr *) & there, &len)) < 0) {
  582. fprintf(stdout, "You must run -i from inetd with inetd.conf line: n");
  583. fprintf(stdout, "service-port stream  tcp wait  bbs  /home/bbs/innbbsd innbbsd -i portn");
  584. fflush(stdout);
  585. exit(5);
  586. }
  587. inetdstart = 1;
  588. startfrominetd(1);
  589. }
  590. break;
  591. case 'd':
  592. dbzdebug(1);
  593. break;
  594. case 's':
  595. Max_Art_Size = atol(optarg);
  596. if (Max_Art_Size < 0)
  597. Max_Art_Size = 0;
  598. break;
  599. case 'h':
  600. case '?':
  601. default:
  602. errflag++;
  603. }
  604. if (errflag > 0) {
  605. innbbsusage(argv[0]);
  606. return (1);
  607. }
  608. if (argc - optind >= 1) {
  609. port = argv[optind];
  610. }
  611. if (argc - optind >= 2) {
  612. path = argv[optind + 1];
  613. }
  614. standaloneinit(port);
  615. initial_bbs("feed");
  616. if (!inetdstart)
  617. fprintf(stderr, "Try to listen in port %s and path %sn", port, path);
  618. HISmaint();
  619. HISsetup();
  620. installinnbbsd();
  621. sethaltfunction(INNBBSDhalt);
  622. signal(SIGPIPE, dopipesig);
  623. inndchannel(port, path);
  624. HISclose();
  625. }