]> code.citadel.org Git - citadel.git/blob - citadel/citserver.c
d3cd6ed3d576c305b023372a071b1659ecd7fb7a
[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
642         do {
643                 time(&CC->lastcmd);
644                 if (client_gets(cmdbuf) < 1) cleanup(EXIT_NULL);
645                 lprintf(5, "citserver[%3d]: %s\n", CC->cs_pid, cmdbuf);
646                 hook_command_received(CC->cs_pid, cmdbuf);
647
648                 /*
649                  * Let other clients see the last command we executed, but
650                  * exclude NOOP because that would be boring.
651                  */
652                 if (struncmp(cmdbuf, "NOOP", 4)) {
653                         strcpy(CC->lastcmdname, "    ");
654                         strncpy(CC->lastcmdname, cmdbuf, 4);
655                         time(&CC->lastidle);
656                         }
657                         
658                 if ((struncmp(cmdbuf, "ENT0", 4)) && (struncmp(cmdbuf, "MESG", 4)) && (struncmp(cmdbuf, "MSGS", 4)))
659                 {
660                    CC->cs_flags &= ~CS_POSTING;
661                 }
662                    
663 /*
664  * This loop recognizes all server commands.
665  */
666
667                 if (!struncmp(cmdbuf,"NOOP",4)) {
668                         cprintf("%d%cok\n",OK,check_express());
669                         }
670
671                 else if (!struncmp(cmdbuf,"QUIT",4)) {
672                         cprintf("%d Goodbye.\n",OK);
673                         }
674
675                 else if (!struncmp(cmdbuf,"LOUT",4)) {
676                         if (CC->logged_in) logout(CC);
677                         cprintf("%d logged out.\n",OK);
678                         }
679
680                 else if (!struncmp(cmdbuf,"USER",4)) {
681                         cmd_user(&cmdbuf[5]);
682                         }
683
684                 else if (!struncmp(cmdbuf,"PASS",4)) {
685                         cmd_pass(&cmdbuf[5]);
686                         }
687
688                 else if (!struncmp(cmdbuf,"NEWU",4)) {
689                         cmd_newu(&cmdbuf[5]);
690                         }
691
692                 else if (!struncmp(cmdbuf,"SETP",4)) {
693                         cmd_setp(&cmdbuf[5]);
694                         }
695
696                 else if (!struncmp(cmdbuf,"LRMS",4)) {
697                         cmd_lrms(&cmdbuf[5]);
698                         }
699
700                 else if (!struncmp(cmdbuf,"LKRA",4)) {
701                         cmd_lkra(&cmdbuf[5]);
702                         }
703
704                 else if (!struncmp(cmdbuf,"LKRN",4)) {
705                         cmd_lkrn(&cmdbuf[5]);
706                         }
707
708                 else if (!struncmp(cmdbuf,"LKRO",4)) {
709                         cmd_lkro(&cmdbuf[5]);
710                         }
711
712                 else if (!struncmp(cmdbuf,"LZRM",4)) {
713                         cmd_lzrm(&cmdbuf[5]);
714                         }
715
716                 else if (!struncmp(cmdbuf,"GETU",4)) {
717                         cmd_getu();
718                         }
719
720                 else if (!struncmp(cmdbuf,"SETU",4)) {
721                         cmd_setu(&cmdbuf[5]);
722                         }
723
724                 else if (!struncmp(cmdbuf,"GOTO",4)) {
725                         cmd_goto(&cmdbuf[5]);
726                         }
727
728                 else if (!struncmp(cmdbuf,"MSGS",4)) {
729                         cmd_msgs(&cmdbuf[5]);
730                         }
731
732                 else if (!struncmp(cmdbuf,"WHOK",4)) {
733                         cmd_whok();
734                         }
735
736                 else if (!struncmp(cmdbuf,"RDIR",4)) {
737                         cmd_rdir();
738                         }
739
740                 else if (!struncmp(cmdbuf,"MSG0",4)) {
741                         cmd_msg0(&cmdbuf[5]);
742                         }
743
744                 else if (!struncmp(cmdbuf,"MSG2",4)) {
745                         cmd_msg2(&cmdbuf[5]);
746                         }
747
748                 else if (!struncmp(cmdbuf,"MSG3",4)) {
749                         cmd_msg3(&cmdbuf[5]);
750                         }
751
752                 else if (!struncmp(cmdbuf,"INFO",4)) {
753                         cmd_info();
754                         }
755
756                 else if (!struncmp(cmdbuf,"SLRP",4)) {
757                         cmd_slrp(&cmdbuf[5]);
758                         }
759
760                 else if (!struncmp(cmdbuf,"INVT",4)) {
761                         cmd_invt_kick(&cmdbuf[5],1);
762                         }
763
764                 else if (!struncmp(cmdbuf,"KICK",4)) {
765                         cmd_invt_kick(&cmdbuf[5],0);
766                         }
767
768                 else if (!struncmp(cmdbuf,"GETR",4)) {
769                         cmd_getr();
770                         }
771
772                 else if (!struncmp(cmdbuf,"SETR",4)) {
773                         cmd_setr(&cmdbuf[5]);
774                         }
775
776                 else if (!struncmp(cmdbuf,"GETA",4)) {
777                         cmd_geta();
778                         }
779
780                 else if (!struncmp(cmdbuf,"SETA",4)) {
781                         cmd_seta(&cmdbuf[5]);
782                         }
783
784                 else if (!struncmp(cmdbuf,"ENT0",4)) {
785                         cmd_ent0(&cmdbuf[5]);
786                         }
787
788                 else if (!struncmp(cmdbuf,"ENT3",4)) {
789                         cmd_ent3(&cmdbuf[5]);
790                         }
791
792                 else if (!struncmp(cmdbuf,"RINF",4)) {
793                         cmd_rinf();
794                         }
795
796                 else if (!struncmp(cmdbuf,"DELE",4)) {
797                         cmd_dele(&cmdbuf[5]);
798                         }
799
800                 else if (!struncmp(cmdbuf,"KILL",4)) {
801                         cmd_kill(&cmdbuf[5]);
802                         }
803
804                 else if (!struncmp(cmdbuf,"CRE8",4)) {
805                         cmd_cre8(&cmdbuf[5]);
806                         }
807
808                 else if (!struncmp(cmdbuf,"MOVE",4)) {
809                         cmd_move(&cmdbuf[5]);
810                         }
811
812                 else if (!struncmp(cmdbuf,"FORG",4)) {
813                         cmd_forg();
814                         }
815
816                 else if (!struncmp(cmdbuf,"MESG",4)) {
817                         cmd_mesg(&cmdbuf[5]);
818                         }
819
820                 else if (!struncmp(cmdbuf,"EMSG",4)) {
821                         cmd_emsg(&cmdbuf[5]);
822                         }
823
824                 else if (!struncmp(cmdbuf,"GNUR",4)) {
825                         cmd_gnur();
826                         }
827
828                 else if (!struncmp(cmdbuf,"GREG",4)) {
829                         cmd_greg(&cmdbuf[5]);
830                         }
831
832                 else if (!struncmp(cmdbuf,"VALI",4)) {
833                         cmd_vali(&cmdbuf[5]);
834                         }
835
836                 else if (!struncmp(cmdbuf,"EINF",4)) {
837                         cmd_einf(&cmdbuf[5]);
838                         }
839
840                 else if (!struncmp(cmdbuf,"LIST",4)) {
841                         cmd_list();
842                         }
843
844                 else if (!struncmp(cmdbuf,"REGI",4)) {
845                         cmd_regi();
846                         }
847
848                 else if (!struncmp(cmdbuf,"CHEK",4)) {
849                         cmd_chek();
850                         }
851
852                 else if (!struncmp(cmdbuf,"DELF",4)) {
853                         cmd_delf(&cmdbuf[5]);
854                         }
855
856                 else if (!struncmp(cmdbuf,"MOVF",4)) {
857                         cmd_movf(&cmdbuf[5]);
858                         }
859
860                 else if (!struncmp(cmdbuf,"NETF",4)) {
861                         cmd_netf(&cmdbuf[5]);
862                         }
863
864                 else if (!struncmp(cmdbuf,"RWHO",4)) {
865                         cmd_rwho();
866                         }
867
868                 else if (!struncmp(cmdbuf,"OPEN",4)) {
869                         cmd_open(&cmdbuf[5]);
870                         }
871
872                 else if (!struncmp(cmdbuf,"CLOS",4)) {
873                         cmd_clos();
874                         }
875
876                 else if (!struncmp(cmdbuf,"UOPN",4)) {
877                         cmd_uopn(&cmdbuf[5]);
878                         }
879
880                 else if (!struncmp(cmdbuf,"UCLS",4)) {
881                         cmd_ucls(&cmdbuf[5]);
882                         }
883
884                 else if (!struncmp(cmdbuf,"READ",4)) {
885                         cmd_read(&cmdbuf[5]);
886                         }
887
888                 else if (!struncmp(cmdbuf,"WRIT",4)) {
889                         cmd_writ(&cmdbuf[5]);
890                         }
891
892                 else if (!struncmp(cmdbuf,"QUSR",4)) {
893                         cmd_qusr(&cmdbuf[5]);
894                         }
895
896                 else if (!struncmp(cmdbuf,"ECHO",4)) {
897                         cmd_echo(&cmdbuf[5]);
898                         }
899
900                 else if (!struncmp(cmdbuf,"OIMG",4)) {
901                         cmd_oimg(&cmdbuf[5]);
902                         }
903
904                 else if (!struncmp(cmdbuf,"MORE",4)) {
905                         cmd_more();
906                         }
907
908                 else if (!struncmp(cmdbuf,"NETP",4)) {
909                         cmd_netp(&cmdbuf[5]);
910                         }
911
912                 else if (!struncmp(cmdbuf,"NDOP",4)) {
913                         cmd_ndop(&cmdbuf[5]);
914                         }
915
916                 else if (!struncmp(cmdbuf,"NUOP",4)) {
917                         cmd_nuop(&cmdbuf[5]);
918                         }
919
920                 else if (!struncmp(cmdbuf,"LFLR",4)) {
921                         cmd_lflr();
922                         }
923
924                 else if (!struncmp(cmdbuf,"CFLR",4)) {
925                         cmd_cflr(&cmdbuf[5]);
926                         }
927
928                 else if (!struncmp(cmdbuf,"KFLR",4)) {
929                         cmd_kflr(&cmdbuf[5]);
930                         }
931
932                 else if (!struncmp(cmdbuf,"EFLR",4)) {
933                         cmd_eflr(&cmdbuf[5]);
934                         }
935
936                 else if (!struncmp(cmdbuf,"IDEN",4)) {
937                         cmd_iden(&cmdbuf[5]);
938                         }
939
940                 else if (!struncmp(cmdbuf,"IPGM",4)) {
941                         cmd_ipgm(&cmdbuf[5]);
942                         }
943
944                 else if (!struncmp(cmdbuf,"CHAT",4)) {
945                         cmd_chat(&cmdbuf[5]);
946                         }
947
948                 else if (!struncmp(cmdbuf,"PEXP",4)) {
949                         cmd_pexp();
950                         }
951
952                 else if (!struncmp(cmdbuf,"SEXP",4)) {
953                         cmd_sexp(&cmdbuf[5]);
954                         }
955
956                 else if (!struncmp(cmdbuf,"EBIO",4)) {
957                         cmd_ebio();
958                         }
959
960                 else if (!struncmp(cmdbuf,"RBIO",4)) {
961                         cmd_rbio(&cmdbuf[5]);
962                         }
963
964                 else if (!struncmp(cmdbuf,"LBIO",4)) {
965                         cmd_lbio();
966                         }
967
968                 else if (!struncmp(cmdbuf,"STEL",4)) {
969                         cmd_stel(&cmdbuf[5]);
970                         }
971
972                 else if (!struncmp(cmdbuf,"TERM",4)) {
973                         cmd_term(&cmdbuf[5]);
974                         }
975
976                 else if (!struncmp(cmdbuf,"DOWN",4)) {
977                         cmd_down();
978                         }
979
980                 else if (!struncmp(cmdbuf,"SCDN",4)) {
981                         cmd_scdn(&cmdbuf[5]);
982                         }
983
984                 else if (!struncmp(cmdbuf, "NSET", 4)) {
985                         cmd_nset(&cmdbuf[5]);
986                         }
987
988                 else if (!struncmp(cmdbuf, "UIMG", 4)) {
989                         cmd_uimg(&cmdbuf[5]);
990                         }
991                 else if (!struncmp(cmdbuf, "UCHG", 4)) {
992                         cmd_uchg(&cmdbuf[5]);
993                         }
994                 else if (!struncmp(cmdbuf, "TIME", 4)) {
995                         cmd_time(&cmdbuf[5]);
996                         }
997                 else if (!struncmp(cmdbuf, "HCHG", 4)) {
998                         cmd_hchg(&cmdbuf[5]);
999                         }
1000                 else if (!struncmp(cmdbuf, "RCHG", 4)) {
1001                         cmd_rchg(&cmdbuf[5]);
1002                         }
1003                 else {
1004                         cprintf("%d Unrecognized or unsupported command.\n",
1005                                 ERROR);
1006                         }
1007
1008                 } while(struncmp(cmdbuf,"QUIT",4));
1009
1010         cleanup(EXIT_NORMAL);
1011         return(NULL);
1012         }