1 /* pref.c
2  *
3  * Copyright (c) 1992-2001 by Mike Gleason.
4  * All rights reserved.
5  *
6  */
7 
8 #include "syshdrs.h"
9 
10 #ifdef ncftp
11 #include "progress.h"
12 #endif
13 
14 #include "pref.h"
15 #include "util.h"
16 
17 /* How many times they've run this program. */
18 extern int gNumProgramRuns;
19 
20 /* Their $PAGER. */
21 char gPager[128];
22 
23 /* These correspond to the various timeouts from LibNcFTP. */
24 int gConnTimeout, gXferTimeout, gCtrlTimeout;
25 
26 /* Active or passive FTP?  (PORT or PASV?)  Or both? */
27 extern int gDataPortMode, gFwDataPortMode;
28 
29 /* When the destination file already exists, resume transfer or ask user? */
30 int gAutoResume;
31 
32 /* "Save a bookmark to this site before closing?" */
33 int gConfirmClose;
34 
35 /* Should we update the bookmark for the user? */
36 int gAutoSaveChangesToExistingBookmarks;
37 
38 /* "Save your password with the bookmark?" */
39 int gSavePasswords;
40 
41 int gMaySetXtermTitle;
42 
43 /* Number of seconds between connection attempts. */
44 int gRedialDelay;
45 
46 /* Some messages we only want to bug the user about once, ever. */
47 char gOneTimeMessagesSeen[256];
48 
49 /* Tune the size of the socket buffer using SO_RCVBUF or SO_SNDBUF? */
50 int gSOBufsize;
51 
52 /* Size of the user log before we trim it.  0 means do not log at all. */
53 int gMaxLogSize;
54 
55 /* Use ASCII mode automatically for files with these extensions. */
56 char gAutoAscii[512];
57 
58 #ifdef ncftp
59 /* Which meter to use. */
60 FTPProgressMeterProc gProgressMeter;
61 #endif
62 
63 /* Allow us to plug our other products? */
64 int gDoNotDisplayAds;
65 
66 /* Do we need to save the prefs, or can we skip it? */
67 int gPrefsDirty = 0;
68 
69 extern FTPLibraryInfo gLib;
70 extern FTPConnectionInfo gConn;
71 extern char gOurDirectoryPath[], gUser[], gVersion[];
72 
73 PrefOpt gPrefOpts[] = {
74 	{ "anonopen",				PREFOBSELETE },
75 	{ "anonpass", 				SetAnonPass, kPrefOptObselete },
76 	{ "anon-password",			SetAnonPass, 1 },
77 	{ "auto-ascii",				SetAutoAscii, 1 },
78 	{ "auto-resume",			SetAutoResume, 1 },
79 	{ "autosave-bookmark-changes",		SetAutoSaveChangesToExistingBookmarks, 1 },
80 	{ "blank-lines",			PREFOBSELETE },
81 	{ "confirm-close",			SetConfirmClose, 1 },
82 	{ "connect-timeout",			SetConnTimeout, 1 },
83 	{ "control-timeout",			SetCtrlTimeout, 1 },
84 	{ "logsize",				SetLogSize, 1 },
85 	{ "maxbookmarks",			PREFOBSELETE },
86 	{ "one-time-messages-seen",		SetOneTimeMessages, 0 },
87 	{ "pager",				SetPager, 1 },
88 	{ "passive",				SetPassive, 1 },
89 	{ "progress-meter",			SetProgressMeter, 1 },
90 	{ "redial-delay",			SetRedialDelay, 1 },
91 	{ "remote-msgs", 			PREFOBSELETE },
92 	{ "restore-lcwd", 			PREFOBSELETE },
93 	{ "save-passwords",			SetSavePasswords, 1 },
94 	{ "show-trailing-space",		PREFOBSELETE },
95 	{ "show-status-in-xterm-titlebar",	SetXtTitle, 1 },
96 #ifdef SO_RCVBUF
97 	{ "so-bufsize",				SetSOBufsize, 1 },
98 #endif
99 	{ "startup-lcwd", 			PREFOBSELETE },
100 	{ "startup-msgs", 			PREFOBSELETE },
101 	{ "timeout",				PREFOBSELETE },
102 	{ "total-runs", 			PREFOBSELETE },
103 	{ "total-xfer-hundredths-of-seconds", 	PREFOBSELETE },
104 	{ "total-xfer-kbytes", 			PREFOBSELETE },
105 	{ "trace",				PREFOBSELETE },
106 	{ "utime",				PREFOBSELETE },
107 	{ "visual",				PREFOBSELETE },
108 	{ "xfer-timeout",			SetXferTimeout, 1 },
109 	{ "yes-i-know-about-NcFTPd",		SetNoAds, 1 },
110 	{ NULL,					(PrefProc) 0, kPrefOptInvisible, },
111 };
112 
113 int gNumPrefOpts = ((int)(sizeof(gPrefOpts) / sizeof(PrefOpt)) - 1);
114 
115 
116 
117 void
SetAnonPass(int UNUSED (t),const char * const val,FILE * const fp)118 SetAnonPass(int UNUSED(t), const char *const val, FILE *const fp)
119 {
120 	LIBNCFTP_USE_VAR(t);
121 	if (fp != NULL) {
122 		(void) fprintf(fp, "%s", gLib.defaultAnonPassword);
123 	} else {
124 		(void) STRNCPY(gLib.defaultAnonPassword, val);
125 	}
126 }	/* SetAnonPass */
127 
128 
129 
130 void
SetAutoAscii(int UNUSED (t),const char * const val,FILE * const fp)131 SetAutoAscii(int UNUSED(t), const char *const val, FILE *const fp)
132 {
133 	LIBNCFTP_USE_VAR(t);
134 	if (fp != NULL) {
135 		(void) fprintf(fp, "%s", gAutoAscii);
136 	} else {
137 		(void) STRNCPY(gAutoAscii, val);
138 		if ((gAutoAscii[0] == '\0') || (ISTREQ(gAutoAscii, "no")) || (ISTREQ(gAutoAscii, "off")) || (ISTREQ(gAutoAscii, "false"))) {
139 			gConn.asciiFilenameExtensions = NULL;
140 		} else {
141 			gConn.asciiFilenameExtensions = gAutoAscii;
142 		}
143 	}
144 }	/* SetAutoAscii */
145 
146 
147 
148 void
SetAutoResume(int UNUSED (t),const char * const val,FILE * const fp)149 SetAutoResume(int UNUSED(t), const char *const val, FILE *const fp)
150 {
151 	LIBNCFTP_USE_VAR(t);
152 	if (fp != NULL) {
153 		(void) fprintf(fp, "%s", YESNO(gAutoResume));
154 	} else {
155 		gAutoResume = StrToBool(val);
156 	}
157 }	/* SetAutoResume */
158 
159 
160 
161 void
SetAutoSaveChangesToExistingBookmarks(int UNUSED (t),const char * const val,FILE * const fp)162 SetAutoSaveChangesToExistingBookmarks(int UNUSED(t), const char *const val, FILE *const fp)
163 {
164 	LIBNCFTP_USE_VAR(t);
165 	if (fp != NULL) {
166 		(void) fprintf(fp, "%s", YESNO(gAutoSaveChangesToExistingBookmarks));
167 	} else {
168 		gAutoSaveChangesToExistingBookmarks = StrToBool(val);
169 	}
170 }	/* SetAutoSaveChangesToExistingBookmarks */
171 
172 
173 
174 void
SetConfirmClose(int UNUSED (t),const char * const val,FILE * const fp)175 SetConfirmClose(int UNUSED(t), const char *const val, FILE *const fp)
176 {
177 	LIBNCFTP_USE_VAR(t);
178 	if (fp != NULL) {
179 		(void) fprintf(fp, "%s", YESNO(gConfirmClose));
180 	} else {
181 		gConfirmClose = StrToBool(val);
182 	}
183 }	/* SetConfirmClose */
184 
185 
186 
187 void
SetConnTimeout(int UNUSED (t),const char * const val,FILE * const fp)188 SetConnTimeout(int UNUSED(t), const char *const val, FILE *const fp)
189 {
190 	LIBNCFTP_USE_VAR(t);
191 	if (fp != NULL) {
192 		(void) fprintf(fp, "%d", gConnTimeout);
193 	} else {
194 		gConn.connTimeout = gConnTimeout = atoi(val);
195 	}
196 }	/* SetConnTimeout */
197 
198 
199 
200 void
SetCtrlTimeout(int UNUSED (t),const char * const val,FILE * const fp)201 SetCtrlTimeout(int UNUSED(t), const char *const val, FILE *const fp)
202 {
203 	LIBNCFTP_USE_VAR(t);
204 	if (fp != NULL) {
205 		(void) fprintf(fp, "%d", gCtrlTimeout);
206 	} else {
207 		gConn.ctrlTimeout = gCtrlTimeout = atoi(val);
208 	}
209 }	/* SetCtrlTimeout */
210 
211 
212 
213 void
SetLogSize(int UNUSED (t),const char * const val,FILE * const fp)214 SetLogSize(int UNUSED(t), const char *const val, FILE *const fp)
215 {
216 	LIBNCFTP_USE_VAR(t);
217 	if (fp != NULL) {
218 		(void) fprintf(fp, "%d", gMaxLogSize);
219 	} else {
220 		gMaxLogSize = atoi(val);
221 	}
222 }	/* SetLogSize */
223 
224 
225 
226 void
SetNoAds(int UNUSED (t),const char * const val,FILE * const fp)227 SetNoAds(int UNUSED(t), const char *const val, FILE *const fp)
228 {
229 	LIBNCFTP_USE_VAR(t);
230 	if (fp != NULL) {
231 		(void) fprintf(fp, "%s", YESNO(gDoNotDisplayAds));
232 	} else {
233 		gDoNotDisplayAds = StrToBool(val);
234 	}
235 }	/* SetNoAds */
236 
237 
238 
239 void
SetOneTimeMessages(int UNUSED (t),const char * const val,FILE * const fp)240 SetOneTimeMessages(int UNUSED(t), const char *const val, FILE *const fp)
241 {
242 	LIBNCFTP_USE_VAR(t);
243 	if (fp != NULL) {
244 		(void) fprintf(fp, "%s", gOneTimeMessagesSeen);
245 	} else {
246 		(void) STRNCPY(gOneTimeMessagesSeen, val);
247 	}
248 }	/* SetOneTimeMessages */
249 
250 
251 
252 void
SetPager(int UNUSED (t),const char * const val,FILE * const fp)253 SetPager(int UNUSED(t), const char *const val, FILE *const fp)
254 {
255 	LIBNCFTP_USE_VAR(t);
256 	if (fp != NULL) {
257 		(void) fprintf(fp, "%s", gPager);
258 	} else {
259 		(void) STRNCPY(gPager, val);
260 	}
261 }	/* SetPager */
262 
263 
264 
265 void
SetPassive(int UNUSED (t),const char * const val,FILE * const fp)266 SetPassive(int UNUSED(t), const char *const val, FILE *const fp)
267 {
268 	int m;
269 
270 	LIBNCFTP_USE_VAR(t);
271 	if (fp != NULL) {
272 		m = (gFwDataPortMode >= 0) ? gFwDataPortMode : gDataPortMode;
273 		if (m == kSendPortMode) {
274 			(void) fprintf(fp, "%s", "off");
275 		} else if (m == kPassiveMode) {
276 			(void) fprintf(fp, "%s", "on");
277 		} else {
278 			(void) fprintf(fp, "%s", "optional");
279 		}
280 	} else {
281 		if (gFwDataPortMode >= 0) {
282 			gDataPortMode = gFwDataPortMode;
283 			return;
284 		}
285 		if (ISTRNEQ(val, "opt", 3))
286 			gDataPortMode = kFallBackToSendPortMode;
287 		else if (ISTREQ(val, "on"))
288 			gDataPortMode = kPassiveMode;
289 		else if ((int) isdigit(val[0]))
290 			gDataPortMode = atoi(val);
291 		else
292 			gDataPortMode = kSendPortMode;
293 		gConn.dataPortMode = gDataPortMode;
294 	}
295 }	/* SetPassive */
296 
297 
298 
299 #ifdef ncftp
300 void
SetProgressMeter(int UNUSED (t),const char * const val,FILE * const fp)301 SetProgressMeter(int UNUSED(t), const char *const val, FILE *const fp)
302 {
303 	LIBNCFTP_USE_VAR(t);
304 	if (fp != NULL) {
305 		if (gProgressMeter == PrStatBar) {
306 			(void) fprintf(fp, "%s", "2 (statbar)");
307 		} else if (gProgressMeter == PrPhilBar) {
308 			(void) fprintf(fp, "%s", "1 (philbar)");
309 		} else {
310 			(void) fprintf(fp, "%s", "0 (simple)");
311 		}
312 	} else {
313 		if ((val[0] == '0') || (ISTRNEQ(val, "simple", 6)))
314 			gProgressMeter = PrSizeAndRateMeter;
315 		else if ((val[0] == '1') || (ISTRNEQ(val, "phil", 4)))
316 			gProgressMeter = PrPhilBar;
317 		else
318 			gProgressMeter = PrStatBar;
319 		gConn.progress = gProgressMeter;
320 	}
321 }	/* SetProgressMeter */
322 #else
323 void
SetProgressMeter(int UNUSED (t),const char * const UNUSED (val),FILE * const UNUSED (fp))324 SetProgressMeter(int UNUSED(t), const char *const UNUSED(val), FILE *const UNUSED(fp))
325 {
326 	LIBNCFTP_USE_VAR(t);
327 	LIBNCFTP_USE_VAR(val);
328 	LIBNCFTP_USE_VAR(fp);
329 }	/* SetProgressMeter */
330 #endif
331 
332 
333 
334 void
SetRedialDelay(int UNUSED (t),const char * const val,FILE * const fp)335 SetRedialDelay(int UNUSED(t), const char *const val, FILE *const fp)
336 {
337 	int i;
338 
339 	LIBNCFTP_USE_VAR(t);
340 	if (fp != NULL) {
341 		(void) fprintf(fp, "%d", gRedialDelay);
342 	} else {
343 		i = atoi(val);
344 		if (i < 10)
345 			i = 10;
346 		gRedialDelay = atoi(val);
347 	}
348 }	/* SetRedialDelay */
349 
350 
351 
352 void
SetSavePasswords(int UNUSED (t),const char * const val,FILE * const fp)353 SetSavePasswords(int UNUSED(t), const char *const val, FILE *const fp)
354 {
355 	LIBNCFTP_USE_VAR(t);
356 	if (fp != NULL) {
357 		if (gSavePasswords < 0)
358 			(void) fprintf(fp, "%s", "ask");
359 		else
360 			(void) fprintf(fp, "%s", YESNO(gSavePasswords));
361 	} else {
362 		if (ISTREQ(val, "ask"))
363 			gSavePasswords = -1;
364 		else
365 			gSavePasswords = StrToBool(val);
366 	}
367 }	/* SetSavePasswords */
368 
369 
370 
371 void
SetSOBufsize(int UNUSED (t),const char * const val,FILE * const fp)372 SetSOBufsize(int UNUSED(t), const char *const val, FILE *const fp)
373 {
374 	LIBNCFTP_USE_VAR(t);
375 	if (fp != NULL) {
376 		(void) fprintf(fp, "%d", gSOBufsize);
377 		if (gSOBufsize <= 0)
378 			(void) fprintf(fp, "%s", " (use system default)");
379 	} else {
380 		gConn.dataSocketRBufSize = gConn.dataSocketSBufSize = gSOBufsize = atoi(val);
381 	}
382 }	/* SetSOBufsize */
383 
384 
385 
386 
387 void
SetXferTimeout(int UNUSED (t),const char * const val,FILE * const fp)388 SetXferTimeout(int UNUSED(t), const char *const val, FILE *const fp)
389 {
390 	LIBNCFTP_USE_VAR(t);
391 	if (fp != NULL) {
392 		(void) fprintf(fp, "%d", gXferTimeout);
393 	} else {
394 		gConn.xferTimeout = gXferTimeout = atoi(val);
395 	}
396 }	/* SetXferTimeout */
397 
398 
399 
400 void
SetXtTitle(int UNUSED (t),const char * const val,FILE * const fp)401 SetXtTitle(int UNUSED(t), const char *const val, FILE *const fp)
402 {
403 	LIBNCFTP_USE_VAR(t);
404 	if (fp != NULL) {
405 		(void) fprintf(fp, "%s", YESNO(gMaySetXtermTitle));
406 	} else {
407 		gMaySetXtermTitle = StrToBool(val);
408 	}
409 }	/* SetXtTitle */
410 
411 
412 
413 
414 static void
Show1(int t)415 Show1(int t)
416 {
417 	PrefOpt *p = &gPrefOpts[t];
418 
419 	(void) printf("%-30s ", p->varname);
420 	if (p->proc != (PrefProc) 0)
421 		(*p->proc)(t, NULL, stdout);
422 	(void) printf("\n");
423 }	/* Show1 */
424 
425 
426 
427 
428 /* Modify or display the program's configuration. */
429 void
Set(const char * const tok1,const char * const tok2)430 Set(const char *const tok1, const char *const tok2)
431 {
432 	int t;
433 
434 	if ((tok1 == NULL) || (ISTREQ(tok1, "all"))) {
435 		/* Show all. */
436 		for (t=0; t<gNumPrefOpts; t++) {
437 			if (gPrefOpts[t].visible == kPrefOptVisible)
438 				Show1(t);
439 		}
440 	} else if (tok2 == NULL) {
441 		/* Show one. */
442 		for (t=0; t<gNumPrefOpts; t++) {
443 			if (ISTREQ(tok1, gPrefOpts[t].varname)) {
444 				if (gPrefOpts[t].visible == kPrefOptObselete) {
445 					(void) printf("The \"%s\" option is obselete or not implemented.\n", tok1);
446 				} else {
447 					Show1(t);
448 				}
449 				break;
450 			}
451 		}
452 		if (t >= gNumPrefOpts) {
453 			(void) printf("Unknown option \"%s\" -- try \"show all\" to list available options.\n", tok1);
454 		}
455 	} else {
456 		/* Set one. */
457 		for (t=0; t<gNumPrefOpts; t++) {
458 			if (ISTREQ(tok1, gPrefOpts[t].varname)) {
459 				if (gPrefOpts[t].visible == kPrefOptObselete) {
460 					(void) printf("The \"%s\" option is obselete or not implemented.\n", tok1);
461 				} else if (gPrefOpts[t].proc != (PrefProc) 0) {
462 					(*gPrefOpts[t].proc)(t, tok2, NULL);
463 					gPrefsDirty++;
464 				}
465 				break;
466 			}
467 		}
468 		if (t >= gNumPrefOpts) {
469 			(void) printf("Unknown option \"%s\" -- try \"show all\" to list available options.\n", tok1);
470 		}
471 	}
472 }	/* Set */
473 
474 
475 
476 int
HasSeenOneTimeMessage(const char * const msg)477 HasSeenOneTimeMessage(const char *const msg)
478 {
479 	char buf[256];
480 	char *a, *b;
481 
482 	memcpy(buf, gOneTimeMessagesSeen, sizeof(buf));
483 	for (a = buf; (b = strtok(a, ",\n")) != NULL; a = NULL) {
484 		if (strcmp(msg, b) == 0)
485 			return (1);
486 	}
487 	return (0);
488 }	/* HasSeenOneTimeMessage */
489 
490 
491 
492 
493 void
SetSeenOneTimeMessage(const char * const msg)494 SetSeenOneTimeMessage(const char *const msg)
495 {
496 	gPrefsDirty++;
497 	if (gOneTimeMessagesSeen[0] == '\0')
498 		STRNCPY(gOneTimeMessagesSeen, msg);
499 	else {
500 		STRNCAT(gOneTimeMessagesSeen, ",");
501 		STRNCAT(gOneTimeMessagesSeen, msg);
502 	}
503 }	/* SetSeenOneTimeMessage */
504 
505 
506 
507 int
OneTimeMessage(const char * const msg)508 OneTimeMessage(const char *const msg)
509 {
510 	if (HasSeenOneTimeMessage(msg))
511 		return (0);
512 	SetSeenOneTimeMessage(msg);
513 	return (1);
514 }	/* OneTimeMessage */
515 
516 
517 
518 
519 void
ProcessPrefsFile(FILE * const fp)520 ProcessPrefsFile(FILE *const fp)
521 {
522 	char line[1024];
523 	char *tok1, *tok2;
524 	int t;
525 
526 	line[sizeof(line) - 1] = '\0';
527 	while (fgets(line, sizeof(line) - 1, fp) != NULL) {
528 		tok1 = strtok(line, " =\t\r\n");
529 		if ((tok1 == NULL) || (tok1[0] == '#'))
530 			continue;
531 		tok2 = strtok(NULL, "\r\n");
532 		if (tok2 == NULL)
533 			continue;
534 
535 		for (t=0; t<gNumPrefOpts; t++) {
536 			if (ISTREQ(tok1, gPrefOpts[t].varname)) {
537 				if (gPrefOpts[t].visible == kPrefOptObselete) {
538 					/* Probably converting an
539 					 * old 2.4.2 file.
540 					 */
541 					gPrefsDirty++;
542 				} else if (gPrefOpts[t].proc != (PrefProc) 0) {
543 					(*gPrefOpts[t].proc)(t, tok2, NULL);
544 				}
545 			}
546 		}
547 	}
548 }	/* ProcessPrefsFile */
549 
550 
551 
552 
553 /* Read the saved configuration settings from a preferences file. */
554 void
LoadPrefs(void)555 LoadPrefs(void)
556 {
557 	FILE *fp;
558 	char pathName[256];
559 
560 	/* As with the firewall preference file, there can be
561 	 * site-wide preferences and user-specific preferences.
562 	 * The user pref file is of course kept in the user's
563 	 * NcFTP home directory.
564 	 *
565 	 * The way we do this is we first look for a global
566 	 * preferences file.  We then process the user's pref
567 	 * file, which could override the global prefs.  Finally,
568 	 * we open a "global fixed" prefs file which then
569 	 * overrides anything the user may have done.
570 	 */
571 
572 	fp = fopen(kGlobalPrefFileName, FOPEN_READ_TEXT);
573 	if (fp != NULL) {
574 		/* Opened the global (but user-overridable) prefs file. */
575 		ProcessPrefsFile(fp);
576 		(void) fclose(fp);
577 	}
578 
579 	if (gOurDirectoryPath[0] != '\0') {
580 		(void) OurDirectoryPath(pathName, sizeof(pathName), kPrefFileName);
581 
582 		fp = fopen(pathName, FOPEN_READ_TEXT);
583 		if (fp == NULL) {
584 			/* Try loading the version 2 prefs.
585 			 * There will be options we no longer recognize, but
586 			 * we'd like to import the prefs when possible.
587 			 */
588 			gPrefsDirty++;
589 			(void) OurDirectoryPath(pathName, sizeof(pathName), kPrefFileNameV2);
590 			fp = fopen(pathName, FOPEN_READ_TEXT);
591 		}
592 
593 		if (fp == NULL) {
594 			/* Write a new one when we're done. */
595 			gPrefsDirty++;
596 		} else {
597 			/* Opened the preferences file. */
598 			ProcessPrefsFile(fp);
599 			(void) fclose(fp);
600 		}
601 	}
602 
603 	fp = fopen(kGlobalFixedPrefFileName, FOPEN_READ_TEXT);
604 	if (fp != NULL) {
605 		/* Opened the global (and not overridable) prefs file. */
606 		ProcessPrefsFile(fp);
607 		(void) fclose(fp);
608 	}
609 }	/* LoadPrefs */
610 
611 
612 
613 
614 /* Initialize the configuration settings, in case the user does not set them. */
615 void
InitPrefs(void)616 InitPrefs(void)
617 {
618 	char *tok1;
619 
620 	/* Set default values. */
621 	gPager[0] = '\0';
622 	memset(gOneTimeMessagesSeen, 0, sizeof(gOneTimeMessagesSeen));
623 	gXferTimeout = 3600;
624 	gConnTimeout = 20;
625 	gCtrlTimeout = 135;
626 	gDataPortMode = kFallBackToSendPortMode;
627 	gConn.dataPortMode = gDataPortMode;
628 	gAutoResume = 0;
629 	gSOBufsize = 0;
630 	gMaxLogSize = 10240;
631 	gConfirmClose = 1;
632 	gAutoSaveChangesToExistingBookmarks = 0;
633 	gRedialDelay = kDefaultRedialDelay;
634 	STRNCPY(gAutoAscii, "|.txt|.asc|.html|.htm|.css|.xml|.ini|.sh|.pl|.hqx|.cfg|.c|.h|.cpp|.hpp|.bat|.m3u|.pls|");
635 
636 	/* PLEASE do not change the default from 0, and please
637 	 * don't hack out the portion in main.c which displays
638 	 * a plug every 7th time you run the program.  This is
639 	 * not much to ask for all the work I've put into this
640 	 * since 1991.
641 	 */
642 	gDoNotDisplayAds = 0;
643 
644 #if (defined(WIN32) || defined(_WINDOWS)) && defined(_CONSOLE)
645 	gMaySetXtermTitle = 1;
646 #else
647 	gMaySetXtermTitle = 0;
648 #endif
649 
650 	gSavePasswords = -1;
651 #ifdef ncftp
652 	gProgressMeter = PrStatBar;
653 #endif
654 
655 	tok1 = getenv("PAGER");
656 	if ((tok1 != NULL) && (tok1[0] != '\0')) {
657 #ifdef HAVE_STRSTR
658 		/* I prefer "less", but it doesn't work well here
659 		 * because it clears the screen after it finishes,
660 		 * and the default at EOF is to stay in less
661 		 * instead of exiting.
662 		 */
663 		if (strstr(gPager, "less") != NULL)
664 			(void) STRNCPY(gPager, "more");
665 		else
666 			(void) STRNCPY(gPager, tok1);
667 #else
668 		(void) STRNCPY(gPager, tok1);
669 #endif
670 	} else {
671 		(void) STRNCPY(gPager, "more");
672 	}
673 }	/* InitPrefs */
674 
675 
676 
677 
678 /* After reading the preferences, do some additional initialization. */
679 void
PostInitPrefs(void)680 PostInitPrefs(void)
681 {
682 	if (gLib.defaultAnonPassword[0] == '\0') {
683 		FTPInitializeAnonPassword(&gLib);
684 		gPrefsDirty++;
685 	}
686 	if (gFwDataPortMode >= 0)
687 		gConn.dataPortMode = gFwDataPortMode;
688 }	/* PostInitPrefs */
689 
690 
691 
692 
693 /* Write the configuration settings to a preferences file. */
694 void
SavePrefs(void)695 SavePrefs(void)
696 {
697 	char pathName[256];
698 	char pathName2[256];
699 	char tName[32];
700 	int t;
701 	FILE *fp;
702 
703 	if (gPrefsDirty == 0)
704 		return;		/* Don't need to save -- no changes made. */
705 
706 	(void) OurDirectoryPath(pathName, sizeof(pathName), kPrefFileName);
707 
708 	(void) sprintf(tName, "tpref%06u.txt", (unsigned int) getpid());
709 	(void) OurDirectoryPath(pathName2, sizeof(pathName2), tName);
710 
711 	fp = fopen(pathName2, FOPEN_WRITE_TEXT);
712 	if (fp == NULL) {
713 		perror("could not save preferences file");
714 	} else {
715 		(void) fprintf(fp, "%s", "# NcFTP 3 preferences file\n# This file is loaded and overwritten each time NcFTP is run.\n#\n");
716 		for (t=0; t<gNumPrefOpts; t++) {
717 			if (gPrefOpts[t].visible != kPrefOptObselete) {
718 				(void) fprintf(fp, "%s=", gPrefOpts[t].varname);
719 				(*gPrefOpts[t].proc)(t, NULL, fp);
720 				(void) fprintf(fp, "\n");
721 			}
722 		}
723 		(void) fclose(fp);
724 		(void) unlink(pathName);
725 		if (rename(pathName2, pathName) < 0) {
726 			perror("could not finish saving preferences file");
727 			(void) unlink(pathName2);
728 		};
729 	}
730 }	/* SavePrefs */
731 
732 
733 
734 /* This maintains the little counter file that is used by version 3.0
735  * to do things based on how many times the program was run.
736  */
737 void
CheckForNewV3User(void)738 CheckForNewV3User(void)
739 {
740 	FILE *fp;
741 	struct stat st;
742 	char pathName[256];
743 	char line[256];
744 
745 	gNumProgramRuns = 0;
746 
747 	/* Don't create in root directory. */
748 	if (gOurDirectoryPath[0] != '\0') {
749 		(void) OurDirectoryPath(pathName, sizeof(pathName), kFirstFileName);
750 
751 		if ((stat(pathName, &st) < 0) && (errno == ENOENT)) {
752 			gNumProgramRuns = 1;
753 			gPrefsDirty++;
754 
755 			/* Create a blank one. */
756 			fp = fopen(pathName, FOPEN_WRITE_TEXT);
757 			if (fp == NULL)
758 				return;
759 			(void) fprintf(fp, "# NcFTP uses this file to mark that you have run it before, and that you do not\n# need any special first-time instructions or setup.\n#\nruns=%d\n", gNumProgramRuns);
760 			(void) fclose(fp);
761 		} else {
762 			fp = fopen(pathName, FOPEN_READ_TEXT);
763 			if (fp != NULL) {
764 				while (fgets(line, sizeof(line) - 1, fp) != NULL) {
765 					if (strncmp(line, "runs=", 5) == 0) {
766 						(void) sscanf(line + 5, "%d",
767 							&gNumProgramRuns);
768 						break;
769 					}
770 				}
771 				(void) fclose(fp);
772 			}
773 
774 			/* Increment the count of program runs. */
775 			gNumProgramRuns++;
776 			if (gNumProgramRuns == 1)
777 				gPrefsDirty++;
778 
779 			/* Race condition between other ncftp processes.
780 			 * This isn't a big deal because this counter isn't
781 			 * critical.
782 			 */
783 
784 			fp = fopen(pathName, FOPEN_WRITE_TEXT);
785 			if (fp != NULL) {
786 				(void) fprintf(fp, "# NcFTP uses this file to mark that you have run it before, and that you do not\n# need any special first-time instructions or setup.\n#\nruns=%d\n", gNumProgramRuns);
787 				(void) fclose(fp);
788 			}
789 		}
790 	}
791 }	/* CheckForNewV3User */
792