]> code.citadel.org Git - citadel.git/blob - citadel/routines.c
* Implemented CONF server command for site-global configs
[citadel.git] / citadel / routines.c
1 /* Citadel/UX support routines */
2 /* $Id$ */
3
4 #include "sysdep.h"
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/ioctl.h>
13 #include <pwd.h>
14 #include <signal.h>
15 #include <dirent.h>
16 #include <errno.h>
17
18
19 #define ROUTINES_C
20
21 #include "citadel.h"
22 #include "routines.h"
23 #include "commands.h"
24
25 void sttybbs(int cmd);
26 void newprompt(char *prompt, char *str, int len);
27 void val_user(char *user);
28 int intprompt(char *prompt, int ival, int imin, int imax);
29 void formout(char *name);
30 void logoff(int code);
31 void set_keepalives(int s);
32 void strprompt(char *prompt, char *str, int len);
33 void newprompt(char *prompt, char *str, int len);
34 void color(int colornum);
35
36 #define IFAIDE if(axlevel>=6)
37 #define IFNAIDE if (axlevel<6)
38
39 extern unsigned userflags;
40 extern char *axdefs[7];
41 extern char sigcaught;
42 extern struct CtdlServInfo serv_info;
43 extern char rc_floor_mode;
44
45 int struncmp(char *lstr, char *rstr, int len)
46 {
47         int pos = 0;
48         char lc,rc;
49         while (pos<len) {
50                 lc=tolower(lstr[pos]);
51                 rc=tolower(rstr[pos]);
52                 if ((lc==0)&&(rc==0)) return(0);
53                 if (lc<rc) return(-1);
54                 if (lc>rc) return(1);
55                 pos=pos+1;
56                 }
57         return(0);
58         }
59
60
61 /* 
62  * check for the presence of a character within a string (returns count)
63  */
64 int haschar(char *st, int ch)
65 {
66         int a,b;
67         b=0;
68         for (a=0; a<strlen(st); ++a) if (st[a]==ch) ++b;
69         return(b);
70         }
71
72
73 /*
74  * num_parms()  -  discover number of parameters...
75  */
76 int num_parms(char *source)
77 {
78         int a;
79         int count = 1;
80
81         for (a=0; a<strlen(source); ++a) 
82                 if (source[a]=='|') ++count;
83         return(count);
84         }
85
86 /*
87  * extract()  -  extract a parameter from a series of "|" separated...
88  */
89 void extract(char *dest, char *source, int parmnum)
90 {
91         char buf[256];
92         int count = 0;
93         int n;
94
95         n = num_parms(source);
96
97         if (parmnum >= n) {
98                 strcpy(dest,"");
99                 return;
100                 }
101         strcpy(buf,source);
102         if ( (parmnum == 0) && (n == 1) ) {
103                 strcpy(dest,buf);
104                 return;
105                 }
106
107         while (count++ < parmnum) do {
108                 strcpy(buf,&buf[1]);
109                 } while( (strlen(buf)>0) && (buf[0]!='|') );
110         if (buf[0]=='|') strcpy(buf,&buf[1]);
111         for (count = 0; count<strlen(buf); ++count)
112                 if (buf[count] == '|') buf[count] = 0;
113         strcpy(dest,buf);
114         }
115
116 /*
117  * extract_int()  -  extract an int parm w/o supplying a buffer
118  */
119 int extract_int(char *source, int parmnum)
120 {
121         char buf[256];
122         
123         extract(buf,source,parmnum);
124         return(atoi(buf));
125         }
126
127 /*
128  * extract_long()  -  extract a long parm w/o supplying a buffer
129  */
130 long extract_long(char *source, int parmnum)
131 {
132         char buf[256];
133         
134         extract(buf,source,parmnum);
135         return(atol(buf));
136         }
137
138 void back(int spaces) /* Destructive backspace */
139             {
140 int a;
141         for (a=1; a<=spaces; ++a) {
142                 putc(8,stdout); putc(32,stdout); putc(8,stdout);
143                 }
144         }
145
146 void hit_any_key(void) {                /* hit any key to continue */
147         int a,b;
148
149         printf("%s\r",serv_info.serv_moreprompt);
150         sttybbs(0);
151         b=inkey();
152         for (a=0; a<strlen(serv_info.serv_moreprompt); ++a)
153                 putc(' ',stdout);
154         putc(13,stdout);
155         sttybbs(1);
156         if (b==NEXT_KEY) sigcaught = SIGINT;
157         if (b==STOP_KEY) sigcaught = SIGQUIT;
158         }
159
160 /*
161  * change a user's access level
162  */
163 void edituser(void)
164 {
165         char who[256];
166         char buf[256];
167
168         newprompt("User name: ",who,25);
169         sprintf(buf,"QUSR %s",who);
170         serv_puts(buf);
171         serv_gets(buf);
172         if (buf[0]!='2') {
173                 printf("%s\n",&buf[4]);
174                 return;
175                 }
176         
177         val_user(who);
178         }
179
180
181 int set_attr(int sval, char *prompt, unsigned int sbit)
182 {
183         int a;
184         int temp;
185
186         temp = sval;
187         color(3);
188         printf("%45s [", prompt);
189         color(1);
190         printf("%3s", ((temp&sbit) ? "Yes":"No"));
191         color(3);
192         printf("]? ");
193         color(2);
194         a=yesno_d(temp&sbit);
195         color(7);
196         temp=(temp|sbit);
197         if (!a) temp=(temp^sbit);
198         return(temp);
199         }
200
201 /*
202  * modes are:  0 - .EC command, 1 - .EC for new user,
203  *             2 - toggle Xpert mode  3 - toggle floor mode
204  */
205 void enter_config(int mode)
206 {
207         int width,height,flags;
208         char buf[128];
209
210         sprintf(buf,"GETU");
211         serv_puts(buf);
212         serv_gets(buf);
213         if (buf[0]!='2') {
214                 printf("%s\n",&buf[4]);
215                 return;
216                 }
217
218         width = extract_int(&buf[4],0);
219         height = extract_int(&buf[4],1);
220         flags = extract_int(&buf[4],2);
221
222         if ((mode==0)||(mode==1)) {
223
224          width = intprompt("Enter your screen width",width,20,255);
225          height = intprompt("Enter your screen height",height,3,255);
226  
227          flags = set_attr(flags,
228                 "Are you an experienced Citadel user",US_EXPERT);
229          if ( ((flags&US_EXPERT)==0) && (mode==1))
230                 return;
231          flags = set_attr(flags,
232                 "Print last old message on New message request",US_LASTOLD);
233          if ((flags&US_EXPERT)==0) formout("unlisted");
234          flags = set_attr(flags,"Be unlisted in userlog",US_UNLISTED);
235          flags = set_attr(flags,"Suppress message prompts",US_NOPROMPT);
236          if ((flags & US_NOPROMPT)==0)
237             flags = set_attr(flags,"Use 'disappearing' prompts",US_DISAPPEAR);
238          flags = set_attr(flags,
239                 "Pause after each screenful of text",US_PAGINATOR);
240          if (rc_floor_mode == RC_DEFAULT) {
241           flags = set_attr(flags,
242                 "View rooms by floor",US_FLOORS);
243           }
244          }
245
246         if (mode==2) {
247          if (flags & US_EXPERT) {
248                 flags = (flags ^ US_EXPERT);
249                 printf("Expert mode now OFF\n");
250                 }
251          else {
252                 flags = (flags | US_EXPERT);
253                 printf("Expert mode now ON\n");
254                 }
255          }
256
257         if (mode==3) {
258          if (flags & US_FLOORS) {
259                 flags = (flags ^ US_FLOORS);
260                 printf("Floor mode now OFF\n");
261                 }
262          else {
263                 flags = (flags | US_FLOORS);
264                 printf("Floor mode now ON\n");
265                 }
266          }
267
268         sprintf(buf,"SETU %d|%d|%d",width,height,flags);
269         serv_puts(buf);
270         serv_gets(buf);
271         if (buf[0]!='2') printf("%s\n",&buf[4]);
272         userflags = flags;
273 }
274
275 /*
276  * getstring()  -  get a line of text from a file
277  *                 ignores lines beginning with "#"
278  */
279 int getstring(FILE *fp, char *string)
280 {
281         int a,c;
282         do {
283                 strcpy(string,"");
284                 a=0;
285                 do {
286                         c=getc(fp);
287                         if (c<0) {
288                                 string[a]=0;
289                                 return(-1);
290                                 }
291                         string[a++]=c;
292                         } while(c!=10);
293                         string[a-1]=0;
294                 } while(string[0]=='#');
295         return(strlen(string));
296         }
297
298 int pattern(char *search, char *patn)   /* Searches for patn in search string */
299               
300             
301 {
302         int a,b;
303         for (a=0; a<strlen(search); ++a)
304         {       b=struncmp(&search[a],patn,strlen(patn));
305                 if (b==0) return(b);
306                 }
307         return(-1);
308 }
309
310 void interr(int errnum) /* display internal error as defined in errmsgs */
311             {
312         printf("*** INTERNAL ERROR %d\n",errnum);
313         printf("(Press any key to continue)\n");
314         inkey();
315         logoff(errnum);
316 }
317
318
319
320 /*
321  * Check to see if we need to pause at the end of a screen.
322  * If we do, we have to disable server keepalives during the pause because
323  * we are probably in the middle of a server operation and the NOOP command
324  * would confuse everything.
325  */
326 int checkpagin(int lp, int pagin, int height)
327 {
328         if (pagin!=1) return(0);
329         if (lp>=(height-1)) {
330                 set_keepalives(KA_NO);
331                 hit_any_key();
332                 set_keepalives(KA_YES);
333                 return(0);
334                 }
335         return(lp);
336         }
337
338
339 void strproc(char *string)
340 {
341         int a;
342
343         if (strlen(string)==0) return;
344
345         /* Convert non-printable characters to blanks */
346         for (a=0; a<strlen(string); ++a) {
347                 if (string[a]<32) string[a]=32;
348                 if (string[a]>126) string[a]=32;
349                 }
350
351         /* Remove leading and trailing blanks */
352         while(string[0]<33) strcpy(string,&string[1]);
353         while(string[strlen(string)-1]<33) string[strlen(string)-1]=0;
354
355         /* Remove double blanks */
356         for (a=0; a<strlen(string); ++a) {
357                 if ((string[a]==32)&&(string[a+1]==32)) {
358                         strcpy(&string[a],&string[a+1]);
359                         a=0;
360                         }
361                 }
362
363         /* remove characters which would interfere with the network */
364         for (a=0; a<strlen(string); ++a) {
365                 if (string[a]=='!') strcpy(&string[a],&string[a+1]);
366                 if (string[a]=='@') strcpy(&string[a],&string[a+1]);
367                 if (string[a]=='_') strcpy(&string[a],&string[a+1]);
368                 if (string[a]==',') strcpy(&string[a],&string[a+1]);
369                 if (string[a]=='%') strcpy(&string[a],&string[a+1]);
370                 if (string[a]=='|') strcpy(&string[a],&string[a+1]);
371                 }
372
373         }
374
375
376 #ifndef HAVE_STRERROR
377 /*
378  * replacement strerror() for systems that don't have it
379  */
380 char *strerror(int e)
381 {
382         static char buf[32];
383
384         sprintf(buf,"errno = %d",e);
385         return(buf);
386         }
387 #endif
388
389
390 void progress(long int curr, long int cmax)
391 {
392         static long dots_printed;
393         long a;
394
395         if (curr==0) {
396                 printf(".......................................");
397                 printf(".......................................\r");
398                 fflush(stdout);
399                 dots_printed = 0;
400                 }
401         else if (curr==cmax) {
402                 printf("\r%79s\n","");
403                 }
404         else {
405                 a=(curr * 100) / cmax;
406                 a=a*78; a=a/100;
407                 while (dots_printed < a) {
408                         printf("*");
409                         ++dots_printed;
410                         fflush(stdout);
411                         }
412                 }
413         }
414
415
416 /*
417  * NOT the same locate_host() in locate_host.c.  This one just does a
418  * 'who am i' to try to discover where the user is...
419  */
420 void locate_host(char *hbuf)
421 {
422         char buf[256];
423         FILE *who;
424         int a,b;
425
426         who = (FILE *)popen("who am i","r");
427         if (who==NULL) {
428                 strcpy(hbuf,serv_info.serv_fqdn);
429                 return; 
430                 }
431         fgets(buf,256,who);
432         pclose(who);
433
434         b = 0;
435         for (a=0; a<strlen(buf); ++a) {
436                 if ((buf[a]=='(')||(buf[a]==')')) ++b;
437                 }
438         if (b<2) {
439                 strcpy(hbuf,serv_info.serv_fqdn);
440                 return;
441                 }
442
443         for (a=0; a<strlen(buf); ++a) {
444                 if (buf[a]=='(') {
445                         strcpy(buf,&buf[a+1]);
446                         }
447                 }
448         for (a=0; a<strlen(buf); ++a) {
449                 if (buf[a]==')') buf[a] = 0;
450                 }
451
452         if (strlen(buf)==0) strcpy(hbuf,serv_info.serv_fqdn);
453         else strncpy(hbuf,buf,24);
454         }
455
456 /*
457  * miscellaneous server commands (testing, etc.)
458  */
459 void misc_server_cmd(char *cmd) {
460         char buf[256];
461
462         serv_puts(cmd);
463         serv_gets(buf);
464         printf("%s\n",buf);
465         if (buf[0]=='1') {
466                 while (serv_gets(buf), strcmp(buf,"000")) {
467                         printf("%s\n",buf);
468                         }
469                 return;
470                 }
471         if (buf[0]=='4') {
472                 do {
473                         newprompt("> ",buf,255);
474                         serv_puts(buf);
475                         } while(strcmp(buf,"000"));
476                 return;
477                 }
478         }
479
480
481 /*
482  * compute the checksum of a file
483  */
484 int file_checksum(char *filename)
485 {
486         int cksum = 0;
487         int ch;
488         FILE *fp;
489
490         fp = fopen(filename,"r");
491         if (fp == NULL) return(0);
492
493         /* yes, this algorithm may allow cksum to overflow, but that's ok
494          * as long as it overflows consistently, which it will.
495          */
496         while (ch=getc(fp), ch>=0) {
497                 cksum = (cksum + ch);
498                 }
499
500         fclose(fp);
501         return(cksum);
502         }
503
504 /*
505  * nuke a directory and its contents
506  */
507 int nukedir(char *dirname)
508 {
509         DIR *dp;
510         struct dirent *d;
511         char filename[256];
512
513         dp = opendir(dirname);
514         if (dp == NULL) {
515                 return(errno);
516                 }
517
518         while (d = readdir(dp), d != NULL) {
519                 sprintf(filename, "%s/%s", dirname, d->d_name);
520                 unlink(filename);
521                 }
522
523         closedir(dp);
524         return(rmdir(dirname));
525         }