/* Initialize resp if RES_INIT is not yet set or if res_init in some other thread requested re-initializing. */ int __res_maybe_init (res_state resp, int preinit) { static time_t last_mtime; struct stat statbuf; int ret; if (resp->options & RES_INIT) { ret = stat (_PATH_RESCONF, &statbuf); if ((ret == 0) && (last_mtime != statbuf.st_mtime)) { last_mtime = statbuf.st_mtime; atomicinclock (lock); atomicinc (__res_initstamp); atomicincunlock (lock); } if (__res_initstamp != resp->_u._ext.initstamp) { if (resp->nscount > 0) __res_iclose (resp, true); return __res_vinit (resp, 1); } return 0; } else if (preinit) { if (!resp->retrans) resp->retrans = RES_TIMEOUT; if (!resp->retry) resp->retry = 4; resp->options = RES_DEFAULT; if (!resp->id) resp->id = res_randomid (); return __res_vinit (resp, 1); } else return __res_ninit (resp); }
int res_init(void) { extern int __res_vinit(res_state, int); /* * These three fields used to be statically initialized. This made * it hard to use this code in a shared library. It is necessary, * now that we're doing dynamic initialization here, that we preserve * the old semantics: if an application modifies one of these three * fields of _res before res_init() is called, res_init() will not * alter them. Of course, if an application is setting them to * _zero_ before calling res_init(), hoping to override what used * to be the static default, we can't detect it and unexpected results * will follow. Zero for any of these fields would make no sense, * so one can safely assume that the applications were already getting * unexpected results. * * _res.options is tricky since some apps were known to diddle the bits * before res_init() was first called. We can't replicate that semantic * with dynamic initialization (they may have turned bits off that are * set in RES_DEFAULT). Our solution is to declare such applications * "broken". They could fool us by setting RES_INIT but none do (yet). */ if (!_res.retrans) _res.retrans = RES_TIMEOUT; if (!_res.retry) _res.retry = 4; if (!(_res.options & RES_INIT)) _res.options = RES_DEFAULT; else if (_res.nscount > 0) { __res_nclose (&_res); /* Close any VC sockets. */ int ns; for (ns = 0; ns < MAXNS; ns++) { free (_res._u._ext.nsaddrs[ns]); _res._u._ext.nsaddrs[ns] = NULL; } } /* * This one used to initialize implicitly to zero, so unless the app * has set it to something in particular, we can randomize it now. */ if (!_res.id) _res.id = res_randomid(); atomicinclock (lock); /* Request all threads to re-initialize their resolver states, resolv.conf might have changed. */ atomicinc (__res_initstamp); atomicincunlock (lock); return (__res_vinit(&_res, 1)); }