* For license terms, see the file COPYING in this directory.
*/
-#include <config.h>
+#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <netdb.h>
#endif /* HAVE_GETHOSTBYNAME */
+#ifdef SUNOS
+#include <stdlib.h>
+#endif
+
#include "fetchmail.h"
#include "tunable.h"
#include "smtp.h"
static int load_params(int, char **, int);
static void dump_params (struct query *);
static int query_host(struct query *);
-static char *visbuf(const char *);
/* controls the detail level of status/progress messages written to stderr */
int outlevel; /* see the O_.* constants above */
-int yydebug; /* enable parse debugging */
/* daemon mode control */
-int poll_interval; /* poll interval in seconds */
-int nodetach; /* if TRUE, don't detach daemon process */
-char *logfile; /* log file for daemon mode */
-int use_syslog; /* if --syslog was set */
-int quitmode; /* if --quit was set */
-int check_only; /* if --probe was set */
+flag nodetach; /* if TRUE, don't detach daemon process */
+flag quitmode; /* if --quit was set */
+flag check_only; /* if --probe was set */
char *cmd_logfile; /* if --logfile was set */
+int cmd_daemon; /* if --daemon was set */
/* miscellaneous global controls */
-char *rcfile; /* path name of rc file */
char *idfile; /* UID list file */
-int versioninfo; /* emit only version info */
+flag versioninfo; /* emit only version info */
char *user; /* the name of the invoking user */
char *fetchmailhost; /* the name of the host running fetchmail */
char *program_name; /* the name to prefix error messages with */
static char *lockfile; /* name of lockfile */
static int querystatus; /* status of query */
+static int successes; /* count number of successful polls */
static int lastsig; /* last signal received */
static void termhook(); /* forward declaration of exit hook */
RETSIGTYPE donothing(sig) int sig; {signal(sig, donothing); lastsig = sig;}
+#ifdef HAVE_ATEXIT
static void unlockit(void)
+#else /* use on_exit(), e.g. on SunOS */
+static void unlockit(int n, void *p)
+#endif
/* must-do actions for exit (but we can't count on being able to do malloc) */
{
unlink(lockfile);
int main (int argc, char **argv)
{
int st, bkgd = FALSE;
- int parsestatus, implicitmode;
- char *home, *tmpdir, tmpbuf[BUFSIZ];
+ int parsestatus, implicitmode = FALSE;
struct passwd *pw;
struct query *ctl;
FILE *lockfp;
netrc_entry *netrc_list;
- char *netrc_file;
+ char *netrc_file, tmpbuf[BUFSIZ];
pid_t pid;
- if ((program_name = strrchr(argv[0], '/')) != NULL)
- ++program_name;
- else
- program_name = argv[0];
-
- if ((user = getenv("USER")) == (char *)NULL)
- user = getenv("LOGNAME");
-
- if ((user == (char *)NULL) || (home = getenv("HOME")) == (char *)NULL)
- {
- if ((pw = getpwuid(getuid())) != NULL)
- {
- user = pw->pw_name;
- home = pw->pw_dir;
- }
- else
- {
- fprintf(stderr,"fetchmail: can't find your name and home directory!\n");
- exit(PS_UNDEFINED);
- }
- }
-
- /* we'll need this for the SMTP forwarding target and error messages */
- if (gethostname(tmpbuf, sizeof(tmpbuf)))
- {
- fprintf(stderr, "fetchmail: can't determine fetchmail's host!");
- exit(PS_IOERR);
- }
- fetchmailhost = xstrdup(tmpbuf);
-
- /*
- * Backward-compatibility hack. If we're called by the name of the
- * ancestral popclient, look for .poprc. This will actually work
- * for popclient files that don't use the removed keywords.
- */
- if (strcmp("popclient", argv[0]) == 0)
- tmpdir = ".poprc";
- else
- tmpdir = ".fetchmailrc";
-
- rcfile = (char *) xmalloc(strlen(home)+strlen(tmpdir)+2);
- strcpy(rcfile, home);
- strcat(rcfile, "/");
- strcat(rcfile, tmpdir);
+ envquery(argc, argv);
#define IDFILE_NAME ".fetchids"
idfile = (char *) xmalloc(strlen(home)+strlen(IDFILE_NAME)+2);
setvbuf(stdout, NULL, _IOLBF, POPBUFSIZE);
if (versioninfo)
- printf("This is fetchmail release %s pl %s\n", RELEASE_ID, PATCHLEVEL);
+ printf("This is fetchmail release %s\n", RELEASE_ID);
/* avoid parsing the config file if all we're doing is killing a daemon */
if (!quitmode)
printf("\n");
else
printf(" and %s\n", rcfile);
+ if (poll_interval)
+ printf("Poll interval is %d seconds\n", poll_interval);
if (outlevel == O_VERBOSE)
printf("Lockfile at %s\n", tmpbuf);
+ if (logfile)
+ printf("Logfile is %s\n", logfile);
for (ctl = querylist; ctl; ctl = ctl->next) {
if (ctl->active && !(implicitmode && ctl->server.skip))
dump_params(ctl);
"No mailservers set up -- perhaps %s is missing?\n", rcfile);
exit(0);
}
- else if (!quitmode && querylist == NULL) {
- (void) fputs("fetchmail: no mailservers have been specified.\n", stderr);
- exit(PS_SYNTAX);
- }
/* check for another fetchmail running concurrently */
pid = -1;
fclose(lockfp);
}
+ /* if no mail servers listed and nothing in background, we're done */
+ if (!quitmode && pid == -1 && querylist == NULL) {
+ (void)fputs("fetchmail: no mailservers have been specified.\n",stderr);
+ exit(PS_SYNTAX);
+ }
+
/* perhaps user asked us to kill the other fetchmail */
if (quitmode)
{
pid);
return(PS_EXCLUDE);
}
+ else if (argc > 1)
+ {
+ fprintf(stderr,
+ "fetchmail: can't accept options while a background fetchmail is running.\n");
+ return(PS_EXCLUDE);
+ }
else if (kill(pid, SIGUSR1) == 0)
{
fprintf(stderr,
{
/*
* Should never happen -- possible only if a background fetchmail
- * croaks after the first kill probe above but before the SIGUSR1/SIGHUP
- * transmission.
+ * croaks after the first kill probe above but before the
+ * SIGUSR1/SIGHUP transmission.
*/
fprintf(stderr,
"fetchmail: elder sibling at %d died mysteriously.\n",
}
}
- /* parse the ~/.netrc file, for future password lookups. */
+ /* parse the ~/.netrc file (if present) for future password lookups. */
netrc_file = (char *) xmalloc (strlen (home) + 8);
strcpy (netrc_file, home);
strcat (netrc_file, "/.netrc");
-
- netrc_list = parse_netrc (netrc_file);
+ netrc_list = parse_netrc(netrc_file);
/* pick up interactively any passwords we need but don't have */
for (ctl = querylist; ctl; ctl = ctl->next)
- if (ctl->active && !(implicitmode && ctl->server.skip) && !ctl->password)
+ if (ctl->active && !(implicitmode && ctl->server.skip)&&!ctl->password)
{
- if (ctl->server.authenticate == A_KERBEROS)
+ if (ctl->server.preauthenticate == A_KERBEROS_V4 || ctl->server.protocol == P_IMAP_K4)
/* Server won't care what the password is, but there
must be some non-null string here. */
ctl->password = ctl->remotename;
else
{
- /* Look up the host and account in the .netrc file. */
+ /* look up the host and account in the .netrc file. */
netrc_entry *p = search_netrc(netrc_list,ctl->server.names->id);
- while (p && strcmp (p->account, ctl->remotename))
- p = search_netrc (p->next, ctl->remotename);
+ while (p && strcmp(p->account, ctl->remotename))
+ p = search_netrc(p->next, ctl->remotename);
- if (p)
- {
- /* We found the entry, so use the password. */
+ /* if we find a matching entry with a password, use it */
+ if (p && p->password)
ctl->password = xstrdup(p->password);
- }
}
- if (ctl->server.protocol != P_ETRN && !ctl->password)
+ if (ctl->server.protocol != P_ETRN && ctl->server.protocol != P_IMAP_K4 && !ctl->password)
{
(void) sprintf(tmpbuf, "Enter password for %s@%s: ",
ctl->remotename, ctl->server.names->id);
openlog(program_name, LOG_PID, LOG_MAIL);
#endif
- if (poll_interval && !nodetach)
- daemonize(logfile, termhook);
+ if (poll_interval)
+ {
+ if (!nodetach)
+ daemonize(logfile, termhook);
+ error( 0, 0, "starting fetchmail %s daemon ", RELEASE_ID);
+ }
/* beyond here we don't want more than one fetchmail running per user */
umask(0077);
if (poll_interval)
fprintf(lockfp," %d", poll_interval);
fclose(lockfp);
+
+#ifdef HAVE_ATEXIT
atexit(unlockit);
+#else
+ on_exit(unlockit, (char *)NULL);
+#endif
}
/*
* as a probe to make sure our nameserver is still up.
* The multidrop case (especially) needs it.
*/
- if (ctl->server.authenticate == A_KERBEROS || MULTIDROP(ctl))
+ if (ctl->server.preauthenticate==A_KERBEROS_V4 || MULTIDROP(ctl))
{
struct hostent *namerec;
#endif /* HAVE_GETHOSTBYNAME */
querystatus = query_host(ctl);
+
+ if (querystatus == PS_SUCCESS)
+ successes++;
+
if (!check_only)
update_str_lists(ctl);
#ifdef linux
* deliver it until the input socket is closed.
*/
for (ctl = querylist; ctl; ctl = ctl->next)
- if (ctl->smtp_sockfp)
+ if (ctl->smtp_socket != -1)
{
- SMTP_quit(ctl->smtp_sockfp);
- fclose(ctl->smtp_sockfp);
- ctl->smtp_sockfp = (FILE *)NULL;
+ SMTP_quit(ctl->smtp_socket);
+ close(ctl->smtp_socket);
+ ctl->smtp_socket = -1;
}
/*
(poll_interval);
if (outlevel == O_VERBOSE)
- fprintf(stderr,"fetchmail: normal termination, status %d\n",querystatus);
+ fprintf(stderr,"fetchmail: normal termination, status %d\n",
+ successes ? PS_SUCCESS : querystatus);
termhook(0);
- exit(querystatus);
+ exit(successes ? PS_SUCCESS : querystatus);
}
static int load_params(int argc, char **argv, int optind)
struct query def_opts, *ctl, *mp;
memset(&def_opts, '\0', sizeof(struct query));
+ def_opts.smtp_socket = -1;
def_opts.server.protocol = P_AUTO;
def_opts.server.timeout = CLIENT_TIMEOUT;
def_opts.remotename = user;
- def_opts.smtphost = fetchmailhost;
+ save_str(&def_opts.smtphunt, -1, fetchmailhost);
/* this builds the host list */
- if (prc_parse_file(rcfile) != 0)
+ if (prc_parse_file(rcfile, !versioninfo) != 0)
exit(PS_SYNTAX);
if ((implicitmode = (optind >= argc)))
}
#endif /* !HAVE_GETHOSTBYNAME || !HAVE_RES_SEARCH */
- /*
- * Assign SMTP leaders. We want to allow all query blocks
- * sharing the same server/SMTP-host pair to use the same
- * SMTP connection. To accomplish this, we initialize
- * each query block's leader field to point to the first
- * block in the list with a matching server/SMTP-host pair.
- *
- * In the typical case, there will be only one SMTP host (the
- * client machine) and thus just one SMTP leader (and one listener
- * process) through the entire poll cycle.
- */
- if (!ctl->mda)
- {
- ctl->smtp_sockfp = (FILE *)NULL;
- for (mp = querylist; mp && mp != ctl; mp = mp->next)
- if (!strcmp(mp->server.names->id, ctl->server.names->id)
- && !strcmp(mp->smtphost, ctl->smtphost))
- {
- ctl->lead_smtp = mp->lead_smtp;
- goto no_new_leader;
- }
- ctl->lead_smtp = ctl;
- no_new_leader:;
- }
-
- /* similarly, compute server leaders for queries */
- for (mp = querylist; mp && mp != ctl; mp = mp->next)
- if (strcmp(mp->server.names->id, ctl->server.names->id) == 0)
- {
- ctl->server.lead_server = mp->server.lead_server;
- goto no_new_server;
- }
- ctl->server.lead_server = &(ctl->server);
- no_new_server:;
-
/* this code enables flags to be turned off */
#define DEFAULT(flag, dflt) if (flag == FLAG_TRUE)\
flag = TRUE;\
else\
flag = (dflt)
DEFAULT(ctl->keep, FALSE);
- DEFAULT(ctl->flush, FALSE);
DEFAULT(ctl->fetchall, FALSE);
+ DEFAULT(ctl->flush, FALSE);
DEFAULT(ctl->rewrite, TRUE);
DEFAULT(ctl->stripcr, (ctl->mda != (char *)NULL));
+ DEFAULT(ctl->forcecr, FALSE);
+ DEFAULT(ctl->pass8bits, FALSE);
+ DEFAULT(ctl->dropstatus, FALSE);
DEFAULT(ctl->server.dns, TRUE);
+ DEFAULT(ctl->server.uidl, FALSE);
#undef DEFAULT
/* plug in the semi-standard way of indicating a mail address */
if (ctl->server.envelope == (char *)NULL)
ctl->server.envelope = "X-Envelope-To:";
+ /* if no folders were specified, set up the null one as default */
+ if (!ctl->mailboxes)
+ save_str(&ctl->mailboxes, -1, (char *)NULL);
+
+ /* maybe user overrode timeout on command line? */
+ if (ctl->server.timeout == -1)
+ ctl->server.timeout = CLIENT_TIMEOUT;
+
/* sanity checks */
if (ctl->server.port < 0)
{
}
/* initialize UID handling */
- if ((st = prc_filecheck(idfile)) != 0)
+ if (!versioninfo && (st = prc_filecheck(idfile)) != 0)
exit(st);
else
initialize_saved_lists(querylist, idfile);
if (cmd_logfile)
logfile = cmd_logfile;
+ /* likewise for poll_interval */
+ if (cmd_daemon >= 0)
+ poll_interval = cmd_daemon;
+
+ /* check and daemon options are not compatible */
+ if (check_only && poll_interval)
+ poll_interval = 0;
+
return(implicitmode);
}
{
struct query *ctl;
+ /*
+ * Craig Metz, the RFC1938 one-time-password guy, points out:
+ * "Remember that most kernels don't zero pages before handing them to the
+ * next process and many kernels share pages between user and kernel space.
+ * You'd be very surprised what you can find from a short program to do a
+ * malloc() and then dump the contents of the pages you got. By zeroing
+ * the secrets at end of run (earlier if you can), you make sure the next
+ * guy can't get the password/pass phrase."
+ *
+ * Right you are, Craig!
+ */
+ for (ctl = querylist; ctl; ctl = ctl->next)
+ if (ctl->password)
+ memset(ctl->password, '\0', strlen(ctl->password));
+
/*
* Sending SMTP QUIT on signal is theoretically nice, but led to a
* subtle bug. If fetchmail was terminated by signal while it was
* shipping message text, it would hang forever waiting for a
- * command acknowledge. In theory we could disable the QUIT
+ * command acknowledge. In theory we could enable the QUIT
* only outside of the message send. In practice, we don't
* care. All mailservers hang up on a dropped TCP/IP connection
* anyway.
else
/* terminate all SMTP connections cleanly */
for (ctl = querylist; ctl; ctl = ctl->next)
- if (ctl->lead_smtp == ctl && ctl->smtp_sockfp != (FILE *)NULL)
- SMTP_quit(ctl->smtp_sockfp);
+ if (ctl->smtp_socket != -1)
+ SMTP_quit(ctl->smtp_socket);
if (!check_only)
write_saved_lists(querylist, idfile);
- exit(querystatus);
-}
-
-static char *showproto(int proto)
-/* protocol index to protocol name mapping */
-{
- switch (proto)
- {
- case P_AUTO: return("auto"); break;
- case P_POP2: return("POP2"); break;
- case P_POP3: return("POP3"); break;
- case P_IMAP: return("IMAP"); break;
- case P_APOP: return("APOP"); break;
- case P_RPOP: return("RPOP"); break;
- case P_ETRN: return("ETRN"); break;
- default: return("unknown?!?"); break;
- }
+ exit(successes ? PS_SUCCESS : querystatus);
}
/*
* Sequence of protocols to try when autoprobing, most capable to least.
*/
+#ifdef POP2_ENABLE
static const int autoprobe[] = {P_IMAP, P_POP3, P_POP2};
+#else
+static const int autoprobe[] = {P_IMAP, P_POP3};
+#endif /* POP2_ENABLE */
static int query_host(struct query *ctl)
/* perform fetch transaction with single host */
{
int i, st;
+ if (poll_interval && ctl->server.interval)
+ {
+ if (ctl->server.poll_count++ % ctl->server.interval)
+ {
+ if (outlevel == O_VERBOSE)
+ fprintf(stderr,
+ "fetchmail: interval not reached, not querying %s\n",
+ ctl->server.names->id);
+ return PS_NOMAIL;
+ }
+ }
+
if (outlevel == O_VERBOSE)
{
time_t now;
time(&now);
- fprintf(stderr, "Querying %s (protocol %s) at %s",
+ fprintf(stderr, "fetchmail: %s querying %s (protocol %s) at %s",
+ RELEASE_ID,
ctl->server.names->id, showproto(ctl->server.protocol), ctime(&now));
}
switch (ctl->server.protocol) {
for (i = 0; i < sizeof(autoprobe)/sizeof(autoprobe[0]); i++)
{
ctl->server.protocol = autoprobe[i];
- if ((st = query_host(ctl)) == PS_SUCCESS || st == PS_NOMAIL || st == PS_AUTHFAIL)
+ if ((st = query_host(ctl)) == PS_SUCCESS || st == PS_NOMAIL || st == PS_AUTHFAIL || st == PS_LOCKBUSY)
break;
}
ctl->server.protocol = P_AUTO;
return(st);
break;
case P_POP2:
+#ifdef POP2_ENABLE
return(doPOP2(ctl));
+#else
+ fprintf(stderr, "POP2 support is not configured.\n");
+ return(PS_PROTOCOL);
+#endif /* POP2_ENABLE */
break;
case P_POP3:
case P_APOP:
return(doPOP3(ctl));
break;
case P_IMAP:
+ case P_IMAP_K4:
return(doIMAP(ctl));
break;
case P_ETRN:
+#ifdef HAVE_GETHOSTBYNAME
return(doETRN(ctl));
+#else
+ fprintf(stderr, "Cannot support ETRN without gethostbyname(2).\n");
+ return(PS_PROTOCOL);
+#endif /* HAVE_GETHOSTBYNAME */
default:
error(0, 0, "unsupported protocol selected.");
return(PS_PROTOCOL);
{
printf("Options for retrieving from %s@%s:\n",
ctl->remotename, visbuf(ctl->server.names->id));
+
+ if (ctl->server.via)
+ printf(" Mail will be retrieved via %s\n", ctl->server.via);
+
+ if (ctl->server.interval)
+ printf(" Poll of this server will occur every %d intervals.\n",
+ ctl->server.interval);
#ifdef HAVE_GETHOSTBYNAME
if (ctl->server.canonical_name)
printf(" Canonical DNS name of server is %s.\n", ctl->server.canonical_name);
printf(" Password = '%s'.\n", visbuf(ctl->password));
if (ctl->server.protocol == P_POP3
&& ctl->server.port == KPOP_PORT
- && ctl->server.authenticate == A_KERBEROS)
+ && ctl->server.preauthenticate == A_KERBEROS_V4)
printf(" Protocol is KPOP");
else
printf(" Protocol is %s", showproto(ctl->server.protocol));
printf(" (using port %d)", ctl->server.port);
else if (outlevel == O_VERBOSE)
printf(" (using default port)");
+ if (ctl->server.uidl)
+ printf(" (forcing UIDL use)");
putchar('.');
putchar('\n');
- if (ctl->server.authenticate == A_KERBEROS)
- printf(" Kerberos authentication enabled.\n");
- printf(" Server nonresponse timeout is %d seconds", ctl->server.timeout);
+ if (ctl->server.preauthenticate == A_KERBEROS_V4)
+ printf(" Kerberos V4 preauthentication enabled.\n");
+ if (ctl->server.timeout > 0)
+ printf(" Server nonresponse timeout is %d seconds", ctl->server.timeout);
if (ctl->server.timeout == CLIENT_TIMEOUT)
printf(" (default).\n");
else
putchar('\n');
}
+ if (!ctl->mailboxes->id)
+ printf(" Default mailbox selected.\n");
+ else
+ {
+ struct idlist *idp;
+
+ printf(" Selected mailboxes are:");
+ for (idp = ctl->mailboxes; idp; idp = idp->next)
+ printf(" %s", idp->id);
+ printf("\n");
+ }
printf(" %s messages will be retrieved (--all %s).\n",
ctl->fetchall ? "All" : "Only new",
ctl->fetchall ? "on" : "off");
printf(" Rewrite of server-local addresses is %sabled (--norewrite %s).\n",
ctl->rewrite ? "en" : "dis",
ctl->rewrite ? "off" : "on");
- printf(" Carriage-return stripping is %sabled (--stripcr %s).\n",
+ printf(" Carriage-return stripping is %sabled (stripcr %s).\n",
ctl->stripcr ? "en" : "dis",
ctl->stripcr ? "on" : "off");
- if (ctl->limit)
+ printf(" Carriage-return forcing is %sabled (forcecr %s).\n",
+ ctl->forcecr ? "en" : "dis",
+ ctl->forcecr ? "on" : "off");
+ printf(" Interpretation of Content-Transfer-Encoding is %sabled (pass8bits %s).\n",
+ ctl->pass8bits ? "dis" : "en",
+ ctl->pass8bits ? "on" : "off");
+ printf(" Nonempty Status lines will be %s (dropstatus %s)\n",
+ ctl->dropstatus ? "discarded" : "kept",
+ ctl->dropstatus ? "on" : "off");
+ if (ctl->limit > 0)
printf(" Message size limit is %d bytes (--limit %d).\n",
ctl->limit, ctl->limit);
else if (outlevel == O_VERBOSE)
printf(" No message size limit (--limit 0).\n");
- if (ctl->fetchlimit)
+ if (ctl->fetchlimit > 0)
printf(" Received-message limit is %d (--fetchlimit %d).\n",
ctl->fetchlimit, ctl->fetchlimit);
else if (outlevel == O_VERBOSE)
printf(" No received-message limit (--fetchlimit 0).\n");
- if (ctl->batchlimit)
+ if (ctl->batchlimit > 0)
printf(" SMTP message batch limit is %d.\n", ctl->batchlimit);
else if (outlevel == O_VERBOSE)
printf(" No SMTP message batch limit.\n");
if (ctl->mda)
printf(" Messages will be delivered with '%s.'\n", visbuf(ctl->mda));
else
- printf(" Messages will be SMTP-forwarded to '%s'.\n", visbuf(ctl->smtphost));
+ {
+ struct idlist *idp;
+
+ printf(" Messages will be SMTP-forwarded to:");
+ for (idp = ctl->smtphunt; idp; idp = idp->next)
+ printf(" %s", idp->id);
+ printf("\n");
+ }
if (ctl->preconnect)
printf(" Server connection will be preinitialized with '%s.'\n", visbuf(ctl->preconnect));
else if (outlevel == O_VERBOSE)
for (idp = ctl->localnames; idp; idp = idp->next)
++count;
- printf(" %d local name(s) recognized%s.\n",
- count,
- (count == 1 && !strcmp(ctl->localnames->id, user)) ? " (by default)" : "");
+ printf(" %d local name(s) recognized.\n", count);
if (outlevel == O_VERBOSE)
{
for (idp = ctl->localnames; idp; idp = idp->next)
}
printf(" DNS lookup for multidrop addresses is %sabled.\n",
- ctl->server.dns ? "en" : "dis",
- ctl->server.dns ? "off" : "on");
+ ctl->server.dns ? "en" : "dis");
if (count > 1)
if (ctl->server.envelope == STRING_DISABLED)
}
}
-/* helper functions for string interpretation and display */
-
-void escapes(cp, tp)
-/* process standard C-style escape sequences in a string */
-const char *cp; /* source string with escapes */
-char *tp; /* target buffer for digested string */
-{
- while (*cp)
- {
- int cval = 0;
-
- if (*cp == '\\' && strchr("0123456789xX", cp[1]))
- {
- char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
- int dcount = 0;
-
- if (*++cp == 'x' || *cp == 'X')
- for (++cp; (dp = strchr(hex, *cp)) && (dcount++ < 2); cp++)
- cval = (cval * 16) + (dp - hex) / 2;
- else if (*cp == '0')
- while (strchr("01234567",*cp) != (char*)NULL && (dcount++ < 3))
- cval = (cval * 8) + (*cp++ - '0');
- else
- while ((strchr("0123456789",*cp)!=(char*)NULL)&&(dcount++ < 3))
- cval = (cval * 10) + (*cp++ - '0');
- }
- else if (*cp == '\\') /* C-style character escapes */
- {
- switch (*++cp)
- {
- case '\\': cval = '\\'; break;
- case 'n': cval = '\n'; break;
- case 't': cval = '\t'; break;
- case 'b': cval = '\b'; break;
- case 'r': cval = '\r'; break;
- default: cval = *cp;
- }
- cp++;
- }
- else
- cval = *cp++;
- *tp++ = cval;
- }
- *tp = '\0';
-}
-
-static char *visbuf(const char *buf)
-/* visibilize a given string */
-{
- static char vbuf[BUFSIZ];
- char *tp = vbuf;
-
- while (*buf)
- {
- if (isprint(*buf) || *buf == ' ')
- *tp++ = *buf++;
- else if (*buf == '\n')
- {
- *tp++ = '\\'; *tp++ = 'n';
- buf++;
- }
- else if (*buf == '\r')
- {
- *tp++ = '\\'; *tp++ = 'r';
- buf++;
- }
- else if (*buf == '\b')
- {
- *tp++ = '\\'; *tp++ = 'b';
- buf++;
- }
- else if (*buf < ' ')
- {
- *tp++ = '\\'; *tp++ = '^'; *tp++ = '@' + *buf;
- buf++;
- }
- else
- {
- (void) sprintf(tp, "\\0x%02x", *buf++);
- tp += strlen(tp);
- }
- }
- *tp++ = '\0';
- return(vbuf);
-}
-
/* fetchmail.c ends here */