char * smalldate(time_t clock) { static char buf[MAX_DATE_STRING]; struct tm *lt, *gm; struct tm gmbuf; if (!clock) time(&clock); gm = gmtime(&clock); memcpy((char *) &gmbuf, (char *) gm, sizeof(gmbuf)); gm = &gmbuf; lt = localtime(&clock); ircsprintf(buf, "%04d/%02d/%02d %02d.%02d", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min); return buf; }
int WriteSeen() { FILE *fp; char tempname[MAXLINE]; aSeen *seen; ircsprintf(tempname, "%s.tmp", SeenServDB); fp = CreateDatabase(tempname, "SeenServ Database"); if (!fp) { putlog(LOG1, "Error writing SeenServ Database (%s): %s", SeenServDB, strerror(errno)); return 0; } for (seen = seenb; seen; seen = seen->next) { if (seen) switch(seen->type) { case 1: fprintf(fp, "->QUIT %s %s %ld :%s\n", seen->nick, seen->userhost, (long) seen->time, seen->msg); break; case 2: fprintf(fp, "->NICK %s %s %ld\n", seen->nick, seen->userhost, (long) seen->time); break; default: break; } } fclose(fp); rename(tempname, SeenServDB); putlog(LOG3, "Wrote %s", SeenServDB); return 1; } /* WriteSeen() */
int WriteStats() { FILE *fp; char tempname[MAXLINE]; ircsprintf(tempname, "%s.tmp", StatServDB); fp = CreateDatabase(tempname, "StatServ Database"); if (!fp) { putlog(LOG1, "Error writing StatServ Database (%s): %s", StatServDB, strerror(errno)); return 0; } fprintf(fp, "->USERS %ld %ld\n", Network->MaxUsers, (long) Network->MaxUsers_ts); fprintf(fp, "->OPERS %ld %ld\n", Network->MaxOperators, (long) Network->MaxOperators_ts); fprintf(fp, "->CHANS %ld %ld\n", Network->MaxChannels, (long) Network->MaxChannels_ts); fprintf(fp, "->SERVS %ld %ld\n", Network->MaxServers, (long) Network->MaxServers_ts); fclose(fp); rename(tempname, StatServDB); putlog(LOG3, "Wrote %s", StatServDB); return 1; } /* WriteStats() */
const char * smalldate(time_t lclock) { static char buf[MAX_DATE_STRING]; struct tm *lt, *gm; struct tm gmbuf; if (!lclock) lclock = CurrentTime; gm = gmtime(&lclock); memcpy((void *)&gmbuf, (void *)gm, sizeof(gmbuf)); gm = &gmbuf; lt = localtime(&lclock); ircsprintf(buf, "%d/%d/%d %02d.%02d", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min); return(buf); }
void mylog (char *file, char *msg, ...) { char tmp[1024]; char buf[1024]; va_list val; FILE *index; time_t tm; ircsprintf(buf,1023,msg,val); tm = time(NULL); snprintf(tmp,1023,"[ %s] %s\n",ctime(&tm),buf); /* The ctime() function returns the result with a trailing '\n' */ *(strstr(tmp,"\n")) = ' '; index = fopen(file,"a+"); if (!index) return; fputs(tmp,index); fclose(index); }
/* * send_authports * * Send the ident server a query giving "theirport , ourport". * The write is only attempted *once* so it is deemed to be a fail if the * entire write doesn't write all the data given. This shouldnt be a * problem since the socket should have a write buffer far greater than * this message to store it in should problems arise. -avalon */ void send_authports(aClient *cptr) { struct sockaddr_in us, them; char authbuf[32]; int ulen, tlen; Debug((DEBUG_NOTICE,"write_authports(%x) fd %d authfd %d stat %d", cptr, cptr->fd, cptr->authfd, cptr->status)); tlen = ulen = sizeof(us); if (getsockname(cptr->fd, (struct sockaddr *)&us, &ulen) || getpeername(cptr->fd, (struct sockaddr *)&them, &tlen)) { #ifdef USE_SYSLOG syslog(LOG_DEBUG, "auth get{sock,peer}name error for %s:%m", get_client_name(cptr, TRUE)); #endif authsenderr(cptr); /* cptr->flags &= ~FLAGS_WRAUTH; */ return; } (void)ircsprintf(authbuf, "%u , %u\r\n", (unsigned int)ntohs(them.sin_port), (unsigned int)ntohs(us.sin_port)); Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", authbuf, inetntoa((char *)&them.sin_addr))); if (write(cptr->authfd, authbuf, strlen(authbuf)) != strlen(authbuf)) { authsenderr(cptr); return; } cptr->flags &= ~FLAGS_WRAUTH; return; }
/* [just a helper for channel_modef_string()] */ static inline char *chmodefstrhelper(char *buf, char t, char tdef, unsigned short l, unsigned char a, unsigned char r) { char *p; char tmpbuf[16], *p2 = tmpbuf; ircsprintf(buf, "%hd", l); p = buf + strlen(buf); *p++ = t; if (a && ((a != tdef) || r)) { *p++ = '#'; *p++ = a; if (r) { sprintf(tmpbuf, "%hd", (short)r); while ((*p = *p2++)) p++; } } *p++ = ','; return p; }
static void write_pidfile(const char *filename) { FBFILE *fb; if ((fb = fbopen(filename, "w"))) { char buff[32]; unsigned int pid = (unsigned int)getpid(); size_t nbytes = ircsprintf(buff, "%u\n", pid); if ((fbputs(buff, fb, nbytes) == -1)) ilog(L_ERROR, "Error writing %u to pid file %s (%s)", pid, filename, strerror(errno)); fbclose(fb); } else { ilog(L_ERROR, "Error opening pid file %s", filename); } }
/* date() * * returns date in human readable form */ static char * date(void) { static char buf[80]; char plus; struct tm *lt; struct tm *gm; struct tm gmbuf; time_t lclock; int minswest; lclock = CurrentTime; gm = gmtime(&lclock); memcpy((void *) &gmbuf, (void *) gm, sizeof(gmbuf)); gm = &gmbuf; lt = localtime(&lclock); if(lt->tm_yday == gm->tm_yday) minswest = (gm->tm_hour - lt->tm_hour) * 60 + (gm->tm_min - lt->tm_min); else if(lt->tm_yday > gm->tm_yday && lt->tm_year == gm->tm_year) minswest = (gm->tm_hour - (lt->tm_hour + 24)) * 60; else minswest = ((gm->tm_hour + 24) - lt->tm_hour) * 60; plus = (minswest > 0) ? '-' : '+'; if(minswest < 0) minswest = -minswest; ircsprintf(buf, "%s %s %d %d -- %02u:%02u:%02u %c%02u:%02u", weekdays[lt->tm_wday], months[lt->tm_mon], lt->tm_mday, lt->tm_year + 1900, lt->tm_hour, lt->tm_min, lt->tm_sec, plus, minswest / 60, minswest % 60); return buf; }
inline char *first_visible_channel(aClient *cptr, aClient *sptr) { Link *lp; int secret = 0; aChannel *chptr = NULL; static char chnbuf[CHANNELLEN + 2]; if(cptr->user->channel) { if(IsAdmin(sptr)) { chptr = cptr->user->channel->value.chptr; if(!(ShowChannel(sptr, chptr))) secret = 1; } else { for(lp = cptr->user->channel; lp; lp = lp->next) { if(ShowChannel(sptr, lp->value.chptr)) break; } if(lp) chptr = lp->value.chptr; } if(chptr) { if(!secret) return chptr->chname; ircsprintf(chnbuf, "%%%s", chptr->chname); return chnbuf; } } return "*"; }
/* ** m_svskill ** parv[0] = sender prefix ** parv[1] = person to disconnect ** parv[2] = reason */ static void m_svskill (struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; dlink_node *server_node; char reason[TOPICLEN + 1]; if (!IsServer (source_p)) return; if ((target_p = (struct Client *) find_client (parv[1])) == NULL) return; ircsprintf (reason, "%s", parv[2]); target_p->flags |= FLAGS_KILLED; exit_client (client_p, target_p, target_p, reason); /* Propigate kill attempts. */ sendto_server (source_p, NULL, NOCAPS, NOCAPS, ":%s SVSKILL %s :%s", parv[0], parv[1], parv[2]); }
int CheckJuped(char *name) { struct Jupe *tempjupe; struct Server *tempserv; char sendstr[MAXLINE + 1], **arv; for (tempjupe = JupeList; tempjupe; tempjupe = tempjupe->next) { if (match(tempjupe->name, name)) { if (tempjupe->isnick) { struct Luser *lptr; if (!(lptr = FindClient(name))) return 0; /* its a nick jupe, not a server jupe */ #ifdef DANCER ircsprintf(sendstr, "NICK %s 1 %ld +i juped juped.com %s %lu :%s\r\n", tempjupe->name, #ifdef NICKSERVICES (long) (lptr->nick_ts - 1), #else (long) (lptr->since - 1), #endif /* NICKSERVICES */ Me.name, 0xffffffffL, tempjupe->reason ? tempjupe->reason : "Jupitered Nickname"); #else /* collide the nickname */ ircsprintf(sendstr, "NICK %s 1 %ld +i %s %s %s :%s\r\n", tempjupe->name, #ifdef NICKSERVICES (long) (lptr->nick_ts - 1), #else (long) (lptr->since - 1), #endif /* NICKSERVICES */ JUPED_USERNAME, JUPED_HOSTNAME, Me.name, tempjupe->reason ? tempjupe->reason : "Jupitered Nickname"); #endif /* DANCER */ toserv("%s", sendstr); DeleteClient(lptr); SplitBuf(sendstr, &arv); AddClient(arv); MyFree(arv); if (Me.sptr) Me.sptr->numoperkills++; Network->TotalOperKills++; #ifdef STATSERVICES if (Network->TotalOperKills > Network->OperKillsT) Network->OperKillsT = Network->TotalOperKills; #endif } else { toserv("SQUIT %s :Juped: %s (%s)\r\n", name, tempjupe->reason, tempjupe->who); tempserv = FindServer(name); DeleteServer(tempserv); /* If the fake server is introduced before the remote server has quited, * we get "server already exists" and services get SQUIT'ed, * so we'll introduce it in s_squit() */ } return 1; } } return 0; } /* CheckJuped */
int WriteChans() { FILE *fp; char tempname[MAXLINE]; struct ChanInfo *cptr, *cnext; int ii, ccnt; ircsprintf(tempname, "%s.tmp", ChanServDB); fp = CreateDatabase(tempname, "ChanServ Database"); if (!fp) { putlog(LOG1, "Error writing ChanServ Database (%s): %s", ChanServDB, strerror(errno)); return 0; } ccnt = 0; for (ii = 0; ii < CHANLIST_MAX; ++ii) { for (cptr = chanlist[ii]; cptr; cptr = cnext) { cnext = cptr->next; if (!GetLink(cptr->contact)) { /* * There is no contact - check if there is an alternate contact. If * so, make them contact, otherwise delete the channel. */ if (cptr->alternate && GetLink(cptr->alternate)) { /* * There is a valid alternate contact - make them contact */ MakeContact(cptr); } else { putlog(LOG2, "%s: dropping channel [%s] (no contact)", n_ChanServ, cptr->name); DeleteChan(cptr); continue; } } if (cptr->alternate) { if (!GetLink(cptr->alternate)) { /* alternate contact's nickname has expired - erase it */ putlog(LOG2, "%s: Alternate contact [%s] for channel [%s] expired, removing", n_ChanServ, cptr->alternate, cptr->name); MyFree(cptr->alternate); cptr->alternate = NULL; } } ++ccnt; /* * format: channel-name flags ts_created ts_lastused */ fprintf(fp, "%s %ld %ld %ld\n", cptr->name, cptr->flags, (long) cptr->created, (long) cptr->lastused); { struct ChanAccess *ca; struct AutoKick *ak; int jj; /* write contact */ fprintf(fp, "->FNDR %s %ld\n", cptr->contact, (long) cptr->last_contact_active); /* write password */ fprintf(fp, "->PASS %s\n", cptr->password); if (cptr->alternate) fprintf(fp, "->SUCCESSOR %s %ld\n", cptr->alternate, (long) cptr->last_alternate_active); if (cptr->topic) fprintf(fp, "->TOPIC :%s\n", cptr->topic); if (cptr->limit) fprintf(fp, "->LIMIT %ld\n", cptr->limit); if (cptr->key) fprintf(fp, "->KEY %s\n", cptr->key); if (cptr->forward) fprintf(fp, "->FORWARD %s\n", cptr->forward); if (cptr->throttle) fprintf(fp, "->THROTTLE %s\n", cptr->throttle); if (cptr->dline) fprintf(fp, "->DLINE %s\n", cptr->dline); if (cptr->modes_on) fprintf(fp, "->MON %d\n", cptr->modes_on); if (cptr->modes_off) fprintf(fp, "->MOFF %d\n", cptr->modes_off); if (cptr->entrymsg) fprintf(fp, "->ENTRYMSG :%s\n", cptr->entrymsg); if (cptr->email) fprintf(fp, "->EMAIL %s\n", cptr->email); if (cptr->url) fprintf(fp, "->URL %s\n", cptr->url); fprintf(fp, "->ALVL"); for (jj = 0; jj <= CA_CONTACT; ++jj) fprintf(fp, " %d", cptr->access_lvl[jj]); fprintf(fp, "\n"); for (ca = cptr->access; ca; ca = ca->next) fprintf(fp, "->ACCESS %s %d %ld %ld\n", ca->nptr ? ca->nptr->nick : stripctrlsymbols(ca->hostmask), ca->level, (long) ca->created, (long) ca->last_used); for (ak = cptr->akick; ak; ak = ak->next) fprintf(fp, "->AKICK %s :%s\n", stripctrlsymbols(ak->hostmask), ak->reason ? stripctrlsymbols(ak->reason) : ""); } } /* for (cptr = chanlist[ii]; cptr; cptr = cnext) */ } /* for (ii = 0; ii < CHANLIST_MAX; ++ii) */ fclose(fp); rename(tempname, ChanServDB); putlog(LOG3, "Wrote %s (%d registered channels)", ChanServDB, ccnt); return (1); } /* WriteChans() */
int WriteNicks() { FILE *fp; char tempname[MAXLINE]; int ii, ncnt; struct NickInfo *nptr; struct NickHost *hptr; int islinked; ircsprintf(tempname, "%s.tmp", NickServDB); fp = CreateDatabase(tempname, "NickServ Database"); if (!fp) { putlog(LOG1, "Error writing NickServ Database (%s): %s", NickServDB, strerror(errno)); return 0; } ncnt = 0; #ifdef LINKED_NICKNAMES /* * We have to go through the nicklist to write out all master entries * first, because the leaf entries will have a ->LINK <master nick>, so * the next time the database is read, we have to make sure we can find * the master nickname entry or we've got problems :-). Basically, make * sure the leaf entries don't get written out before master entries. * Unfortunately, we have to repeat some code here. */ for (ii = 0; ii < NICKLIST_MAX; ++ii) { for (nptr = nicklist[ii]; nptr; nptr = nptr->next) { if (nptr->master || !nptr->nextlink) { /* This is not a master nickname */ continue; } ++ncnt; /* write out "nickname flags created last-seen" to file */ fprintf(fp, "%s %ld %ld %ld\n", nptr->nick, nptr->flags, (long) nptr->created, (long) nptr->lastseen); /* write out password only if not forbidden! -kre */ if (nptr->password) fprintf(fp, "->PASS %s\n", nptr->password); if (nptr->cloak) fprintf(fp, "->CLOAK %s\n", nptr->cloak); if (nptr->email) fprintf(fp, "->EMAIL %s\n", nptr->email); if (nptr->url) fprintf(fp, "->URL %s\n", nptr->url); if (nptr->gsm) fprintf(fp, "->GSM %s\n", nptr->gsm); if (nptr->phone) fprintf(fp, "->PHONE %s\n", nptr->phone); if (nptr->UIN) fprintf(fp, "->UIN %s\n", nptr->UIN); if (LastSeenInfo) { if (nptr->lastu && nptr->lasth) fprintf(fp, "->LASTUH %s %s\n", nptr->lastu, nptr->lasth); if (nptr->lastqmsg) fprintf(fp, "->LASTQMSG :%s\n", nptr->lastqmsg); } for (hptr = nptr->hosts; hptr; hptr = hptr->next) fprintf(fp, "->HOST %s\n", hptr->hostmask); } /* for (nptr = nicklist[ii]; nptr; nptr = nptr->next) */ } /* for (ii = 0; ii < NICKLIST_MAX; ++ii) */ #endif /* LINKED_NICKNAMES */ /* * Now go through and write out all non-master nickname * entries */ for (ii = 0; ii < NICKLIST_MAX; ++ii) { for (nptr = nicklist[ii]; nptr; nptr = nptr->next) { islinked = 0; #ifdef LINKED_NICKNAMES if (nptr->master) islinked = 1; else { /* * If nptr->master is NULL, but nptr->nextlink is not, * this is a master nickname, which was already written, * continue the loop */ if (nptr->nextlink) continue; } #endif /* LINKED_NICKNAMES */ ++ncnt; /* write out "nickname flags created last-seen" to file */ fprintf(fp, "%s %ld %ld %ld\n", nptr->nick, nptr->flags, (long) nptr->created, (long) nptr->lastseen); if (nptr->password) fprintf(fp, "->PASS %s\n", nptr->password); if (nptr->cloak) fprintf(fp, "->CLOAK %s\n", nptr->cloak); if (nptr->email) fprintf(fp, "->EMAIL %s\n", nptr->email); if (nptr->url) fprintf(fp, "->URL %s\n", nptr->url); if (nptr->gsm) fprintf(fp, "->GSM %s\n", nptr->gsm); if (nptr->phone) fprintf(fp, "->PHONE %s\n", nptr->phone); if (nptr->UIN) fprintf(fp, "->UIN %s\n", nptr->UIN); if (LastSeenInfo) { if (nptr->lastu && nptr->lasth) fprintf(fp, "->LASTUH %s %s\n", nptr->lastu, nptr->lasth); if (nptr->lastqmsg) fprintf(fp, "->LASTQMSG :%s\n", nptr->lastqmsg); } if (!islinked) { /* * write out hostmasks only if this nickname is * not linked - if it is, the master nickname * (previously written) has the access list */ for (hptr = nptr->hosts; hptr; hptr = hptr->next) fprintf(fp, "->HOST %s\n", hptr->hostmask); } #ifdef LINKED_NICKNAMES #if 0 assert(nptr != nptr->master); #endif /* Quickfix. Seems unlink is broken atm. But, there is no need to * die here since master was not written because of * nptr->nextlink. Huh. Should fix link copying routines -kre */ if ((nptr != nptr->master) && nptr->master) fprintf(fp, "->LINK %s\n", nptr->master->nick); #endif /* LINKED_NICKNAMES */ } /* for (nptr = nicklist[ii]; nptr; nptr = nptr->next) */ } /* for (ii = 0; ii < NICKLIST_MAX; ++ii) */ fclose(fp); rename(tempname, NickServDB); putlog(LOG3, "Wrote %s (%d registered nicknames)", NickServDB, ncnt); return (1); } /* WriteNicks() */
/* DoListen() */ void DoListen(struct PortInfo *portptr) { struct addrinfo hints; struct addrinfo *res, *res_o; int error; char port[MAXLINE]; /* can't use standard LookupHostname */ memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ircsprintf(port, "%d", portptr->port); error = getaddrinfo(LocalHostName, port, &hints, &res); res_o = res; if (error) { putlog(LOG1, "Unable to get local addresses, this should never happen: %s", gai_strerror(error)); return; } while (res != NULL) { if ((portptr->socket = socket(res->ai_family, SOCK_STREAM, 6)) == -1) { res = res->ai_next; portptr->socket = NOSOCKET; continue; } /* set various socket options */ SetSocketOptions(portptr->socket); SetPort((struct sockaddr *)res->ai_addr, portptr->port); if (bind(portptr->socket, res->ai_addr, res->ai_addrlen) == -1) { putlog(LOG1, "FATAL: Unable to bind port tcp/%d: %s", portptr->port, strerror(errno)); close(portptr->socket); portptr->socket = NOSOCKET; } else #ifdef SOMAXCONN if (listen(portptr->socket, SOMAXCONN) == -1) #else if (listen(portptr->socket, HYBSERV_SOMAXCONN) == -1) #endif { putlog(LOG1, "Unable to listen on port tcp/%d: %s", portptr->port, strerror(errno)); close(portptr->socket); portptr->socket = NOSOCKET; } else { putlog(LOG1, "Listener successfully started on host [%s] port tcp/%d", (LocalHostName != NULL) ? LocalHostName : "*", portptr->port); } res = res->ai_next; } portptr->tries++; if (res_o != NULL) freeaddrinfo(res_o); } /* DoListen() */
void BackupDatabases(time_t unixtime) { struct tm *backup_tm; char bpath[MAXLINE], temp[MAXLINE]; /* * First make sure HPath/backup/ exists * Notice that %s/backup/something has to be under 512 characters. -kre */ ircsprintf(bpath, "%s/backup", HPath); /* Function mkdir() returns -1 on failure -kre */ if (mkdir(bpath, 0700)==-1) { /* Proceed if errno is set. This usually should not be necessary, but * this code should help me find why Solaris complains -kre */ if (errno && errno!=EEXIST) { putlog(LOG1, "Error creating backup directory [%s]: %s", bpath, strerror(errno)); return; } } backup_tm = localtime(&unixtime); ircsprintf(bpath, "%s/backup/%d%02d%02d", HPath, 1900 + backup_tm->tm_year, backup_tm->tm_mon + 1, backup_tm->tm_mday); /* * Make the directory permissions: drwx------ * Function mkdir() returns -1 on failure -kre */ if (mkdir(bpath, 0700)==-1) { /* Proceed if errno is set. This usually should not be necessary, but * this code should help me find why Solaris complains -kre */ if (errno && errno!=EEXIST) { putlog(LOG1, "Error creating backup directory [%s]: %s", bpath, strerror(errno)); return; } } ircsprintf(temp, "%s/%s", bpath, OperServDB); CopyFile(OperServDB, temp); #ifdef STATSERVICES ircsprintf(temp, "%s/%s", bpath, StatServDB); CopyFile(StatServDB, temp); #endif /* STATSERVICES */ #ifdef NICKSERVICES ircsprintf(temp, "%s/%s", bpath, NickServDB); CopyFile(NickServDB, temp); #ifdef CHANNELSERVICES ircsprintf(temp, "%s/%s", bpath, ChanServDB); CopyFile(ChanServDB, temp); #endif /* CHANNELSERVICES */ #ifdef MEMOSERVICES ircsprintf(temp, "%s/%s", bpath, MemoServDB); CopyFile(MemoServDB, temp); #endif /* MEMOSERVICES */ /* SeenServDB should be backed up too. -kre */ #ifdef SEENSERVICES ircsprintf(temp, "%s/%s", bpath, SeenServDB); CopyFile(SeenServDB, temp); #endif #endif /* NICKSERVICES */ } /* BackupDatabases() */
static void ss_greplog(struct Luser *lptr, int ac, char **av ) { int day; char buf[MAXLINE + 1]; char date[10]; FILE * lf; char grep_log_filename[MAXLINE + 1]; int i; struct tm * tm; int iCounter; if (ac < 3) { notice(n_StatServ,lptr->nick, "Syntax: \002GREPLOG <service> <pattern> [days]\002"); return; } if (ac > 3 && av[3] != NULL) day = atoi(av[3]); else day = 0; if (day < 0) { notice(n_StatServ, lptr->nick, "Day count should be positive."); return; } if (!GetService(av[1])) { notice(n_StatServ, lptr->nick, "Invalid service!"); return; } iCounter = 0; tm = localtime(¤t_ts); RecordCommand("%s: %s!%s@%s GREPLOG [%s %s] %s", n_StatServ, lptr->nick, lptr->username, lptr->hostname, av[1], av[2], (ac >= 4) ? av[3] : ""); ircsprintf(date, "%4.4d%2.2d%2.2d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); for (i = 0; i <= day; i++) { if (i == 0) ircsprintf(grep_log_filename, "%s/%s", LogPath, LogFile); else ircsprintf(grep_log_filename, "%s/%s.%8.8ld", LogPath, LogFile, korectdat(atol(date), -i)); if ((lf = fopen(grep_log_filename, "r")) == NULL) { notice(n_StatServ, lptr->nick, "No log file: %s", grep_log_filename); continue; } notice(n_StatServ, lptr->nick, "Searching for [%s] with service [%s] for [%d] days in file [%s]", av[2], av[1], day, grep_log_filename); while (fgets(buf, sizeof(buf), lf)) { if ((ircncmp(buf + 25, av[1], strlen(av[1])) == 0) && match(av[2], buf + 25 + strlen(av[1]) + 2)) { iCounter ++; notice(n_StatServ, lptr->nick, "[%d] ... %s", iCounter, buf); } } fclose(lf); } notice(n_StatServ, lptr->nick, "End of search." ); return; } /* o_greplog */
static time_t io_loop(time_t delay) { static char to_send[200]; static time_t lasttime = 0; static long lastrecvK = 0; static int lrv = 0; time_t lasttimeofday; lasttimeofday = CurrentTime; if (CurrentTime < lasttimeofday) { ircsprintf(to_send, "System clock is running backwards - (%d < %d)", CurrentTime, lasttimeofday); report_error(to_send, me.name, 0); } if(!next_gc) { next_gc = CurrentTime + 600; } /* * This chunk of code determines whether or not * "life sucks", that is to say if the traffic * level is so high that standard server * commands should be restricted * * Changed by Taner so that it tells you what's going on * as well as allows forced on (long LCF), etc... */ if ((CurrentTime - lasttime) >= LCF) { lrv = LRV * LCF; lasttime = CurrentTime; currlife = (float)((long)me.receiveK - lastrecvK)/(float)LCF; if (((long)me.receiveK - lrv) > lastrecvK ) { if (!LIFESUX) { LIFESUX = 1; if (NOISYHTM) { sprintf(to_send, "Entering high-traffic mode - (%.1fk/s > %dk/s)", (float)currlife, LRV); sendto_ops("%s", to_send); } } else { LIFESUX++; /* Ok, life really sucks! */ LCF += 2; /* Wait even longer */ if (NOISYHTM) { sprintf(to_send, "Still high-traffic mode %d%s (%d delay): %.1fk/s", LIFESUX, (LIFESUX & 0x04) ? " (TURBO)" : "", (int)LCF, (float)currlife); sendto_ops("%s", to_send); } } } else { LCF = LOADCFREQ; if (LIFESUX) { LIFESUX = 0; if (NOISYHTM) sendto_ops("Resuming standard operation . . . ."); } } lastrecvK = (long)me.receiveK; } /* ** We only want to connect if a connection is due, ** not every time through. Note, if there are no ** active C lines, this call to Tryconnections is ** made once only; it will return 0. - avalon */ if (nextconnect && CurrentTime >= nextconnect) nextconnect = try_connections(CurrentTime); /* ** take the smaller of the two 'timed' event times as ** the time of next event (stops us being late :) - avalon ** WARNING - nextconnect can return 0! */ if (nextconnect) delay = IRCD_MIN(nextping, nextconnect); delay -= CurrentTime; /* ** Adjust delay to something reasonable [ad hoc values] ** (one might think something more clever here... --msa) ** We don't really need to check that often and as long ** as we don't delay too long, everything should be ok. ** waiting too long can cause things to timeout... ** i.e. PINGS -> a disconnection :( ** - avalon */ if (delay < 1) delay = 1; else delay = IRCD_MIN(delay, TIMESEC); /* * We want to read servers on every io_loop, as well * as "busy" clients (which again, includes servers. * If "lifesux", then we read servers AGAIN, and then * flush any data to servers. * -Taner */ #ifndef NO_PRIORITY read_message(0, FDL_SERVER); read_message(0, FDL_BUSY); if (LIFESUX) { read_message(0, FDL_SERVER); if (LIFESUX & 0x4) { /* life really sucks */ read_message(0, FDL_BUSY); read_message(0, FDL_SERVER); } flush_server_connections(); } /* * CLIENT_SERVER = TRUE: * If we're in normal mode, or if "lifesux" and a few * seconds have passed, then read everything. * CLIENT_SERVER = FALSE: * If it's been more than lifesux*2 seconds (that is, * at most 1 second, or at least 2s when lifesux is * != 0) check everything. * -Taner */ { static time_t lslasttime=0; #ifdef CLIENT_SERVER if (!LIFESUX || (lslasttime + LIFESUX) < CurrentTime) { #else if ((lslasttime + (LIFESUX + 1)) < CurrentTime) { #endif read_message(0, FDL_ALL); /* check everything! */ lslasttime = CurrentTime; } } #else read_message(0, FDL_ALL); /* check everything! */ flush_server_connections(); #endif /* ** ...perhaps should not do these loops every time, ** but only if there is some chance of something ** happening (but, note that conf->hold times may ** be changed elsewhere--so precomputed next event ** time might be too far away... (similarly with ** ping times) --msa */ if (CurrentTime >= nextping) { nextping = check_pings(CurrentTime); timeout_auth_queries(CurrentTime); } if (dorehash && !LIFESUX) { rehash(&me, &me, 1); dorehash = 0; } /* ** Flush output buffers on all connections now if they ** have data in them (or at least try to flush) ** -avalon */ flush_connections(0); #ifndef NO_PRIORITY fdlist_check(CurrentTime); #endif if(CurrentTime >= next_gc) { block_garbage_collect(); next_gc = CurrentTime + 600; } return delay; } /* * initalialize_global_set_options * * inputs - none * output - none * side effects - This sets all global set options needed */ static void initialize_global_set_options(void) { memset( &GlobalSetOptions, 0, sizeof(GlobalSetOptions)); MAXCLIENTS = MAX_CLIENTS; NOISYHTM = NOISY_HTM; GlobalSetOptions.autoconn = 1; #ifdef FLUD FLUDNUM = FLUD_NUM; FLUDTIME = FLUD_TIME; FLUDBLOCK = FLUD_BLOCK; #endif #ifdef IDLE_CHECK IDLETIME = MIN_IDLETIME; #endif #ifdef ANTI_SPAMBOT SPAMTIME = MIN_JOIN_LEAVE_TIME; SPAMNUM = MAX_JOIN_LEAVE_COUNT; #endif #ifdef ANTI_DRONE_FLOOD DRONETIME = DEFAULT_DRONE_TIME; DRONECOUNT = DEFAULT_DRONE_COUNT; #endif #ifdef NEED_SPLITCODE SPLITDELAY = (DEFAULT_SERVER_SPLIT_RECOVERY_TIME * 60); SPLITNUM = SPLIT_SMALLNET_SIZE; SPLITUSERS = SPLIT_SMALLNET_USER_SIZE; server_split_time = CurrentTime; #endif /* End of global set options */ }
static void mo_spoof(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *host, *spoof, *password; const char *tmp = NULL; const char *user = NULL; const char *flags = NULL; int i = 0; #ifdef SPOOF_FILE int class_opers; FBFILE *f; char buffer[1024]; struct AddressRec *arec; #endif if (MyConnect(source_p) && !IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "SPOOF"); return; } /* check the user@host mask */ if (strchr(parv[1], '!') != NULL) { syntax: if (MyConnect(source_p)) sendto_one(source_p, ":%s NOTICE %s :Syntax: SPOOF <umask@hmask> " "<spoof/-> [flags/- [password]]", me.name, source_p->name); return; } (void) collapse(parv[1]); for (tmp = parv[1]; *tmp; tmp++) if (!IsKWildChar(*tmp)) if (++i >= ConfigFileEntry.min_nonwildcard) break; if (i < ConfigFileEntry.min_nonwildcard) { if (MyConnect(source_p)) sendto_one(source_p, ":%s NOTICE %s :Not enough non-wildcard characters " "in user@host mask", me.name, source_p->name); return; } host = strchr(parv[1], '@'); if (host) { user = parv[1]; *host = '\0'; host++; } else { user = "******"; host = parv[1]; } /* check the spoof field */ spoof = parv[2]; if (spoof == NULL || !*spoof) goto syntax; if (spoof[0] != '-' || spoof[1] != '\0') { for (tmp = spoof; *tmp; tmp++) if (!IsHostChar(*tmp)) { if (MyConnect(source_p)) sendto_one(source_p, ":%s NOTICE %s :The spoof [%s] is invalid", me.name, source_p->name, spoof); return; } if (strlen(spoof) >= HOSTLEN) { if (MyConnect(source_p)) sendto_one(source_p, ":%s NOTICE %s :Spoofs must be less than %d.." "ignoring it", me.name, source_p->name, HOSTLEN); return; } } flags = (parc > 3) ? parv[3] : "-"; password = (parc > 4 && parv[4][0]) ? parv[4] : NULL; #ifdef PROPAGATE_SPOOF sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS, LL_ICLIENT, ":%s SPOOF %s@%s %s %s :%s", source_p->name, user, host, spoof, flags, password ? password : ""); #endif #ifdef SPOOF_FILE /* Walk through auth {} items and check if we have another auth block * for this hostname */ for (i = 0; i < ATABLE_SIZE; i++) for (arec = atable[i]; arec; arec = arec->next) if (arec->type == CONF_CLIENT && !irccmp(arec->aconf->host, host) && !irccmp(arec->aconf->user, user)) { /* auth entry already exists */ if (MyConnect(source_p)) sendto_one(source_p, ":%s NOTICE %s :auth for %s@%s already exists, you need " "to use /DELSPOOF first", me.name, source_p->name, user, host); #ifdef LOG_SPOOF sendto_realops_flags(UMODE_ALL, L_ALL, "%s attemped to re-add auth for %s@%s " "[spoof: %s, flags: %s]", source_p->name, user, host, spoof, flags); #endif return; } /* Add the spoof to the the spoof file */ if ((f = fbopen(SPOOF_FILE, "a")) == NULL) { sendto_realops_flags(UMODE_ALL, L_ALL, "Could not open %s file, auth for %s@%s " "[spoof: %s, flags: %s, requested by %s] not added", SPOOF_FILE, user, host, spoof, flags, source_p->name); return; } /* write the auth {} block */ fbputs("auth {\n", f, 7); i = ircsprintf(buffer, "\tuser = \"%s@%s\";\n", user, host); fbputs(buffer, f, i); if (spoof[0] != '-' || spoof[1] != '\0') { i = ircsprintf(buffer, "\tspoof = \"%s\";\n", spoof); fbputs(buffer, f, i); } if (password) { i = ircsprintf(buffer, "\tpassword = \"%s\";\n", password); fbputs(buffer, f, i); } /* process given flags */ i = class_opers = 0; for (tmp = flags; *tmp; ++tmp) switch (*tmp) { case 't': i |= CONF_FLAGS_NO_TILDE; /* no_tilde = yes; */ break; case 'i': i |= CONF_FLAGS_NEED_IDENTD; /* need_ident = yes; */ break; case 'k': i |= CONF_FLAGS_EXEMPTKLINE; /* kline_exempt = yes; */ break; case 'g': i |= CONF_FLAGS_EXEMPTGLINE; /* gline_exempt = yes; */ break; case 'l': i |= CONF_FLAGS_NOLIMIT; /* exceed_limit = yes; */ break; case 'o': class_opers = 1; /* class = "opers"; */ break; case 'f': i |= CONF_FLAGS_CAN_FLOOD; /* can_flood = yes; */ break; case 'p': i|= CONF_FLAGS_NEED_PASSWORD; /* need_password = yes; */ } if (i) { fbputs("\tflags = ", f, 9); try_flag(f, &i, CONF_FLAGS_NO_TILDE, "no_tilde"); try_flag(f, &i, CONF_FLAGS_NEED_IDENTD, "need_ident"); try_flag(f, &i, CONF_FLAGS_EXEMPTKLINE, "kline_exempt"); try_flag(f, &i, CONF_FLAGS_EXEMPTGLINE, "gline_exempt"); try_flag(f, &i, CONF_FLAGS_NOLIMIT, "exceed_limit"); try_flag(f, &i, CONF_FLAGS_CAN_FLOOD, "can_flood"); try_flag(f, &i, CONF_FLAGS_NEED_PASSWORD, "need_password"); } if (class_opers) fbputs("\tclass = \"opers\";\n", f, 18); else fbputs("\tclass = \"users\";\n", f, 18); fbputs("};\n\n", f, 4); fbclose(f); rehash(0); #endif #ifdef LOG_SPOOF sendto_realops_flags(UMODE_ALL, L_ALL, "%s added auth for %s@%s [spoof: %s, flags: %s]", source_p->name, user, host, spoof, flags); ilog(L_TRACE, "%s added auth for %s@%s [spoof: %s, flags: %s]", source_p->name, user, host, spoof, flags); #endif }
static void do_ison(struct Client *client_p, struct Client *up, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL; char *nick; char *p; char *current_insert_point, *current_insert_point2; char buf[IRCD_BUFSIZE]; char buf2[IRCD_BUFSIZE]; int len; int i; int done = 0; int relay_to_hub = 0; current_insert_point2 = buf2; *buf2 = '\0'; len = ircsprintf(buf, form_str(RPL_ISON), me.name, parv[0]); current_insert_point = buf + len; /* rfc1459 is ambigious about how to handle ISON * this should handle both interpretations. */ for (i = 1; i < parc; i++) { for (nick = strtoken(&p, parv[i], " "); nick; nick = strtoken(&p, NULL, " ")) { if ((target_p = find_person(client_p, nick))) { len = strlen(target_p->name); if ((current_insert_point + (len + 5)) < (buf + sizeof(buf))) { memcpy(current_insert_point, target_p->name, len); current_insert_point += len; *current_insert_point++ = ' '; } else { done = 1; break; } } if (up) { /* Build up a single list, for use if we relay.. */ len = strlen(nick); if ((current_insert_point2 + len + 5) < (buf2 + sizeof(buf2))) { memcpy(current_insert_point2, nick, len); current_insert_point2 += len; *current_insert_point2++ = ' '; } if (target_p == NULL) { /* * XXX Ick. we need to ask our hub if nick is online. * it's probably safest to relay the whole command, * unless we can answer it fully ourselves. * -davidt */ relay_to_hub = 1; /* Also cache info about nick */ sendto_one(up, ":%s NBURST %s", ID_or_name(&me, up), nick); } } } if (done) break; } /* current_insert_point--; * Do NOT take out the trailing space, it breaks ircII * --Rodder */ *current_insert_point = '\0'; *current_insert_point2 = '\0'; if (relay_to_hub) sendto_one(up, ":%s ISON :%s", ID_or_name(source_p, up), buf2); else sendto_one(source_p, "%s", buf); }
/* * * parc number of arguments ('sender' counted as one!) * parv[0] pointer to 'sender' (may point to empty string) (not used) * parv[1]..parv[parc-1] * pointers to additional parameters, this is a NULL * terminated list (parv[parc] == NULL). * * *WARNING* * Numerics are mostly error reports. If there is something * wrong with the message, just *DROP* it! Don't even think of * sending back a neat error message -- big danger of creating * a ping pong error message... */ static void do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; struct Channel *chptr; if(parc < 2 || !IsServer(source_p)) return; /* Remap low number numerics. */ if(numeric[0] == '0') numeric[0] = '1'; /* * Prepare the parameter portion of the message into 'buffer'. * (Because the buffer is twice as large as the message buffer * for the socket, no overflow can occur here... ...on current * assumptions--bets are off, if these are changed --msa) * Note: if buffer is non-empty, it will begin with SPACE. */ if(parc > 1) { char *t = buffer; /* Current position within the buffer */ int i; int tl; /* current length of presently being built string in t */ for (i = 2; i < (parc - 1); i++) { tl = ircsprintf(t, " %s", parv[i]); t += tl; } ircsprintf(t, " :%s", parv[parc - 1]); } if((target_p = find_client(parv[1])) != NULL) { if(IsMe(target_p)) { /* * We shouldn't get numerics sent to us, * any numerics we do get indicate a bug somewhere.. */ /* ugh. this is here because of nick collisions. when two servers * relink, they burst each other their nicks, then perform collides. * if there is a nick collision, BOTH servers will kill their own * nicks, and BOTH will kill the other servers nick, which wont exist, * because it will have been already killed by the local server. * * unfortunately, as we cant guarantee other servers will do the * "right thing" on a nick collision, we have to keep both kills. * ergo we need to ignore ERR_NOSUCHNICK. --fl_ */ /* quick comment. This _was_ tried. i.e. assume the other servers * will do the "right thing" and kill a nick that is colliding. * unfortunately, it did not work. --Dianora */ if(atoi(numeric) != ERR_NOSUCHNICK) sendto_realops_flags(UMODE_ALL, L_ADMIN, "*** %s(via %s) sent a %s numeric to me: %s", source_p->name, client_p->name, numeric, buffer); return; } else if(target_p->from == client_p) { /* This message changed direction (nick collision?) * ignore it. */ return; } /* csircd will send out unknown umode flag for +a (admin), drop it here. */ if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p)) return; /* Fake it for server hiding, if its our client */ if(ConfigServerHide.hide_servers && MyClient(target_p) && !IsOper(target_p)) sendto_one(target_p, ":%s %s %s%s", me.name, numeric, parv[1], buffer); else sendto_one(target_p, ":%s %s %s%s", source_p->name, numeric, parv[1], buffer); return; } else if((chptr = hash_find_channel(parv[1])) != NULL) sendto_channel_local(ALL_MEMBERS, chptr, ":%s %s %s %s", source_p->name, numeric, chptr->chname, buffer); }
static void ss_stats(struct Luser *lptr, int ac, char **av) { float avgops, avguc, avgus; struct tm *tmp_tm; char str[MAXLINE + 1], tmp[MAXLINE + 1]; char **tav; time_t currtime; RecordCommand("%s: %s!%s@%s STATS", n_StatServ, lptr->nick, lptr->username, lptr->hostname); avgops = Network->TotalOperators / Network->TotalServers; if (Network->TotalChannels > 0.0) avguc = Network->TotalUsers / Network->TotalChannels; else avguc = 0; avgus = Network->TotalUsers / Network->TotalServers; notice(n_StatServ, lptr->nick, "Current Users: %1.0f (avg. %1.2f users per server)", Network->TotalUsers, avgus); notice(n_StatServ, lptr->nick, "Current Operators: %1.0f (avg. %1.2f operators per server)", Network->TotalOperators, avgops); notice(n_StatServ, lptr->nick, "Current Channels: %1.0f (avg. %1.2f users per channel)", Network->TotalChannels, avguc); notice(n_StatServ, lptr->nick, "Current Servers: %1.0f", Network->TotalServers); strlcpy(str, ctime(&Network->MaxUsers_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; notice(n_StatServ, lptr->nick, "Max Users: %ld on %s", Network->MaxUsers, str); if (Network->MaxOperators_ts) { strlcpy(str, "on ", sizeof(str)); strlcat(str, ctime(&Network->MaxOperators_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Operators: %ld %s", Network->MaxOperators, str); if (Network->MaxChannels_ts) { strlcpy(str, "on ", sizeof(str)); strlcat(str, ctime(&Network->MaxChannels_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Channels: %ld %s", Network->MaxChannels, str); strlcpy(str, ctime(&Network->MaxServers_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; notice(n_StatServ, lptr->nick, "Max Servers: %ld on %s", Network->MaxServers, str); notice(n_StatServ, lptr->nick, "Identd Users: %ld", Network->Identd); notice(n_StatServ, lptr->nick, "Non-Identd Users: %ld", Network->NonIdentd); notice(n_StatServ, lptr->nick, "Resolving Host Users: %ld", Network->ResHosts); notice(n_StatServ, lptr->nick, "Non-Resolving Host Users: %ld", (long) Network->TotalUsers - Network->ResHosts); currtime = current_ts; strlcpy(tmp, ctime(&currtime), sizeof(tmp)); SplitBuf(tmp, &tav); ircsprintf(str, "%s %s %s, %s", tav[0], tav[1], tav[2], tav[4]); notice(n_StatServ, lptr->nick, "-- \002So far today:\002 (%s) --", str); MyFree(tav); if (Network->MaxUsersT_ts) { tmp_tm = localtime(&Network->MaxUsersT_ts); ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Users: %ld %s", Network->MaxUsersT, str); if (Network->MaxOperatorsT_ts) { tmp_tm = localtime(&Network->MaxOperatorsT_ts); ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Operators: %ld %s", Network->MaxOperatorsT, str); if (Network->MaxChannelsT_ts) { tmp_tm = localtime(&Network->MaxChannelsT_ts); ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Channels: %ld %s", Network->MaxChannelsT, str); if (Network->MaxServersT_ts) { tmp_tm = localtime(&Network->MaxServersT_ts); ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Servers: %ld %s", Network->MaxServersT, str); notice(n_StatServ, lptr->nick, "Operator Kills: %ld", Network->OperKillsT); notice(n_StatServ, lptr->nick, "Server Kills: %ld", Network->ServKillsT); } /* ss_stats() */
static void ShowServerInfo(struct Server *servptr, struct Luser *lptr, int showinfo) { char str[MAXLINE + 1]; assert(servptr != 0); assert(lptr != 0); if (!showinfo) { #ifdef SPLIT_INFO if (!servptr->split_ts) #endif notice(n_StatServ, lptr->nick, "%-30s connected: %s, users: %d", servptr->name, timeago(servptr->connect_ts, 0), servptr->numusers); #ifdef SPLIT_INFO else notice(n_StatServ, lptr->nick, "%-30s currently in \002netsplit\002 for %s", servptr->name, timeago(servptr->split_ts, 0)); #endif return; } #ifdef SPLIT_INFO if (!servptr->split_ts) #endif notice(n_StatServ, lptr->nick, "Statistics for server: \002%s\002", servptr->name); #ifdef SPLIT_INFO else notice(n_StatServ, lptr->nick, "Last known statistics for server: \002%s\002", servptr->name); #endif notice(n_StatServ, lptr->nick, "Current Clients: %ld", servptr->numusers); notice(n_StatServ, lptr->nick, "Current Opers: %ld", servptr->numopers); notice(n_StatServ, lptr->nick, "Current Servers: %ld", servptr->numservs); if (servptr->maxusers_ts) { strlcpy(str, "on ", sizeof(str)); strlcat(str, ctime(&servptr->maxusers_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Clients: %ld %s", servptr->maxusers, str); if (servptr->maxopers_ts) { strlcpy(str, "on ", sizeof(str)); strlcat(str, ctime(&servptr->maxopers_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Opers: %ld %s", servptr->maxopers, str); if (servptr->maxservs_ts) { strlcpy(str, "on ", sizeof(str)); strlcat(str, ctime(&servptr->maxservs_ts), sizeof(str)); str[strlen(str) - 1] = '\0'; } else str[0] = '\0'; notice(n_StatServ, lptr->nick, "Max Servers: %ld %s", servptr->maxservs, str); notice(n_StatServ, lptr->nick, "Identd Users: %ld", servptr->numidentd); notice(n_StatServ, lptr->nick, "Non-Identd Users: %ld", servptr->numusers - servptr->numidentd); notice(n_StatServ, lptr->nick, "Resolving Hosts: %ld", servptr->numreshosts); notice(n_StatServ, lptr->nick, "Non-Resolving Hosts: %ld", servptr->numusers - servptr->numreshosts); notice(n_StatServ, lptr->nick, "Operator Kills: %ld", servptr->numoperkills); notice(n_StatServ, lptr->nick, "Server Kills: %ld", servptr->numservkills); if (servptr->ping > 0.0) { notice(n_StatServ, lptr->nick, "Current Ping: %5.4f seconds", servptr->ping); if ((servptr->maxping > 0.0) && servptr->maxping_ts) { ircsprintf(str, "on %s", ctime(&servptr->maxping_ts)); str[strlen(str) - 1] = '\0'; notice(n_StatServ, lptr->nick, "Highest Ping: %5.4f seconds %s", servptr->maxping, str); } if ((servptr->minping > 0.0) && servptr->minping_ts) { ircsprintf(str, "on %s", ctime(&servptr->minping_ts)); str[strlen(str) - 1] = '\0'; notice(n_StatServ, lptr->nick, "Lowest Ping: %5.4f seconds %s", servptr->minping, str); } } if (servptr->uplink) notice(n_StatServ, lptr->nick, "Current Hub: %s (connected for [%s])", servptr->uplink->name, timeago(servptr->connect_ts, 0)); #ifdef SPLIT_INFO else notice(n_StatServ, lptr->nick, "Currently in \002netsplit\002 for %s", servptr->name, timeago(servptr->connect_ts, 0)); #endif } /* ShowServerInfo() */
static void ss_server(struct Luser *lptr, int ac, char **av) { struct Server *servptr, *hub; char argbuf[MAXLINE + 1], str[MAXLINE + 1]; char *target; /* target server */ int maxusers, /* -maxusers */ minusers, /* -minusers */ info; /* -info */ int ii, alen, cnt; if (ac < 2) { notice(n_StatServ, lptr->nick, "Syntax: SERVER <server | mask> [options]"); notice(n_StatServ, lptr->nick, ERR_MORE_INFO, n_StatServ, "SERVER"); return; } hub = NULL; maxusers = -1; minusers = -1; target = NULL; info = 0; /* * Parse their args */ for (ii = 1; ii < ac; ii++) { alen = strlen(av[ii]); if (!ircncmp(av[ii], "-maxusers", alen)) { if (++ii >= ac) { notice(n_StatServ, lptr->nick, "No maximum user count given"); return; } maxusers = atoi(av[ii]); } else if (!ircncmp(av[ii], "-minusers", alen)) { if (++ii >= ac) { notice(n_StatServ, lptr->nick, "No minimum user count given"); return; } minusers = atoi(av[ii]); } else if (!ircncmp(av[ii], "-info", alen)) info = 1; else if (!ircncmp(av[ii], "-hub", alen)) { if (++ii >= ac) { notice(n_StatServ, lptr->nick, "No hub server given"); return; } if (!(hub = FindServer(av[ii]))) { notice(n_StatServ, lptr->nick, "No such server: %s", av[ii]); return; } } else { if (!target) target = av[ii]; } } if (!target) { notice(n_StatServ, lptr->nick, "No target server specified"); return; } argbuf[0] = '\0'; if (maxusers >= 0) { ircsprintf(str, "-maxusers %d ", maxusers); strlcat(argbuf, str, sizeof(argbuf)); } if (minusers >= 0) { ircsprintf(str, "-minusers %d ", minusers); strlcat(argbuf, str, sizeof(argbuf)); } if (info) strlcat(argbuf, "-info ", sizeof(argbuf)); if (hub) { ircsprintf(str, "-hub %s ", hub->name); strlcat(argbuf, str, sizeof(argbuf)); } RecordCommand("%s: %s!%s@%s SERVER [%s] %s", n_StatServ, lptr->nick, lptr->username, lptr->hostname, target, argbuf); if ((servptr = FindServer(target))) { ShowServerInfo(servptr, lptr, 1); return; } cnt = 0; for (servptr = ServerList; servptr; servptr = servptr->next) { if (!match(target, servptr->name)) continue; if (((maxusers >= 0) && (servptr->numusers > maxusers)) || ((minusers >= 0) && (servptr->numusers < minusers))) continue; else if (hub && (servptr->uplink != hub)) continue; /* * servptr passes all the tests */ ++cnt; notice(n_StatServ, lptr->nick, "-----"); ShowServerInfo(servptr, lptr, info); } notice(n_StatServ, lptr->nick, "%d match%s found", cnt, (cnt == 1) ? "" : "es"); } /* ss_server() */
/* clicap_generate() * Generates a list of capabilities. * * Inputs: client to send to, subcmd to send, * flags to match against: 0 to do none, -1 if client has no flags, * int to whether we are doing CAP CLEAR * Outputs: None */ static void clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clear) { char buf[BUFSIZE]; char capbuf[BUFSIZE]; char *p; int buflen = 0; int curlen, mlen; int i; mlen = ircsprintf(buf, ":%s CAP %s %s", me.name, EmptyString(source_p->name) ? "*" : source_p->name, subcmd); p = capbuf; buflen = mlen; /* shortcut, nothing to do */ if(flags == -1) { sendto_one(source_p, "%s :", buf); return; } for(i = 0; i < CLICAP_LIST_LEN; i++) { if(flags) { if(!IsCapable(source_p, clicap_list[i].cap_serv)) continue; /* they are capable of this, check sticky */ else if(clear && clicap_list[i].flags & CLICAP_FLAGS_STICKY) continue; } /* \r\n\0, possible "-~=", space, " *" */ if(buflen + clicap_list[i].namelen >= BUFSIZE - 10) { /* remove our trailing space -- if buflen == mlen * here, we didnt even succeed in adding one. */ if(buflen != mlen) *(p - 1) = '\0'; else *p = '\0'; sendto_one(source_p, "%s * :%s", buf, capbuf); p = capbuf; buflen = mlen; } if(clear) { *p++ = '-'; buflen++; /* needs a client ack */ if(clicap_list[i].cap_cli && IsCapable(source_p, clicap_list[i].cap_cli)) { *p++ = '~'; buflen++; } } else { if(clicap_list[i].flags & CLICAP_FLAGS_STICKY) { *p++ = '='; buflen++; } /* if we're doing an LS, then we only send this if * they havent ack'd */ if(clicap_list[i].cap_cli && (!flags || !IsCapable(source_p, clicap_list[i].cap_cli))) { *p++ = '~'; buflen++; } } curlen = ircsprintf(p, "%s ", clicap_list[i].name); p += curlen; buflen += curlen; } /* remove trailing space */ if(buflen != mlen) *(p - 1) = '\0'; else *p = '\0'; sendto_one(source_p, "%s :%s", buf, capbuf); }
/* * ms_bmask() * * inputs - parv[0] = SID * parv[1] = TS * parv[2] = channel name * parv[3] = type of ban to add ('b' 'I' or 'e') * parv[4] = space delimited list of masks to add * outputs - none * side effects - propgates unchanged bmask line to CAP_TS6 servers, * sends plain modes to the others. nothing is sent * to the server the issuing server is connected through */ static void ms_bmask(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { static char modebuf[BUFSIZE]; static char parabuf[BUFSIZE]; static char banbuf[BUFSIZE]; struct Channel *chptr; char *s, *t, *mbuf, *pbuf; long mode_type; int mlen; int plen = 0; int tlen; int modecount = 0; int needcap = NOCAPS; if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2])) return; if((chptr = hash_find_channel(parv[2])) == NULL) return; /* TS is higher, drop it. */ if(atol(parv[1]) > chptr->channelts) return; switch(parv[3][0]) { case 'b': mode_type = CHFL_BAN; break; case 'e': mode_type = CHFL_EXCEPTION; needcap = CAP_EX; break; case 'I': mode_type = CHFL_INVEX; needcap = CAP_IE; break; /* maybe we should just blindly propagate this? */ default: return; } parabuf[0] = '\0'; s = banbuf; strlcpy(s, parv[4], sizeof(banbuf)); /* only need to construct one buffer, for non-ts6 servers */ mlen = ircsprintf(modebuf, ":%s MODE %s +", source_p->name, chptr->chname); mbuf = modebuf + mlen; pbuf = parabuf; if((t = strchr(s, ' ')) != NULL) *t++ = '\0'; while(s != NULL) { tlen = strlen(s); /* I dont even want to begin parsing this.. */ if(tlen > MODEBUFLEN) break; if(tlen && add_id(source_p, chptr, s, mode_type)) { /* this new one wont fit.. */ if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 4 || modecount >= MAXMODEPARAMS) { *mbuf = '\0'; *(pbuf - 1) = '\0'; sendto_channel_local(ALL_MEMBERS, chptr, "%s %s", modebuf, parabuf); sendto_server(client_p, NULL, chptr, needcap, CAP_TS6, NOFLAGS, "%s %s", modebuf, parabuf); mbuf = modebuf + mlen; pbuf = parabuf; plen = modecount = 0; } *mbuf++ = parv[3][0]; plen = ircsprintf(pbuf, "%s ", s); pbuf += plen; modecount++; } s = t; if(s != NULL) { /* trailing space marking the end. */ if(*s == '\0') break; if((t = strchr(s, ' ')) != NULL) *t++ = '\0'; } } if(modecount) { *mbuf = *(pbuf - 1) = '\0'; sendto_channel_local(ALL_MEMBERS, chptr, "%s %s", modebuf, parabuf); sendto_server(client_p, NULL, chptr, needcap, CAP_TS6, NOFLAGS, "%s %s", modebuf, parabuf); } /* assumption here is that since the server sent BMASK, they are TS6, so they have an ID */ sendto_server(client_p, NULL, chptr, CAP_TS6|needcap, NOCAPS, NOFLAGS, ":%s BMASK %lu %s %s :%s", source_p->id, (unsigned long)chptr->channelts, chptr->chname, parv[3], parv[4]); }
int _register_user(aClient *cptr, aClient *sptr, char *nick, char *username, char *umode, char *virthost, char *ip) { ConfigItem_ban *bconf; char *parv[3], *tmpstr; #ifdef HOSTILENAME char stripuser[USERLEN + 1], *u1 = stripuser, *u2, olduser[USERLEN + 1], userbad[USERLEN * 2 + 1], *ubad = userbad, noident = 0; #endif int xx; anUser *user = sptr->user; aClient *nsptr; int i; char mo[256]; char *tkllayer[9] = { me.name, /*0 server.name */ "+", /*1 +|- */ "z", /*2 G */ "*", /*3 user */ NULL, /*4 host */ NULL, NULL, /*6 expire_at */ NULL, /*7 set_at */ NULL /*8 reason */ }; aTKline *savetkl = NULL; ConfigItem_tld *tlds; cptr->last = TStime(); parv[0] = sptr->name; parv[1] = parv[2] = NULL; nick = sptr->name; /* <- The data is always the same, but the pointer is sometimes not, * I need this for one of my modules, so do not remove! ;) -- Syzop */ if (MyConnect(sptr)) { if ((i = check_client(sptr, username))) { /* This had return i; before -McSkaf */ if (i == -5) return FLUSH_BUFFER; sendto_snomask(SNO_CLIENT, "*** Notice -- %s from %s.", i == -3 ? "Too many connections" : "Unauthorized connection", get_client_host(sptr)); ircstp->is_ref++; ircsprintf(mo, "This server is full."); return exit_client(cptr, sptr, &me, i == -3 ? mo : "You are not authorized to connect to this server"); } if (sptr->hostp) { /* reject ascci < 32 and ascii >= 127 (note: upper resolver might be even more strict) */ for (tmpstr = sptr->sockhost; *tmpstr > ' ' && *tmpstr < 127; tmpstr++); /* if host contained invalid ASCII _OR_ the DNS reply is an IP-like reply * (like: 1.2.3.4), then reject it and use IP instead. */ if (*tmpstr || !*user->realhost || (isdigit(*sptr->sockhost) && isdigit(*tmpstr - 1))) strncpyzt(sptr->sockhost, (char *)Inet_ia2p((struct IN_ADDR*)&sptr->ip), sizeof(sptr->sockhost)); } strncpyzt(user->realhost, sptr->sockhost, sizeof(sptr->sockhost)); /* SET HOSTNAME */ /* * I do not consider *, ~ or ! 'hostile' in usernames, * as it is easy to differentiate them (Use \*, \? and \\) * with the possible? * exception of !. With mIRC etc. ident is easy to fake * to contain @ though, so if that is found use non-ident * username. -Donwulff * * I do, We only allow a-z A-Z 0-9 _ - and . now so the * !strchr(sptr->username, '@') check is out of date. -Cabal95 * * Moved the noident stuff here. -OnyxDragon */ if (!(sptr->flags & FLAGS_DOID)) strncpyzt(user->username, username, USERLEN + 1); else if (sptr->flags & FLAGS_GOTID) strncpyzt(user->username, sptr->username, USERLEN + 1); else { /* because username may point to user->username */ char temp[USERLEN + 1]; strncpyzt(temp, username, USERLEN + 1); if (IDENT_CHECK == 0) { strncpyzt(user->username, temp, USERLEN + 1); } else { *user->username = '******'; strncpyzt((user->username + 1), temp, USERLEN); #ifdef HOSTILENAME noident = 1; #endif } } #ifdef HOSTILENAME /* * Limit usernames to just 0-9 a-z A-Z _ - and . * It strips the "bad" chars out, and if nothing is left * changes the username to the first 8 characters of their * nickname. After the MOTD is displayed it sends numeric * 455 to the user telling them what(if anything) happened. * -Cabal95 * * Moved the noident thing to the right place - see above * -OnyxDragon * * No longer use nickname if the entire ident is invalid, * if thats the case, it is likely the user is trying to cause * problems so just ban them. (Using the nick could introduce * hostile chars) -- codemastr */ for (u2 = user->username + noident; *u2; u2++) { if (isallowed(*u2)) *u1++ = *u2; else if (*u2 < 32) { /* * Make sure they can read what control * characters were in their username. */ *ubad++ = '^'; *ubad++ = *u2 + '@'; } else *ubad++ = *u2; } *u1 = '\0'; *ubad = '\0'; if (strlen(stripuser) != strlen(user->username + noident)) { if (stripuser[0] == '\0') { return exit_client(cptr, cptr, cptr, "Hostile username. Please use only 0-9 a-z A-Z _ - and . in your username."); } strcpy(olduser, user->username + noident); strncpy(user->username + 1, stripuser, USERLEN - 1); user->username[0] = '~'; user->username[USERLEN] = '\0'; } else u1 = NULL; #endif /* * following block for the benefit of time-dependent K:-lines */ if ((bconf = Find_ban(sptr, make_user_host(user->username, user->realhost), CONF_BAN_USER))) { ircstp->is_ref++; sendto_one(cptr, ":%s %d %s :*** You are not welcome on this server (%s)" " Email %s for more information.", me.name, ERR_YOUREBANNEDCREEP, cptr->name, bconf->reason ? bconf->reason : "", KLINE_ADDRESS); return exit_client(cptr, cptr, cptr, "You are banned"); } if ((bconf = Find_ban(NULL, sptr->info, CONF_BAN_REALNAME))) { ircstp->is_ref++; sendto_one(cptr, ":%s %d %s :*** Your GECOS (real name) is not allowed on this server (%s)" " Please change it and reconnect", me.name, ERR_YOUREBANNEDCREEP, cptr->name, bconf->reason ? bconf->reason : ""); return exit_client(cptr, sptr, &me, "Your GECOS (real name) is banned from this server"); } tkl_check_expire(NULL); /* Check G/Z lines before shuns -- kill before quite -- codemastr */ if ((xx = find_tkline_match(sptr, 0)) < 0) { ircstp->is_ref++; return xx; } find_shun(sptr); /* Technical note regarding next few lines of code: * If the spamfilter matches, depending on the action: * If it's block/dccblock/whatever the retval is -1 ===> we return, client stays "locked forever". * If it's kill/tklline the retval is -2 ==> we return with -2 (aka: FLUSH_BUFFER) * If it's action is viruschan the retval is -5 ==> we continue, and at the end of this return * take special actions. We cannot do that directly here since the user is not fully registered * yet (at all). * -- Syzop */ spamfilter_build_user_string(spamfilter_user, sptr->name, sptr); xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, &savetkl); if ((xx < 0) && (xx != -5)) return xx; RunHookReturnInt(HOOKTYPE_PRE_LOCAL_CONNECT, sptr, !=0); } else {
static void accept_connection(int pfd, void *data) { static time_t last_oper_notice = 0; struct irc_sockaddr_storage sai; socklen_t addrlen = sizeof(sai); int fd; struct Listener *listener = data; struct ConfItem *aconf; char buf[BUFSIZE]; s_assert(listener != NULL); if(listener == NULL) return; for(;;) /* loop until something breaks us out */ { /* * There may be many reasons for error return, but * in otherwise correctly working environment the * probable cause is running out of file descriptors * (EMFILE, ENFILE or others?). The man pages for * accept don't seem to list these as possible, * although it's obvious that it may happen here. * Thus no specific errors are tested at this * point, just assume that connections cannot * be accepted until some old is closed first. */ fd = comm_accept(listener->fd, (struct sockaddr *) &sai, &addrlen); /* This needs to be done here, otherwise we break dlines */ mangle_mapped_sockaddr((struct sockaddr *) &sai); if(fd < 0) { /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener); return; } /* * check for connection limit */ if((maxconnections - 10) < fd) { ++ServerStats->is_ref; /* * slow down the whining to opers bit */ if((last_oper_notice + 20) <= CurrentTime) { sendto_realops_flags(UMODE_ALL, L_ALL, "All connections in use. (%s)", get_listener_name(listener)); last_oper_notice = CurrentTime; } write(fd, "ERROR :All connections in use\r\n", 32); comm_close(fd); /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener); return; } /* Do an initial check we aren't connecting too fast or with too many * from this IP... */ if((aconf = conf_connect_allowed((struct sockaddr *) &sai, sai.ss_family)) != NULL) { ServerStats->is_ref++; if(ConfigFileEntry.dline_with_reason) { if(ircsnprintf (buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd) >= (sizeof(buf) - 1)) { buf[sizeof(buf) - 3] = '\r'; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = '\0'; } } else ircsprintf(buf, "ERROR :You have been D-lined.\r\n"); write(fd, buf, strlen(buf)); comm_close(fd); /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener); return; } ServerStats->is_ac++; add_connection(listener, fd, (struct sockaddr *) &sai); } /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener); }
/* * m_topic * parv[0] = sender prefix * parv[1] = channel name * parv[2] = new topic, if setting topic */ static int m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char *p = NULL; if((p = strchr(parv[1], ','))) *p = '\0'; if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if(!IsChannelName(parv[1])) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } chptr = find_channel(parv[1]); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } /* setting topic */ if(parc > 2) { msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), parv[1]); return 0; } if((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_chanop(msptr) || !MyClient(source_p)) { char topic_info[USERHOST_REPLYLEN]; ircsprintf(topic_info, "%s!%s@%s", source_p->name, source_p->username, source_p->host); set_channel_topic(chptr, parv[2], topic_info, CurrentTime); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s", use_id(source_p), chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_server(client_p, chptr, NOCAPS, CAP_TS6, ":%s TOPIC %s :%s", source_p->name, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s TOPIC %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); } else sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name, source_p->name, parv[1]); } else if(MyClient(source_p)) { if(!IsMember(source_p, chptr) && SecretChannel(chptr)) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), parv[1]); return 0; } if(chptr->topic == NULL) sendto_one(source_p, form_str(RPL_NOTOPIC), me.name, source_p->name, parv[1]); else { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } } return 0; }
int main(int argc, char *argv[]) { #if !defined DEBUGMODE && !defined DAEMONTOOLS pid_t pid; /* pid of this process */ #endif /* !DEBUGMODE && !DAEMONTOOLS */ #ifdef GDB_DEBUG int GDBAttached = 0; #endif /* GDB_DEBUG */ #if defined GIMMECORE || defined DEBUGMODE struct rlimit rlim; /* resource limits -kre */ #endif /* GIMMECORE || DEBUGMODE */ FILE *pidfile; /* to write our pid */ uid_t uid; /* real user id */ uid_t euid; /* effective user id */ #if defined HAVE_BOEHM_GC GC_INIT(); #endif /* HAVE_BOEHM_GC */ myargv = argv; /* Initialise current TS for services -kre */ TimeStarted = current_ts = time(NULL); /* Be sure, be paranoid, be safe. -kre */ umask(077); fprintf(stderr, "Hybserv2 TS services version %s by Hybserv2 team\n" #if defined __DATE__ && defined __TIME__ "Compiled at %s, %s\n", #endif hVersion #if defined __DATE__ && defined __TIME__ , __DATE__, __TIME__ #endif ); #ifdef GDB_DEBUG while (!GDBAttached) sleep(1); #endif /* GDB_DEBUG */ /* * Load SETPATH (settings.conf) - this must be done * before the config file is loaded, and before any * putlog() calls are made, since LogFile is specified * in settings.conf */ if (LoadSettings(0) == 0) { fprintf(stderr, "Fatal errors encountered parsing %s, exiting\n" "Check logfile %s/%s\n", SETPATH, LogPath ? LogPath : "", LogFile ? LogFile : "*unknown*"); return (0); } /* * If they run ./shownicks or ./showchans rather than ./hybserv * display nicknames/channels */ if (strstr(argv[0], "shownicks")) { #ifdef NICKSERVICES ShowNicknames(argc, argv); #endif /* NICKSERVICES */ return (0); } else if (strstr(argv[0], "showchans")) { #if defined(NICKSERVICES) && defined(CHANNELSERVICES) ShowChannels(argc, argv); #endif /* defined(NICKSERVICES) && defined(CHANNELSERVICES) */ return 0; } /* Check for running services -kre */ if ((pidfile = fopen(PidFile, "r")) == NULL) fprintf(stderr, "WARNING: Unable to read pid file %s\n", PidFile); else { pid_t mypid; char line[MAXLINE + 1]; if (fgets(line, sizeof(line), pidfile) != NULL) { mypid = atoi(line); if (mypid && !kill(mypid, 0)) { fprintf(stderr, "FATAL: Services are already running!\n"); fclose(pidfile); exit(EXIT_FAILURE); } } fclose(pidfile); } uid = getuid(); /* the user id of the user who ran the process */ euid = geteuid(); /* the effective id (different if setuid) */ if (!uid || !euid) { fprintf(stderr, "FATAL: Please don't run services as root. Now exiting.\n"); exit(EXIT_FAILURE); } if (chdir(HPath) != 0) { fprintf(stderr, "HPath is an invalid directory, please check %s\n", SETPATH); exit(EXIT_FAILURE); } putlog(LOG1, "Hybserv2 TS services version %s started", hVersion); /* Get the offset from GMT (London time) */ gmt_offset = GetTZOffset(TimeStarted); /* * the Network list must be initialized before the config * file is loaded */ InitLists(); /* load server, jupe, gline, user, admin info */ LoadConfig(); /* load nick/chan/memo/stat databases */ LoadData(); #ifdef GLOBALSERVICES if (LogonNews) { Network->LogonNewsFile.filename = LogonNews; ReadMessageFile(&Network->LogonNewsFile); } #endif /* GLOBALSERVICES */ if (LocalHostName) SetupVirtualHost(); #if !defined DEBUGMODE && !defined GDB_DEBUG /* Daemontools compatibility stuff */ #ifndef DAEMONTOOLS pid = fork(); if (pid == -1) { printf("Unable to fork(), exiting.\n"); exit(EXIT_FAILURE); } if (pid != 0) { printf("Running in background (pid: %d)\n", (int)pid); exit(EXIT_SUCCESS); } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); /* Make current process session leader -kre */ if (setsid() == -1) { exit(EXIT_FAILURE); } #else printf("Entering foreground debug mode\n"); #endif /* DEBUGMODE */ #endif /* DAEMONTOOLS */ #if defined GIMMECORE || defined DEBUGMODE printf("Setting corefile limit... "); /* Set corefilesize to maximum - therefore we ensure that core will be * generated, no matter of shell limits -kre */ getrlimit(RLIMIT_CORE, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit(RLIMIT_CORE, &rlim); printf("done.\n"); #endif /* GIMMECORE || DEBUGMODE */ /* Signals must be set up after fork(), since the parent exits */ InitSignals(); /* Initialise random number generator -kre */ srandom(current_ts); srandom((unsigned int)random()); /* Write our pid to a file */ if ((pidfile = fopen(PidFile, "w")) == NULL) putlog(LOG1, "Unable to open %s", PidFile); else { char line[MAXLINE + 1]; ircsprintf(line, "%d\n", getpid()); fputs(line, pidfile); fclose(pidfile); } /* initialize tcm/user listening ports */ InitListenPorts(); /* initialize hash tables */ ClearHashes(1); #ifdef BLOCK_ALLOCATION InitHeaps(); #endif HubSock = NOSOCKET; CycleServers(); while (1) { /* enter loop waiting for server info */ ReadSocketInfo(); if (Me.hub) SendUmode(OPERUMODE_Y, "*** Disconnected from %s", Me.hub->name); else SendUmode(OPERUMODE_Y, "*** Disconnected from hub server"); if (currenthub) { if (currenthub->realname) { MyFree(currenthub->realname); currenthub->realname = NULL; } currenthub->connect_ts = 0; } close(HubSock); /* There was an error */ HubSock = NOSOCKET; /* * whenever Hybserv connects/reconnects to a server, clear * users, servers, and chans */ ClearUsers(); ClearChans(); ClearServs(); /* * ClearHashes() must be called AFTER ClearUsers(), * or StatServ's unique client counts will be off since * cloneTable[] would be NULL while it was trying to find * clones */ ClearHashes(0); PostCleanup(); } /* while (1) */ return 0; } /* main() */