1 /* More Citadel/UX routines...
2 * unlike routines.c, some of these DO use global variables.
20 #include "routines2.h"
24 void interr(int errnum);
25 void strprompt(char *prompt, char *str, int len);
26 void newprompt(char *prompt, char *str, int len);
27 void sttybbs(int cmd);
29 int ka_wait(pid_t *kstatus);
30 void serv_write(char *buf, int nbytes);
31 void extract(char *dest, char *source, int parmnum);
32 int haschar(char *st, int ch);
33 void progress(long int curr, long int cmax);
34 void citedit(FILE *fp, long int base_pos);
38 extern char tempdir[];
39 extern char *axdefs[7];
40 extern long highest_msg_read;
41 extern long maxmsgnum;
42 extern unsigned room_flags;
43 extern int screenwidth;
46 int eopen(char *name, int mode)
49 ret = open(name,mode);
51 fprintf(stderr,"Cannot open file '%s', mode=%d, errno=%d\n",
59 int room_prompt(int qrflags) /* return proper room prompt character */
63 if (qrflags&QR_DIRECTORY) a=']';
64 if ((a==']')&&(qrflags&QR_NETWORK)) a='}';
65 if ((a=='>')&&(qrflags&QR_NETWORK)) a=')';
69 void entregis(void) /* register with name and address */
90 serv_puts("GREG _SELF_");
94 while (serv_gets(buf), strcmp(buf,"000")) {
95 if (a==2) strcpy(tmpname,buf);
96 if (a==3) strcpy(tmpaddr,buf);
97 if (a==4) strcpy(tmpcity,buf);
98 if (a==5) strcpy(tmpstate,buf);
99 if (a==6) strcpy(tmpzip,buf);
100 if (a==7) strcpy(tmpphone,buf);
101 if (a==9) strcpy(tmpemail,buf);
106 strprompt("REAL name",tmpname,29);
107 strprompt("Address",tmpaddr,24);
108 strprompt("City/town",tmpcity,14);
109 strprompt("State",tmpstate,2);
110 strprompt("ZIP Code",tmpzip,10);
111 strprompt("Telephone number",tmpphone,14);
112 strprompt("Email address",tmpemail,31);
114 /* now send the registration info back to the server */
118 printf("%s\n",&buf[4]);
132 void updatels(void) { /* make all messages old in current room */
134 serv_puts("SLRP HIGHEST");
136 if (buf[0]!='2') printf("%s\n",&buf[4]);
139 void updatelsa(void) { /* only make messages old in this room that have been read */
141 sprintf(buf,"SLRP %ld",highest_msg_read);
144 if (buf[0]!='2') printf("%s\n",&buf[4]);
149 * This routine completes a client upload
151 void do_upload(int fd) {
154 long transmitted_bytes, total_bytes;
158 /* learn the size of the file */
159 total_bytes = lseek(fd,0L,2);
162 transmitted_bytes = 0L;
163 progress(transmitted_bytes,total_bytes);
165 bytes_to_send = read(fd,tbuf,4096);
166 if (bytes_to_send>0) {
167 sprintf(buf,"WRIT %d",bytes_to_send);
171 bytes_expected = atoi(&buf[4]);
172 serv_write(tbuf,bytes_expected);
175 printf("%s\n",&buf[4]);
178 transmitted_bytes = transmitted_bytes + (long)bytes_to_send;
179 progress(transmitted_bytes, total_bytes);
180 } while (bytes_to_send > 0);
182 /* close the upload file, locally and at the server */
186 printf("%s\n",&buf[4]);
191 * client-based uploads (for users with their own clientware)
193 void cli_upload(void) {
201 if ((room_flags & QR_UPLOAD) == 0) {
202 printf("*** You cannot upload to this room.\n");
206 newprompt("File to be uploaded: ",flnm,55);
207 fd = open(flnm,O_RDONLY);
209 printf("Cannot open '%s': %s\n",flnm,strerror(errno));
212 printf("Enter a description of this file:\n");
213 newprompt(": ",desc,75);
215 /* keep generating filenames in hope of finding a unique one */
218 if (a==10) return; /* fail if tried 10 times */
220 while ((strlen(buf)>0)&&(haschar(buf,'/')))
222 if (a>0) sprintf(&buf[strlen(buf)],"%d",a);
223 sprintf(tbuf,"UOPN %s|%s",buf,desc);
226 if (buf[0]!='2') printf("%s\n",&buf[4]);
228 } while (buf[0]!='2');
230 /* at this point we have an open upload file at the server */
236 * Function used for various image upload commands
238 void cli_image_upload(char *keyname) {
243 sprintf(buf, "UIMG 0|%s", keyname);
247 printf("%s\n", &buf[4]);
251 newprompt("Image file to be uploaded: ",flnm,55);
252 fd = open(flnm,O_RDONLY);
254 printf("Cannot open '%s': %s\n",flnm,strerror(errno));
258 sprintf(buf, "UIMG 1|%s", keyname);
262 printf("%s\n", &buf[4]);
271 * protocol-based uploads (Xmodem, Ymodem, Zmodem)
273 void upload(int c) /* c = upload mode */
284 if ((room_flags & QR_UPLOAD) == 0) {
285 printf("*** You cannot upload to this room.\n");
289 /* we don't need a filename when receiving batch y/z modem */
290 if ((c==2)||(c==3)) strcpy(flnm,"x");
291 else newprompt("Enter filename: ",flnm,15);
293 for (a=0; a<strlen(flnm); ++a)
294 if ( (flnm[a]=='/') || (flnm[a]=='\\') || (flnm[a]=='>')
295 || (flnm[a]=='?') || (flnm[a]=='*')
296 || (flnm[a]==';') || (flnm[a]=='&') ) flnm[a]='_';
298 newprompt("Enter a short description of the file:\n: ",desc,150);
300 /* create a temporary directory... */
301 if (mkdir(tempdir,0700) != 0) {
302 printf("*** Could not create temporary directory %s: %s\n",
303 tempdir,strerror(errno));
307 /* now do the transfer ... in a separate process */
314 printf("Receiving %s - press Ctrl-D to end.\n",flnm);
315 fp = fopen(flnm,"w");
330 execlp("rx","rx",flnm,NULL);
334 execlp("rb","rb",NULL);
338 execlp("rz","rz",NULL);
344 } while ((b!=xfer_pid)&&(b!=(-1)));
348 printf("\r*** Transfer unsuccessful.\n");
353 printf("\r*** Transfer successful. Sending file(s) to server...\n");
354 sprintf(buf,"cd %s; ls",tempdir);
355 lsfp = popen(buf,"r");
357 while (fgets(flnm,256,lsfp)!=NULL) {
358 flnm[strlen(flnm)-1] = 0;
359 sprintf(buf,"%s/%s",tempdir,flnm);
360 fd = open(buf,O_RDONLY);
364 sprintf(buf,"UOPN %s|%s",flnm,desc);
365 if (a>0) sprintf(&buf[strlen(buf)],
370 } while((buf[0]!='2')&&(a<100));
371 if (buf[0]=='2') do {
372 a=read(fd,tbuf,4096);
374 sprintf(buf,"WRIT %d",a);
384 printf("%s\n",&buf[4]);
396 void val_user(char *user)
403 sprintf(cmd,"GREG %s",user);
411 if (a==1) printf("User #%s - %s ",
413 if (a==2) printf("PW: %s\n",buf);
414 if (a==3) printf("%s\n",buf);
415 if (a==4) printf("%s\n",buf);
416 if (a==5) printf("%s, ",buf);
417 if (a==6) printf("%s ",buf);
418 if (a==7) printf("%s\n",buf);
419 if (a==8) printf("%s\n",buf);
420 if (a==9) ax=atoi(buf);
421 if (a==10) printf("%s\n",buf);
422 } while(strcmp(buf,"000"));
423 printf("Current access level: %d (%s)\n",ax,axdefs[ax]);
426 printf("%-30s\n%s\n",user,&cmd[4]);
429 /* now set the access level */
431 printf("Access level (? for list): ");
436 printf("%d %s\n",b,axdefs[b]);
439 } while((a<0)||(a>6));
441 sprintf(cmd,"VALI %s|%d",user,a);
444 if (cmd[0]!='2') printf("%s\n",&cmd[4]);
449 void validate(void) { /* validate new users */
457 if (cmd[0]!='3') finished = 1;
458 if (cmd[0]=='2') printf("%s\n",&cmd[4]);
463 } while(finished==0);
466 void subshell(void) {
471 signal(SIGINT,SIG_DFL);
472 signal(SIGQUIT,SIG_DFL);
473 execlp(getenv("SHELL"),getenv("SHELL"),NULL);
474 printf("Could not open a shell: %s\n", strerror(errno));
479 } while ((a!=b)&&(a!=(-1)));
484 * <.A>ide <F>ile <D>elete command
486 void deletefile(void) {
490 newprompt("Filename: ",filename,31);
491 if (strlen(filename)==0) return;
492 sprintf(cmd,"DELF %s",filename);
495 printf("%s\n",&cmd[4]);
499 * <.A>ide <F>ile <S>end command
501 void netsendfile(void) {
502 char filename[32],destsys[20],cmd[256];
504 newprompt("Filename: ",filename,31);
505 if (strlen(filename)==0) return;
506 newprompt("System to send to: ",destsys,19);
507 sprintf(cmd,"NETF %s|%s",filename,destsys);
510 printf("%s\n",&cmd[4]);
515 * <.A>ide <F>ile <M>ove command
517 void movefile(void) {
519 char newroom[ROOMNAMELEN];
522 newprompt("Filename: ",filename,63);
523 if (strlen(filename)==0) return;
524 newprompt("Enter target room: ",newroom,ROOMNAMELEN-1);
526 sprintf(cmd,"MOVF %s|%s",filename,newroom);
529 printf("%s\n",&cmd[4]);
534 * list of users who have filled out a bio
536 void list_bio(void) {
543 printf("%s\n",&buf[4]);
546 while (serv_gets(buf), strcmp(buf,"000")) {
547 if ((pos+strlen(buf)+5)>screenwidth) {
552 pos = pos + strlen(buf) + 2;
554 printf("%c%c \n\n",8,8);
561 void read_bio(void) {
566 newprompt("Read bio for who ('?' for list) : ",who,25);
568 if (!strcmp(who,"?")) list_bio();
569 } while(!strcmp(who,"?"));
570 sprintf(buf,"RBIO %s",who);
574 printf("%s\n",&buf[4]);
577 while (serv_gets(buf), strcmp(buf,"000")) {
584 * General system configuration command
586 void do_system_configuration(void) {
590 int expire_value = 0;
593 /* Clear out the config buffers */
594 bzero(&sc[0][0], sizeof(sc));
596 /* Fetch the current config */
597 serv_puts("CONF get");
601 while (serv_gets(buf), strcmp(buf, "000")) {
602 if (a<17) strcpy(&sc[a][0], buf);
607 /* Fetch the expire policy (this will silently fail on old servers,
608 * resulting in "default" policy)
610 serv_puts("GPEX site");
613 expire_mode = extract_int(&buf[4], 0);
614 expire_value = extract_int(&buf[4], 1);
617 strprompt("Node name", &sc[0][0], 15);
618 strprompt("Fully qualified domain name", &sc[1][0], 63);
619 strprompt("Human readable node name", &sc[2][0], 20);
620 strprompt("Modem dialup number", &sc[3][0], 15);
621 /* FIX add the rest of them */
623 /* Angels and demons dancing in my head... */
625 sprintf(buf, "%d", expire_mode);
626 strprompt("System default message expire policy (? for list)",
630 printf("1. Never automatically expire messages\n");
631 printf("2. Expire by message count\n");
632 printf("3. Expire by message age\n");
634 } while((buf[0]<49)||(buf[0]>51));
635 expire_mode = buf[0] - 48;
637 /* ...lunatics and monsters underneath my bed */
638 if (expire_mode == 2) {
639 sprintf(buf, "%d", expire_value);
640 strprompt("Keep how many messages online?", buf, 10);
641 expire_value = atol(buf);
644 if (expire_mode == 3) {
645 sprintf(buf, "%d", expire_value);
646 strprompt("Keep messages for how many days?", buf, 10);
647 expire_value = atol(buf);
651 printf("Save this configuration? ");
653 serv_puts("CONF set");
656 for (a=0; a<17; ++a) serv_puts(&sc[a][0]);
660 snprintf(buf, sizeof buf, "SPEX site|%d|%d",
661 expire_mode, expire_value);