ead5ddc5628709b7dbf43150f580f99cd07118d4
[citadel.git] / citadel / citserver.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <fcntl.h>
5 #include <signal.h>
6 #include <time.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <pthread.h>
11 #include <syslog.h>
12 #include "citadel.h"
13 #include "server.h"
14 #include "proto.h"
15
16 struct config config;
17
18 struct CitContext *ContextList = NULL;
19 int ScheduledShutdown = 0;
20
21         
22 /*
23  * Various things that need to be initialized at startup
24  */
25 void master_startup() {
26         lprintf(7, "Opening databases\n");
27         open_databases();
28
29         lprintf(7, "Checking floor reference counts\n");
30         check_ref_counts();
31         }
32
33 /*
34  * Cleanup routine to be called when the server is shutting down.
35  */
36 void master_cleanup() {
37
38         /* Cancel all running sessions */
39         lprintf(7, "Cancelling running sessions...\n");
40         while (ContextList != NULL) {
41                 kill_session(ContextList->cs_pid);
42                 }
43
44         /* Close databases */
45         lprintf(7, "Closing databases\n");
46         close_databases();
47
48         /* Do system-dependent stuff */
49         sysdep_master_cleanup();
50
51         /* Now go away. */
52         hook_cleanup();
53         lprintf(3, "citserver: exiting.\n");
54         exit(0);
55         }
56
57
58 /*
59  * Gracefully terminate the session and thread.
60  * (This is called as a cleanup handler by the thread library.)
61  */
62 void cleanup_stuff()
63 {
64         struct ExpressMessage *emptr;
65
66         lprintf(9, "cleanup_stuff() called\n");
67
68         lprintf(7, "Calling logout(%d)\n", CC->cs_pid);
69         logout(CC);
70
71         rec_log(CL_TERMINATE,CC->curr_user);
72         unlink(CC->temp);
73         lprintf(3, "citserver[%3d]: ended.\n",CC->cs_pid);
74         hook_end_session(CC->cs_pid);
75         syslog(LOG_NOTICE,"session %d ended", CC->cs_pid);
76         
77         /* Deallocate any unsent express messages */
78         begin_critical_section(S_SESSION_TABLE);
79         while (CC->FirstExpressMessage != NULL) {
80                 emptr = CC->FirstExpressMessage;
81                 CC->FirstExpressMessage = CC->FirstExpressMessage->next;
82                 free(emptr);
83                 }
84         end_critical_section(S_SESSION_TABLE);
85
86         /* Now get rid of the session and context */
87         lprintf(7, "cleanup_stuff() is calling RemoveContext(%d)\n", CC->cs_pid);
88         RemoveContext(CC);
89
90         /* While we still have an extra thread with no user attached to it,
91          * take the opportunity to do some housekeeping before exiting.
92          */
93         do_housekeeping();
94         }
95
96
97 /*
98  * set_wtmpsupp()  -  alter the session listing
99  */
100 void set_wtmpsupp(char *newtext)
101 {
102         strncpy(CC->cs_room,newtext,19);
103         CC->cs_room[19] = 0;
104         time(&CC->cs_lastupdt);
105         hook_room_name(CC->cs_pid, CC->cs_room);
106         }
107
108
109 /*
110  * cmd_info()  -  tell the client about this server
111  */
112 void cmd_info(void) {
113         cprintf("%d Server info:\n",LISTING_FOLLOWS);
114         cprintf("%d\n",CC->cs_pid);
115         cprintf("%s\n",config.c_nodename);
116         cprintf("%s\n",config.c_humannode);
117         cprintf("%s\n",config.c_fqdn);
118         cprintf("%s\n",CITADEL);
119         cprintf("%d\n",REV_LEVEL);
120         cprintf("%s\n",config.c_bbs_city);
121         cprintf("%s\n",config.c_sysadm);
122         cprintf("%d\n",SERVER_TYPE);
123         cprintf("%s\n",config.c_moreprompt);
124         cprintf("1\n"); /* 1 = yes, this system supports floors */
125         cprintf("000\n");
126         }
127
128 void cmd_rchg(char *newroomname)
129 {
130    if ((newroomname) && (newroomname[0]))
131    {
132       bzero(CC->fake_roomname, 20);
133       strncpy(CC->fake_roomname, newroomname, 19);
134    }
135    else
136       CC->fake_roomname[0] = '\0';
137    cprintf("%d\n",OK);
138 }
139
140 void cmd_hchg(char *newhostname)
141 {
142    if ((newhostname) && (newhostname[0]))
143    {
144       bzero(CC->fake_hostname, 25);
145       strncpy(CC->fake_hostname, newhostname, 24);
146    }
147    else
148       CC->fake_hostname[0] = '\0';
149    cprintf("%d\n",OK);
150 }
151
152 void cmd_uchg(char *newusername)
153 {
154    if (CC->usersupp.axlevel < 6) 
155    {
156       cprintf("%d You must be an Aide to use UCHG.\n",
157                 ERROR+HIGHER_ACCESS_REQUIRED);
158       return;
159    }
160    if ((newusername) && (newusername[0]))
161    {
162       CC->cs_flags &= ~CS_STEALTH;
163       bzero(CC->fake_username, 32);
164       if (struncmp(newusername, CC->curr_user, strlen(CC->curr_user)))
165          strncpy(CC->fake_username, newusername, 31);
166    }
167    else
168    {
169       CC->fake_username[0] = '\0';
170       CC->cs_flags |= CS_STEALTH;
171    }
172    cprintf("%d\n",OK);
173 }
174
175 void cmd_time()
176 {
177    time_t tv;
178    
179    tv = time(NULL);
180    
181    cprintf("%d|%ld\n", OK, tv);
182 }
183
184 /*
185  * check a hostname against the public_clients file
186  */
187 int is_public_client(char *where)
188 {
189         char buf[256];
190         FILE *fp;
191
192         if (!strucmp(where,"localhost")) return(1);
193         if (!strucmp(where,config.c_fqdn)) return(1);
194
195         fp = fopen("public_clients","r");
196         if (fp == NULL) return(0);
197
198         while (fgets(buf,256,fp)!=NULL) {
199                 while (isspace((buf[strlen(buf)-1]))) 
200                         buf[strlen(buf)-1] = 0;
201                 if (!strucmp(buf,where)) {
202                         fclose(fp);
203                         return(1);
204                         }
205                 }
206
207         fclose(fp);
208         return(0);
209         }
210
211
212 /*
213  * the client is identifying itself to the server
214  */
215 void cmd_iden(char *argbuf)
216 {
217         int dev_code;
218         int cli_code;
219         int rev_level;
220         char desc[256];
221         char from_host[256];
222
223         if (num_parms(argbuf)<4) {
224                 cprintf("%d usage error\n",ERROR);
225                 return;
226                 }
227
228         dev_code = extract_int(argbuf,0);
229         cli_code = extract_int(argbuf,1);
230         rev_level = extract_int(argbuf,2);
231         extract(desc,argbuf,3);
232
233         strcpy(from_host,config.c_fqdn);
234         if (num_parms(argbuf)>=5) extract(from_host,argbuf,4);
235
236         CC->cs_clientdev = dev_code;
237         CC->cs_clienttyp = cli_code;
238         CC->cs_clientver = rev_level;
239         strncpy(CC->cs_clientname,desc,31);
240         CC->cs_clientname[31] = 0;
241
242         if ((strlen(from_host)>0) && 
243            (is_public_client(CC->cs_host))) {
244                 strncpy(CC->cs_host,from_host,24);
245                 CC->cs_host[24] = 0;
246                 }
247         set_wtmpsupp(CC->quickroom.QRname);
248
249         syslog(LOG_NOTICE,"client %d/%d/%01d.%02d (%s)\n",
250                 dev_code,
251                 cli_code,
252                 (rev_level / 100),
253                 (rev_level % 100),
254                 desc);
255                 cprintf("%d Ok\n",OK);
256         }
257
258
259 /*
260  * enter or exit "stealth mode"
261  */
262 void cmd_stel(char *cmdbuf)
263 {
264         int requested_mode;
265
266         requested_mode = extract_int(cmdbuf,0);
267         if (requested_mode !=0) requested_mode = 1;
268
269         if (!CC->logged_in) {
270                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
271                 return;
272                 }
273
274         if (CC->usersupp.axlevel < 6) {
275                 cprintf("%d You must be an Aide to use stealth mode.\n",
276                         ERROR+HIGHER_ACCESS_REQUIRED);
277                 return;
278                 }
279
280         if (CC->cs_flags & CS_STEALTH) {
281                 if (requested_mode == 0)
282                         CC->cs_flags = CC->cs_flags-CS_STEALTH;
283                 }
284         else {
285                 if (requested_mode == 1)
286                         CC->cs_flags = CC->cs_flags|CS_STEALTH;
287                 }
288
289         set_wtmpsupp(CC->quickroom.QRname);
290         cprintf("%d Ok\n",OK);
291         }
292
293
294
295
296 /*
297  * display system messages or help
298  */
299 void cmd_mesg(char *mname)
300 {
301         FILE *mfp;
302         char targ[256];
303         char buf[256];
304         char *dirs[2];
305
306         extract(buf,mname,0);
307
308
309         dirs[0]=malloc(64);
310         dirs[1]=malloc(64);
311         strcpy(dirs[0],"messages");
312         strcpy(dirs[1],"help");
313         mesg_locate(targ,buf,2,dirs);
314         free(dirs[0]);
315         free(dirs[1]);
316
317
318         if (strlen(targ)==0) {
319                 cprintf("%d '%s' not found.\n",ERROR,mname);
320                 return;
321                 }
322
323         mfp = fopen(targ,"r");
324         if (mfp==NULL) {
325                 cprintf("%d Cannot open '%s': %s\n",
326                         ERROR,targ,strerror(errno));
327                 return;
328                 }
329         cprintf("%d %s\n",LISTING_FOLLOWS,buf);
330
331         while (fgets(buf,255,mfp)!=NULL) {
332                 buf[strlen(buf)-1] = 0;
333                 do_help_subst(buf);
334                 cprintf("%s\n",buf);
335                 }
336
337         fclose(mfp);
338         cprintf("000\n");
339         }
340
341
342 /*
343  * enter system messages or help
344  */
345 void cmd_emsg(char *mname)
346 {
347         FILE *mfp;
348         char targ[256];
349         char buf[256];
350         char *dirs[2];
351         int a;
352
353         if (CC->usersupp.axlevel < 6) {
354                 cprintf("%d You must be an Aide to edit system messages.\n",
355                         ERROR+HIGHER_ACCESS_REQUIRED);
356                 return;
357                 }
358
359         extract(buf,mname,0);
360         for (a=0; a<strlen(buf); ++a) {         /* security measure */
361                 if (buf[a] == '/') buf[a] = '.';
362                 }
363
364         dirs[0]=malloc(64);
365         dirs[1]=malloc(64);
366         strcpy(dirs[0],"messages");
367         strcpy(dirs[1],"help");
368         mesg_locate(targ,buf,2,dirs);
369         free(dirs[0]);
370         free(dirs[1]);
371
372         if (strlen(targ)==0) {
373                 sprintf(targ, "./help/%s", buf);
374                 }
375
376         mfp = fopen(targ,"w");
377         if (mfp==NULL) {
378                 cprintf("%d Cannot open '%s': %s\n",
379                         ERROR,targ,strerror(errno));
380                 return;
381                 }
382         cprintf("%d %s\n", SEND_LISTING, targ);
383
384         while (client_gets(buf), strcmp(buf, "000")) {
385                 fprintf(mfp, "%s\n", buf);
386                 }
387
388         fclose(mfp);
389         }
390
391
392 /*
393  * who's online
394  */
395 void cmd_rwho(void) {
396         struct CitContext *cptr;
397         int spoofed = 0;
398         int aide;
399         char un[40], room[40], host[40], flags[5];
400         
401         aide = CC->usersupp.axlevel >= 6;
402         cprintf("%d\n",LISTING_FOLLOWS);
403         
404         for (cptr = ContextList; cptr != NULL; cptr = cptr->next) 
405         {
406                 flags[0] = '\0';
407                 spoofed = 0;
408                 
409                 if (cptr->cs_flags & CS_POSTING)
410                    strcat(flags, "*");
411                 else
412                    strcat(flags, ".");
413                    
414                 if (cptr->fake_username[0])
415                 {
416                    strcpy(un, cptr->fake_username);
417                    spoofed = 1;
418                 }
419                 else
420                    strcpy(un, cptr->curr_user);
421                    
422                 if (cptr->fake_hostname[0])
423                 {
424                    strcpy(host, cptr->fake_hostname);
425                    spoofed = 1;
426                 }
427                 else
428                    strcpy(host, cptr->cs_host);
429
430                 if (cptr->fake_roomname[0])
431                 {
432                    strcpy(room, cptr->fake_roomname);
433                    spoofed = 1;
434                 }
435                 else
436                    strcpy(room, cptr->cs_room);
437                    
438                 
439                 if ((aide) && (spoofed))
440                    strcat(flags, "+");
441                 
442                 if ((cptr->cs_flags & CS_STEALTH) && (aide))
443                    strcat(flags, "-");
444                 
445                 if (((cptr->cs_flags&CS_STEALTH)==0) || (aide))
446                 {
447                         cprintf("%d|%s|%s|%s|%s|%ld|%s|%s\n",
448                                 cptr->cs_pid, un, room,
449                                 host, cptr->cs_clientname,
450                                 (long)(cptr->lastidle),
451                                 cptr->lastcmdname, flags);
452                 }
453                 if ((spoofed) && (aide))
454                 {
455                         cprintf("%d|%s|%s|%s|%s|%ld|%s|%s\n",
456                                 cptr->cs_pid, cptr->curr_user, cptr->cs_room,
457                                 cptr->cs_host, cptr->cs_clientname,
458                                 (long)(cptr->lastidle),
459                                 cptr->lastcmdname, flags);
460                 
461                 }
462         }
463         cprintf("000\n");
464         }
465
466
467 /*
468  * Terminate another running session
469  */
470 void cmd_term(char *cmdbuf)
471 {
472         int session_num;
473         struct CitContext *ccptr;
474
475         if (!CC->logged_in) {
476                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
477                 return;
478                 }
479
480         if (CC->usersupp.axlevel < 6) {
481                 cprintf("%d You must be an Aide to terminate sessions.\n",
482                         ERROR+HIGHER_ACCESS_REQUIRED);
483                 return;
484                 }
485
486         session_num = extract_int(cmdbuf, 0);
487         if (session_num == CC->cs_pid) {
488                 cprintf("%d You can't kill your own session.\n", ERROR);
489                 return;
490                 }
491
492         for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
493                 if (session_num == ccptr->cs_pid) {
494                         kill_session(ccptr->cs_pid);
495                         cprintf("%d Session terminated.\n", OK);
496                         return;
497                         }
498                 }
499
500         cprintf("%d No such session.\n", ERROR);
501         }
502
503
504
505
506
507 /* 
508  * get the paginator prompt
509  */
510 void cmd_more(void) {
511         cprintf("%d %s\n",OK,config.c_moreprompt);
512         }
513
514 /*
515  * echo 
516  */
517 void cmd_echo(char *etext)
518 {
519         cprintf("%d %s\n",OK,etext);
520         }
521
522
523
524 /* 
525  * identify as internal program
526  */
527 void cmd_ipgm(char *argbuf)
528 {
529         int secret;
530
531         secret = extract_int(argbuf, 0);
532         if (secret == config.c_ipgm_secret) {
533                 CC->internal_pgm = 1;
534                 strcpy(CC->curr_user, "<internal program>");
535                 CC->cs_flags = CC->cs_flags|CS_STEALTH;
536                 cprintf("%d Authenticated as an internal program.\n",OK);
537                 }
538         else {
539                 cprintf("%d Authentication failed.\n",ERROR);
540                 }
541         }
542
543
544 /*
545  * Shut down the server
546  */
547 void cmd_down(void) {
548         if (!CC->logged_in) {
549                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
550                 return;
551                 }
552
553         if (CC->usersupp.axlevel < 6) {
554                 cprintf("%d You must be an Aide to shut down the server.\n",
555                         ERROR+HIGHER_ACCESS_REQUIRED);
556                 return;
557                 }
558
559         cprintf("%d Shutting down server.  Goodbye.\n", OK);
560         master_cleanup();
561         }
562
563 /*
564  * Shut down the server
565  */
566 void cmd_scdn(char *argbuf)
567 {
568         int new_state;
569
570         if (!CC->logged_in) {
571                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
572                 return;
573                 }
574
575         if (CC->usersupp.axlevel < 6) {
576                 cprintf("%d You must be an Aide to schedule a shutdown.\n",
577                         ERROR+HIGHER_ACCESS_REQUIRED);
578                 return;
579                 }
580
581         new_state = extract_int(argbuf, 0);
582         if ((new_state == 0) || (new_state == 1)) {
583                 ScheduledShutdown = new_state;
584                 }
585         cprintf("%d %d\n", OK, ScheduledShutdown);
586         }
587
588 /*
589  * main context loop
590  */
591 void *context_loop(struct CitContext *con)
592 {
593         char cmdbuf[256];
594         int session_num;
595
596         /*
597          * Wedge our way into the context table.
598          */
599         InitMyContext(con);
600
601         /* 
602          * Initialize some variables specific to our context.
603          */
604         CC->curr_rm = (-1);
605         CC->logged_in = 0;
606         CC->internal_pgm = 0;
607         CC->download_fp = NULL;
608         CC->upload_fp = NULL;
609         CC->cs_pid = con->client_socket;        /* not necessarily portable */
610         CC->FirstExpressMessage = NULL;
611         time(&CC->lastcmd);
612         time(&CC->lastidle);
613         strcpy(CC->lastcmdname, "    ");
614         strcpy(CC->cs_clientname, "(unknown)");
615         strcpy(CC->curr_user,"");
616         strcpy(CC->net_node,"");
617         sprintf(CC->temp,"/tmp/CitServer.%d.%d", getpid(), CC->cs_pid);
618         strcpy(CC->cs_room, "");
619         strcpy(CC->cs_host, config.c_fqdn);
620         locate_host(CC->cs_host);
621         CC->cs_flags = 0;
622         CC->upload_type = UPL_FILE;
623         CC->dl_is_net = 0;
624
625         session_num = session_count();
626         CC->nologin = 0;
627         if ((config.c_maxsessions > 0)&&(session_num >= config.c_maxsessions))
628                 CC->nologin = 1;
629
630         if (CC->nologin==1) {
631            cprintf("%d %s: Too many users are already online (maximum is %d)\n",
632                 ERROR+MAX_SESSIONS_EXCEEDED,
633                 config.c_nodename,config.c_maxsessions);
634                 }
635         else {
636            cprintf("%d %s Citadel/UX server ready.\n",OK,config.c_nodename);
637                 }
638
639         lprintf(3, "citserver[%3d]: started.\n", CC->cs_pid);
640         hook_start_session(CC->cs_pid);
641         rec_log(CL_CONNECT, "");
642
643         do {
644                 time(&CC->lastcmd);
645                 if (client_gets(cmdbuf) < 1) cleanup(EXIT_NULL);
646                 lprintf(5, "citserver[%3d]: %s\n", CC->cs_pid, cmdbuf);
647                 hook_command_received(CC->cs_pid, cmdbuf);
648
649                 /*
650                  * Let other clients see the last command we executed, but
651                  * exclude NOOP because that would be boring.
652                  */
653                 if (struncmp(cmdbuf, "NOOP", 4)) {
654                         strcpy(CC->lastcmdname, "    ");
655                         strncpy(CC->lastcmdname, cmdbuf, 4);
656                         time(&CC->lastidle);
657                         }
658                         
659                 if ((struncmp(cmdbuf, "ENT0", 4)) && (struncmp(cmdbuf, "MESG", 4)) && (struncmp(cmdbuf, "MSGS", 4)))
660                 {
661                    CC->cs_flags &= ~CS_POSTING;
662                 }
663                    
664 /*
665  * This loop recognizes all server commands.
666  */
667
668                 if (!struncmp(cmdbuf,"NOOP",4)) {
669                         cprintf("%d%cok\n",OK,check_express());
670                         }
671
672                 else if (!struncmp(cmdbuf,"QUIT",4)) {
673                         cprintf("%d Goodbye.\n",OK);
674                         }
675
676                 else if (!struncmp(cmdbuf,"LOUT",4)) {
677                         if (CC->logged_in) logout(CC);
678                         cprintf("%d logged out.\n",OK);
679                         }
680
681                 else if (!struncmp(cmdbuf,"USER",4)) {
682                         cmd_user(&cmdbuf[5]);
683                         }
684
685                 else if (!struncmp(cmdbuf,"PASS",4)) {
686                         cmd_pass(&cmdbuf[5]);
687                         }
688
689                 else if (!struncmp(cmdbuf,"NEWU",4)) {
690                         cmd_newu(&cmdbuf[5]);
691                         }
692
693                 else if (!struncmp(cmdbuf,"SETP",4)) {
694                         cmd_setp(&cmdbuf[5]);
695                         }
696
697                 else if (!struncmp(cmdbuf,"LRMS",4)) {
698                         cmd_lrms(&cmdbuf[5]);
699                         }
700
701                 else if (!struncmp(cmdbuf,"LKRA",4)) {
702                         cmd_lkra(&cmdbuf[5]);
703                         }
704
705                 else if (!struncmp(cmdbuf,"LKRN",4)) {
706                         cmd_lkrn(&cmdbuf[5]);
707                         }
708
709                 else if (!struncmp(cmdbuf,"LKRO",4)) {
710                         cmd_lkro(&cmdbuf[5]);
711                         }
712
713                 else if (!struncmp(cmdbuf,"LZRM",4)) {
714                         cmd_lzrm(&cmdbuf[5]);
715                         }
716
717                 else if (!struncmp(cmdbuf,"GETU",4)) {
718                         cmd_getu();
719                         }
720
721                 else if (!struncmp(cmdbuf,"SETU",4)) {
722                         cmd_setu(&cmdbuf[5]);
723                         }
724
725                 else if (!struncmp(cmdbuf,"GOTO",4)) {
726                         cmd_goto(&cmdbuf[5]);
727                         }
728
729                 else if (!struncmp(cmdbuf,"MSGS",4)) {
730                         cmd_msgs(&cmdbuf[5]);
731                         }
732
733                 else if (!struncmp(cmdbuf,"WHOK",4)) {
734                         cmd_whok();
735                         }
736
737                 else if (!struncmp(cmdbuf,"RDIR",4)) {
738                         cmd_rdir();
739                         }
740
741                 else if (!struncmp(cmdbuf,"MSG0",4)) {
742                         cmd_msg0(&cmdbuf[5]);
743                         }
744
745                 else if (!struncmp(cmdbuf,"MSG2",4)) {
746                         cmd_msg2(&cmdbuf[5]);
747                         }
748
749                 else if (!struncmp(cmdbuf,"MSG3",4)) {
750                         cmd_msg3(&cmdbuf[5]);
751                         }
752
753                 else if (!struncmp(cmdbuf,"INFO",4)) {
754                         cmd_info();
755                         }
756
757                 else if (!struncmp(cmdbuf,"SLRP",4)) {
758                         cmd_slrp(&cmdbuf[5]);
759                         }
760
761                 else if (!struncmp(cmdbuf,"INVT",4)) {
762                         cmd_invt_kick(&cmdbuf[5],1);
763                         }
764
765                 else if (!struncmp(cmdbuf,"KICK",4)) {
766                         cmd_invt_kick(&cmdbuf[5],0);
767                         }
768
769                 else if (!struncmp(cmdbuf,"GETR",4)) {
770                         cmd_getr();
771                         }
772
773                 else if (!struncmp(cmdbuf,"SETR",4)) {
774                         cmd_setr(&cmdbuf[5]);
775                         }
776
777                 else if (!struncmp(cmdbuf,"GETA",4)) {
778                         cmd_geta();
779                         }
780
781                 else if (!struncmp(cmdbuf,"SETA",4)) {
782                         cmd_seta(&cmdbuf[5]);
783                         }
784
785                 else if (!struncmp(cmdbuf,"ENT0",4)) {
786                         cmd_ent0(&cmdbuf[5]);
787                         }
788
789                 else if (!struncmp(cmdbuf,"ENT3",4)) {
790                         cmd_ent3(&cmdbuf[5]);
791                         }
792
793                 else if (!struncmp(cmdbuf,"RINF",4)) {
794                         cmd_rinf();
795                         }
796
797                 else if (!struncmp(cmdbuf,"DELE",4)) {
798                         cmd_dele(&cmdbuf[5]);
799                         }
800
801                 else if (!struncmp(cmdbuf,"KILL",4)) {
802                         cmd_kill(&cmdbuf[5]);
803                         }
804
805                 else if (!struncmp(cmdbuf,"CRE8",4)) {
806                         cmd_cre8(&cmdbuf[5]);
807                         }
808
809                 else if (!struncmp(cmdbuf,"MOVE",4)) {
810                         cmd_move(&cmdbuf[5]);
811                         }
812
813                 else if (!struncmp(cmdbuf,"FORG",4)) {
814                         cmd_forg();
815                         }
816
817                 else if (!struncmp(cmdbuf,"MESG",4)) {
818                         cmd_mesg(&cmdbuf[5]);
819                         }
820
821                 else if (!struncmp(cmdbuf,"EMSG",4)) {
822                         cmd_emsg(&cmdbuf[5]);
823                         }
824
825                 else if (!struncmp(cmdbuf,"GNUR",4)) {
826                         cmd_gnur();
827                         }
828
829                 else if (!struncmp(cmdbuf,"GREG",4)) {
830                         cmd_greg(&cmdbuf[5]);
831                         }
832
833                 else if (!struncmp(cmdbuf,"VALI",4)) {
834                         cmd_vali(&cmdbuf[5]);
835                         }
836
837                 else if (!struncmp(cmdbuf,"EINF",4)) {
838                         cmd_einf(&cmdbuf[5]);
839                         }
840
841                 else if (!struncmp(cmdbuf,"LIST",4)) {
842                         cmd_list();
843                         }
844
845                 else if (!struncmp(cmdbuf,"REGI",4)) {
846                         cmd_regi();
847                         }
848
849                 else if (!struncmp(cmdbuf,"CHEK",4)) {
850                         cmd_chek();
851                         }
852
853                 else if (!struncmp(cmdbuf,"DELF",4)) {
854                         cmd_delf(&cmdbuf[5]);
855                         }
856
857                 else if (!struncmp(cmdbuf,"MOVF",4)) {
858                         cmd_movf(&cmdbuf[5]);
859                         }
860
861                 else if (!struncmp(cmdbuf,"NETF",4)) {
862                         cmd_netf(&cmdbuf[5]);
863                         }
864
865                 else if (!struncmp(cmdbuf,"RWHO",4)) {
866                         cmd_rwho();
867                         }
868
869                 else if (!struncmp(cmdbuf,"OPEN",4)) {
870                         cmd_open(&cmdbuf[5]);
871                         }
872
873                 else if (!struncmp(cmdbuf,"CLOS",4)) {
874                         cmd_clos();
875                         }
876
877                 else if (!struncmp(cmdbuf,"UOPN",4)) {
878                         cmd_uopn(&cmdbuf[5]);
879                         }
880
881                 else if (!struncmp(cmdbuf,"UCLS",4)) {
882                         cmd_ucls(&cmdbuf[5]);
883                         }
884
885                 else if (!struncmp(cmdbuf,"READ",4)) {
886                         cmd_read(&cmdbuf[5]);
887                         }
888
889                 else if (!struncmp(cmdbuf,"WRIT",4)) {
890                         cmd_writ(&cmdbuf[5]);
891                         }
892
893                 else if (!struncmp(cmdbuf,"QUSR",4)) {
894                         cmd_qusr(&cmdbuf[5]);
895                         }
896
897                 else if (!struncmp(cmdbuf,"ECHO",4)) {
898                         cmd_echo(&cmdbuf[5]);
899                         }
900
901                 else if (!struncmp(cmdbuf,"OIMG",4)) {
902                         cmd_oimg(&cmdbuf[5]);
903                         }
904
905                 else if (!struncmp(cmdbuf,"MORE",4)) {
906                         cmd_more();
907                         }
908
909                 else if (!struncmp(cmdbuf,"NETP",4)) {
910                         cmd_netp(&cmdbuf[5]);
911                         }
912
913                 else if (!struncmp(cmdbuf,"NDOP",4)) {
914                         cmd_ndop(&cmdbuf[5]);
915                         }
916
917                 else if (!struncmp(cmdbuf,"NUOP",4)) {
918                         cmd_nuop(&cmdbuf[5]);
919                         }
920
921                 else if (!struncmp(cmdbuf,"LFLR",4)) {
922                         cmd_lflr();
923                         }
924
925                 else if (!struncmp(cmdbuf,"CFLR",4)) {
926                         cmd_cflr(&cmdbuf[5]);
927                         }
928
929                 else if (!struncmp(cmdbuf,"KFLR",4)) {
930                         cmd_kflr(&cmdbuf[5]);
931                         }
932
933                 else if (!struncmp(cmdbuf,"EFLR",4)) {
934                         cmd_eflr(&cmdbuf[5]);
935                         }
936
937                 else if (!struncmp(cmdbuf,"IDEN",4)) {
938                         cmd_iden(&cmdbuf[5]);
939                         }
940
941                 else if (!struncmp(cmdbuf,"IPGM",4)) {
942                         cmd_ipgm(&cmdbuf[5]);
943                         }
944
945                 else if (!struncmp(cmdbuf,"CHAT",4)) {
946                         cmd_chat(&cmdbuf[5]);
947                         }
948
949                 else if (!struncmp(cmdbuf,"PEXP",4)) {
950                         cmd_pexp();
951                         }
952
953                 else if (!struncmp(cmdbuf,"SEXP",4)) {
954                         cmd_sexp(&cmdbuf[5]);
955                         }
956
957                 else if (!struncmp(cmdbuf,"EBIO",4)) {
958                         cmd_ebio();
959                         }
960
961                 else if (!struncmp(cmdbuf,"RBIO",4)) {
962                         cmd_rbio(&cmdbuf[5]);
963                         }
964
965                 else if (!struncmp(cmdbuf,"LBIO",4)) {
966                         cmd_lbio();
967                         }
968
969                 else if (!struncmp(cmdbuf,"STEL",4)) {
970                         cmd_stel(&cmdbuf[5]);
971                         }
972
973                 else if (!struncmp(cmdbuf,"TERM",4)) {
974                         cmd_term(&cmdbuf[5]);
975                         }
976
977                 else if (!struncmp(cmdbuf,"DOWN",4)) {
978                         cmd_down();
979                         }
980
981                 else if (!struncmp(cmdbuf,"SCDN",4)) {
982                         cmd_scdn(&cmdbuf[5]);
983                         }
984
985                 else if (!struncmp(cmdbuf, "NSET", 4)) {
986                         cmd_nset(&cmdbuf[5]);
987                         }
988
989                 else if (!struncmp(cmdbuf, "UIMG", 4)) {
990                         cmd_uimg(&cmdbuf[5]);
991                         }
992                 else if (!struncmp(cmdbuf, "UCHG", 4)) {
993                         cmd_uchg(&cmdbuf[5]);
994                         }
995                 else if (!struncmp(cmdbuf, "TIME", 4)) {
996                         cmd_time(&cmdbuf[5]);
997                         }
998                 else if (!struncmp(cmdbuf, "HCHG", 4)) {
999                         cmd_hchg(&cmdbuf[5]);
1000                         }
1001                 else if (!struncmp(cmdbuf, "RCHG", 4)) {
1002                         cmd_rchg(&cmdbuf[5]);
1003                         }
1004                 else {
1005                         cprintf("%d Unrecognized or unsupported command.\n",
1006                                 ERROR);
1007                         }
1008
1009                 } while(struncmp(cmdbuf,"QUIT",4));
1010
1011         cleanup(EXIT_NORMAL);
1012         return(NULL);
1013         }