]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tools.cc
add memcpy
[thirdparty/squid.git] / src / tools.cc
CommitLineData
94e891ea 1
30a4f2a8 2/*
0b6d1622 3 * $Id: tools.cc,v 1.75 1996/10/19 00:13: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
24382924 123static void fatal_common _PARAMS((char *));
124static void mail_warranty _PARAMS((void));
125
b8d8561b 126static char *
0673c0ba 127dead_msg(void)
090089c4 128{
95d659f0 129 LOCAL_ARRAY(char, msg, 1024);
8213067d 130 sprintf(msg, DEAD_MSG, version_string, version_string);
090089c4 131 return msg;
132}
133
24382924 134static void
0673c0ba 135mail_warranty(void)
090089c4 136{
019dd986 137 FILE *fp = NULL;
6e40f263 138 char *filename;
139 static char command[256];
140 if ((filename = tempnam(NULL, appname)) == NULL)
141 return;
142 if ((fp = fopen(filename, "w")) == NULL)
143 return;
144 fprintf(fp, "From: %s\n", appname);
edae7bc0 145 fprintf(fp, "To: %s\n", Config.adminEmail);
6e40f263 146 fprintf(fp, "Subject: %s\n", dead_msg());
147 fclose(fp);
edae7bc0 148 sprintf(command, "mail %s < %s", Config.adminEmail, filename);
6e40f263 149 system(command); /* XXX should avoid system(3) */
150 unlink(filename);
090089c4 151}
152
b8d8561b 153static void
154dumpMallocStats(FILE * f)
3f43b19b 155{
156#if HAVE_MALLINFO
157 struct mallinfo mp;
30a4f2a8 158 int t;
3f43b19b 159 if (!do_mallinfo)
160 return;
3f43b19b 161 mp = mallinfo();
30a4f2a8 162 fprintf(f, "Memory usage for %s via mallinfo():\n", appname);
163 fprintf(f, "\ttotal space in arena: %6d KB\n",
164 mp.arena >> 10);
165 fprintf(f, "\tOrdinary blocks: %6d KB %6d blks\n",
166 mp.uordblks >> 10, mp.ordblks);
167 fprintf(f, "\tSmall blocks: %6d KB %6d blks\n",
168 mp.usmblks >> 10, mp.smblks);
169 fprintf(f, "\tHolding blocks: %6d KB %6d blks\n",
170 mp.hblkhd >> 10, mp.hblks);
171 fprintf(f, "\tFree Small blocks: %6d KB\n",
172 mp.fsmblks >> 10);
173 fprintf(f, "\tFree Ordinary blocks: %6d KB\n",
174 mp.fordblks >> 10);
175 t = mp.uordblks + mp.usmblks + mp.hblkhd;
176 fprintf(f, "\tTotal in use: %6d KB %d%%\n",
177 t >> 10, percent(t, mp.arena));
178 t = mp.fsmblks + mp.fordblks;
179 fprintf(f, "\tTotal free: %6d KB %d%%\n",
180 t >> 10, percent(t, mp.arena));
181#ifdef WE_DONT_USE_KEEP
182 fprintf(f, "\tKeep option: %6d KB\n",
183 mp.keepcost >> 10);
184#endif
46c883ed 185#if HAVE_EXT_MALLINFO
30a4f2a8 186 fprintf(f, "\tmax size of small blocks:\t%d\n",
187 mp.mxfast);
188 fprintf(f, "\tnumber of small blocks in a holding block:\t%d\n",
3f43b19b 189 mp.nlblks);
30a4f2a8 190 fprintf(f, "\tsmall block rounding factor:\t%d\n",
191 mp.grain);
192 fprintf(f, "\tspace (including overhead) allocated in ord. blks:\t%d\n",
3f43b19b 193 mp.uordbytes);
30a4f2a8 194 fprintf(f, "\tnumber of ordinary blocks allocated:\t%d\n",
3f43b19b 195 mp.allocated);
30a4f2a8 196 fprintf(f, "\tbytes used in maintaining the free tree:\t%d\n",
3f43b19b 197 mp.treeoverhead);
46c883ed 198#endif /* HAVE_EXT_MALLINFO */
3f43b19b 199#if PRINT_MMAP
200 mallocmap();
201#endif /* PRINT_MMAP */
202#endif /* HAVE_MALLINFO */
203}
30a4f2a8 204
b8d8561b 205static int
ff8d0ea6 206PrintRusage(void (*f) (void), FILE * lf)
f0f81709 207{
30a4f2a8 208#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
f0f81709 209 struct rusage rusage;
210 getrusage(RUSAGE_SELF, &rusage);
30a4f2a8 211 fprintf(lf, "CPU Usage: user %d sys %d\n",
212 (int) rusage.ru_utime.tv_sec, (int) rusage.ru_stime.tv_sec);
213 fprintf(lf, "Memory Usage: rss %ld KB\n",
214 rusage.ru_maxrss * getpagesize() >> 10);
215 fprintf(lf, "Page faults with physical i/o: %ld\n",
f0f81709 216 rusage.ru_majflt);
217#endif
218 dumpMallocStats(lf);
219 if (f)
ff8d0ea6 220 f();
f0f81709 221 return 0;
222}
223
b8d8561b 224void
225death(int sig)
44a47c6e 226{
0e08ce4b 227 if (sig == SIGSEGV)
2c47cf74 228 fprintf(debug_log, "FATAL: Received Segment Violation...dying.\n");
0e08ce4b 229 else if (sig == SIGBUS)
6e40f263 230 fprintf(debug_log, "FATAL: Received Bus Error...dying.\n");
0e08ce4b 231 else
2c47cf74 232 fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
6e40f263 233#if SA_RESETHAND == 0
44a47c6e 234 signal(SIGSEGV, SIG_DFL);
235 signal(SIGBUS, SIG_DFL);
0e08ce4b 236 signal(sig, SIG_DFL);
30a4f2a8 237#endif
44a47c6e 238 storeWriteCleanLog();
2c47cf74 239 PrintRusage(NULL, debug_log);
6e40f263 240 if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
241 /* skip if more than 10 days old */
edae7bc0 242 if (Config.adminEmail)
6e40f263 243 mail_warranty();
244 else
245 puts(dead_msg());
246 }
44a47c6e 247 abort();
248}
249
250
b8d8561b 251void
252sigusr2_handle(int sig)
090089c4 253{
30a4f2a8 254 static int state = 0;
255 debug(21, 1, "sigusr2_handle: SIGUSR2 received.\n");
256 if (state == 0) {
b6f794d6 257 _db_init(Config.Log.log, "ALL,10");
30a4f2a8 258 state = 1;
259 } else {
b6f794d6 260 _db_init(Config.Log.log, Config.debugOptions);
30a4f2a8 261 state = 0;
262 }
263#if !HAVE_SIGACTION
264 signal(sig, sigusr2_handle); /* reinstall */
090089c4 265#endif
266}
267
b8d8561b 268void
f3753518 269setSocketShutdownLifetimes(int lft)
30a4f2a8 270{
271 FD_ENTRY *f = NULL;
30a4f2a8 272 int cur;
273 int i;
274 for (i = fdstat_biggest_fd(); i >= 0; i--) {
275 f = &fd_table[i];
276 if (!f->read_handler && !f->write_handler && !f->except_handler)
277 continue;
278 if (fdstatGetType(i) != FD_SOCKET)
279 continue;
280 cur = comm_get_fd_lifetime(i);
281 if (cur > 0 && (cur - squid_curtime) <= lft)
282 continue;
283 comm_set_fd_lifetime(i, lft);
284 }
285}
286
b8d8561b 287void
0673c0ba 288normal_shutdown(void)
4d64d74a 289{
290 debug(21, 1, "Shutting down...\n");
b6f794d6 291 if (Config.pidFilename) {
30a4f2a8 292 enter_suid();
b6f794d6 293 safeunlink(Config.pidFilename, 0);
30a4f2a8 294 leave_suid();
234967c9 295 }
4d64d74a 296 storeWriteCleanLog();
297 PrintRusage(NULL, debug_log);
457bedbd 298 storeCloseLog();
299 statCloseLog();
0a21bd84 300 configFreeMemory();
301 diskFreeMemory();
302 storeFreeMemory();
303 commFreeMemory();
304 filemapFreeMemory();
305 dnsFreeMemory();
306 redirectFreeMemory();
307 fdstatFreeMemory();
308 errorpageFreeMemory();
309 stmemFreeMemory();
e5f6c5c2 310 netdbFreeMemory();
56e15c50 311 ipcacheFreeMemory();
312 fqdncacheFreeMemory();
0a21bd84 313 debug(21, 0, "Squid Cache (Version %s): Exiting normally.\n",
314 version_string);
c7433536 315 fclose(debug_log);
4d64d74a 316 exit(0);
317}
147d3115 318
24382924 319static void
b8d8561b 320fatal_common(char *message)
090089c4 321{
db40ae20 322#if HAVE_SYSLOG
6e40f263 323 if (opt_syslog_enable)
233794cd 324 syslog(LOG_ALERT, "%s", message);
db40ae20 325#endif
2c47cf74 326 fprintf(debug_log, "FATAL: %s\n", message);
c5c666ab 327 fprintf(debug_log, "Squid Cache (Version %s): Terminated abnormally.\n",
8213067d 328 version_string);
2c47cf74 329 fflush(debug_log);
330 PrintRusage(NULL, debug_log);
090089c4 331}
332
333/* fatal */
b8d8561b 334void
335fatal(char *message)
090089c4 336{
337 fatal_common(message);
338 exit(1);
339}
340
341/* fatal with dumping core */
b8d8561b 342void
343fatal_dump(char *message)
090089c4 344{
345 if (message)
346 fatal_common(message);
0b6d1622 347 if (!opt_catch_signals)
090089c4 348 storeWriteCleanLog();
349 abort();
350}
351
85b701ed 352/* fatal with dumping core */
b8d8561b 353void
354_debug_trap(char *message)
85b701ed 355{
356 if (opt_catch_signals)
357 fatal_dump(message);
fedac7e5 358 _db_print(0, 0, "WARNING: %s\n", message);
85b701ed 359}
360
b8d8561b 361void
362sig_child(int sig)
090089c4 363{
30a4f2a8 364#ifdef _SQUID_NEXT_
365 union wait status;
366#else
090089c4 367 int status;
090089c4 368#endif
ff8d0ea6 369 pid_t pid;
090089c4 370
30a4f2a8 371 do {
372#ifdef _SQUID_NEXT_
373 pid = wait3(&status, WNOHANG, NULL);
090089c4 374#else
30a4f2a8 375 pid = waitpid(-1, &status, WNOHANG);
090089c4 376#endif
30a4f2a8 377 debug(21, 3, "sig_child: Ate pid %d\n", pid);
378#if HAVE_SIGACTION
379 } while (pid > 0);
234967c9 380#else
30a4f2a8 381 } while (pid > 0 || (pid < 0 && errno == EINTR));
382 signal(sig, sig_child);
234967c9 383#endif
30a4f2a8 384}
44a47c6e 385
b8d8561b 386char *
0673c0ba 387getMyHostname(void)
44a47c6e 388{
95d659f0 389 LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
44a47c6e 390 static int present = 0;
391 struct hostent *h = NULL;
019dd986 392 char *t = NULL;
393
b6f794d6 394 if ((t = Config.visibleHostname))
019dd986 395 return t;
44a47c6e 396
397 /* Get the host name and store it in host to return */
398 if (!present) {
399 host[0] = '\0';
400 if (gethostname(host, SQUIDHOSTNAMELEN) == -1) {
019dd986 401 debug(21, 1, "getMyHostname: gethostname failed: %s\n",
44a47c6e 402 xstrerror());
403 return NULL;
404 } else {
e5f6c5c2 405 if ((h = gethostbyname(host)) != NULL) {
44a47c6e 406 /* DNS lookup successful */
407 /* use the official name from DNS lookup */
408 strcpy(host, h->h_name);
409 }
410 present = 1;
411 }
412 }
413 return host;
414}
415
b8d8561b 416int
417safeunlink(char *s, int quiet)
44a47c6e 418{
419 int err;
420 if ((err = unlink(s)) < 0)
421 if (!quiet)
019dd986 422 debug(21, 1, "safeunlink: Couldn't delete %s. %s\n", s, xstrerror());
44a47c6e 423 return (err);
424}
12b9e9b1 425
30a4f2a8 426/* leave a privilegied section. (Give up any privilegies)
427 * Routines that need privilegies can rap themselves in enter_suid()
428 * and leave_suid()
429 * To give upp all posibilites to gain privilegies use no_suid()
12b9e9b1 430 */
b8d8561b 431void
0673c0ba 432leave_suid(void)
12b9e9b1 433{
434 struct passwd *pwd = NULL;
435 struct group *grp = NULL;
30a4f2a8 436 debug(21, 3, "leave_suid: PID %d called\n", getpid());
12b9e9b1 437 if (geteuid() != 0)
438 return;
439 /* Started as a root, check suid option */
b6f794d6 440 if (Config.effectiveUser == NULL)
12b9e9b1 441 return;
b6f794d6 442 if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
12b9e9b1 443 return;
b6f794d6 444 if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
12b9e9b1 445 setgid(grp->gr_gid);
446 } else {
447 setgid(pwd->pw_gid);
448 }
30a4f2a8 449 debug(21, 3, "leave_suid: PID %d giving up root, becoming '%s'\n",
450 getpid(), pwd->pw_name);
234967c9 451#if HAVE_SETRESUID
452 setresuid(pwd->pw_uid, pwd->pw_uid, 0);
453#elif HAVE_SETEUID
454 seteuid(pwd->pw_uid);
455#else
12b9e9b1 456 setuid(pwd->pw_uid);
234967c9 457#endif
458}
459
30a4f2a8 460/* Enter a privilegied section */
b8d8561b 461void
0673c0ba 462enter_suid(void)
234967c9 463{
30a4f2a8 464 debug(21, 3, "enter_suid: PID %d taking root priveleges\n", getpid());
234967c9 465#if HAVE_SETRESUID
466 setresuid(-1, 0, -1);
467#else
468 setuid(0);
469#endif
470}
471
30a4f2a8 472/* Give up the posibility to gain privilegies.
473 * this should be used before starting a sub process
474 */
b8d8561b 475void
0673c0ba 476no_suid(void)
234967c9 477{
478 uid_t uid;
30a4f2a8 479 leave_suid();
234967c9 480 uid = geteuid();
30a4f2a8 481 debug(21, 3, "leave_suid: PID %d giving up root priveleges forever\n", getpid());
234967c9 482#if HAVE_SETRESUID
483 setresuid(uid, uid, uid);
484#else
485 setuid(0);
486 setuid(uid);
487#endif
12b9e9b1 488}
ccff9601 489
b8d8561b 490void
0673c0ba 491writePidFile(void)
ccff9601 492{
493 FILE *pid_fp = NULL;
494 char *f = NULL;
495
b6f794d6 496 if ((f = Config.pidFilename) == NULL)
ccff9601 497 return;
30a4f2a8 498 enter_suid();
499 pid_fp = fopen(f, "w");
500 leave_suid();
501 if (pid_fp != NULL) {
502 fprintf(pid_fp, "%d\n", (int) getpid());
503 fclose(pid_fp);
504 } else {
019dd986 505 debug(21, 0, "WARNING: Could not write pid file\n");
506 debug(21, 0, " %s: %s\n", f, xstrerror());
ccff9601 507 }
ccff9601 508}
c4fb974e 509
510
ff8d0ea6 511pid_t
0673c0ba 512readPidFile(void)
7690e8eb 513{
514 FILE *pid_fp = NULL;
515 char *f = NULL;
ff8d0ea6 516 pid_t pid = -1;
517 int i;
7690e8eb 518
519 if ((f = Config.pidFilename) == NULL) {
520 fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
521 exit(1);
522 }
523 pid_fp = fopen(f, "r");
524 if (pid_fp != NULL) {
ff8d0ea6 525 pid = 0;
526 if (fscanf(pid_fp, "%d", &i) == 1)
527 pid = (pid_t) i;
7690e8eb 528 fclose(pid_fp);
529 } else {
530 if (errno != ENOENT) {
531 fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
532 fprintf(stderr, "\t%s: %s\n", f, xstrerror());
533 exit(1);
534 }
535 }
536 return pid;
537}
538
539
b8d8561b 540void
0673c0ba 541setMaxFD(void)
c4fb974e 542{
234967c9 543#if HAVE_SETRLIMIT
c4fb974e 544 /* try to use as many file descriptors as possible */
545 /* System V uses RLIMIT_NOFILE and BSD uses RLIMIT_OFILE */
546 struct rlimit rl;
547#if defined(RLIMIT_NOFILE)
548 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
a8f7d3ee 549 debug(21, 0, "setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 550 } else {
234967c9 551 rl.rlim_cur = FD_SETSIZE;
30a4f2a8 552 if (rl.rlim_cur > rl.rlim_max)
553 rl.rlim_cur = rl.rlim_max;
c4fb974e 554 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
234967c9 555 sprintf(tmp_error_buf, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
556 fatal_dump(tmp_error_buf);
c4fb974e 557 }
558 }
559#elif defined(RLIMIT_OFILE)
560 if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
a8f7d3ee 561 debug(21, 0, "setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 562 } else {
234967c9 563 rl.rlim_cur = FD_SETSIZE;
30a4f2a8 564 if (rl.rlim_cur > rl.rlim_max)
565 rl.rlim_cur = rl.rlim_max;
c4fb974e 566 if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
234967c9 567 sprintf(tmp_error_buf, "setrlimit: RLIMIT_OFILE: %s", xstrerror());
568 fatal_dump(tmp_error_buf);
c4fb974e 569 }
570 }
571#endif
c4fb974e 572#else /* HAVE_SETRLIMIT */
a8f7d3ee 573 debug(21, 1, "setMaxFD: Cannot increase: setrlimit() not supported on this system\n");
30a4f2a8 574#endif /* HAVE_SETRLIMIT */
575
576#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
577 if (getrlimit(RLIMIT_DATA, &rl) < 0) {
a8f7d3ee 578 debug(21, 0, "getrlimit: RLIMIT_DATA: %s\n", xstrerror());
30a4f2a8 579 } else {
580 rl.rlim_cur = rl.rlim_max; /* set it to the max */
581 if (setrlimit(RLIMIT_DATA, &rl) < 0) {
582 sprintf(tmp_error_buf, "setrlimit: RLIMIT_DATA: %s", xstrerror());
583 fatal_dump(tmp_error_buf);
584 }
585 }
586#endif /* RLIMIT_DATA */
c4fb974e 587}
3a57089e 588
b8d8561b 589time_t
0673c0ba 590getCurrentTime(void)
3a57089e 591{
94e891ea 592#if GETTIMEOFDAY_NO_TZP
30a4f2a8 593 gettimeofday(&current_time);
594#else
d598947a 595 gettimeofday(&current_time, NULL);
5f3f8d0e 596#endif
30a4f2a8 597 return squid_curtime = current_time.tv_sec;
5f3f8d0e 598}
fe113054 599
b8d8561b 600int
601percent(int a, int b)
30a4f2a8 602{
603 return b ? ((int) (100.0 * a / b + 0.5)) : 0;
604}
605
b8d8561b 606void
67508012 607squid_signal(int sig, void (*func) _PARAMS((int)), int flags)
30a4f2a8 608{
609#if HAVE_SIGACTION
610 struct sigaction sa;
611 sa.sa_handler = func;
612 sa.sa_flags = flags;
613 sigemptyset(&sa.sa_mask);
614 if (sigaction(sig, &sa, NULL) < 0)
615 debug(1, 0, "sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
616#else
617 (void) signal(sig, func);
618#endif
619}
396c5745 620
16b204c4 621struct in_addr
622inaddrFromHostent(struct hostent *hp)
623{
cc6a9d2e 624 struct in_addr s;
3c0117c9 625 xmemcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr));
cc6a9d2e 626 return s;
16b204c4 627}