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