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