tin  2.4.4
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.4.4.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

header.c
Go to the documentation of this file.
1 /*
2  * Project : tin - a Usenet reader
3  * Module : header.c
4  * Author : Urs Janssen <urs@tin.org>
5  * Created : 1997-03-10
6  * Updated : 2019-07-07
7  *
8  * Copyright (c) 1997-2020 Urs Janssen <urs@tin.org>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  * this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * 3. Neither the name of the copyright holder nor the names of its
23  * contributors may be used to endorse or promote products derived from
24  * this software without specific prior written permission.
25  *
26  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #ifndef TIN_H
40 # include "tin.h"
41 #endif /* !TIN_H */
42 #ifndef TNNTP_H
43 # include "tnntp.h"
44 #endif /* !TNNTP_H */
45 
46 static const char *get_full_name(void);
47 static const char *get_user_name(void);
48 
49 
50 /* find hostname */
51 const char *
53  void)
54 {
55  char *ptr;
56  static char hostname[MAXHOSTNAMELEN + 1]; /* need space for '\0' */
57 
58  hostname[0] = '\0';
59 
60 #ifdef HAVE_GETHOSTNAME
61  gethostname(hostname, sizeof(hostname) - 1);
62 #endif /* HAVE_GETHOSTNAME */
63 #ifdef HAVE_SYS_UTSNAME_H
64  if (!*hostname)
65  my_strncpy(hostname, system_info.nodename, sizeof(hostname) - 1);
66 #endif /* HAVE_SYS_UTSNAME_H */
67  if (!*hostname) {
68  if ((ptr = getenv("HOST")) != NULL)
69  my_strncpy(hostname, ptr, sizeof(hostname) - 1);
70  else {
71  if ((ptr = getenv("HOSTNAME")) != NULL)
72  my_strncpy(hostname, ptr, sizeof(hostname) - 1);
73  else
74  hostname[0] = '\0';
75  }
76  }
77  hostname[MAXHOSTNAMELEN] = '\0';
78  return hostname;
79 }
80 
81 
82 #ifdef DOMAIN_NAME
83 /*
84  * find domainname - check DOMAIN_NAME
85  * TODO: check /etc/defaultdomain as a last resort?
86  */
87 const char *
89  void)
90 {
91  FILE *fp;
92  char *ptr;
93  char buff[MAXHOSTNAMELEN + 1];
94  static char domain[8192];
95 
96  domain[0] = '\0';
97 
98  if (strlen(DOMAIN_NAME))
99  strcpy(domain, DOMAIN_NAME);
100 
101  if (domain[0] == '/' && domain[1]) {
102  /* read domainname from specified file */
103  if ((fp = fopen(domain, "r")) != NULL) {
104  while (fgets(buff, (int) sizeof(buff), fp) != NULL) {
105  if (buff[0] == '#' || buff[0] == '\n')
106  continue;
107 
108  if ((ptr = strrchr(buff, '\n'))) {
109  *ptr = '\0';
110  strcpy(domain, buff);
111  }
112  }
113  if (domain[0] == '/') /* '/' is not allowed in domainames -> file was empty */
114  domain[0] = '\0';
115 
116  fclose(fp);
117  } else
118  domain[0] = '\0';
119  }
120  domain[MAXHOSTNAMELEN + 1] = '\0';
121  return domain;
122 }
123 #endif /* DOMAIN_NAME */
124 
125 
126 #ifdef HAVE_GETHOSTBYNAME
127 # define MAXLINELEN 1024
128 # define WS " \f\t\v"
129 /* find FQDN - gethostbyaddr() */
130 const char *
131 get_fqdn(
132  const char *host)
133 {
134  char *domain;
135  char line[MAXLINELEN + 1];
136  char name[MAXHOSTNAMELEN + 1];
137  static char fqdn[1024];
138  struct hostent *hp;
139  struct in_addr in = {0};
140 
141  *fqdn = '\0';
142  domain = NULL;
143  name[MAXHOSTNAMELEN] = '\0';
144 
145  if (host) {
146  if (strchr(host, '.'))
147  return host;
148  my_strncpy(name, host, sizeof(name) - 1);
149  } else {
150 # ifdef HAVE_GETHOSTNAME
151  if (gethostname(name, sizeof(name) - 1))
152 # endif /* HAVE_GETHOSTNAME */
153  return NULL;
154  }
155 
156 # ifdef HAVE_INET_ADDR
157  if (*name >= '0' && *name <= '9') {
158  in_addr_t addr = inet_addr(name);
159 
160  if ((hp = gethostbyaddr((char *) &addr, 4, AF_INET)))
161 # ifdef HAVE_HOSTENT_H_ADDR_LIST
162  in.s_addr = (*hp->h_addr_list[0]);
163 # else
164  in.s_addr = (*hp->h_addr);
165 # endif /* HAVE_HOSTENT_H_ADDR_LIST */
166  return (hp && strchr(hp->h_name, '.') ? hp->h_name : inet_ntoa(in));
167  }
168 # endif /* HAVE_INET_ADDR */
169  if ((hp = gethostbyname(name)) && !strchr(hp->h_name, '.'))
170 # ifdef HAVE_HOSTENT_H_ADDR_LIST
171  if ((hp = gethostbyaddr(hp->h_addr_list[0], hp->h_length, hp->h_addrtype)))
172  in.s_addr = (*hp->h_addr_list[0]);
173 # else
174  if ((hp = gethostbyaddr(hp->h_addr, hp->h_length, hp->h_addrtype)))
175  in.s_addr = (*hp->h_addr);
176 # endif /* HAVE_HOSTENT_H_ADDR_LIST */
177  snprintf(fqdn, sizeof(fqdn), "%s", hp
178  ? strchr(hp->h_name, '.')
179  ? hp->h_name : inet_ntoa(in)
180  : "");
181 
182  if (!*fqdn || (fqdn[strlen(fqdn) - 1] <= '9')) {
183  FILE *inf;
184 
185  *fqdn = '\0';
186 
187  if ((inf = fopen("/etc/resolv.conf", "r")) != NULL) {
188  char *eos;
189  int j;
190 
191  while (fgets(line, MAXLINELEN, inf)) {
192  if (line[0] == '#' || line[0] == '\n')
193  continue;
194 
195  line[MAXLINELEN] = '\0';
196 
197  if ((eos = strpbrk(line, WS)) != NULL) {
198  if ((j = eos - line)) {
199  if (!strncmp(line, "domain", j) || !strncmp(line, "search", j)) {
200  domain = strtok(eos, WS);
201  break;
202  }
203  }
204  }
205  }
206  if (domain)
207  snprintf(fqdn, sizeof(fqdn), "%s.%s", name, strip_line(domain));
208 
209  fclose(inf);
210  }
211  }
212  return fqdn;
213 }
214 #endif /* HAVE_GETHOSTBYNAME */
215 
216 
217 /*
218  * Find username & fullname
219  */
220 void
222  char *user_name,
223  char *full_name)
224 {
225  const char *ptr;
226 
227  user_name[0] = '\0';
228  full_name[0] = '\0';
229 
230  if ((ptr = get_full_name()))
231  strcpy(full_name, ptr);
232  if ((ptr = get_user_name()))
233  strcpy(user_name, ptr);
234 }
235 
236 
237 static const char *
239  void)
240 {
241  static char username[128];
242  struct passwd *pw;
243 
244  username[0] = '\0';
245 
246  if ((pw = getpwuid(getuid())) != NULL)
247  STRCPY(username, pw->pw_name);
248  else {
249  if (!*username)
251  }
252 
253  return username;
254 }
255 
256 
257 static const char *
259  void)
260 {
261  char *p;
262  static char fullname[128];
263 # ifndef DONT_HAVE_PW_GECOS
264  char buf[128];
265  char tmp[128];
266  struct passwd *pw;
267 # endif /* !DONT_HAVE_PW_GECOS */
268 
269  fullname[0] = '\0';
270 
271  if ((p = getenv("NAME")) != NULL) {
272  my_strncpy(fullname, p, sizeof(fullname) - 1);
273  return fullname;
274  }
275  if ((p = getenv("REALNAME")) != NULL) {
276  my_strncpy(fullname, p, sizeof(fullname) - 1);
277  return fullname;
278  }
279 
280 # ifndef DONT_HAVE_PW_GECOS
281  if ((pw = getpwuid(getuid())) != NULL) {
282  STRCPY(buf, pw->pw_gecos);
283  if ((p = strchr(buf, ',')))
284  *p = '\0';
285  if ((p = strchr(buf, '&'))) {
286  *p++ = '\0';
287  STRCPY(tmp, pw->pw_name);
288  if (*tmp && isalpha((int)(unsigned char) *tmp) && islower((int)(unsigned char) *tmp))
289  *tmp = my_toupper((int)(unsigned char) *tmp);
290  snprintf(fullname, sizeof(fullname), "%s%s%s", buf, tmp, p);
291  } else
292  STRCPY(fullname, buf);
293  }
294 # endif /* !DONT_HAVE_PW_GECOS */
295  return fullname;
296 }
297 
298 
299 /*
300  * FIXME to:
301  * char *build_from(full_name, user_name, domain_name)
302  */
303 /*
304  * build From: in 'name <user@host.doma.in>' format
305  */
306 void
308  char *from_name,
309  struct t_group *thisgrp)
310 {
311  char *fromhost = domain_name;
312 
313  if (thisgrp && *thisgrp->attribute->from != '\0') {
314  strcpy(from_name, thisgrp->attribute->from);
315  return;
316  }
317 
318  sprintf(from_name, ((strpbrk(get_full_name(), "!()<>@,;:\\\".[]")) ? "\"%s\" <%s@%s>" : "%s <%s@%s>"), BlankIfNull(get_full_name()), BlankIfNull(get_user_name()), BlankIfNull(fromhost));
319 
320 # ifdef DEBUG
321  if (debug & DEBUG_MISC)
322  error_message(2, "FROM=[%s] USER=[%s] HOST=[%s] NAME=[%s]", BlankIfNull(from_name), BlankIfNull(get_user_name()), domain_name, BlankIfNull(get_full_name()));
323 # endif /* DEBUG */
324 }
325 
326 
327 /*
328  * build_sender()
329  * returns *(Full_Name <user@fq.domainna.me>)
330  */
331 #ifndef FORGERY
332 char *
334  void)
335 {
336  const char *ptr;
337  static char sender[8192];
338 
339  sender[0] = '\0';
340 
341  if ((ptr = get_full_name()))
342  snprintf(sender, sizeof(sender), ((strpbrk(ptr, "\".:;<>@[]()\\")) ? "\"%s\"" : "%s "), ptr);
343  if ((ptr = get_user_name())) {
344  snprintf(sender + strlen(sender), sizeof(sender) - strlen(sender), "<%s@", ptr);
345 
346 # ifdef HAVE_GETHOSTBYNAME
347  if ((ptr = get_fqdn(get_host_name())))
348 # else
349  if ((ptr = get_host_name()))
350 # endif /* HAVE_GETHOSTBYNAME */
351  snprintf(sender + strlen(sender), sizeof(sender) - strlen(sender), "%s>", ptr);
352  else
353  return NULL;
354  } else
355  return NULL;
356 
357  return sender;
358 }
359 #endif /* !FORGERY */
name
const char * name
Definition: signal.c:117
DEBUG_MISC
#define DEBUG_MISC
Definition: debug.h:54
_
#define _(Text)
Definition: tin.h:94
t_group
Definition: tin.h:1772
get_from_name
void get_from_name(char *from_name, struct t_group *thisgrp)
Definition: header.c:307
get_full_name
static const char * get_full_name(void)
Definition: header.c:258
my_toupper
int my_toupper(int)
Definition: string.c:269
tin.h
tin_done
void tin_done(int ret, const char *fmt,...)
Definition: misc.c:557
get_fqdn
const char * get_fqdn(const char *host)
get_user_info
void get_user_info(char *user_name, char *full_name)
Definition: header.c:221
strip_line
char * strip_line(char *line)
Definition: misc.c:3599
my_strncpy
void my_strncpy(char *p, const char *q, size_t n)
Definition: string.c:190
MAXHOSTNAMELEN
#define MAXHOSTNAMELEN
Definition: tnntp.h:114
buf
static char buf[16]
Definition: langinfo.c:50
get_user_name
static const char * get_user_name(void)
Definition: header.c:238
build_sender
char * build_sender(void)
Definition: header.c:333
get_host_name
const char * get_host_name(void)
Definition: header.c:52
get_domain_name
const char * get_domain_name(void)
EXIT_FAILURE
#define EXIT_FAILURE
Definition: tin.h:1277
BlankIfNull
#define BlankIfNull(p)
Definition: tin.h:2206
domain_name
char domain_name[]
Definition: init.c:75
STRCPY
#define STRCPY(dst, src)
Definition: tin.h:814
debug
unsigned short debug
Definition: debug.c:51
snprintf
#define snprintf
Definition: tin.h:2417
error_message
void error_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:184
t_group::attribute
struct t_attribute * attribute
Definition: tin.h:1790
tnntp.h
t_attribute::from
char * from
Definition: tin.h:1583
strpbrk
char * strpbrk(const char *str1, const char *str2)
Definition: string.c:305
txt_error_passwd_missing
constext txt_error_passwd_missing[]
Definition: lang.c:259