4 * Client-side support functions.
15 #include <sys/types.h>
16 #include <sys/ioctl.h>
22 #if TIME_WITH_SYS_TIME
23 # include <sys/time.h>
27 # include <sys/time.h>
42 #include "citadel_ipc.h"
45 #ifndef HAVE_GETUTLINE
46 struct utmp *getutline(struct utmp *ut);
55 #include "citadel_decls.h"
56 #include "routines2.h"
58 #define IFAIDE if(axlevel>=6)
59 #define IFNAIDE if (axlevel<6)
61 extern unsigned userflags;
62 extern char *axdefs[7];
63 extern char sigcaught;
64 extern struct CtdlServInfo serv_info;
65 extern char rc_floor_mode;
66 extern int rc_ansi_color;
67 extern int rc_prompt_control;
69 /* Destructive backspace */
70 void back(int spaces) {
72 for (a=0; a<spaces; ++a) {
79 void hit_any_key(void) { /* hit any key to continue */
84 scr_printf("%s\r",serv_info.serv_moreprompt);
88 for (a=0; a<strlen(serv_info.serv_moreprompt); ++a)
92 if ( (rc_prompt_control == 1)
93 || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
94 if (b == 'q' || b == 'Q' || b == 's' || b == 'S')
96 if (b == 'n' || b == 'N')
99 if (b==NEXT_KEY) sigcaught = SIGINT;
100 if (b==STOP_KEY) sigcaught = SIGQUIT;
104 * change a user's access level
109 char who[USERNAME_SIZE];
110 struct usersupp *user = NULL;
112 int r; /* IPC response code */
114 newprompt("User name: ", who, 25);
115 while ((r = CtdlIPCAideGetUserParameters(who, &user, buf)) / 100 != 2) {
116 scr_printf("%s\n", buf);
117 scr_printf("Do you want to create this user? ");
119 r = CtdlIPCCreateUser(who, 0, buf);
124 scr_printf("%s\n",&buf[4]);
130 val_user(user->fullname, 0); /* Display registration */
132 if (newnow || boolprompt("Change password", 0)) { /* I'm lazy */
133 strprompt("Password", user->password, -19);
136 user->axlevel = intprompt("Access level", user->axlevel, 0, 6);
137 if (boolprompt("Ask user to register again", !(user->flags & US_REGIS)))
138 user->flags &= ~US_REGIS;
140 user->flags |= US_REGIS;
141 user->timescalled = intprompt("Times called",
142 user->timescalled, 0, INT_MAX);
143 user->posted = intprompt("Messages posted",
144 user->posted, 0, INT_MAX);
145 user->lastcall = boolprompt("Set last call to now", 0) ?
146 time(NULL) : user->lastcall;
147 user->USuserpurge = intprompt("Purge time (in days, 0 for system default",
148 user->USuserpurge, 0, INT_MAX);
150 r = CtdlIPCAideSetUserParameters(user, buf);
152 scr_printf("%s\n", buf);
158 /* Display a prompt and flip a bit based on whether the user answers
159 * yes or no. Yes=1 and No=0, unless 'backwards' is set to a nonzero value
160 * in which case No=1 and Yes=0.
162 int set_attr(int sval, char *prompt, unsigned int sbit, int backwards)
169 scr_printf("%45s ", prompt);
172 color(BRIGHT_MAGENTA);
175 scr_printf("%3s", ((temp&sbit) ? "No":"Yes"));
178 scr_printf("%3s", ((temp&sbit) ? "Yes":"No"));
186 if (backwards) a = 1 - a;
188 if (backwards) a = 1 - a;
191 if (!a) temp = (temp^sbit);
196 * modes are: 0 - .EC command, 1 - .EC for new user,
197 * 2 - toggle Xpert mode 3 - toggle floor mode
199 void enter_config(int mode)
202 struct usersupp *user = NULL;
203 int r; /* IPC response code */
205 r = CtdlIPCGetConfig(&user, buf);
207 scr_printf("%s\n", buf);
212 if (mode == 0 || mode == 1) {
214 user->USscreenwidth = intprompt("Enter your screen width",
215 user->USscreenwidth, 20, 255);
216 user->USscreenheight = intprompt("Enter your screen height",
217 user->USscreenheight, 3, 255);
219 user->flags = set_attr(user->flags,
220 "Are you an experienced Citadel user",
222 if ((user->flags & US_EXPERT) == 0 && mode == 1) {
227 user->flags = set_attr(user->flags,
228 "Print last old message on New message request",
231 user->flags = set_attr(user->flags,
232 "Prompt after each message",
235 if ((user->flags & US_NOPROMPT) == 0)
236 user->flags = set_attr(user->flags,
237 "Use 'disappearing' prompts",
240 user->flags = set_attr(user->flags,
241 "Pause after each screenful of text",
244 if (rc_prompt_control == 3 && (user->flags & US_PAGINATOR))
245 user->flags = set_attr(user->flags,
246 "<N>ext and <S>top work at paginator prompt",
249 if (rc_floor_mode == RC_DEFAULT)
250 user->flags = set_attr(user->flags,
251 "View rooms by floor",
254 if (rc_ansi_color == 3)
255 user->flags = set_attr(user->flags,
256 "Enable color support",
259 if ((user->flags & US_EXPERT) == 0)
262 user->flags = set_attr(user->flags,
263 "Be unlisted in userlog",
268 if (user->flags & US_EXPERT) {
269 user->flags ^= US_EXPERT;
270 scr_printf("Expert mode now OFF\n");
272 user->flags |= US_EXPERT;
273 scr_printf("Expert mode now ON\n");
278 if (user->flags & US_FLOORS) {
279 user->flags ^= US_FLOORS;
280 scr_printf("Floor mode now OFF\n");
282 user->flags |= US_FLOORS;
283 scr_printf("Floor mode now ON\n");
287 r = CtdlIPCSetConfig(user, buf);
288 if (r / 100 != 2) scr_printf("%s\n", buf);
289 userflags = user->flags;
294 * getstring() - get a line of text from a file
295 * ignores lines beginning with "#"
297 int getstring(FILE *fp, char *string)
312 } while(string[0]=='#');
313 return(strlen(string));
317 /* Searches for patn in search string */
318 int pattern(char *search, char *patn) {
321 for (a=0; a<strlen(search); ++a) {
322 b=strncasecmp(&search[a],patn,strlen(patn));
329 /* display internal error as defined in errmsgs */
330 void interr(int errnum) {
331 scr_printf("*** INTERNAL ERROR %d\n"
332 "(Press any key to continue)\n", errnum);
337 void strproc(char *string)
341 if (strlen(string)==0) return;
343 /* Convert non-printable characters to blanks */
344 for (a=0; a<strlen(string); ++a) {
345 if (string[a]<32) string[a]=32;
346 if (string[a]>126) string[a]=32;
349 /* Remove leading and trailing blanks */
350 while(string[0]<33) strcpy(string,&string[1]);
351 while(string[strlen(string)-1]<33) string[strlen(string)-1]=0;
353 /* Remove double blanks */
354 for (a=0; a<strlen(string); ++a) {
355 if ((string[a]==32)&&(string[a+1]==32)) {
356 strcpy(&string[a],&string[a+1]);
361 /* remove characters which would interfere with the network */
362 for (a=0; a<strlen(string); ++a) {
363 if (string[a]=='!') strcpy(&string[a],&string[a+1]);
364 if (string[a]=='@') strcpy(&string[a],&string[a+1]);
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]);
374 #ifndef HAVE_STRERROR
376 * replacement strerror() for systems that don't have it
378 char *strerror(int e)
380 static char buf[128];
382 snprintf(buf, sizeof buf, "errno = %d",e);
388 void progress(long int curr, long int cmax)
390 static long dots_printed;
394 scr_printf(".......................................");
395 scr_printf(".......................................\r");
399 else if (curr==cmax) {
400 scr_printf("\r%79s\n","");
403 a=(curr * 100) / cmax;
405 while (dots_printed < a) {
415 * NOT the same locate_host() in locate_host.c. This one just does a
416 * 'who am i' to try to discover where the user is...
418 void locate_host(char *hbuf)
425 who = (FILE *)popen("who am i","r");
427 strcpy(hbuf,serv_info.serv_fqdn);
430 fgets(buf,sizeof buf,who);
434 for (a=0; a<strlen(buf); ++a) {
435 if ((buf[a]=='(')||(buf[a]==')')) ++b;
438 strcpy(hbuf,serv_info.serv_fqdn);
442 for (a=0; a<strlen(buf); ++a) {
444 strcpy(buf,&buf[a+1]);
447 for (a=0; a<strlen(buf); ++a) {
448 if (buf[a]==')') buf[a] = 0;
451 if (strlen(buf)==0) strcpy(hbuf,serv_info.serv_fqdn);
452 else strncpy(hbuf,buf,24);
454 char *tty = ttyname(0);
455 #ifdef HAVE_GETUTXLINE
456 struct utmpx ut, *put;
458 struct utmp ut, *put;
463 safestrncpy(hbuf, serv_info.serv_fqdn, 24);
467 if (strncmp(tty, "/dev/", 5))
470 safestrncpy(ut.ut_line, &tty[5], sizeof ut.ut_line);
472 #ifdef HAVE_GETUTXLINE /* Solaris uses this */
473 if ((put = getutxline(&ut)) == NULL)
475 if ((put = getutline(&ut)) == NULL)
479 #if defined(HAVE_UT_TYPE) || defined(HAVE_GETUTXLINE)
480 if (put->ut_type == USER_PROCESS) {
482 #if defined(HAVE_UT_HOST) || defined(HAVE_GETUTXLINE)
484 safestrncpy(hbuf, put->ut_host, 24);
487 safestrncpy(hbuf, put->ut_line, 24);
488 #if defined(HAVE_UT_TYPE) || defined(HAVE_GETUTXLINE)
492 #endif /* HAVE_UTMP_H */
496 * miscellaneous server commands (testing, etc.)
498 void misc_server_cmd(char *cmd) {
503 scr_printf("%s\n",buf);
505 set_keepalives(KA_HALF);
506 while (serv_gets(buf), strcmp(buf,"000")) {
507 scr_printf("%s\n",buf);
509 set_keepalives(KA_YES);
514 newprompt("> ",buf,255);
516 } while(strcmp(buf,"000"));
523 * compute the checksum of a file
525 int file_checksum(char *filename)
531 fp = fopen(filename,"r");
532 if (fp == NULL) return(0);
534 /* yes, this algorithm may allow cksum to overflow, but that's ok
535 * as long as it overflows consistently, which it will.
537 while (ch=getc(fp), ch>=0) {
538 cksum = (cksum + ch);
546 * nuke a directory and its contents
548 int nukedir(char *dirname)
554 dp = opendir(dirname);
559 while (d = readdir(dp), d != NULL) {
560 snprintf(filename, sizeof filename, "%s/%s",
566 return(rmdir(dirname));