2 * Client-side support functions.
12 #include <sys/types.h>
13 #include <sys/ioctl.h>
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
24 # include <sys/time.h>
40 #include <libcitadel.h>
42 #include "citadel_ipc.h"
45 #ifndef HAVE_GETUTLINE
46 struct utmp *getutline(struct utmp *ut);
54 #include "citadel_decls.h"
55 #include "routines2.h"
57 #define IFAIDE if(axlevel>=AxAideU)
58 #define IFNAIDE if (axlevel<AxAideU)
60 extern unsigned userflags;
61 //extern char *axdefs[8];
62 extern char sigcaught;
63 extern char rc_floor_mode;
64 extern int rc_ansi_color;
65 extern int rc_prompt_control;
67 /* Destructive backspace */
68 void back(int spaces) {
70 for (a=0; a<spaces; ++a) {
78 * Edit or delete a user (cmd=25 to edit/create, 96 to delete)
80 void edituser(CtdlIPC *ipc, int cmd)
83 char who[USERNAME_SIZE];
84 char newname[USERNAME_SIZE];
85 struct ctdluser *user = NULL;
87 int r; /* IPC response code */
92 newprompt("User name: ", who, 29);
93 while ((r = CtdlIPCAideGetUserParameters(ipc, who, &user, buf)) / 100 != 2) {
94 scr_printf("%s\n", buf);
96 scr_printf("Do you want to create this user? ");
98 r = CtdlIPCCreateUser(ipc, who, 0, buf);
103 scr_printf("%s\n", buf);
111 val_user(ipc, user->fullname, 0); /* Display registration */
115 while (change_name == 1) {
116 if (boolprompt("Change name", 0)) {
117 strprompt("New name", newname, USERNAME_SIZE-1);
118 r = CtdlIPCRenameUser(ipc, user->fullname, newname, buf);
120 scr_printf("%s\n", buf);
123 strcpy(user->fullname, newname);
133 if (newnow || boolprompt("Change password", 0)) {
134 strprompt("Password", user->password, -19);
137 user->axlevel = intprompt("Access level", user->axlevel, 0, 6);
138 if (boolprompt("Permission to send Internet mail", (user->flags & US_INTERNET)))
139 user->flags |= US_INTERNET;
141 user->flags &= ~US_INTERNET;
142 if (boolprompt("Ask user to register again", !(user->flags & US_REGIS)))
143 user->flags &= ~US_REGIS;
145 user->flags |= US_REGIS;
146 user->timescalled = intprompt("Times called",
147 user->timescalled, 0, INT_MAX);
148 user->posted = intprompt("Messages posted",
149 user->posted, 0, INT_MAX);
150 user->lastcall = boolprompt("Set last call to now", 0) ?
151 time(NULL) : user->lastcall;
152 user->USuserpurge = intprompt("Purge time (in days, 0 for system default",
153 user->USuserpurge, 0, INT_MAX);
157 scr_printf("Do you want to delete this user? ");
162 user->axlevel = AxDeleted;
165 r = CtdlIPCAideSetUserParameters(ipc, user, buf);
167 scr_printf("%s\n", buf);
173 /* Display a prompt and flip a bit based on whether the user answers
174 * yes or no. Yes=1 and No=0, unless 'backwards' is set to a nonzero value
175 * in which case No=1 and Yes=0.
177 int set_attr(CtdlIPC *ipc, unsigned int sval, char *prompt, unsigned int sbit, int backwards)
184 scr_printf("%50s ", prompt);
187 color(BRIGHT_MAGENTA);
190 scr_printf("%3s", ((temp&sbit) ? "No":"Yes"));
193 scr_printf("%3s", ((temp&sbit) ? "Yes":"No"));
201 if (backwards) a = 1 - a;
203 if (backwards) a = 1 - a;
206 if (!a) temp = (temp^sbit);
211 * modes are: 0 - .EC command, 1 - .EC for new user,
212 * 2 - toggle Xpert mode 3 - toggle floor mode
214 void enter_config(CtdlIPC *ipc, int mode)
217 struct ctdluser *user = NULL;
218 int r; /* IPC response code */
220 r = CtdlIPCGetConfig(ipc, &user, buf);
222 scr_printf("%s\n", buf);
227 if (mode == 0 || mode == 1) {
229 user->flags = set_attr(ipc, user->flags,
230 "Are you an experienced Citadel user",
232 if ((user->flags & US_EXPERT) == 0 && mode == 1) {
237 user->flags = set_attr(
240 "Print last old message on New message request",
245 user->flags = set_attr(
248 "Prompt after each message",
253 if ((user->flags & US_NOPROMPT) == 0) {
254 user->flags = set_attr(
257 "Use 'disappearing' prompts",
263 user->flags = set_attr(
266 "Pause after each screenful of text",
271 if (rc_prompt_control == 3 && (user->flags & US_PAGINATOR)) {
272 user->flags = set_attr(
275 "<N>ext and <S>top work at paginator prompt",
281 if (rc_floor_mode == RC_DEFAULT) {
282 user->flags = set_attr(
285 "View rooms by floor",
291 if (rc_ansi_color == 3) {
292 user->flags = set_attr(
295 "Enable color support",
301 if ((user->flags & US_EXPERT) == 0) {
302 formout(ipc, "unlisted");
305 user->flags = set_attr(
308 "Be unlisted in userlog",
313 if (!IsEmptyStr(editor_paths[0])) {
314 user->flags = set_attr(
317 "Always enter messages with the full-screen editor",
326 if (user->flags & US_EXPERT) {
327 user->flags ^= US_EXPERT;
328 scr_printf("Expert mode now OFF\n");
330 user->flags |= US_EXPERT;
331 scr_printf("Expert mode now ON\n");
336 if (user->flags & US_FLOORS) {
337 user->flags ^= US_FLOORS;
338 scr_printf("Floor mode now OFF\n");
340 user->flags |= US_FLOORS;
341 scr_printf("Floor mode now ON\n");
345 r = CtdlIPCSetConfig(ipc, user, buf);
346 if (r / 100 != 2) scr_printf("%s\n", buf);
347 userflags = user->flags;
352 * getstring() - get a line of text from a file
353 * ignores lines beginning with "#"
355 int getstring(FILE *fp, char *string)
370 } while(string[0]=='#');
371 return(strlen(string));
375 /* Searches for patn in search string */
376 int pattern(char *search, char *patn) {
380 for (a=0; !IsEmptyStr(&search[a]); ++a) {
381 b=strncasecmp(&search[a],patn,len);
388 void strproc(char *string)
392 if (IsEmptyStr(string)) return;
394 /* Convert non-printable characters to blanks */
395 for (a=0; !IsEmptyStr(&string[a]); ++a) {
396 if (string[a]<32) string[a]=32;
397 if (string[a]>126) string[a]=32;
400 /* Remove leading and trailing blanks */
401 while(string[0]<33) strcpy(string,&string[1]);
402 while(string[strlen(string)-1]<33) string[strlen(string)-1]=0;
404 /* Remove double blanks */
405 for (a=0; a<strlen(string); ++a) {
406 if ((string[a]==32)&&(string[a+1]==32)) {
407 strcpy(&string[a],&string[a+1]);
412 /* remove characters which would interfere with the network */
413 for (a=0; a<strlen(string); ++a) {
414 if (string[a]=='!') strcpy(&string[a],&string[a+1]);
415 if (string[a]=='@') strcpy(&string[a],&string[a+1]);
416 if (string[a]=='_') strcpy(&string[a],&string[a+1]);
417 if (string[a]==',') strcpy(&string[a],&string[a+1]);
418 if (string[a]=='%') strcpy(&string[a],&string[a+1]);
419 if (string[a]=='|') strcpy(&string[a],&string[a+1]);
425 #ifndef HAVE_STRERROR
427 * replacement strerror() for systems that don't have it
429 char *strerror(int e)
431 static char buf[128];
433 snprintf(buf, sizeof buf, "errno = %d",e);
439 void progress(CtdlIPC* ipc, unsigned long curr, unsigned long cmax)
442 "**************************************************";
443 char dots_printed[51];
448 scr_printf("\r%79s\r","");
450 /* a will be range 0-50 rather than 0-100 */
451 a=(curr * 50) / cmax;
452 sprintf(fmt, "[%%s%%%lds] %%3ld%%%% %%10ld/%%10ld\r", 50 - a);
453 strncpy(dots_printed, dots, a);
455 scr_printf(fmt, dots_printed, "",
456 curr * 100 / cmax, curr, cmax);
463 * NOT the same locate_host() in locate_host.c. This one just does a
464 * 'who am i' to try to discover where the user is...
466 void locate_host(CtdlIPC* ipc, char *hbuf)
473 who = (FILE *)popen("who am i","r");
475 strcpy(hbuf, ipc->ServInfo.fqdn);
478 fgets(buf,sizeof buf,who);
482 for (a=0; !IsEmptyStr(&buf[a]); ++a) {
483 if ((buf[a]=='(')||(buf[a]==')')) ++b;
486 strcpy(hbuf, ipc->ServInfo.fqdn);
490 for (a=0; a<strlen(buf); ++a) {
492 strcpy(buf,&buf[a+1]);
495 for (a=0; a<strlen(buf); ++a) {
496 if (buf[a]==')') buf[a] = 0;
499 if (IsEmptyStr(buf)) strcpy(hbuf, ipc->ServInfo.fqdn);
500 else strncpy(hbuf,buf,24);
502 char *tty = ttyname(0);
503 #ifdef HAVE_GETUTXLINE
504 struct utmpx ut, *put;
506 struct utmp ut, *put;
511 safestrncpy(hbuf, ipc->ServInfo.fqdn, 24);
515 if (strncmp(tty, "/dev/", 5))
518 safestrncpy(ut.ut_line, &tty[5], sizeof ut.ut_line);
520 #ifdef HAVE_GETUTXLINE /* Solaris uses this */
521 if ((put = getutxline(&ut)) == NULL)
523 if ((put = getutline(&ut)) == NULL)
527 #if defined(HAVE_UT_TYPE) || defined(HAVE_GETUTXLINE)
528 if (put->ut_type == USER_PROCESS) {
530 #if defined(HAVE_UT_HOST) || defined(HAVE_GETUTXLINE)
532 safestrncpy(hbuf, put->ut_host, 24);
535 safestrncpy(hbuf, put->ut_line, 24);
536 #if defined(HAVE_UT_TYPE) || defined(HAVE_GETUTXLINE)
540 #endif /* HAVE_UTMP_H */
544 * miscellaneous server commands (testing, etc.)
546 void misc_server_cmd(CtdlIPC *ipc, char *cmd) {
549 CtdlIPC_chat_send(ipc, cmd);
550 CtdlIPC_chat_recv(ipc, buf);
551 scr_printf("%s\n",buf);
553 set_keepalives(KA_HALF);
554 while (CtdlIPC_chat_recv(ipc, buf), strcmp(buf,"000")) {
555 scr_printf("%s\n",buf);
557 set_keepalives(KA_YES);
562 newprompt("> ",buf,255);
563 CtdlIPC_chat_send(ipc, buf);
564 } while(strcmp(buf,"000"));
571 * compute the checksum of a file
573 int file_checksum(char *filename)
579 fp = fopen(filename,"r");
580 if (fp == NULL) return(0);
582 /* yes, this algorithm may allow cksum to overflow, but that's ok
583 * as long as it overflows consistently, which it will.
585 while (ch=getc(fp), ch>=0) {
586 cksum = (cksum + ch);
594 * nuke a directory and its contents
596 int nukedir(char *dirname)
602 dp = opendir(dirname);
607 while (d = readdir(dp), d != NULL) {
608 snprintf(filename, sizeof filename, "%s/%s",
614 return(rmdir(dirname));