]> Pileus Git - ~andy/fetchmail/blob - env.c
4533275dbae073bb0d0d422b1d6ae3bc8d46aeb3
[~andy/fetchmail] / env.c
1 /*
2  * env.c -- small service routines
3  *
4  * Copyright 1998 by Eric S. Raymond
5  * For license terms, see the file COPYING in this directory.
6  */
7
8 #include "config.h"
9 #include <stdio.h>
10 #include <ctype.h>
11 #if defined(STDC_HEADERS)
12 #include <stdlib.h>
13 #endif
14 #if defined(HAVE_UNISTD_H)
15 #include <unistd.h>
16 #endif
17 #include <pwd.h>
18 #include <string.h>
19 #ifdef HAVE_NET_SOCKET_H
20 #include <net/socket.h>
21 #endif
22 #ifdef HAVE_GETHOSTBYNAME
23 #include <netdb.h>
24 #endif /* HAVE_GETHOSTBYNAME */
25 #include  <sys/types.h>
26 #include  <time.h>
27 #include "fetchmail.h"
28
29 #include "i18n.h"
30
31 extern char *getenv();  /* needed on sysV68 R3V7.1. */
32
33 extern char *program_name;
34
35 void envquery(int argc, char **argv)
36 /* set up basic stuff from the environment (including the rc file name) */
37 {
38     struct passwd by_name, by_uid, *pwp;
39
40     (user = getenv("FETCHMAILUSER"))
41         || (user = getenv("LOGNAME"))
42         || (user = getenv("USER"));
43
44     if (!(pwp = getpwuid(getuid())))
45     {
46         fprintf(stderr,
47                 _("%s: You don't exist.  Go away.\n"),
48                 program_name);
49         exit(PS_UNDEFINED);
50     }
51     else
52     {
53         memcpy(&by_uid, pwp, sizeof(struct passwd));
54         if (!user || !(pwp = getpwnam(user)))
55             pwp = &by_uid;
56         else
57         {
58             /*
59              * This logic is needed to handle gracefully the possibility
60              * that multiple names might be mapped to one UID.
61              */
62             memcpy(&by_name, pwp, sizeof(struct passwd));
63
64             if (by_name.pw_uid == by_uid.pw_uid)
65                 pwp = &by_name;
66             else
67                 pwp = &by_uid;
68         }
69         user = xstrdup(pwp->pw_name);
70     }
71
72     /* compute user's home directory */
73     if (!(home = getenv("HOME")))
74         home = pwp->pw_dir;
75
76     /* compute fetchmail's home directory */
77     if (!(fmhome = getenv("FETCHMAILHOME")))
78         fmhome = home;
79
80     if ((program_name = strrchr(argv[0], '/')) != NULL)
81         ++program_name;
82     else
83         program_name = argv[0];
84
85 #define RCFILE_NAME     "fetchmailrc"
86     /*
87      * The (fmhome==home) leaves an extra character for a . at the
88      * beginning of the rc file's name, iff fetchmail is using $HOME
89      * for its files. We don't want to do that if fetchmail has its
90      * own home ($FETCHMAILHOME), however.
91      */
92     rcfile = (char *)xmalloc(strlen(fmhome)+sizeof(RCFILE_NAME)+(fmhome==home)+2);
93     /* avoid //.fetchmailrc */
94     if (strcmp(fmhome, "/") != 0)
95         strcpy(rcfile, fmhome);
96     else
97         *rcfile = '\0';
98
99     if (rcfile[strlen(rcfile) - 1] != '/')
100         strcat(rcfile, "/");
101     if (fmhome==home)
102         strcat(rcfile, ".");
103     strcat(rcfile, RCFILE_NAME);
104 }
105
106 char *host_fqdn(void)
107 /* get the FQDN of the machine we're running */
108 {
109     char        tmpbuf[HOSTLEN+1];
110
111     if (gethostname(tmpbuf, sizeof(tmpbuf)))
112     {
113         fprintf(stderr, _("%s: can't determine your host!"),
114                 program_name);
115         exit(PS_DNS);
116     }
117 #ifdef HAVE_GETHOSTBYNAME
118     /* if we got a . in the hostname assume it is a FQDN */
119     if (strchr(tmpbuf, '.') == NULL)
120     {
121         struct hostent *hp;
122
123         /* if we got a basename (as we do in Linux) make a FQDN of it */
124         hp = gethostbyname(tmpbuf);
125         if (hp == (struct hostent *) NULL)
126         {
127             /* exit with error message */
128             fprintf(stderr,
129                     _("gethostbyname failed for %s\n"), tmpbuf);
130             exit(PS_DNS);
131         }
132         return(xstrdup(hp->h_name));
133     }
134     else
135 #endif /* HAVE_GETHOSTBYNAME */
136         return(xstrdup(tmpbuf));
137 }
138
139 static char *tzoffset(time_t *now)
140 /* calculate timezone offset */
141 {
142     static char offset_string[6];
143     struct tm gmt, *lt;
144     int off;
145     char sign = '+';
146
147     gmt = *gmtime(now);
148     lt = localtime(now);
149     off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
150     if (lt->tm_year < gmt.tm_year)
151         off -= 24 * 60;
152     else if (lt->tm_year > gmt.tm_year)
153         off += 24 * 60;
154     else if (lt->tm_yday < gmt.tm_yday)
155         off -= 24 * 60;
156     else if (lt->tm_yday > gmt.tm_yday)
157         off += 24 * 60;
158     if (off < 0) {
159         sign = '-';
160         off = -off;
161     }
162     if (off >= 24 * 60)                 /* should be impossible */
163         off = 23 * 60 + 59;             /* if not, insert silly value */
164     sprintf(offset_string, "%c%02d%02d", sign, off / 60, off % 60);
165     return (offset_string);
166 }
167
168 char *rfc822timestamp(void)
169 /* return a timestamp in RFC822 form */
170 {
171     time_t      now;
172     static char buf[50];
173
174     time(&now);
175 #ifdef HAVE_STRFTIME
176     /*
177      * Conform to RFC822.  We generate a 4-digit year here, avoiding
178      * Y2K hassles.  Max length of this timestamp in an English locale
179      * should be 29 chars.  The only things that should vary by locale
180      * are the day and month abbreviations.
181      */
182     strftime(buf, sizeof(buf)-1, 
183              "%a, %d %b %Y %H:%M:%S XXXXX (%Z)", localtime(&now));
184     strncpy(strstr(buf, "XXXXX"), tzoffset(&now), 5);
185 #else
186     /*
187      * This is really just a portability fallback, as the
188      * date format ctime(3) emits is not RFC822
189      * conformant.
190      */
191     strcpy(buf, ctime(&now));
192     buf[strlen(buf)-1] = '\0';  /* remove trailing \n */
193 #endif /* HAVE_STRFTIME */
194
195     return(buf);
196 }
197
198 const char *showproto(int proto)
199 /* protocol index to protocol name mapping */
200 {
201     switch (proto)
202     {
203     case P_AUTO: return("auto");
204 #ifdef POP2_ENABLE
205     case P_POP2: return("POP2");
206 #endif /* POP2_ENABLE */
207 #ifdef POP3_ENABLE
208     case P_POP3: return("POP3");
209     case P_APOP: return("APOP");
210     case P_RPOP: return("RPOP");
211 #endif /* POP3_ENABLE */
212 #ifdef IMAP_ENABLE
213     case P_IMAP: return("IMAP");
214 #endif /* IMAP_ENABLE */
215 #ifdef ETRN_ENABLE
216     case P_ETRN: return("ETRN");
217 #endif /* ETRN_ENABLE */
218 #ifdef ODMR_ENABLE
219     case P_ODMR: return("ODMR");
220 #endif /* ODMR_ENABLE */
221     default: return("unknown?!?");
222     }
223 }
224
225 char *visbuf(const char *buf)
226 /* visibilize a given string */
227 {
228     static char vbuf[BUFSIZ];
229     char *tp = vbuf;
230
231     while (*buf)
232     {
233         if (*buf == '"')
234         {
235             *tp++ = '\\'; *tp++ = '"';
236             buf++;
237         }
238         else if (*buf == '\\')
239         {
240             *tp++ = '\\'; *tp++ = '\\';
241             buf++;
242         }
243         else if (isprint(*buf) || *buf == ' ')
244             *tp++ = *buf++;
245         else if (*buf == '\n')
246         {
247             *tp++ = '\\'; *tp++ = 'n';
248             buf++;
249         }
250         else if (*buf == '\r')
251         {
252             *tp++ = '\\'; *tp++ = 'r';
253             buf++;
254         }
255         else if (*buf == '\b')
256         {
257             *tp++ = '\\'; *tp++ = 'b';
258             buf++;
259         }
260         else if (*buf < ' ')
261         {
262             *tp++ = '\\'; *tp++ = '^'; *tp++ = '@' + *buf;
263             buf++;
264         }
265         else
266         {
267             (void) sprintf(tp, "\\0x%02x", *buf++);
268             tp += strlen(tp);
269         }
270     }
271     *tp++ = '\0';
272     return(vbuf);
273 }
274
275 /* env.c ends here */