02f8dc4e2d11e5fc72b7cda64caf51be83b30a3e
[citadel.git] / citadel / rooms.c
1 /* Citadel/UX room-oriented routines */
2
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <signal.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/wait.h>
13 #include <errno.h>
14 #include "citadel.h"
15
16 #define IFEXPERT if (userflags&US_EXPERT)
17 #define IFNEXPERT if ((userflags&US_EXPERT)==0)
18 #define IFAIDE if (axlevel>=6)
19 #define IFNAIDE if (axlevel<6)
20
21
22 long finduser();
23 void sttybbs();
24 void extract();
25 int extract_int();
26 void hit_any_key();
27 int yesno();
28 int yesno_d();
29 void strprompt();
30 void newprompt();
31 int struncmp();
32 void dotgoto();
33 long extract_long();
34 void serv_read();
35 void formout();
36 int inkey();
37 int fmout();
38 void citedit();
39 void progress();
40 int pattern();
41 int file_checksum();
42 int nukedir();
43 void color();
44
45 extern unsigned room_flags;
46 extern char room_name[];
47 extern char temp[];
48 extern char tempdir[];
49 extern int editor_pid;
50 extern char editor_path[];
51 extern int screenwidth;
52 extern int screenheight;
53 extern char fullname[];
54 extern int userflags;
55 extern char sigcaught;
56 extern char floor_mode;
57 extern char curr_floor;
58
59
60 extern int ugnum;
61 extern long uglsn;
62 extern char ugname[];
63
64 extern char floorlist[128][256];
65
66
67 void load_floorlist() {
68         int a;
69         char buf[256];
70
71         for (a=0; a<128; ++a) floorlist[a][0] = 0;
72
73         serv_puts("LFLR");
74         serv_gets(buf);
75         if (buf[0]!='1') {
76                 strcpy(floorlist[0],"Main Floor");
77                 return;
78                 }
79         while (serv_gets(buf), strcmp(buf,"000")) {
80                 extract(floorlist[extract_int(buf,0)],buf,1);
81                 }
82         }
83
84 void listrms(variety)
85 char *variety; {
86         char buf[256];
87         char rmname[32];
88         int f,c;
89
90         serv_puts(variety);
91         serv_gets(buf);
92         if (buf[0]!='1') return;
93         c = 1;
94         sigcaught = 0;
95         sttybbs(SB_YES_INTR);
96         while (serv_gets(buf), strcmp(buf,"000")) if (sigcaught==0) {
97                 extract(rmname,buf,0);
98                 if ((c + strlen(rmname) + 4) > screenwidth) {
99                         printf("\n");
100                         c = 1;
101                         }
102                 f = extract_int(buf,1);
103                 if (f & QR_PRIVATE) {
104                         color(1);
105                         }
106                 else {
107                         color(2);
108                         }
109                 printf("%s",rmname);
110                 if ((f & QR_DIRECTORY) && (f & QR_NETWORK)) printf("}  ");
111                 else if (f & QR_DIRECTORY) printf("]  ");
112                 else if (f & QR_NETWORK) printf(")  ");
113                 else printf(">  ");
114                 c = c + strlen(rmname) + 3;
115                 }
116         color(7);
117         sttybbs(SB_NO_INTR);
118         }
119
120
121 void list_other_floors() {
122         int a,c;
123
124         c = 1;
125         for (a=0; a<128; ++a) if ((strlen(floorlist[a])>0)&&(a!=curr_floor)) {
126                 if ((c + strlen(floorlist[a]) + 4) > screenwidth) {
127                         printf("\n");
128                         c = 1;
129                         }
130                 printf("%s:  ",floorlist[a]);
131                 c = c + strlen(floorlist[a]) + 3;
132                 }
133         }
134
135
136 /*
137  * List known rooms.  kn_floor_mode should be set to 0 for a 'flat' listing,
138  * 1 to list rooms on the current floor, or 1 to list rooms on all floors.
139  */
140 void knrooms(kn_floor_mode)
141 int kn_floor_mode; {
142         char buf[256];
143         int a;
144
145         load_floorlist();
146
147         if (kn_floor_mode == 0) {
148                 color(3);
149                 printf("\n   Rooms with unread messages:\n");
150                 listrms("LKRN");
151                 color(3);
152                 printf("\n\n   No unseen messages in:\n");
153                 listrms("LKRO");
154                 printf("\n");
155                 }
156
157         if (kn_floor_mode == 1) {
158                 color(3);
159                 printf("\n   Rooms with unread messages on %s:\n",
160                         floorlist[(int)curr_floor]);
161                 sprintf(buf,"LKRN %d",curr_floor);
162                 listrms(buf);
163                 color(3);
164                 printf("\n\n   Rooms with no new messages on %s:\n",
165                         floorlist[(int)curr_floor]);
166                 sprintf(buf,"LKRO %d",curr_floor);
167                 listrms(buf);
168                 color(3);
169                 printf("\n\n   Other floors:\n");
170                 list_other_floors();
171                 printf("\n");
172                 }
173
174         if (kn_floor_mode == 2) {
175                 for (a=0; a<128; ++a) if (floorlist[a][0]!=0) {
176                         color(3);
177                         printf("\n   Rooms on %s:\n",floorlist[a]);
178                         sprintf(buf,"LKRA %d",a);
179                         listrms(buf);
180                         printf("\n");
181                         }
182                 }
183         
184         color(7);
185         IFNEXPERT hit_any_key();
186         }
187
188
189 void listzrooms() {             /* list public forgotten rooms */
190         color(3);
191         printf("\n   Forgotten public rooms:\n");
192         listrms("LZRM");
193         printf("\n");
194         color(7);
195         IFNEXPERT hit_any_key();
196         }
197
198
199 int set_room_attr(ibuf,prompt,sbit)
200 int ibuf;
201 char *prompt;
202 unsigned sbit; {
203         int a;
204
205         printf("%s [%s]? ",prompt,((ibuf&sbit) ? "Yes":"No"));
206         a=yesno_d(ibuf&sbit);
207         ibuf=(ibuf|sbit);
208         if (!a) ibuf=(ibuf^sbit);
209         return(ibuf);
210         }
211
212
213
214 /*
215  * Select a floor (used in several commands)
216  * The supplied argument is the 'default' floor number.
217  * This function returns the selected floor number.
218  */
219 int select_floor(rfloor)
220 int rfloor; {
221         int a, newfloor;
222         char floorstr[256];
223
224         if (floor_mode == 1) {
225                 if (floorlist[(int)curr_floor][0]==0) load_floorlist();
226
227                 do {
228                         newfloor = (-1);
229                         strcpy(floorstr,&floorlist[rfloor][0]);
230                         strprompt("Which floor",floorstr,256);
231                         for (a=0; a<128; ++a) {
232                                 if (!strucmp(floorstr,&floorlist[a][0]))
233                                         newfloor = a;
234                                 if ((newfloor<0)&&(!struncmp(floorstr,
235                                         &floorlist[a][0],strlen(floorstr))))
236                                                 newfloor = a;
237                                 if ((newfloor<0)&&(pattern(&floorlist[a][0],
238                                         floorstr)>=0)) newfloor = a;
239                                 }
240                         if (newfloor<0) {
241                                 printf("\n One of:\n");
242                                 for (a=0; a<128; ++a)
243                                         if (floorlist[a][0]!=0)
244                                                 printf("%s\n",
245                                                         &floorlist[a][0]);
246                                 }
247                         } while(newfloor < 0);
248                 return(newfloor);
249                 }
250         return(rfloor);
251         }
252
253
254
255
256 /*
257  * .<A>ide <E>dit room
258  */
259 void editthisroom() {
260         char rname[20];
261         char rpass[10];
262         char rdir[15];
263         unsigned rflags;
264         int rbump;
265         char raide[32];
266         char buf[256];
267         int rfloor;
268
269         serv_puts("GETR");
270         serv_gets(buf);
271         if (buf[0]!='2') {
272                 printf("%s\n",&buf[4]);
273                 return;
274                 }
275
276         extract(rname,&buf[4],0);
277         extract(rpass,&buf[4],1);
278         extract(rdir, &buf[4],2);
279         rflags = extract_int(&buf[4],3);
280         rfloor = extract_int(&buf[4],4);
281         rbump = 0;
282
283         serv_puts("GETA");
284         serv_gets(buf);
285         if (buf[0]=='2') strcpy(raide,&buf[4]);
286         else strcpy(raide,"");
287         if (strlen(raide)==0) strcpy(raide,"none");
288
289         strprompt("Room name",rname,19);
290
291         rfloor = select_floor(rfloor);
292         rflags = set_room_attr(rflags,"Private room",QR_PRIVATE);
293         if (rflags & QR_PRIVATE)
294                 rflags = set_room_attr(rflags,
295                         "Accessible by guessing room name",QR_GUESSNAME);
296
297         /* if it's public, clear the privacy classes */
298         if ((rflags & QR_PRIVATE)==0) {
299                 if (rflags & QR_GUESSNAME)  rflags = rflags - QR_GUESSNAME;
300                 if (rflags & QR_PASSWORDED) rflags = rflags - QR_PASSWORDED;
301                 }
302
303         /* if it's private, choose the privacy classes */
304         if ( (rflags & QR_PRIVATE)
305            && ( (rflags & QR_GUESSNAME) == 0) ) {
306                 rflags = set_room_attr(rflags,
307                         "Accessible by entering a password",QR_PASSWORDED);
308                 }
309         if ( (rflags & QR_PRIVATE)
310            && ((rflags&QR_PASSWORDED)==QR_PASSWORDED) ) {
311                 strprompt("Room password",rpass,9);
312                 }
313
314         if ((rflags&QR_PRIVATE)==QR_PRIVATE) {
315                 printf("Cause current users to forget room [No] ? ");
316                 if (yesno_d(0)==1) rbump = 1;
317                 }
318
319         rflags = set_room_attr(rflags,"Preferred users only",QR_PREFONLY);
320         rflags = set_room_attr(rflags,"Read-only room",QR_READONLY);
321         rflags = set_room_attr(rflags,"Directory room",QR_DIRECTORY);
322         rflags = set_room_attr(rflags,"Permanent room",QR_PERMANENT);
323         if (rflags & QR_DIRECTORY) {
324                 strprompt("Directory name",rdir,14);
325                 rflags = set_room_attr(rflags,"Uploading allowed",QR_UPLOAD);
326                 rflags = set_room_attr(rflags,"Downloading allowed",
327                                                                 QR_DOWNLOAD);
328                 rflags = set_room_attr(rflags,"Visible directory",QR_VISDIR);
329                 }
330         rflags = set_room_attr(rflags,"Network shared room",QR_NETWORK);
331         rflags = set_room_attr(rflags,
332                 "Automatically make all messages anonymous",QR_ANONONLY);
333         if ( (rflags & QR_ANONONLY) == 0) {
334                 rflags = set_room_attr(rflags,
335                         "Ask users whether to make messages anonymous",
336                         QR_ANON2);
337                 }
338
339         do {
340                 strprompt("Room aide (or 'none')",raide,29);
341                 if (!strucmp(raide,"none")) {
342                         strcpy(raide,"");
343                         strcpy(buf,"200");
344                         }
345                 else {
346                         sprintf(buf,"QUSR %s",raide);
347                         serv_puts(buf);
348                         serv_gets(buf);
349                         if (buf[0]!='2') printf("%s\n",&buf[4]);
350                         }
351                 } while(buf[0]!='2');
352
353         if (!strucmp(raide,"none")) strcpy(raide,"");
354
355         printf("Save changes (y/n)? ");
356         if (yesno()==1) {
357                 sprintf(buf,"SETR %s|%s|%s|%d|%d|%d",
358                         rname,rpass,rdir,rflags,rbump,rfloor);
359                 serv_puts(buf);
360                 serv_gets(buf);
361                 printf("%s\n",&buf[4]);
362                 sprintf(buf,"SETA %s",raide);
363                 serv_puts(buf);
364                 serv_gets(buf);
365                 if (buf[0]=='2') dotgoto(rname,2);
366                 }
367         }
368
369
370 /*
371  * un-goto the previous room
372  */
373 void ungoto() { 
374         char buf[256];
375         
376         if (!strcmp(ugname,"")) return;
377         sprintf(buf,"GOTO %s",ugname);
378         serv_puts(buf);
379         serv_gets(buf);
380         if (buf[0]!='2') {
381                 printf("%s\n",&buf[4]);
382                 return;
383                 }
384         sprintf(buf,"SLRP %ld",uglsn);
385         serv_puts(buf);
386         serv_gets(buf);
387         if (buf[0]!='2') printf("%s\n",&buf[4]);
388         strcpy(buf,ugname);
389         strcpy(ugname,"");
390         dotgoto(buf,0);
391         }
392
393
394 /*
395  * download()  -  download a file or files.  The argument passed to this
396  *                function determines which protocol to use.
397  */
398 void download(proto)
399 int proto; {
400
401 /*
402   - 0 = paginate, 1 = xmodem, 2 = raw, 3 = ymodem, 4 = zmodem, 5 = save
403 */
404
405
406         char buf[256];
407         char dbuf[4096];
408         char filename[256];
409         long total_bytes = 0L;
410         long transmitted_bytes = 0L;
411         long aa,bb;
412         int a,b;
413         int packet;
414         FILE *tpipe = NULL;
415         FILE *savefp = NULL;
416         int proto_pid;
417         int broken = 0;
418
419         if ((room_flags & QR_DOWNLOAD) == 0) {
420                 printf("*** You cannot download from this room.\n");
421                 return;
422                 }
423         
424         newprompt("Enter filename: ",filename,255);
425
426         sprintf(buf,"OPEN %s",filename);
427         serv_puts(buf);
428         serv_gets(buf);
429         if (buf[0]!='2') {
430                 printf("%s\n",&buf[4]);
431                 return;
432                 }
433         total_bytes = extract_long(&buf[4],0);
434
435
436         /* Here's the code for simply transferring the file to the client,
437          * for folks who have their own clientware.  It's a lot simpler than
438          * the [XYZ]modem code below...
439          */
440         if (proto == 5) {
441                 printf("Enter the name of the directory to save '%s'\n",
442                         filename);
443                 printf("to, or press return for the current directory.\n");
444                 newprompt("Directory: ",dbuf,256);
445                 if (strlen(dbuf)==0) strcpy(dbuf,".");
446                 strcat(dbuf,"/");
447                 strcat(dbuf,filename);
448                 
449                 savefp = fopen(dbuf,"w");
450                 if (savefp == NULL) {
451                         printf("Cannot open '%s': %s\n",dbuf,strerror(errno));
452                         /* close the download file at the server */
453                         serv_puts("CLOS");
454                         serv_gets(buf);
455                         if (buf[0]!='2') {
456                                 printf("%s\n",&buf[4]);
457                                 }
458                         return;
459                         }
460                 progress(0,total_bytes);
461                 while ( (transmitted_bytes < total_bytes) && (broken == 0) ) {
462                         bb = total_bytes - transmitted_bytes;
463                         aa = ((bb < 4096) ? bb : 4096);
464                         sprintf(buf,"READ %ld|%ld",transmitted_bytes,aa);
465                         serv_puts(buf);
466                         serv_gets(buf);
467                         if (buf[0]!='6') {
468                                 printf("%s\n",&buf[4]);
469                                 return;
470                                 }
471                         packet = extract_int(&buf[4],0);
472                         serv_read(dbuf,packet);
473                         if (fwrite(dbuf,packet,1,savefp) < 1) broken = 1;
474                         transmitted_bytes = transmitted_bytes + (long)packet;
475                         progress(transmitted_bytes,total_bytes);
476                         }
477                 fclose(savefp);
478                 /* close the download file at the server */
479                 serv_puts("CLOS");
480                 serv_gets(buf);
481                 if (buf[0]!='2') {
482                         printf("%s\n",&buf[4]);
483                         }
484                 return;
485                 }
486
487
488         mkdir(tempdir,0700);
489 #ifdef USE_MKFIFO
490         sprintf(buf,"mkfifo %s/%s",tempdir,filename);
491 #else
492         sprintf(buf,"mknod %s/%s p",tempdir,filename);
493 #endif
494         system(buf);
495
496         /* We do the remainder of this function as a separate process in
497          * order to allow recovery if the transfer is aborted.  If the
498          * file transfer program aborts, the first child process receives a
499          * "broken pipe" signal and aborts.  We *should* be able to catch
500          * this condition with signal(), but it doesn't seem to work on all
501          * systems.
502          */
503         a = fork();
504         if (a!=0) {
505                 /* wait for the download to finish */
506                 while (wait(&b)!=a) ;;
507                 sttybbs(0);
508                 /* close the download file at the server */
509                 serv_puts("CLOS");
510                 serv_gets(buf);
511                 if (buf[0]!='2') {
512                         printf("%s\n",&buf[4]);
513                         }
514                 /* clean up the temporary directory */
515                 nukedir(tempdir);
516                 return;
517                 }
518
519         sprintf(buf,"%s/%s",tempdir,filename);  /* full pathname */
520
521         /* The next fork() creates a second child process that is used for
522          * the actual file transfer program (usually sz).
523          */
524         proto_pid = fork();
525         if (proto_pid == 0) {
526                 if (proto==0)  {
527                         sttybbs(0);
528                         signal(SIGINT,SIG_DFL);
529                         signal(SIGQUIT,SIG_DFL);
530                         sprintf(dbuf,"SHELL=/dev/null; export SHELL; TERM=dumb; export TERM; exec more -d <%s",buf);
531                         system(dbuf);
532                         sttybbs(SB_NO_INTR);
533                         exit(0);
534                         }
535                 sttybbs(3);
536                 signal(SIGINT,SIG_DFL);
537                 signal(SIGQUIT,SIG_DFL);
538                 if (proto==1) execlp("sx","sx",buf,NULL);
539                 if (proto==2) execlp("cat","cat",buf,NULL);
540                 if (proto==3) execlp("sb","sb",buf,NULL);
541                 if (proto==4) execlp("sz","sz",buf,NULL);
542                 execlp("cat","cat",buf,NULL);
543                 exit(1);
544                 }
545
546         tpipe = fopen(buf,"w");
547
548         while ( (transmitted_bytes < total_bytes) && (broken == 0) ) {
549                 bb = total_bytes - transmitted_bytes;
550                 aa = ((bb < 4096) ? bb : 4096);
551                 sprintf(buf,"READ %ld|%ld",transmitted_bytes,aa);
552                 serv_puts(buf);
553                 serv_gets(buf);
554                 if (buf[0]!='6') {
555                         printf("%s\n",&buf[4]);
556                         return;
557                         }
558                 packet = extract_int(&buf[4],0);
559                 serv_read(dbuf,packet);
560                 if (fwrite(dbuf,packet,1,tpipe) < 1) broken = 1;
561                 transmitted_bytes = transmitted_bytes + (long)packet;
562                 }
563         if (tpipe!=NULL) fclose(tpipe);
564
565         /* Hang out and wait for the file transfer program to finish */
566         while (wait(&a) != proto_pid) ;;
567
568
569         putc(7,stdout);
570         exit(0);        /* transfer control back to the main program */
571         }
572
573
574 /*
575  * read directory of this room
576  */
577 void roomdir() {
578         char flnm[256];
579         char flsz[32];
580         char comment[256];
581         char buf[256];
582
583         serv_puts("RDIR");
584         serv_gets(buf);
585         if (buf[0]!='1') {
586                 printf("%s\n",&buf[4]);
587                 return;
588                 }
589
590         extract(comment,&buf[4],0);
591         extract(flnm,&buf[4],1);
592         printf("\nDirectory of %s on %s\n",flnm,comment);
593         printf("-----------------------\n");
594         while (serv_gets(buf), strcmp(buf,"000")) {
595                 extract(flnm,buf,0);
596                 extract(flsz,buf,1);
597                 extract(comment,buf,2);
598                 if (strlen(flnm)<=14)
599                         printf("%-14s %8s %s\n",flnm,flsz,comment);
600                 else
601                         printf("%s\n%14s %8s %s\n",flnm,"",flsz,comment);
602                 }
603         }
604
605
606 /*
607  * add a user to a private room
608  */
609 void invite() {
610         char aaa[31],bbb[256];
611
612         if ((room_flags & QR_PRIVATE)==0) {
613                 printf("This is not a private room.\n");
614                 return;
615                 }
616
617         newprompt("Name of user? ",aaa,30);
618         if (aaa[0]==0) return;
619
620         sprintf(bbb,"INVT %s",aaa);
621         serv_puts(bbb);
622         serv_gets(bbb);
623         printf("%s\n",&bbb[4]);
624         }
625
626
627 /*
628  * kick a user out of a room
629  */
630 void kickout() {
631         char aaa[31],bbb[256];
632
633         if ((room_flags & QR_PRIVATE)==0) {
634                 printf("Note: this is not a private room.  Kicking a user ");
635                 printf("out of this room will only\nhave the same effect ");
636                 printf("as if they <Z>apped the room.\n\n");
637                 }
638
639         newprompt("Name of user? ",aaa,30);
640         if (aaa[0]==0) return;
641
642         sprintf(bbb,"KICK %s",aaa);
643         serv_puts(bbb);
644         serv_gets(bbb);
645         printf("%s\n",&bbb[4]);
646         }
647
648
649 /*
650  * aide command: kill the current room
651  */
652 void killroom() {
653         char aaa[100];
654
655         serv_puts("KILL 0");
656         serv_gets(aaa);
657         if (aaa[0]!='2') {
658                 printf("%s\n",&aaa[4]);
659                 return;
660                 }
661
662         printf("Are you sure you want to kill this room? ");
663         if (yesno()==0) return;
664
665         serv_puts("KILL 1");
666         serv_gets(aaa);
667         printf("%s\n",&aaa[4]);
668         if (aaa[0]!='2') return;
669         dotgoto("_BASEROOM_",0);
670         }
671
672 void forget() { /* forget the current room */
673         char cmd[256];
674
675         printf("Are you sure you want to forget this room? ");
676         if (yesno()==0) return;
677
678         serv_puts("FORG");
679         serv_gets(cmd);
680         if (cmd[0]!='2') {
681                 printf("%s\n",&cmd[4]);
682                 return;
683                 }
684
685         /* now return to the lobby */
686         dotgoto("_BASEROOM_",0);
687         }
688
689
690 /*
691  * create a new room
692  */
693 void entroom() {
694         char cmd[256];
695         char new_room_name[20];
696         int new_room_type;
697         char new_room_pass[10];
698         int new_room_floor;
699         int a,b;
700
701         serv_puts("CRE8 0");
702         serv_gets(cmd);
703         
704         if (cmd[0]!='2') {
705                 printf("%s\n",&cmd[4]);
706                 return;
707                 }
708         
709         newprompt("Name for new room? ",new_room_name,19);
710         if (strlen(new_room_name)==0) return;
711         for (a=0; a<strlen(new_room_name); ++a)
712                 if (new_room_name[a] == '|') new_room_name[a]='_';
713
714         new_room_floor = select_floor((int)curr_floor);
715
716         IFNEXPERT formout("roomaccess");
717         do {
718                 printf("<?>Help\n<1>Public room\n<2>Guess-name room\n");
719                 printf("<3>Passworded room\n<4>Invitation-only room\n");
720                 printf("Enter room type: ");
721                 do {
722                         b=inkey();
723                         } while (((b<'1')||(b>'4')) && (b!='?'));
724                 if (b=='?') {
725                         printf("?\n");
726                         formout("roomaccess");
727                         }
728                 } while ((b<'1')||(b>'4'));
729         b=b-48;
730         printf("%d\n",b);
731         new_room_type = b - 1;
732         if (new_room_type==2) {
733                 newprompt("Enter a room password: ",new_room_pass,9);
734                 for (a=0; a<strlen(new_room_pass); ++a)
735                         if (new_room_pass[a] == '|') new_room_pass[a]='_';
736                 }
737         else strcpy(new_room_pass,"");
738
739         printf("\042%s\042, a",new_room_name);
740         if (b==1) printf(" public room.");
741         if (b==2) printf(" guess-name room.");
742         if (b==3) printf(" passworded room, password: %s",new_room_pass);
743         if (b==4) printf("n invitation-only room.");
744         printf("\nInstall it? (y/n) : ");
745         a=yesno();
746         if (a==0) return;
747
748         sprintf(cmd, "CRE8 1|%s|%d|%s|%d", new_room_name,
749                 new_room_type, new_room_pass, new_room_floor);
750         serv_puts(cmd);
751         serv_gets(cmd);
752         if (cmd[0]!='2') {
753                 printf("%s\n",&cmd[4]);
754                 return;
755                 }
756
757         /* command succeeded... now GO to the new room! */
758         dotgoto(new_room_name,0);
759         }
760
761
762
763 void readinfo() {       /* read info file for current room */
764         char cmd[256];
765         
766         sprintf(cmd,"RINF");
767         serv_puts(cmd);
768         serv_gets(cmd);
769
770         if (cmd[0]!='1') return;
771
772         fmout(screenwidth,NULL,
773                 ((userflags & US_PAGINATOR) ? 1 : 0),
774                 screenheight,0,1);
775         }
776
777
778 /*
779  * <W>ho knows room...
780  */
781 void whoknows() {
782         char buf[256];
783         serv_puts("WHOK");
784         serv_gets(buf);
785         if (buf[0]!='1') {
786                 printf("%s\n",&buf[5]);
787                 return;
788                 }
789         sigcaught = 0;
790         sttybbs(SB_YES_INTR);
791         while (serv_gets(buf), strncmp(buf,"000",3)) {
792                 if (sigcaught==0) printf("%s\n",buf);
793                 }
794         sttybbs(SB_NO_INTR);
795         }
796
797
798 void do_edit(desc,read_cmd,check_cmd,write_cmd)
799 char *desc;
800 char *read_cmd;
801 char *check_cmd;
802 char *write_cmd;
803         {
804         FILE *fp;
805         char cmd[256];
806         int b,cksum,editor_exit;
807
808
809         if (strlen(editor_path)==0) {
810                 printf("Do you wish to re-enter %s? ",desc);
811                 if (yesno()==0) return;
812                 }
813
814         fp = fopen(temp,"w");
815         fclose(fp);
816
817         serv_puts(check_cmd);
818         serv_gets(cmd);
819         if (cmd[0]!='2') {
820                 printf("%s\n",&cmd[4]);
821                 return;
822                 }
823
824         if (strlen(editor_path)>0) {
825                 serv_puts(read_cmd);
826                 serv_gets(cmd);
827                 if (cmd[0]=='1') {
828                         fp = fopen(temp,"w");
829                         while (serv_gets(cmd), strcmp(cmd,"000")) {
830                                 fprintf(fp,"%s\n",cmd);
831                                 }
832                         fclose(fp);
833                         }
834                 }
835
836         cksum = file_checksum(temp);
837
838         if (strlen(editor_path)>0) {
839                 editor_pid=fork();
840                 if (editor_pid==0) {
841                         chmod(temp,0600);
842                         sttybbs(SB_RESTORE);
843                         execlp(editor_path,editor_path,temp,NULL);
844                         exit(1);
845                         }
846                 if (editor_pid>0) do {
847                         editor_exit = 0;
848                         b=wait(&editor_exit);
849                         } while((b!=editor_pid)&&(b>=0));
850                 editor_pid = (-1);
851                 printf("Executed %s\n", editor_path);
852                 sttybbs(0);
853                 }
854         else {
855                 printf("Entering %s.  ",desc);
856                 printf("Press return twice when finished.\n");
857                 fp=fopen(temp,"r+");
858                 citedit(fp,0);
859                 fclose(fp);
860                 }
861
862         if (file_checksum(temp) == cksum) {
863                 printf("*** Aborted.\n");
864                 }
865
866         else {
867                 serv_puts(write_cmd);
868                 serv_gets(cmd);
869                 if (cmd[0]!='4') {
870                         printf("%s\n",&cmd[4]);
871                         return;
872                         }
873
874                 fp=fopen(temp,"r");
875                 while (fgets(cmd,255,fp)!=NULL) {
876                         cmd[strlen(cmd)-1] = 0;
877                         serv_puts(cmd);
878                         }
879                 fclose(fp);
880                 serv_puts("000");
881                 }
882
883         unlink(temp);
884         }
885
886
887 void enterinfo() {              /* edit info file for current room */
888         do_edit("the Info file for this room","RINF","EINF 0","EINF 1");
889         }
890
891 void enter_bio() {
892         char cmd[256];
893         sprintf(cmd,"RBIO %s",fullname);
894         do_edit("your Bio",cmd,"NOOP","EBIO");
895         }
896
897 /*
898  * create a new floor
899  */
900 void create_floor() {
901         char buf[256];
902         char newfloorname[256];
903
904         serv_puts("CFLR xx|0");
905         serv_gets(buf);
906         if (buf[0]!='2') {
907                 printf("%s\n",&buf[4]);
908                 return;
909                 }
910
911         newprompt("Name for new floor: ",newfloorname,255);
912         sprintf(buf,"CFLR %s|1",newfloorname);
913         serv_puts(buf);
914         serv_gets(buf);
915         if (buf[0]=='2') {
916                 printf("Floor has been created.\n");
917                 }
918         else {
919                 printf("%s\n",&buf[4]);
920                 }
921         }
922
923 /*
924  * edit the current floor
925  */
926 void edit_floor() {
927         char buf[256];
928
929         if (floorlist[(int)curr_floor][0]==0) load_floorlist();
930         strprompt("New floor name",&floorlist[(int)curr_floor][0],255);
931         sprintf(buf,"EFLR %d|%s",curr_floor,&floorlist[(int)curr_floor][0]);
932         serv_puts(buf);
933         serv_gets(buf);
934         printf("%s\n",&buf[4]);
935         load_floorlist();
936         }
937
938
939
940
941 /*
942  * kill the current floor 
943  */
944 void kill_floor() {
945         int floornum_to_delete,a;
946         char buf[256];
947
948         if (floorlist[(int)curr_floor][0]==0) load_floorlist();
949         do {
950                 floornum_to_delete = (-1);
951                 printf("(Press return to abort)\n");
952                 newprompt("Delete which floor? ",buf,255);
953                 if (strlen(buf)==0) return;
954                 for (a=0; a<128; ++a)
955                         if (!strucmp(&floorlist[a][0],buf))
956                                 floornum_to_delete = a;
957                 if (floornum_to_delete < 0) {
958                         printf("No such floor.  Select one of:\n");
959                         for (a=0; a<128; ++a)
960                                 if (floorlist[a][0]!=0)
961                                         printf("%s\n",&floorlist[a][0]);
962                         }
963                 } while (floornum_to_delete < 0);
964         sprintf(buf,"KFLR %d|1",floornum_to_delete);
965         serv_puts(buf);
966         serv_gets(buf);
967         printf("%s\n",&buf[4]);
968         }