Make all the other read/writes into recv/sends, except when they shouldn't be.
[tor.git] / src / common / util.c
blob16e191d1405f2ee506b93c02820da03e1ecbdeff
1 /* Copyright 2003 Roger Dingledine */
2 /* See LICENSE for licensing information */
3 /* $Id$ */
5 #include "../or/or.h"
7 #ifdef HAVE_UNAME
8 #include <sys/utsname.h>
9 #endif
12 * Memory wrappers
15 void *tor_malloc(size_t size) {
16 void *result;
18 result = malloc(size);
20 if(!result) {
21 log_fn(LOG_ERR, "Out of memory. Dying.");
22 exit(1);
24 // memset(result,'X',size); /* deadbeef to encourage bugs */
25 return result;
28 void *tor_malloc_zero(size_t size) {
29 void *result = tor_malloc(size);
30 memset(result, 0, size);
31 return result;
34 void *tor_realloc(void *ptr, size_t size) {
35 void *result;
37 result = realloc(ptr, size);
38 if (!result) {
39 log_fn(LOG_ERR, "Out of memory. Dying.");
40 exit(1);
42 return result;
45 char *tor_strdup(const char *s) {
46 char *dup;
47 assert(s);
49 dup = strdup(s);
50 if(!dup) {
51 log_fn(LOG_ERR,"Out of memory. Dying.");
52 exit(1);
54 return dup;
57 char *tor_strndup(const char *s, size_t n) {
58 char *dup;
59 assert(s);
60 dup = tor_malloc(n+1);
61 strncpy(dup, s, n);
62 dup[n] = 0;
63 return dup;
67 * A simple smartlist interface to make an unordered list of acceptable
68 * nodes and then choose a random one.
69 * smartlist_create() mallocs the list, _free() frees the list,
70 * _add() adds an element, _remove() removes an element if it's there,
71 * _choose() returns a random element.
74 smartlist_t *smartlist_create(int max_elements) {
75 smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
76 sl->list = tor_malloc(sizeof(void *) * max_elements);
77 sl->num_used = 0;
78 sl->max = max_elements;
79 return sl;
82 void smartlist_free(smartlist_t *sl) {
83 free(sl->list);
84 free(sl);
87 /* add element to the list, but only if there's room */
88 void smartlist_add(smartlist_t *sl, void *element) {
89 if(sl->num_used < sl->max)
90 sl->list[sl->num_used++] = element;
91 else
92 log_fn(LOG_WARN,"We've already got %d elements, discarding.",sl->max);
95 void smartlist_remove(smartlist_t *sl, void *element) {
96 int i;
97 if(element == NULL)
98 return;
99 for(i=0; i < sl->num_used; i++)
100 if(sl->list[i] == element) {
101 sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
102 i--; /* so we process the new i'th element */
106 int smartlist_isin(smartlist_t *sl, void *element) {
107 int i;
108 for(i=0; i < sl->num_used; i++)
109 if(sl->list[i] == element)
110 return 1;
111 return 0;
114 int smartlist_overlap(smartlist_t *sl1, smartlist_t *sl2) {
115 int i;
116 for(i=0; i < sl2->num_used; i++)
117 if(smartlist_isin(sl1, sl2->list[i]))
118 return 1;
119 return 0;
122 /* remove elements of sl1 that aren't in sl2 */
123 void smartlist_intersect(smartlist_t *sl1, smartlist_t *sl2) {
124 int i;
125 for(i=0; i < sl1->num_used; i++)
126 if(!smartlist_isin(sl2, sl1->list[i])) {
127 sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
128 i--; /* so we process the new i'th element */
132 /* remove all elements of sl2 from sl1 */
133 void smartlist_subtract(smartlist_t *sl1, smartlist_t *sl2) {
134 int i;
135 for(i=0; i < sl2->num_used; i++)
136 smartlist_remove(sl1, sl2->list[i]);
139 void *smartlist_choose(smartlist_t *sl) {
140 if(sl->num_used)
141 return sl->list[crypto_pseudo_rand_int(sl->num_used)];
142 return NULL; /* no elements to choose from */
146 * String manipulation
149 /* return the first char of s that is not whitespace and not a comment */
150 const char *eat_whitespace(const char *s) {
151 assert(s);
153 while(isspace(*s) || *s == '#') {
154 while(isspace(*s))
155 s++;
156 if(*s == '#') { /* read to a \n or \0 */
157 while(*s && *s != '\n')
158 s++;
159 if(!*s)
160 return s;
163 return s;
166 const char *eat_whitespace_no_nl(const char *s) {
167 while(*s == ' ' || *s == '\t')
168 ++s;
169 return s;
172 /* return the first char of s that is whitespace or '#' or '\0 */
173 const char *find_whitespace(const char *s) {
174 assert(s);
176 while(*s && !isspace(*s) && *s != '#')
177 s++;
179 return s;
183 * Time
186 void tor_gettimeofday(struct timeval *timeval) {
187 #ifdef HAVE_GETTIMEOFDAY
188 if (gettimeofday(timeval, NULL)) {
189 log_fn(LOG_ERR, "gettimeofday failed.");
190 /* If gettimeofday dies, we have either given a bad timezone (we didn't),
191 or segfaulted.*/
192 exit(1);
194 #elif defined(HAVE_FTIME)
195 ftime(timeval);
196 #else
197 #error "No way to get time."
198 #endif
199 return;
202 long
203 tv_udiff(struct timeval *start, struct timeval *end)
205 long udiff;
206 long secdiff = end->tv_sec - start->tv_sec;
208 if (secdiff+1 > LONG_MAX/1000000) {
209 log_fn(LOG_WARN, "comparing times too far apart.");
210 return LONG_MAX;
213 udiff = secdiff*1000000L + (end->tv_usec - start->tv_usec);
214 if(udiff < 0) {
215 log_fn(LOG_INFO, "start (%ld.%ld) is after end (%ld.%ld). Returning 0.",
216 (long)start->tv_sec, (long)start->tv_usec, (long)end->tv_sec, (long)end->tv_usec);
217 return 0;
219 return udiff;
222 int tv_cmp(struct timeval *a, struct timeval *b) {
223 if (a->tv_sec > b->tv_sec)
224 return 1;
225 if (a->tv_sec < b->tv_sec)
226 return -1;
227 if (a->tv_usec > b->tv_usec)
228 return 1;
229 if (a->tv_usec < b->tv_usec)
230 return -1;
231 return 0;
234 void tv_add(struct timeval *a, struct timeval *b) {
235 a->tv_usec += b->tv_usec;
236 a->tv_sec += b->tv_sec + (a->tv_usec / 1000000);
237 a->tv_usec %= 1000000;
240 void tv_addms(struct timeval *a, long ms) {
241 a->tv_usec += (ms * 1000) % 1000000;
242 a->tv_sec += ((ms * 1000) / 1000000) + (a->tv_usec / 1000000);
243 a->tv_usec %= 1000000;
247 #define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
248 static int n_leapdays(int y1, int y2) {
249 --y1;
250 --y2;
251 return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
253 static const int days_per_month[] =
254 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
256 time_t tor_timegm (struct tm *tm) {
257 /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
258 * It's way more brute-force than fiddling with tzset().
260 time_t ret;
261 unsigned long year, days, hours, minutes;
262 int i;
263 year = tm->tm_year + 1900;
264 assert(year >= 1970);
265 assert(tm->tm_mon >= 0 && tm->tm_mon <= 11);
266 days = 365 * (year-1970) + n_leapdays(1970,year);
267 for (i = 0; i < tm->tm_mon; ++i)
268 days += days_per_month[i];
269 if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
270 ++days;
271 days += tm->tm_mday - 1;
272 hours = days*24 + tm->tm_hour;
274 minutes = hours*60 + tm->tm_min;
275 ret = minutes*60 + tm->tm_sec;
276 return ret;
280 * Low-level I/O.
283 /* a wrapper for write(2) that makes sure to write all count bytes.
284 * Only use if fd is a blocking fd. */
285 int write_all(int fd, const char *buf, size_t count, int isSocket) {
286 size_t written = 0;
287 int result;
289 while(written != count) {
290 if (isSocket)
291 result = send(fd, buf+written, count-written, 0);
292 else
293 result = write(fd, buf+written, count-written);
294 if(result<0)
295 return -1;
296 written += result;
298 return count;
301 /* a wrapper for read(2) that makes sure to read all count bytes.
302 * Only use if fd is a blocking fd. */
303 int read_all(int fd, char *buf, size_t count, int isSocket) {
304 size_t numread = 0;
305 int result;
307 while(numread != count) {
308 if (isSocket)
309 result = recv(fd, buf+numread, count-numread, 0);
310 else
311 result = read(fd, buf+numread, count-numread);
312 if(result<=0)
313 return -1;
314 numread += result;
316 return count;
319 void set_socket_nonblocking(int socket)
321 #ifdef MS_WINDOWS
322 /* Yes means no and no means yes. Do you not want to be nonblocking? */
323 int nonblocking = 0;
324 ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
325 #else
326 fcntl(socket, F_SETFL, O_NONBLOCK);
327 #endif
331 * Process control
334 /* Minimalist interface to run a void function in the background. On
335 * unix calls fork, on win32 calls beginthread. Returns -1 on failure.
336 * func should not return, but rather should call spawn_exit.
338 int spawn_func(int (*func)(void *), void *data)
340 #ifdef MS_WINDOWS
341 int rv;
342 rv = _beginthread(func, 0, data);
343 if (rv == (unsigned long) -1)
344 return -1;
345 return 0;
346 #else
347 pid_t pid;
348 pid = fork();
349 if (pid<0)
350 return -1;
351 if (pid==0) {
352 /* Child */
353 func(data);
354 assert(0); /* Should never reach here. */
355 return 0; /* suppress "control-reaches-end-of-non-void" warning. */
356 } else {
357 /* Parent */
358 return 0;
360 #endif
363 void spawn_exit()
365 #ifdef MS_WINDOWS
366 _endthread();
367 #else
368 exit(0);
369 #endif
374 * Windows compatibility.
377 tor_socketpair(int family, int type, int protocol, int fd[2])
379 #ifdef HAVE_SOCKETPAIR_XXXX
380 /* For testing purposes, we never fall back to real socketpairs. */
381 return socketpair(family, type, protocol, fd);
382 #else
383 int listener = -1;
384 int connector = -1;
385 int acceptor = -1;
386 struct sockaddr_in listen_addr;
387 struct sockaddr_in connect_addr;
388 int size;
390 if (protocol
391 #ifdef AF_UNIX
392 || family != AF_UNIX
393 #endif
395 #ifdef MS_WINDOWS
396 errno = WSAEAFNOSUPPORT;
397 #else
398 errno = EAFNOSUPPORT;
399 #endif
400 return -1;
402 if (!fd) {
403 errno = EINVAL;
404 return -1;
407 listener = socket(AF_INET, type, 0);
408 if (listener == -1)
409 return -1;
410 memset (&listen_addr, 0, sizeof (listen_addr));
411 listen_addr.sin_family = AF_INET;
412 listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
413 listen_addr.sin_port = 0; /* kernel choses port. */
414 if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
415 == -1)
416 goto tidy_up_and_fail;
417 if (listen(listener, 1) == -1)
418 goto tidy_up_and_fail;
420 connector = socket(AF_INET, type, 0);
421 if (connector == -1)
422 goto tidy_up_and_fail;
423 /* We want to find out the port number to connect to. */
424 size = sizeof (connect_addr);
425 if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
426 goto tidy_up_and_fail;
427 if (size != sizeof (connect_addr))
428 goto abort_tidy_up_and_fail;
429 if (connect(connector, (struct sockaddr *) &connect_addr,
430 sizeof (connect_addr)) == -1)
431 goto tidy_up_and_fail;
433 size = sizeof (listen_addr);
434 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
435 if (acceptor == -1)
436 goto tidy_up_and_fail;
437 if (size != sizeof(listen_addr))
438 goto abort_tidy_up_and_fail;
439 close(listener);
440 /* Now check we are talking to ourself by matching port and host on the
441 two sockets. */
442 if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
443 goto tidy_up_and_fail;
444 if (size != sizeof (connect_addr)
445 || listen_addr.sin_family != connect_addr.sin_family
446 || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
447 || listen_addr.sin_port != connect_addr.sin_port) {
448 goto abort_tidy_up_and_fail;
450 fd[0] = connector;
451 fd[1] = acceptor;
452 return 0;
454 abort_tidy_up_and_fail:
455 #ifdef MS_WINDOWS
456 errno = WSAECONNABORTED;
457 #else
458 errno = ECONNABORTED; /* I hope this is portable and appropriate. */
459 #endif
460 tidy_up_and_fail:
462 int save_errno = errno;
463 if (listener != -1)
464 close(listener);
465 if (connector != -1)
466 close(connector);
467 if (acceptor != -1)
468 close(acceptor);
469 errno = save_errno;
470 return -1;
472 #endif
475 #ifdef MS_WINDOWS
476 int correct_socket_errno(int s)
478 int optval, optvallen=sizeof(optval);
479 assert(errno == WSAEWOULDBLOCK);
480 if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
481 return errno;
482 if (optval)
483 return optval;
484 return WSAEWOULDBLOCK;
486 #endif
489 * Filesystem operations.
492 /* Return FN_ERROR if filename can't be read, FN_NOENT if it doesn't
493 * exist, FN_FILE if it is a regular file, or FN_DIR if it's a
494 * directory. */
495 file_status_t file_status(const char *fname)
497 struct stat st;
498 if (stat(fname, &st)) {
499 if (errno == ENOENT) {
500 return FN_NOENT;
502 return FN_ERROR;
504 if (st.st_mode & S_IFDIR)
505 return FN_DIR;
506 else if (st.st_mode & S_IFREG)
507 return FN_FILE;
508 else
509 return FN_ERROR;
512 /* Check whether dirname exists and is private. If yes returns
513 0. Else returns -1. */
514 int check_private_dir(const char *dirname, int create)
516 int r;
517 struct stat st;
518 if (stat(dirname, &st)) {
519 if (errno != ENOENT) {
520 log(LOG_WARN, "Directory %s cannot be read: %s", dirname,
521 strerror(errno));
522 return -1;
524 if (!create) {
525 log(LOG_WARN, "Directory %s does not exist.", dirname);
526 return -1;
528 log(LOG_INFO, "Creating directory %s", dirname);
529 #ifdef MS_WINDOWS
530 r = mkdir(dirname);
531 #else
532 r = mkdir(dirname, 0700);
533 #endif
534 if (r) {
535 log(LOG_WARN, "Error creating directory %s: %s", dirname,
536 strerror(errno));
537 return -1;
538 } else {
539 return 0;
542 if (!(st.st_mode & S_IFDIR)) {
543 log(LOG_WARN, "%s is not a directory", dirname);
544 return -1;
546 #ifndef MS_WINDOWS
547 if (st.st_uid != getuid()) {
548 log(LOG_WARN, "%s is not owned by this UID (%d)", dirname, (int)getuid());
549 return -1;
551 if (st.st_mode & 0077) {
552 log(LOG_WARN, "Fixing permissions on directory %s", dirname);
553 if (chmod(dirname, 0700)) {
554 log(LOG_WARN, "Could not chmod directory %s: %s", dirname,
555 strerror(errno));
556 return -1;
557 } else {
558 return 0;
561 #endif
562 return 0;
566 write_str_to_file(const char *fname, const char *str)
568 char tempname[1024];
569 int fd;
570 FILE *file;
571 if (strlen(fname) > 1000) {
572 log(LOG_WARN, "Filename %s is too long.", fname);
573 return -1;
575 strcpy(tempname,fname);
576 strcat(tempname,".tmp");
577 if ((fd = open(tempname, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
578 log(LOG_WARN, "Couldn't open %s for writing: %s", tempname,
579 strerror(errno));
580 return -1;
582 if (!(file = fdopen(fd, "w"))) {
583 log(LOG_WARN, "Couldn't fdopen %s for writing: %s", tempname,
584 strerror(errno));
585 close(fd); return -1;
587 if (fputs(str,file) == EOF) {
588 log(LOG_WARN, "Error writing to %s: %s", tempname, strerror(errno));
589 fclose(file); return -1;
591 fclose(file);
592 if (rename(tempname, fname)) {
593 log(LOG_WARN, "Error replacing %s: %s", fname, strerror(errno));
594 return -1;
596 return 0;
599 char *read_file_to_str(const char *filename) {
600 int fd; /* router file */
601 struct stat statbuf;
602 char *string;
604 assert(filename);
606 if(strcspn(filename,CONFIG_LEGAL_FILENAME_CHARACTERS) != 0) {
607 log_fn(LOG_WARN,"Filename %s contains illegal characters.",filename);
608 return NULL;
611 if(stat(filename, &statbuf) < 0) {
612 log_fn(LOG_INFO,"Could not stat %s.",filename);
613 return NULL;
616 fd = open(filename,O_RDONLY,0);
617 if (fd<0) {
618 log_fn(LOG_WARN,"Could not open %s.",filename);
619 return NULL;
622 string = tor_malloc(statbuf.st_size+1);
624 if(read_all(fd,string,statbuf.st_size,0) != statbuf.st_size) {
625 log_fn(LOG_WARN,"Couldn't read all %ld bytes of file '%s'.",
626 (long)statbuf.st_size,filename);
627 free(string);
628 close(fd);
629 return NULL;
631 close(fd);
633 string[statbuf.st_size] = 0; /* null terminate it */
634 return string;
637 /* read lines from f (no more than maxlen-1 bytes each) until we
638 * get a non-whitespace line. If it isn't of the form "key value"
639 * (value can have spaces), return -1.
640 * Point *key to the first word in line, point *value * to the second.
641 * Put a \0 at the end of key, remove everything at the end of value
642 * that is whitespace or comment.
643 * Return 1 if success, 0 if no more lines, -1 if error.
645 int parse_line_from_file(char *line, int maxlen, FILE *f, char **key_out, char **value_out) {
646 char *s, *key, *end, *value;
648 try_next_line:
649 if(!fgets(line, maxlen, f)) {
650 if(feof(f))
651 return 0;
652 return -1; /* real error */
655 if((s = strchr(line,'#'))) /* strip comments */
656 *s = 0; /* stop the line there */
658 /* remove end whitespace */
659 s = strchr(line, 0); /* now we're at the null */
660 do {
661 *s = 0;
662 s--;
663 } while (s >= line && isspace(*s));
665 key = line;
666 while(isspace(*key))
667 key++;
668 if(*key == 0)
669 goto try_next_line; /* this line has nothing on it */
670 end = key;
671 while(*end && !isspace(*end))
672 end++;
673 value = end;
674 while(*value && isspace(*value))
675 value++;
677 if(!*end || !*value) { /* only a key on this line. no value. */
678 *end = 0;
679 log_fn(LOG_WARN,"Line has keyword '%s' but no value. Failing.",key);
680 return -1;
682 *end = 0; /* null it out */
684 log_fn(LOG_DEBUG,"got keyword '%s', value '%s'", key, value);
685 *key_out = key, *value_out = value;
686 return 1;
689 static char uname_result[256];
690 static int uname_result_is_set = 0;
692 const char *
693 get_uname(void)
695 #ifdef HAVE_UNAME
696 struct utsname u;
697 #endif
698 if (!uname_result_is_set) {
699 #ifdef HAVE_UNAME
700 if (!uname((&u))) {
701 snprintf(uname_result, 255, "%s %s %s",
702 u.sysname, u.nodename, u.machine);
703 uname_result[255] = '\0';
704 } else
705 #endif
707 strcpy(uname_result, "Unknown platform");
709 uname_result_is_set = 1;
711 return uname_result;
714 #ifndef MS_WINDOWS
715 /* Based on code contributed by christian grothoff */
716 static int start_daemon_called = 0;
717 static int finish_daemon_called = 0;
718 static int daemon_filedes[2];
719 void start_daemon(char *desired_cwd)
721 pid_t pid;
723 if (start_daemon_called)
724 return;
725 start_daemon_called = 1;
727 if(!desired_cwd)
728 desired_cwd = "/";
729 /* Don't hold the wrong FS mounted */
730 if (chdir(desired_cwd) < 0) {
731 log_fn(LOG_ERR,"chdir to %s failed. Exiting.",desired_cwd);
732 exit(1);
735 pipe(daemon_filedes);
736 pid = fork();
737 if (pid < 0) {
738 log_fn(LOG_ERR,"fork failed. Exiting.");
739 exit(1);
741 if (pid) { /* Parent */
742 int ok;
743 char c;
745 close(daemon_filedes[1]); /* we only read */
746 ok = -1;
747 while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
748 if (c == '.')
749 ok = 1;
751 fflush(stdout);
752 if (ok == 1)
753 exit(0);
754 else
755 exit(1); /* child reported error */
756 } else { /* Child */
757 close(daemon_filedes[0]); /* we only write */
759 pid = setsid(); /* Detach from controlling terminal */
761 * Fork one more time, so the parent (the session group leader) can exit.
762 * This means that we, as a non-session group leader, can never regain a
763 * controlling terminal. This part is recommended by Stevens's
764 * _Advanced Programming in the Unix Environment_.
766 if (fork() != 0) {
767 exit(0);
769 return;
773 void finish_daemon(void)
775 int nullfd;
776 char c = '.';
777 if (finish_daemon_called)
778 return;
779 if (!start_daemon_called)
780 start_daemon(NULL);
781 finish_daemon_called = 1;
783 nullfd = open("/dev/null",
784 O_CREAT | O_RDWR | O_APPEND);
785 if (nullfd < 0) {
786 log_fn(LOG_ERR,"/dev/null can't be opened. Exiting.");
787 exit(1);
789 /* close fds linking to invoking terminal, but
790 * close usual incoming fds, but redirect them somewhere
791 * useful so the fds don't get reallocated elsewhere.
793 if (dup2(nullfd,0) < 0 ||
794 dup2(nullfd,1) < 0 ||
795 dup2(nullfd,2) < 0) {
796 log_fn(LOG_ERR,"dup2 failed. Exiting.");
797 exit(1);
799 write(daemon_filedes[1], &c, sizeof(char)); /* signal success */
800 close(daemon_filedes[1]);
802 #else
803 /* defined(MS_WINDOWS) */
804 void start_daemon(char *cp) {}
805 void finish_daemon(void) {}
806 #endif
808 void write_pidfile(char *filename) {
809 #ifndef MS_WINDOWS
810 FILE *pidfile;
812 if ((pidfile = fopen(filename, "w")) == NULL) {
813 log_fn(LOG_WARN, "unable to open %s for writing: %s", filename,
814 strerror(errno));
815 } else {
816 fprintf(pidfile, "%d", getpid());
817 fclose(pidfile);
819 #endif
822 int switch_id(char *user, char *group) {
823 #ifndef MS_WINDOWS
824 struct passwd *pw = NULL;
825 struct group *gr = NULL;
827 if (user) {
828 pw = getpwnam(user);
829 if (pw == NULL) {
830 log_fn(LOG_ERR,"User '%s' not found.", user);
831 return -1;
835 /* switch the group first, while we still have the privileges to do so */
836 if (group) {
837 gr = getgrnam(group);
838 if (gr == NULL) {
839 log_fn(LOG_ERR,"Group '%s' not found.", group);
840 return -1;
843 if (setgid(gr->gr_gid) != 0) {
844 log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
845 return -1;
847 } else if (user) {
848 if (setgid(pw->pw_gid) != 0) {
849 log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
850 return -1;
854 /* now that the group is switched, we can switch users and lose
855 privileges */
856 if (user) {
857 if (setuid(pw->pw_uid) != 0) {
858 log_fn(LOG_ERR,"Error setting UID: %s", strerror(errno));
859 return -1;
863 return 0;
864 #endif
866 log_fn(LOG_ERR,
867 "User or group specified, but switching users is not supported.");
869 return -1;
872 int tor_inet_aton(const char *c, struct in_addr* addr)
874 #ifdef HAVE_INET_ATON
875 return inet_aton(c, addr);
876 #else
877 uint32_t r;
878 assert(c && addr);
879 if (strcmp(c, "255.255.255.255") == 0) {
880 addr->s_addr = 0xFFFFFFFFu;
881 return 1;
883 r = inet_addr(c);
884 if (r == INADDR_NONE)
885 return 0;
886 addr->s_addr = r;
887 return 1;
888 #endif