]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tools.cc
fix fcntl F_SETFL calls
[thirdparty/squid.git] / src / tools.cc
CommitLineData
94e891ea 1
30a4f2a8 2/*
0a21bd84 3 * $Id: tools.cc,v 1.66 1996/09/26 19:19:24 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 21 Misc Functions
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Internet Object Cache http://www.nlanr.net/Squid/
9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
019dd986 31
32/*
30a4f2a8 33 * Copyright (c) 1994, 1995. All rights reserved.
34 *
35 * The Harvest software was developed by the Internet Research Task
36 * Force Research Group on Resource Discovery (IRTF-RD):
37 *
38 * Mic Bowman of Transarc Corporation.
39 * Peter Danzig of the University of Southern California.
40 * Darren R. Hardy of the University of Colorado at Boulder.
41 * Udi Manber of the University of Arizona.
42 * Michael F. Schwartz of the University of Colorado at Boulder.
43 * Duane Wessels of the University of Colorado at Boulder.
44 *
45 * This copyright notice applies to software in the Harvest
46 * ``src/'' directory only. Users should consult the individual
47 * copyright notices in the ``components/'' subdirectories for
48 * copyright information about other software bundled with the
49 * Harvest source code distribution.
50 *
51 * TERMS OF USE
52 *
53 * The Harvest software may be used and re-distributed without
54 * charge, provided that the software origin and research team are
55 * cited in any use of the system. Most commonly this is
56 * accomplished by including a link to the Harvest Home Page
57 * (http://harvest.cs.colorado.edu/) from the query page of any
58 * Broker you deploy, as well as in the query result pages. These
59 * links are generated automatically by the standard Broker
60 * software distribution.
61 *
62 * The Harvest software is provided ``as is'', without express or
63 * implied warranty, and with no support nor obligation to assist
64 * in its use, correction, modification or enhancement. We assume
65 * no liability with respect to the infringement of copyrights,
66 * trade secrets, or any patents, and are not responsible for
67 * consequential damages. Proper use of the Harvest software is
68 * entirely the responsibility of the user.
69 *
70 * DERIVATIVE WORKS
71 *
72 * Users may make derivative works from the Harvest software, subject
73 * to the following constraints:
74 *
75 * - You must include the above copyright notice and these
76 * accompanying paragraphs in all forms of derivative works,
77 * and any documentation and other materials related to such
78 * distribution and use acknowledge that the software was
79 * developed at the above institutions.
80 *
81 * - You must notify IRTF-RD regarding your distribution of
82 * the derivative work.
83 *
84 * - You must clearly notify users that your are distributing
85 * a modified version and not the original Harvest software.
86 *
87 * - Any derivative product is also subject to these copyright
88 * and use restrictions.
89 *
90 * Note that the Harvest software is NOT in the public domain. We
91 * retain copyright, as specified above.
92 *
93 * HISTORY OF FREE SOFTWARE STATUS
94 *
95 * Originally we required sites to license the software in cases
96 * where they were going to build commercial products/services
97 * around Harvest. In June 1995 we changed this policy. We now
98 * allow people to use the core Harvest software (the code found in
99 * the Harvest ``src/'' directory) for free. We made this change
100 * in the interest of encouraging the widest possible deployment of
101 * the technology. The Harvest software is really a reference
102 * implementation of a set of protocols and formats, some of which
103 * we intend to standardize. We encourage commercial
104 * re-implementations of code complying to this set of standards.
019dd986 105 */
44a47c6e 106
107#include "squid.h"
108
090089c4 109int do_mallinfo = 0; /* don't do mallinfo() unless this gets set */
b8de7ebe 110time_t squid_curtime;
3a57089e 111struct timeval current_time;
090089c4 112
090089c4 113#define DEAD_MSG "\
c5c666ab 114The Squid Cache (version %s) died.\n\
090089c4 115\n\
c5c666ab 116You've encountered a fatal error in the Squid Cache version %s.\n\
090089c4 117If a core file was created (possibly in the swap directory),\n\
b8de7ebe 118please execute 'gdb squid core' or 'dbx squid core', then type 'where',\n\
234967c9 119and report the trace back to squid-bugs@nlanr.net.\n\
090089c4 120\n\
121Thanks!\n"
122
b8d8561b 123static char *
0673c0ba 124dead_msg(void)
090089c4 125{
95d659f0 126 LOCAL_ARRAY(char, msg, 1024);
8213067d 127 sprintf(msg, DEAD_MSG, version_string, version_string);
090089c4 128 return msg;
129}
130
b8d8561b 131void
0673c0ba 132mail_warranty(void)
090089c4 133{
019dd986 134 FILE *fp = NULL;
6e40f263 135 char *filename;
136 static char command[256];
137 if ((filename = tempnam(NULL, appname)) == NULL)
138 return;
139 if ((fp = fopen(filename, "w")) == NULL)
140 return;
141 fprintf(fp, "From: %s\n", appname);
edae7bc0 142 fprintf(fp, "To: %s\n", Config.adminEmail);
6e40f263 143 fprintf(fp, "Subject: %s\n", dead_msg());
144 fclose(fp);
edae7bc0 145 sprintf(command, "mail %s < %s", Config.adminEmail, filename);
6e40f263 146 system(command); /* XXX should avoid system(3) */
147 unlink(filename);
090089c4 148}
149
b8d8561b 150static void
151dumpMallocStats(FILE * f)
3f43b19b 152{
153#if HAVE_MALLINFO
154 struct mallinfo mp;
30a4f2a8 155 int t;
3f43b19b 156 if (!do_mallinfo)
157 return;
3f43b19b 158 mp = mallinfo();
30a4f2a8 159 fprintf(f, "Memory usage for %s via mallinfo():\n", appname);
160 fprintf(f, "\ttotal space in arena: %6d KB\n",
161 mp.arena >> 10);
162 fprintf(f, "\tOrdinary blocks: %6d KB %6d blks\n",
163 mp.uordblks >> 10, mp.ordblks);
164 fprintf(f, "\tSmall blocks: %6d KB %6d blks\n",
165 mp.usmblks >> 10, mp.smblks);
166 fprintf(f, "\tHolding blocks: %6d KB %6d blks\n",
167 mp.hblkhd >> 10, mp.hblks);
168 fprintf(f, "\tFree Small blocks: %6d KB\n",
169 mp.fsmblks >> 10);
170 fprintf(f, "\tFree Ordinary blocks: %6d KB\n",
171 mp.fordblks >> 10);
172 t = mp.uordblks + mp.usmblks + mp.hblkhd;
173 fprintf(f, "\tTotal in use: %6d KB %d%%\n",
174 t >> 10, percent(t, mp.arena));
175 t = mp.fsmblks + mp.fordblks;
176 fprintf(f, "\tTotal free: %6d KB %d%%\n",
177 t >> 10, percent(t, mp.arena));
178#ifdef WE_DONT_USE_KEEP
179 fprintf(f, "\tKeep option: %6d KB\n",
180 mp.keepcost >> 10);
181#endif
46c883ed 182#if HAVE_EXT_MALLINFO
30a4f2a8 183 fprintf(f, "\tmax size of small blocks:\t%d\n",
184 mp.mxfast);
185 fprintf(f, "\tnumber of small blocks in a holding block:\t%d\n",
3f43b19b 186 mp.nlblks);
30a4f2a8 187 fprintf(f, "\tsmall block rounding factor:\t%d\n",
188 mp.grain);
189 fprintf(f, "\tspace (including overhead) allocated in ord. blks:\t%d\n",
3f43b19b 190 mp.uordbytes);
30a4f2a8 191 fprintf(f, "\tnumber of ordinary blocks allocated:\t%d\n",
3f43b19b 192 mp.allocated);
30a4f2a8 193 fprintf(f, "\tbytes used in maintaining the free tree:\t%d\n",
3f43b19b 194 mp.treeoverhead);
46c883ed 195#endif /* HAVE_EXT_MALLINFO */
3f43b19b 196#if PRINT_MMAP
197 mallocmap();
198#endif /* PRINT_MMAP */
199#endif /* HAVE_MALLINFO */
200}
30a4f2a8 201
b8d8561b 202static int
203PrintRusage(void (*f) (), FILE * lf)
f0f81709 204{
30a4f2a8 205#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
f0f81709 206 struct rusage rusage;
207 getrusage(RUSAGE_SELF, &rusage);
30a4f2a8 208 fprintf(lf, "CPU Usage: user %d sys %d\n",
209 (int) rusage.ru_utime.tv_sec, (int) rusage.ru_stime.tv_sec);
210 fprintf(lf, "Memory Usage: rss %ld KB\n",
211 rusage.ru_maxrss * getpagesize() >> 10);
212 fprintf(lf, "Page faults with physical i/o: %ld\n",
f0f81709 213 rusage.ru_majflt);
214#endif
215 dumpMallocStats(lf);
216 if (f)
217 f(0);
218 return 0;
219}
220
b8d8561b 221void
222death(int sig)
44a47c6e 223{
0e08ce4b 224 if (sig == SIGSEGV)
2c47cf74 225 fprintf(debug_log, "FATAL: Received Segment Violation...dying.\n");
0e08ce4b 226 else if (sig == SIGBUS)
6e40f263 227 fprintf(debug_log, "FATAL: Received Bus Error...dying.\n");
0e08ce4b 228 else
2c47cf74 229 fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
6e40f263 230#if SA_RESETHAND == 0
44a47c6e 231 signal(SIGSEGV, SIG_DFL);
232 signal(SIGBUS, SIG_DFL);
0e08ce4b 233 signal(sig, SIG_DFL);
30a4f2a8 234#endif
44a47c6e 235 storeWriteCleanLog();
2c47cf74 236 PrintRusage(NULL, debug_log);
6e40f263 237 if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
238 /* skip if more than 10 days old */
edae7bc0 239 if (Config.adminEmail)
6e40f263 240 mail_warranty();
241 else
242 puts(dead_msg());
243 }
44a47c6e 244 abort();
245}
246
247
b8d8561b 248void
249sigusr2_handle(int sig)
090089c4 250{
30a4f2a8 251 static int state = 0;
252 debug(21, 1, "sigusr2_handle: SIGUSR2 received.\n");
253 if (state == 0) {
b6f794d6 254 _db_init(Config.Log.log, "ALL,10");
30a4f2a8 255 state = 1;
256 } else {
b6f794d6 257 _db_init(Config.Log.log, Config.debugOptions);
30a4f2a8 258 state = 0;
259 }
260#if !HAVE_SIGACTION
261 signal(sig, sigusr2_handle); /* reinstall */
090089c4 262#endif
263}
264
b8d8561b 265void
f3753518 266setSocketShutdownLifetimes(int lft)
30a4f2a8 267{
268 FD_ENTRY *f = NULL;
30a4f2a8 269 int cur;
270 int i;
271 for (i = fdstat_biggest_fd(); i >= 0; i--) {
272 f = &fd_table[i];
273 if (!f->read_handler && !f->write_handler && !f->except_handler)
274 continue;
275 if (fdstatGetType(i) != FD_SOCKET)
276 continue;
277 cur = comm_get_fd_lifetime(i);
278 if (cur > 0 && (cur - squid_curtime) <= lft)
279 continue;
280 comm_set_fd_lifetime(i, lft);
281 }
282}
283
b8d8561b 284void
0673c0ba 285normal_shutdown(void)
4d64d74a 286{
287 debug(21, 1, "Shutting down...\n");
b6f794d6 288 if (Config.pidFilename) {
30a4f2a8 289 enter_suid();
b6f794d6 290 safeunlink(Config.pidFilename, 0);
30a4f2a8 291 leave_suid();
234967c9 292 }
4d64d74a 293 storeWriteCleanLog();
294 PrintRusage(NULL, debug_log);
457bedbd 295 storeCloseLog();
296 statCloseLog();
297 fclose(debug_log);
0a21bd84 298 configFreeMemory();
299 diskFreeMemory();
300 storeFreeMemory();
301 commFreeMemory();
302 filemapFreeMemory();
303 dnsFreeMemory();
304 redirectFreeMemory();
305 fdstatFreeMemory();
306 errorpageFreeMemory();
307 stmemFreeMemory();
308 debug(21, 0, "Squid Cache (Version %s): Exiting normally.\n",
309 version_string);
4d64d74a 310 exit(0);
311}
147d3115 312
b8d8561b 313void
314fatal_common(char *message)
090089c4 315{
db40ae20 316#if HAVE_SYSLOG
6e40f263 317 if (opt_syslog_enable)
233794cd 318 syslog(LOG_ALERT, "%s", message);
db40ae20 319#endif
2c47cf74 320 fprintf(debug_log, "FATAL: %s\n", message);
c5c666ab 321 fprintf(debug_log, "Squid Cache (Version %s): Terminated abnormally.\n",
8213067d 322 version_string);
2c47cf74 323 fflush(debug_log);
324 PrintRusage(NULL, debug_log);
090089c4 325}
326
327/* fatal */
b8d8561b 328void
329fatal(char *message)
090089c4 330{
331 fatal_common(message);
332 exit(1);
333}
334
335/* fatal with dumping core */
b8d8561b 336void
337fatal_dump(char *message)
090089c4 338{
339 if (message)
340 fatal_common(message);
1758c627 341 if (opt_catch_signals)
090089c4 342 storeWriteCleanLog();
343 abort();
344}
345
85b701ed 346/* fatal with dumping core */
b8d8561b 347void
348_debug_trap(char *message)
85b701ed 349{
350 if (opt_catch_signals)
351 fatal_dump(message);
fedac7e5 352 _db_print(0, 0, "WARNING: %s\n", message);
85b701ed 353}
354
b8d8561b 355void
356sig_child(int sig)
090089c4 357{
30a4f2a8 358#ifdef _SQUID_NEXT_
359 union wait status;
360#else
090089c4 361 int status;
090089c4 362#endif
30a4f2a8 363 int pid;
090089c4 364
30a4f2a8 365 do {
366#ifdef _SQUID_NEXT_
367 pid = wait3(&status, WNOHANG, NULL);
090089c4 368#else
30a4f2a8 369 pid = waitpid(-1, &status, WNOHANG);
090089c4 370#endif
30a4f2a8 371 debug(21, 3, "sig_child: Ate pid %d\n", pid);
372#if HAVE_SIGACTION
373 } while (pid > 0);
234967c9 374#else
30a4f2a8 375 } while (pid > 0 || (pid < 0 && errno == EINTR));
376 signal(sig, sig_child);
234967c9 377#endif
30a4f2a8 378}
44a47c6e 379
b8d8561b 380char *
0673c0ba 381getMyHostname(void)
44a47c6e 382{
95d659f0 383 LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
44a47c6e 384 static int present = 0;
385 struct hostent *h = NULL;
019dd986 386 char *t = NULL;
387
b6f794d6 388 if ((t = Config.visibleHostname))
019dd986 389 return t;
44a47c6e 390
391 /* Get the host name and store it in host to return */
392 if (!present) {
393 host[0] = '\0';
394 if (gethostname(host, SQUIDHOSTNAMELEN) == -1) {
019dd986 395 debug(21, 1, "getMyHostname: gethostname failed: %s\n",
44a47c6e 396 xstrerror());
397 return NULL;
398 } else {
30a4f2a8 399 if ((h = ipcache_gethostbyname(host, IP_BLOCKING_LOOKUP)) != NULL) {
44a47c6e 400 /* DNS lookup successful */
401 /* use the official name from DNS lookup */
402 strcpy(host, h->h_name);
403 }
404 present = 1;
405 }
406 }
407 return host;
408}
409
b8d8561b 410int
411safeunlink(char *s, int quiet)
44a47c6e 412{
413 int err;
414 if ((err = unlink(s)) < 0)
415 if (!quiet)
019dd986 416 debug(21, 1, "safeunlink: Couldn't delete %s. %s\n", s, xstrerror());
44a47c6e 417 return (err);
418}
12b9e9b1 419
30a4f2a8 420/* leave a privilegied section. (Give up any privilegies)
421 * Routines that need privilegies can rap themselves in enter_suid()
422 * and leave_suid()
423 * To give upp all posibilites to gain privilegies use no_suid()
12b9e9b1 424 */
b8d8561b 425void
0673c0ba 426leave_suid(void)
12b9e9b1 427{
428 struct passwd *pwd = NULL;
429 struct group *grp = NULL;
30a4f2a8 430 debug(21, 3, "leave_suid: PID %d called\n", getpid());
12b9e9b1 431 if (geteuid() != 0)
432 return;
433 /* Started as a root, check suid option */
b6f794d6 434 if (Config.effectiveUser == NULL)
12b9e9b1 435 return;
b6f794d6 436 if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
12b9e9b1 437 return;
b6f794d6 438 if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
12b9e9b1 439 setgid(grp->gr_gid);
440 } else {
441 setgid(pwd->pw_gid);
442 }
30a4f2a8 443 debug(21, 3, "leave_suid: PID %d giving up root, becoming '%s'\n",
444 getpid(), pwd->pw_name);
234967c9 445#if HAVE_SETRESUID
446 setresuid(pwd->pw_uid, pwd->pw_uid, 0);
447#elif HAVE_SETEUID
448 seteuid(pwd->pw_uid);
449#else
12b9e9b1 450 setuid(pwd->pw_uid);
234967c9 451#endif
452}
453
30a4f2a8 454/* Enter a privilegied section */
b8d8561b 455void
0673c0ba 456enter_suid(void)
234967c9 457{
30a4f2a8 458 debug(21, 3, "enter_suid: PID %d taking root priveleges\n", getpid());
234967c9 459#if HAVE_SETRESUID
460 setresuid(-1, 0, -1);
461#else
462 setuid(0);
463#endif
464}
465
30a4f2a8 466/* Give up the posibility to gain privilegies.
467 * this should be used before starting a sub process
468 */
b8d8561b 469void
0673c0ba 470no_suid(void)
234967c9 471{
472 uid_t uid;
30a4f2a8 473 leave_suid();
234967c9 474 uid = geteuid();
30a4f2a8 475 debug(21, 3, "leave_suid: PID %d giving up root priveleges forever\n", getpid());
234967c9 476#if HAVE_SETRESUID
477 setresuid(uid, uid, uid);
478#else
479 setuid(0);
480 setuid(uid);
481#endif
12b9e9b1 482}
ccff9601 483
b8d8561b 484void
0673c0ba 485writePidFile(void)
ccff9601 486{
487 FILE *pid_fp = NULL;
488 char *f = NULL;
489
b6f794d6 490 if ((f = Config.pidFilename) == NULL)
ccff9601 491 return;
30a4f2a8 492 enter_suid();
493 pid_fp = fopen(f, "w");
494 leave_suid();
495 if (pid_fp != NULL) {
496 fprintf(pid_fp, "%d\n", (int) getpid());
497 fclose(pid_fp);
498 } else {
019dd986 499 debug(21, 0, "WARNING: Could not write pid file\n");
500 debug(21, 0, " %s: %s\n", f, xstrerror());
ccff9601 501 }
ccff9601 502}
c4fb974e 503
504
b8d8561b 505int
0673c0ba 506readPidFile(void)
7690e8eb 507{
508 FILE *pid_fp = NULL;
509 char *f = NULL;
510 int pid = -1;
511
512 if ((f = Config.pidFilename) == NULL) {
513 fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
514 exit(1);
515 }
516 pid_fp = fopen(f, "r");
517 if (pid_fp != NULL) {
518 if (fscanf(pid_fp, "%d", &pid) != 1)
519 pid = 0;
520 fclose(pid_fp);
521 } else {
522 if (errno != ENOENT) {
523 fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
524 fprintf(stderr, "\t%s: %s\n", f, xstrerror());
525 exit(1);
526 }
527 }
528 return pid;
529}
530
531
b8d8561b 532void
0673c0ba 533setMaxFD(void)
c4fb974e 534{
234967c9 535#if HAVE_SETRLIMIT
c4fb974e 536 /* try to use as many file descriptors as possible */
537 /* System V uses RLIMIT_NOFILE and BSD uses RLIMIT_OFILE */
538 struct rlimit rl;
539#if defined(RLIMIT_NOFILE)
540 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
a8f7d3ee 541 debug(21, 0, "setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 542 } else {
234967c9 543 rl.rlim_cur = FD_SETSIZE;
30a4f2a8 544 if (rl.rlim_cur > rl.rlim_max)
545 rl.rlim_cur = rl.rlim_max;
c4fb974e 546 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
234967c9 547 sprintf(tmp_error_buf, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
548 fatal_dump(tmp_error_buf);
c4fb974e 549 }
550 }
551#elif defined(RLIMIT_OFILE)
552 if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
a8f7d3ee 553 debug(21, 0, "setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 554 } else {
234967c9 555 rl.rlim_cur = FD_SETSIZE;
30a4f2a8 556 if (rl.rlim_cur > rl.rlim_max)
557 rl.rlim_cur = rl.rlim_max;
c4fb974e 558 if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
234967c9 559 sprintf(tmp_error_buf, "setrlimit: RLIMIT_OFILE: %s", xstrerror());
560 fatal_dump(tmp_error_buf);
c4fb974e 561 }
562 }
563#endif
c4fb974e 564#else /* HAVE_SETRLIMIT */
a8f7d3ee 565 debug(21, 1, "setMaxFD: Cannot increase: setrlimit() not supported on this system\n");
30a4f2a8 566#endif /* HAVE_SETRLIMIT */
567
568#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
569 if (getrlimit(RLIMIT_DATA, &rl) < 0) {
a8f7d3ee 570 debug(21, 0, "getrlimit: RLIMIT_DATA: %s\n", xstrerror());
30a4f2a8 571 } else {
572 rl.rlim_cur = rl.rlim_max; /* set it to the max */
573 if (setrlimit(RLIMIT_DATA, &rl) < 0) {
574 sprintf(tmp_error_buf, "setrlimit: RLIMIT_DATA: %s", xstrerror());
575 fatal_dump(tmp_error_buf);
576 }
577 }
578#endif /* RLIMIT_DATA */
c4fb974e 579}
3a57089e 580
b8d8561b 581time_t
0673c0ba 582getCurrentTime(void)
3a57089e 583{
94e891ea 584#if GETTIMEOFDAY_NO_TZP
30a4f2a8 585 gettimeofday(&current_time);
586#else
d598947a 587 gettimeofday(&current_time, NULL);
5f3f8d0e 588#endif
30a4f2a8 589 return squid_curtime = current_time.tv_sec;
5f3f8d0e 590}
fe113054 591
b8d8561b 592int
593percent(int a, int b)
30a4f2a8 594{
595 return b ? ((int) (100.0 * a / b + 0.5)) : 0;
596}
597
b8d8561b 598void
67508012 599squid_signal(int sig, void (*func) _PARAMS((int)), int flags)
30a4f2a8 600{
601#if HAVE_SIGACTION
602 struct sigaction sa;
603 sa.sa_handler = func;
604 sa.sa_flags = flags;
605 sigemptyset(&sa.sa_mask);
606 if (sigaction(sig, &sa, NULL) < 0)
607 debug(1, 0, "sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
608#else
609 (void) signal(sig, func);
610#endif
611}
396c5745 612
16b204c4 613struct in_addr
614inaddrFromHostent(struct hostent *hp)
615{
cc6a9d2e 616 struct in_addr s;
617 memcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr));
618 return s;
16b204c4 619}