2 * Client-side support functions.
4 * Copyright (c) 1987-2016 by the citadel.org team
6 * This program is open source software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
29 #if TIME_WITH_SYS_TIME
30 # include <sys/time.h>
34 # include <sys/time.h>
44 #include <libcitadel.h>
45 #include "citadel_ipc.h"
52 #include "citadel_decls.h"
53 #include "routines2.h"
54 #include "tuiconfig.h"
56 #define IFAIDE if(axlevel>=AxAideU)
57 #define IFNAIDE if (axlevel<AxAideU)
59 extern unsigned userflags;
60 //extern char *axdefs[8];
61 extern char sigcaught;
62 extern char rc_floor_mode;
63 extern int rc_ansi_color;
64 extern int rc_prompt_control;
66 /* Destructive backspace */
67 void back(int spaces) {
69 for (a=0; a<spaces; ++a) {
77 * Edit or delete a user (cmd=25 to edit/create, 96 to delete)
79 void edituser(CtdlIPC *ipc, int cmd)
82 char who[USERNAME_SIZE];
83 char newname[USERNAME_SIZE];
84 struct ctdluser *user = NULL;
86 int r; /* IPC response code */
91 newprompt("User name: ", who, 29);
92 while ((r = CtdlIPCAideGetUserParameters(ipc, who, &user, buf)) / 100 != 2) {
93 scr_printf("%s\n", buf);
95 scr_printf("Do you want to create this user? ");
97 r = CtdlIPCCreateUser(ipc, who, 0, buf);
102 scr_printf("%s\n", buf);
110 val_user(ipc, user->fullname, 0); /* Display registration */
114 while (change_name == 1) {
115 if (boolprompt("Change name", 0)) {
116 strprompt("New name", newname, USERNAME_SIZE-1);
117 r = CtdlIPCRenameUser(ipc, user->fullname, newname, buf);
119 scr_printf("%s\n", buf);
122 strcpy(user->fullname, newname);
132 if (newnow || boolprompt("Change password", 0)) {
133 strprompt("Password", user->password, -19);
136 user->axlevel = intprompt("Access level", user->axlevel, 0, 6);
137 if (boolprompt("Permission to send Internet mail", (user->flags & US_INTERNET)))
138 user->flags |= US_INTERNET;
140 user->flags &= ~US_INTERNET;
141 if (boolprompt("Ask user to register again", !(user->flags & US_REGIS)))
142 user->flags &= ~US_REGIS;
144 user->flags |= US_REGIS;
145 user->timescalled = intprompt("Times called",
146 user->timescalled, 0, INT_MAX);
147 user->posted = intprompt("Messages posted",
148 user->posted, 0, INT_MAX);
149 user->lastcall = boolprompt("Set last call to now", 0) ?
150 time(NULL) : user->lastcall;
151 user->USuserpurge = intprompt("Purge time (in days, 0 for system default",
152 user->USuserpurge, 0, INT_MAX);
156 scr_printf("Do you want to delete this user? ");
161 user->axlevel = AxDeleted;
164 r = CtdlIPCAideSetUserParameters(ipc, user, buf);
166 scr_printf("%s\n", buf);
172 /* Display a prompt and flip a bit based on whether the user answers
173 * yes or no. Yes=1 and No=0, unless 'backwards' is set to a nonzero value
174 * in which case No=1 and Yes=0.
176 int set_attr(CtdlIPC *ipc, unsigned int sval, char *prompt, unsigned int sbit, int backwards)
183 scr_printf("%50s ", prompt);
186 color(BRIGHT_MAGENTA);
189 scr_printf("%3s", ((temp&sbit) ? "No":"Yes"));
192 scr_printf("%3s", ((temp&sbit) ? "Yes":"No"));
200 if (backwards) a = 1 - a;
202 if (backwards) a = 1 - a;
205 if (!a) temp = (temp^sbit);
210 * modes are: 0 - .EC command, 1 - .EC for new user,
211 * 2 - toggle Xpert mode 3 - toggle floor mode
213 void enter_config(CtdlIPC *ipc, int mode)
216 struct ctdluser *user = NULL;
217 int r; /* IPC response code */
219 r = CtdlIPCGetConfig(ipc, &user, buf);
221 scr_printf("%s\n", buf);
226 if (mode == 0 || mode == 1) {
228 user->flags = set_attr(ipc, user->flags,
229 "Are you an experienced Citadel user",
231 if ((user->flags & US_EXPERT) == 0 && mode == 1) {
236 user->flags = set_attr(
239 "Print last old message on New message request",
244 user->flags = set_attr(
247 "Prompt after each message",
252 if ((user->flags & US_NOPROMPT) == 0) {
253 user->flags = set_attr(
256 "Use 'disappearing' prompts",
262 user->flags = set_attr(
265 "Pause after each screenful of text",
270 if (rc_prompt_control == 3 && (user->flags & US_PAGINATOR)) {
271 user->flags = set_attr(
274 "<N>ext and <S>top work at paginator prompt",
280 if (rc_floor_mode == RC_DEFAULT) {
281 user->flags = set_attr(
284 "View rooms by floor",
290 if (rc_ansi_color == 3) {
291 user->flags = set_attr(
294 "Enable color support",
300 if ((user->flags & US_EXPERT) == 0) {
301 formout(ipc, "unlisted");
304 user->flags = set_attr(
307 "Be unlisted in userlog",
312 if (!IsEmptyStr(editor_path)) {
313 user->flags = set_attr(
316 "Always enter messages with the full-screen editor",
325 if (user->flags & US_EXPERT) {
326 user->flags ^= US_EXPERT;
327 scr_printf("Expert mode now OFF\n");
329 user->flags |= US_EXPERT;
330 scr_printf("Expert mode now ON\n");
335 if (user->flags & US_FLOORS) {
336 user->flags ^= US_FLOORS;
337 scr_printf("Floor mode now OFF\n");
339 user->flags |= US_FLOORS;
340 scr_printf("Floor mode now ON\n");
344 r = CtdlIPCSetConfig(ipc, user, buf);
345 if (r / 100 != 2) scr_printf("%s\n", buf);
346 userflags = user->flags;
351 * getstring() - get a line of text from a file
352 * ignores lines beginning with "#"
354 int getstring(FILE *fp, char *string)
369 } while(string[0]=='#');
370 return(strlen(string));
374 /* Searches for patn in search string */
375 int pattern(char *search, char *patn) {
379 for (a=0; !IsEmptyStr(&search[a]); ++a) {
380 b=strncasecmp(&search[a],patn,len);
387 void strproc(char *string)
391 if (IsEmptyStr(string)) return;
393 /* Convert non-printable characters to blanks */
394 for (a=0; !IsEmptyStr(&string[a]); ++a) {
395 if (string[a]<32) string[a]=32;
396 if (string[a]>126) string[a]=32;
399 /* Remove leading and trailing blanks */
400 while(string[0]<33) strcpy(string,&string[1]);
401 while(string[strlen(string)-1]<33) string[strlen(string)-1]=0;
403 /* Remove double blanks */
404 for (a=0; a<strlen(string); ++a) {
405 if ((string[a]==32)&&(string[a+1]==32)) {
406 strcpy(&string[a],&string[a+1]);
411 /* remove characters which would interfere with the network */
412 for (a=0; a<strlen(string); ++a) {
413 if (string[a]=='!') strcpy(&string[a],&string[a+1]);
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]);
424 void progress(CtdlIPC* ipc, unsigned long curr, unsigned long cmax)
427 "**************************************************";
428 char dots_printed[51];
433 scr_printf("\r%79s\r","");
435 /* a will be range 0-50 rather than 0-100 */
436 a=(curr * 50) / cmax;
437 sprintf(fmt, "[%%s%%%lds] %%3ld%%%% %%10ld/%%10ld\r", 50 - a);
438 strncpy(dots_printed, dots, a);
440 scr_printf(fmt, dots_printed, "",
441 curr * 100 / cmax, curr, cmax);
448 * NOT the same locate_host() in locate_host.c. This one just does a
449 * 'who am i' to try to discover where the user is...
451 void locate_host(CtdlIPC* ipc, char *hbuf)
453 FILE *who = (FILE *)popen("who am i","r");
455 strcpy(hbuf, ipc->ServInfo.fqdn);
458 fgets(hbuf, SIZ, who);
460 stripallbut(hbuf, '(' , ')' );
464 * miscellaneous server commands (testing, etc.)
466 void misc_server_cmd(CtdlIPC *ipc, char *cmd) {
469 CtdlIPC_chat_send(ipc, cmd);
470 CtdlIPC_chat_recv(ipc, buf);
471 scr_printf("%s\n",buf);
473 set_keepalives(KA_HALF);
474 while (CtdlIPC_chat_recv(ipc, buf), strcmp(buf,"000")) {
475 scr_printf("%s\n",buf);
477 set_keepalives(KA_YES);
482 newprompt("> ",buf,255);
483 CtdlIPC_chat_send(ipc, buf);
484 } while(strcmp(buf,"000"));
491 * compute the checksum of a file
493 int file_checksum(char *filename)
499 fp = fopen(filename,"r");
500 if (fp == NULL) return(0);
502 /* yes, this algorithm may allow cksum to overflow, but that's ok
503 * as long as it overflows consistently, which it will.
505 while (ch=getc(fp), ch>=0) {
506 cksum = (cksum + ch);
514 * nuke a directory and its contents
516 int nukedir(char *dirname)
522 dp = opendir(dirname);
527 while (d = readdir(dp), d != NULL) {
528 snprintf(filename, sizeof filename, "%s/%s",
534 return(rmdir(dirname));