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