]> code.citadel.org Git - citadel.git/blob - citadel/routines2.c
* Fully migrated cmd_greg() and cmd_regi() into serv_vcard (still has bugs)
[citadel.git] / citadel / routines2.c
1 /* More Citadel/UX routines...
2  * unlike routines.c, some of these DO use global variables.
3  * $Id$
4  */
5
6 #include "sysdep.h"
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <string.h>
15 #include <time.h>
16 #include <signal.h>
17 #include <pwd.h>
18 #include <setjmp.h>
19 #include <errno.h>
20 #include <stdarg.h>
21 #include "citadel.h"
22 #include "routines2.h"
23 #include "routines.h"
24 #include "commands.h"
25 #include "tools.h"
26 #include "messages.h"
27 #ifndef HAVE_SNPRINTF
28 #include "snprintf.h"
29 #endif
30
31 void interr(int errnum);
32 void strprompt(char *prompt, char *str, int len);
33 void newprompt(char *prompt, char *str, int len);
34 void sttybbs(int cmd);
35 int inkey(void);
36 void serv_write(char *buf, int nbytes);
37 int haschar(char *st, int ch);
38 void progress(long int curr, long int cmax);
39 void citedit(FILE *fp, long int base_pos);
40 int yesno(void);
41
42 extern char temp[];
43 extern char tempdir[];
44 extern char *axdefs[7];
45 extern long highest_msg_read;
46 extern long maxmsgnum;
47 extern unsigned room_flags;
48 extern int screenwidth;
49
50
51 int eopen(char *name, int mode)
52 {
53         int ret;
54         ret = open(name,mode);
55         if (ret<0) {
56                 fprintf(stderr,"Cannot open file '%s', mode=%d, errno=%d\n",
57                         name,mode,errno);
58                 interr(errno);
59                 }
60         return(ret);
61         }
62
63
64 int room_prompt(int qrflags)    /* return proper room prompt character */
65              {
66         int a;
67         a='>';
68         if (qrflags&QR_DIRECTORY) a=']';
69         if ((a==']')&&(qrflags&QR_NETWORK)) a='}';
70         if ((a=='>')&&(qrflags&QR_NETWORK)) a=')';
71         return(a);
72         }
73
74 void entregis(void)     /* register with name and address */
75         {
76
77         char buf[256];
78         char tmpname[256];
79         char tmpaddr[256];
80         char tmpcity[256];
81         char tmpstate[256];
82         char tmpzip[256];
83         char tmpphone[256];
84         char tmpemail[256];
85         int a;
86
87         strcpy(tmpname,"");
88         strcpy(tmpaddr,"");
89         strcpy(tmpcity,"");
90         strcpy(tmpstate,"");
91         strcpy(tmpzip,"");
92         strcpy(tmpphone,"");
93         strcpy(tmpemail,"");
94
95         serv_puts("GREG _SELF_");
96         serv_gets(buf);
97         if (buf[0]=='1') {
98                 a = 0;
99                 while (serv_gets(buf), strcmp(buf,"000")) {
100                         if (a==2) strcpy(tmpname,buf);
101                         if (a==3) strcpy(tmpaddr,buf);
102                         if (a==4) strcpy(tmpcity,buf);
103                         if (a==5) strcpy(tmpstate,buf);
104                         if (a==6) strcpy(tmpzip,buf);
105                         if (a==7) strcpy(tmpphone,buf);
106                         if (a==9) strcpy(tmpemail,buf);
107                         ++a;
108                         }
109                 }
110
111         strprompt("REAL name",tmpname,29);
112         strprompt("Address",tmpaddr,24);
113         strprompt("City/town",tmpcity,14);
114         strprompt("State",tmpstate,2);
115         strprompt("ZIP Code",tmpzip,10);
116         strprompt("Telephone number",tmpphone,14);
117         strprompt("Email address",tmpemail,31);
118
119         /* now send the registration info back to the server */
120         serv_puts("REGI");
121         serv_gets(buf);
122         if (buf[0]!='4') {
123                 printf("%s\n",&buf[4]);
124                 return;
125                 }
126         serv_puts(tmpname);
127         serv_puts(tmpaddr);
128         serv_puts(tmpcity);
129         serv_puts(tmpstate);
130         serv_puts(tmpzip);
131         serv_puts(tmpphone);
132         serv_puts(tmpemail);
133         serv_puts("000");
134         printf("\n");
135         }
136
137 void updatels(void) {   /* make all messages old in current room */
138         char buf[256];
139         serv_puts("SLRP HIGHEST");
140         serv_gets(buf);
141         if (buf[0]!='2') printf("%s\n",&buf[4]);
142         }
143
144 void updatelsa(void) {   /* only make messages old in this room that have been read */
145         char buf[256];
146         sprintf(buf,"SLRP %ld",highest_msg_read);
147         serv_puts(buf);
148         serv_gets(buf);
149         if (buf[0]!='2') printf("%s\n",&buf[4]);
150         }
151
152
153 /*
154  * This routine completes a client upload
155  */
156 void do_upload(int fd) {
157         char buf[256];
158         char tbuf[4096];
159         long transmitted_bytes, total_bytes;
160         int bytes_to_send;
161         int bytes_expected;
162
163         /* learn the size of the file */
164         total_bytes = lseek(fd,0L,2);
165         lseek(fd,0L,0);
166
167         transmitted_bytes = 0L;
168         progress(transmitted_bytes,total_bytes);
169         do {
170                 bytes_to_send = read(fd,tbuf,4096);
171                 if (bytes_to_send>0) {
172                         sprintf(buf,"WRIT %d",bytes_to_send);
173                         serv_puts(buf);
174                         serv_gets(buf);
175                         if (buf[0]=='7') {
176                                 bytes_expected = atoi(&buf[4]);
177                                 serv_write(tbuf,bytes_expected);
178                                 }
179                         else {
180                                 printf("%s\n",&buf[4]);
181                                 }
182                         }
183                 transmitted_bytes = transmitted_bytes + (long)bytes_to_send;
184                 progress(transmitted_bytes, total_bytes);
185                 } while (bytes_to_send > 0);
186
187         /* close the upload file, locally and at the server */
188         close(fd);
189         serv_puts("UCLS 1");
190         serv_gets(buf);
191         printf("%s\n",&buf[4]);
192         }
193
194
195 /*
196  * client-based uploads (for users with their own clientware)
197  */
198 void cli_upload(void) {
199         char flnm[256];
200         char desc[151];
201         char buf[256];
202         char tbuf[256];
203         int a;
204         int fd;
205
206         if ((room_flags & QR_UPLOAD) == 0) {
207                 printf("*** You cannot upload to this room.\n");
208                 return;
209                 }
210
211         newprompt("File to be uploaded: ",flnm,55);
212         fd = open(flnm,O_RDONLY);
213         if (fd<0) {
214                 printf("Cannot open '%s': %s\n",flnm,strerror(errno));
215                 return;
216                 }
217         printf("Enter a description of this file:\n");
218         newprompt(": ",desc,75);
219
220         /* keep generating filenames in hope of finding a unique one */
221         a = 0;
222         do {
223                 if (a==10) return; /* fail if tried 10 times */
224                 strcpy(buf,flnm);
225                 while ((strlen(buf)>0)&&(haschar(buf,'/')))
226                         strcpy(buf,&buf[1]);
227                 if (a>0) sprintf(&buf[strlen(buf)],"%d",a);
228                 sprintf(tbuf,"UOPN %s|%s",buf,desc);
229                 serv_puts(tbuf);
230                 serv_gets(buf);
231                 if (buf[0]!='2') printf("%s\n",&buf[4]);
232                 ++a;
233                 } while (buf[0]!='2');
234
235         /* at this point we have an open upload file at the server */
236         do_upload(fd);
237         }
238
239
240 /*
241  * Function used for various image upload commands
242  */
243 void cli_image_upload(char *keyname) {
244         char flnm[256];
245         char buf[256];
246         int fd;
247
248         sprintf(buf, "UIMG 0|%s", keyname);
249         serv_puts(buf);
250         serv_gets(buf);
251         if (buf[0] != '2') {
252                 printf("%s\n", &buf[4]);
253                 return;
254                 }
255
256         newprompt("Image file to be uploaded: ",flnm,55);
257         fd = open(flnm,O_RDONLY);
258         if (fd<0) {
259                 printf("Cannot open '%s': %s\n",flnm,strerror(errno));
260                 return;
261                 }
262
263         sprintf(buf, "UIMG 1|%s", keyname);
264         serv_puts(buf);
265         serv_gets(buf);
266         if (buf[0] != '2') {
267                 printf("%s\n", &buf[4]);
268                 return;
269                 }
270
271         do_upload(fd);
272         }
273
274
275 /*
276  * protocol-based uploads (Xmodem, Ymodem, Zmodem)
277  */
278 void upload(int c)      /* c = upload mode */
279        {
280         char flnm[256];
281         char desc[151];
282         char buf[256];
283         char tbuf[4096];
284         int xfer_pid;
285         int a,b;
286         FILE *fp,*lsfp;
287         int fd;
288
289         if ((room_flags & QR_UPLOAD) == 0) {
290                 printf("*** You cannot upload to this room.\n");
291                 return;
292                 }
293
294         /* we don't need a filename when receiving batch y/z modem */
295         if ((c==2)||(c==3)) strcpy(flnm,"x");
296         else newprompt("Enter filename: ",flnm,15);
297
298         for (a=0; a<strlen(flnm); ++a)
299                 if ( (flnm[a]=='/') || (flnm[a]=='\\') || (flnm[a]=='>')
300                      || (flnm[a]=='?') || (flnm[a]=='*')
301                      || (flnm[a]==';') || (flnm[a]=='&') ) flnm[a]='_';
302
303         newprompt("Enter a short description of the file:\n: ",desc,150);
304
305         /* create a temporary directory... */
306         if (mkdir(tempdir,0700) != 0) {
307                 printf("*** Could not create temporary directory %s: %s\n",
308                         tempdir,strerror(errno));
309                 return;
310                 }
311
312         /* now do the transfer ... in a separate process */
313         xfer_pid = fork();
314         if (xfer_pid == 0) {
315             chdir(tempdir);
316             switch(c) {
317                 case 0:
318                         sttybbs(0);
319                         printf("Receiving %s - press Ctrl-D to end.\n",flnm);
320                         fp = fopen(flnm,"w");
321                         do {
322                                 b=inkey(); 
323                                 if (b==13) {
324                                         b=10; printf("\r");
325                                         }
326                                 if (b!=4) {
327                                         printf("%c",b);
328                                         putc(b,fp);
329                                         }
330                                 } while(b!=4);
331                         fclose(fp);
332                         exit(0);
333                 case 1:
334                         sttybbs(3);
335                         execlp("rx","rx",flnm,NULL);
336                         exit(1);
337                 case 2:
338                         sttybbs(3);
339                         execlp("rb","rb",NULL);
340                         exit(1);
341                 case 3:
342                         sttybbs(3);
343                         execlp("rz","rz",NULL);
344                         exit(1);
345                         }
346                 }
347         else do {
348                 b=ka_wait(&a);
349                 } while ((b!=xfer_pid)&&(b!=(-1)));
350         sttybbs(0);
351
352         if (a != 0) {
353                 printf("\r*** Transfer unsuccessful.\n");
354                 nukedir(tempdir);
355                 return;
356                 }
357
358         printf("\r*** Transfer successful.  Sending file(s) to server...\n");
359         sprintf(buf,"cd %s; ls",tempdir);
360         lsfp = popen(buf,"r");
361         if (lsfp!=NULL) {
362                 while (fgets(flnm,256,lsfp)!=NULL) {
363                         flnm[strlen(flnm)-1] = 0;
364                         sprintf(buf,"%s/%s",tempdir,flnm);
365                         fd = open(buf,O_RDONLY);
366                         if (fd>=0) {
367                                 a = 0;
368                                 do {
369                                         sprintf(buf,"UOPN %s|%s",flnm,desc);
370                                         if (a>0) sprintf(&buf[strlen(buf)],
371                                                 ".%d",a);
372                                         ++a;
373                                         serv_puts(buf);
374                                         serv_gets(buf);
375                                         } while((buf[0]!='2')&&(a<100));
376                                 if (buf[0]=='2') do {
377                                         a=read(fd,tbuf,4096);
378                                         if (a>0) {
379                                                 sprintf(buf,"WRIT %d",a);
380                                                 serv_puts(buf);
381                                                 serv_gets(buf);
382                                                 if (buf[0]=='7')
383                                                         serv_write(tbuf,a);
384                                                 }
385                                         } while (a>0);
386                                 close(fd);
387                                 serv_puts("UCLS 1");
388                                 serv_gets(buf);
389                                 printf("%s\n",&buf[4]);
390                                 }
391                         }
392                 pclose(lsfp);
393                 }
394
395         nukedir(tempdir);
396         }
397
398 /* 
399  * validate a user
400  */
401 void val_user(char *user, int do_validate)
402 {
403         int a;
404         char cmd[256];
405         char buf[256];
406         int ax = 0;
407
408         sprintf(cmd, "GREG %s", user);
409         serv_puts(cmd);
410         serv_gets(cmd);
411         if (cmd[0]=='1') {
412                 a = 0;
413                 do {
414                         serv_gets(buf);
415                         ++a;
416                         if (a==1) printf("User #%s - %s  ", buf, &cmd[4]);
417                         if (a==2) printf("PW: %s\n",buf);
418                         if (a==3) printf("%s\n",buf);
419                         if (a==4) printf("%s\n",buf);
420                         if (a==5) printf("%s, ",buf);
421                         if (a==6) printf("%s ",buf);
422                         if (a==7) printf("%s\n",buf);
423                         if (a==8) printf("%s\n",buf);
424                         if (a==9) ax=atoi(buf);
425                         if (a==10) printf("%s\n",buf);
426                         } while(strcmp(buf,"000"));
427                 printf("Current access level: %d (%s)\n",ax,axdefs[ax]);
428                 }
429         else {
430                 printf("%-30s\n%s\n",user,&cmd[4]);
431                 }
432
433         if (do_validate) {
434                 /* now set the access level */
435                 ax = intprompt("Access level", ax, 0, 6);
436                 sprintf(cmd,"VALI %s|%d",user,ax);
437                 serv_puts(cmd);
438                 serv_gets(cmd);
439                 if (cmd[0]!='2') printf("%s\n",&cmd[4]);
440                 }
441         printf("\n");
442         }
443
444
445 void validate(void) {   /* validate new users */
446         char cmd[256];
447         char buf[256];
448         int finished = 0;
449
450         do {
451                 serv_puts("GNUR");
452                 serv_gets(cmd);
453                 if (cmd[0]!='3') finished = 1;
454                 if (cmd[0]=='2') printf("%s\n",&cmd[4]);
455                 if (cmd[0]=='3') {
456                         extract(buf, cmd, 0);
457                         val_user(&buf[4], 1);
458                         }
459                 } while(finished==0);
460         }
461
462 void subshell(void) {
463         int a,b;
464         a=fork();
465         if (a==0) {
466                 sttybbs(SB_RESTORE);
467                 signal(SIGINT,SIG_DFL);
468                 signal(SIGQUIT,SIG_DFL);
469                 execlp(getenv("SHELL"),getenv("SHELL"),NULL);
470                 printf("Could not open a shell: %s\n", strerror(errno));
471                 exit(errno);
472                 }
473         do {
474                 b=ka_wait(NULL);
475                 } while ((a!=b)&&(a!=(-1)));
476         sttybbs(0);
477         }
478
479 /*
480  * <.A>ide <F>ile <D>elete command
481  */
482 void deletefile(void) {
483         char filename[32];
484         char cmd[256];
485
486         newprompt("Filename: ",filename,31);
487         if (strlen(filename)==0) return;
488         sprintf(cmd,"DELF %s",filename);
489         serv_puts(cmd);
490         serv_gets(cmd);
491         printf("%s\n",&cmd[4]);
492         }
493
494 /*
495  * <.A>ide <F>ile <S>end command
496  */
497 void netsendfile(void) {
498         char filename[32],destsys[20],cmd[256];
499
500         newprompt("Filename: ",filename,31);
501         if (strlen(filename)==0) return;
502         newprompt("System to send to: ",destsys,19);
503         sprintf(cmd,"NETF %s|%s",filename,destsys);
504         serv_puts(cmd);
505         serv_gets(cmd);
506         printf("%s\n",&cmd[4]);
507         return;
508         }
509
510 /*
511  * <.A>ide <F>ile <M>ove command
512  */
513 void movefile(void) {
514         char filename[64];
515         char newroom[ROOMNAMELEN];
516         char cmd[256];
517
518         newprompt("Filename: ",filename,63);
519         if (strlen(filename)==0) return;
520         newprompt("Enter target room: ",newroom,ROOMNAMELEN-1);
521
522         sprintf(cmd,"MOVF %s|%s",filename,newroom);
523         serv_puts(cmd);
524         serv_gets(cmd);
525         printf("%s\n",&cmd[4]);
526         }
527
528
529 /* 
530  * list of users who have filled out a bio
531  */
532 void list_bio(void) {
533         char buf[256];
534         int pos = 1;
535
536         serv_puts("LBIO");
537         serv_gets(buf);
538         if (buf[0]!='1') {
539                 printf("%s\n",&buf[4]);
540                 return;
541                 }
542         while (serv_gets(buf), strcmp(buf,"000")) {
543                 if ((pos+strlen(buf)+5)>screenwidth) {
544                         printf("\n");
545                         pos = 1;
546                         }
547                 printf("%s, ",buf);
548                 pos = pos + strlen(buf) + 2;
549                 }
550         printf("%c%c  \n\n",8,8);
551         }
552
553
554 /*
555  * read bio
556  */
557 void read_bio(void) {
558         char who[256];
559         char buf[256];
560
561         do {
562                 newprompt("Read bio for who ('?' for list) : ",who,25);
563                 printf("\n");
564                 if (!strcmp(who,"?")) list_bio();
565                 } while(!strcmp(who,"?"));
566         sprintf(buf,"RBIO %s",who);
567         serv_puts(buf);
568         serv_gets(buf);
569         if (buf[0]!='1') {
570                 printf("%s\n",&buf[4]);
571                 return;
572                 }
573         while (serv_gets(buf), strcmp(buf,"000")) {
574                 printf("%s\n",buf);
575                 }
576         }
577
578
579 /* 
580  * General system configuration command
581  */
582 void do_system_configuration(void) {
583         char buf[256];
584         char sc[21][256];
585         int expire_mode = 0;
586         int expire_value = 0;
587         int a;
588
589         /* Clear out the config buffers */
590         memset(&sc[0][0], 0, sizeof(sc));
591
592         /* Fetch the current config */
593         serv_puts("CONF get");
594         serv_gets(buf);
595         if (buf[0] == '1') {
596                 a = 0;
597                 while (serv_gets(buf), strcmp(buf, "000")) {
598                         if (a<21) strcpy(&sc[a][0], buf);
599                         ++a;
600                         }
601                 }
602
603         /* Fetch the expire policy (this will silently fail on old servers,
604          * resulting in "default" policy)
605          */
606         serv_puts("GPEX site");
607         serv_gets(buf);
608         if (buf[0]=='2') {
609                 expire_mode = extract_int(&buf[4], 0);
610                 expire_value = extract_int(&buf[4], 1);
611                 }
612
613         strprompt("Node name", &sc[0][0], 15);
614         strprompt("Fully qualified domain name", &sc[1][0], 63);
615         strprompt("Human readable node name", &sc[2][0], 20);
616         strprompt("Modem dialup number", &sc[3][0], 15);
617
618         sprintf(&sc[4][0], "%d", (boolprompt(
619                 "Automatically give room aide privs to a user who creates a private room",
620                 atoi(&sc[4][0]))));
621
622         strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
623         strprompt("Initial access level for new users", &sc[6][0], 1);
624         strprompt("Access level required to create rooms", &sc[19][0], 1);
625
626         sprintf(&sc[7][0], "%d", (boolprompt(
627                 "Require registration for new users",
628                 atoi(&sc[7][0]))));
629
630         sprintf(&sc[8][0], "%d", (boolprompt(
631                 "Automatically move problem user messages to twit room",
632                 atoi(&sc[8][0]))));
633
634         strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
635         strprompt("Paginator prompt", &sc[10][0], 79);
636
637         sprintf(&sc[11][0], "%d", (boolprompt(
638                 "Restrict Internet mail to only those with that privilege",
639                 atoi(&sc[11][0]))));
640
641         strprompt("Geographic location of this system", &sc[12][0], 31);
642         strprompt("Name of system administrator", &sc[13][0], 25);
643         strprompt("Maximum concurrent sessions", &sc[14][0], 4);
644         strprompt("Server-to-server networking password", &sc[15][0], 19);
645         strprompt("Default user purge time (days)", &sc[16][0], 5);
646         strprompt("Default room purge time (days)", &sc[17][0], 5);
647         strprompt("Name of room to log pages", &sc[18][0], ROOMNAMELEN);
648         strprompt("Maximum message length", &sc[20][0], 20);
649
650         /* Angels and demons dancing in my head... */
651         do {
652                 sprintf(buf, "%d", expire_mode);
653                 strprompt("System default message expire policy (? for list)",
654                         buf, 1);
655                 if (buf[0] == '?') {
656                         printf("\n");
657                         printf("1. Never automatically expire messages\n");
658                         printf("2. Expire by message count\n");
659                         printf("3. Expire by message age\n");
660                         }
661                 } while((buf[0]<49)||(buf[0]>51));
662         expire_mode = buf[0] - 48;
663
664         /* ...lunatics and monsters underneath my bed */
665         if (expire_mode == 2) {
666                 sprintf(buf, "%d", expire_value);
667                 strprompt("Keep how many messages online?", buf, 10);
668                 expire_value = atol(buf);
669                 }
670
671         if (expire_mode == 3) {
672                 sprintf(buf, "%d", expire_value);
673                 strprompt("Keep messages for how many days?", buf, 10);
674                 expire_value = atol(buf);
675                 }
676
677         /* Save it */
678         printf("Save this configuration? ");
679         if (yesno()) {
680                 serv_puts("CONF set");
681                 serv_gets(buf);
682                 if (buf[0] == '4') {
683                         for (a=0; a<21; ++a) serv_puts(&sc[a][0]);
684                         serv_puts("000");
685                         }
686
687                 snprintf(buf, sizeof buf, "SPEX site|%d|%d",
688                         expire_mode, expire_value);
689                 serv_puts(buf);
690                 serv_gets(buf);
691                 }
692         }