FILE * DBTable::file(DB::Access access) { if(!f_file){ if(strcmp(f_name, DATABASE_STDIO) == 0){ f_file = access == DB::CREATE ? stdout : stdin; }else{ const char *p = f_database->path(); char *path = new char[strlen(p) + 1 + strlen(f_name) + 1]; sprintf(path, "%s/%s", p, f_name); f_file = fopen(path, access == DB::CREATE ? "w" : "r"); if(!f_file){ throw(PosixError(errno, path)); } delete path; } } return f_file; }
void DBCursor::short_list(FILE *fp, int *qout, int ltype, void *out) { int c; int ret; c = fgetc(fp); FRIENDLY_ASSERT(c == '#'); c = fgetc(fp); FRIENDLY_ASSERT(c == '\n'); switch(ltype){ case STRING_CODE: { typedef const char** ccpp; ccpp *cpout = (ccpp*)out; assert(f_list == NULL); /* only one SHORT_LIST per record supported */ f_list = new StringList; while((c = fgetc(fp)) != '#'){ char *item; int ftype; ungetc(c, fp); ret = fscanf(fp, "%d\n", &ftype); if(ret == 0) throw(PosixError(errno, "Unable to fscanf\n")); FRIENDLY_ASSERT(ftype == STRING_CODE); string_field(fp, &item, NULL); f_list->append(item); } *cpout = f_list->array(); *qout = f_list->qty(); } break; default: abort(); /* only strings supported */ } c = fgetc(fp); FRIENDLY_ASSERT(c == '\n'); }
static void makedir(const char *path) /* throw(PosixError) */ { if(mkdir((char*)path, DATABASE_DIRECTORY_MODE) != 0){ throw(PosixError(errno, path)); } }
int main(int argc, char *argv[]) { struct servent *se; struct sockaddr_in taddr, laddr; struct sockaddr_in saddr, daddr; int trap_s, serv_s, rc, i; socklen_t dlen, llen; fd_set fds; static int cl_addr[FD_SETSIZE]; char buf[8192]; int go_on; int mcast_s = -1; char *name; unsigned short port; const int on = 1; /* * Check the number of arguments. We accept an optional argument * which specifies the port number we are listening on. */ if (argc > 2) { fprintf(stderr, "usage: nmtrapd [port]\n"); exit(1); } if (argc == 2) { name = argv[1]; port = atoi(argv[1]); } else { name = SNMP_TRAP_NAME; port = SNMP_TRAP_PORT; } /* * Get the port that we are going to listen to. Check that * we do not try to open a priviledged port number, with * the exception of the SNMP trap port. */ if ((se = getservbyname(name, "udp"))) { port = ntohs(se->s_port); } if (port != SNMP_TRAP_PORT && port < 1024) { fprintf(stderr, "nmtrapd: access to port %d denied\n", port); exit(1); } /* * Fork a new process so that the calling process returns * immediately. This makes sure that Tcl is not waiting for * this process to terminate when it exits. */ switch (fork()) { case -1: PosixError("unable to fork daemon (ignored)"); break; case 0: break; default: exit(0); } /* * Close any "leftover" FDs from the parent. There is a relatively * high probability that the parent will be scotty, and that the * client side of the scotty-nmtrapd connection is among the open * FDs. This is bad news if the parent scotty goes away, since * this will eventually cause nmtrapd to "block against itself" in * the "forward data to client" write() calls below, since nmtrapd * itself is not consuming data from the client side of the * leftover open socket. */ for (i = 0; i < FD_SETSIZE; i++) { (void) close(i); } setsid(); /* * Open the connection to the system logger. Beware: some old BSD * systems have an old syslog interface. */ #ifdef ultrix openlog("nmtrapd", LOG_PID); #else openlog("nmtrapd", LOG_PID, LOG_USER); #endif /* * Open and bind the normal trap socket: */ if ((trap_s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { PosixError("unable to open trap socket"); exit(1); } taddr.sin_family = AF_INET; taddr.sin_port = htons(port); taddr.sin_addr.s_addr = INADDR_ANY; #ifdef SO_REUSEADDR setsockopt(trap_s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); #endif if (bind(trap_s, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) { PosixError("unable to bind trap socket"); exit(1); } #ifdef HAVE_MULTICAST if ((mcast_s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { PosixError("unable to open multicast trap socket"); } if (mcast_s > 0) { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(SNMP_TRAP_MCIP); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(mcast_s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mreq, sizeof(mreq)) == -1) { PosixError("unable to join multicast group"); close(mcast_s); mcast_s = -1; } } #ifdef SO_REUSEADDR if (mcast_s > 0) { setsockopt(mcast_s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); } #endif if (mcast_s > 0) { struct sockaddr_in maddr; maddr.sin_family = AF_INET; maddr.sin_port = htons(port); maddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(mcast_s, (struct sockaddr*) &maddr, sizeof(maddr)) == -1) { PosixError("unable to bind multicast trap socket"); close(mcast_s); mcast_s = -1; } } #endif /* * Switch back to normal user rights: */ setuid(getuid ()); if ((serv_s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { PosixError("unable to open server socket"); exit(1); } memset((char *) &saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(SNMP_FRWD_PORT); saddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(serv_s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { PosixError("unable to bind server socket"); exit(1); } if (listen(serv_s, 5) < 0) { PosixError("unable to listen on server socket"); exit(1); } #ifdef SIGPIPE signal(SIGPIPE, IgnorePipe); #endif /* * If there is a steady stream of traps bound for this host, we * need to allow some time for the client (scotty) to connect to * us. Otherwise, nmtrapd will just exit when the first trap * message arrives. The client does 5 retries with 1 second * in-between, so sleeping for 3 should be enough to let the * client connect. There really ought to be a better way to do * this. */ sleep(3); /* * Fine everything is ready; lets listen for events: * the for(;;) loop aborts, if the last client went away. */ for (go_on = 1; go_on; ) { FD_ZERO(&fds); FD_SET(trap_s, &fds); FD_SET(serv_s, &fds); if (mcast_s > 0) { FD_SET(mcast_s, &fds); } /* fd's connected from clients. listen for EOF's: */ for (i = 0; i < FD_SETSIZE; i++) { if (cl_addr[i] > 0) { FD_SET(i, &fds); } } rc = select(FD_SETSIZE, &fds, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if (rc < 0) { if (errno == EINTR || errno == EAGAIN) continue; PosixError("select failed"); } if (FD_ISSET(serv_s, &fds)) { memset((char *) &daddr, 0, sizeof(daddr)); dlen = sizeof(daddr); rc = accept(serv_s, (struct sockaddr *) &daddr, &dlen); if (rc < 0) { PosixError("accept failed"); continue; } /* * Check for a potential buffer overflow if the accept() * call returns a file descriptor larger than FD_SETSIZE. */ if (rc >= FD_SETSIZE) { InternalError("too many clients"); close(rc); continue; } cl_addr[rc] = 1; } else if (FD_ISSET(trap_s, &fds)) { llen = sizeof(laddr); if ((rc = recvfrom(trap_s, buf, sizeof(buf), 0, (struct sockaddr *) &laddr, &llen)) < 0) { PosixError("unable to receive trap"); continue; } for (i = 0; i < FD_SETSIZE; i++) { if (cl_addr[i] > 0) { if (! ForwardTrap(i, &laddr, buf, rc)) { cl_addr[i] = 0; close(i); } } } /* should we go on ? */ for (go_on = 0, i = 0; i < FD_SETSIZE; i++) { go_on += cl_addr[i] > 0; } } else if (mcast_s > 0 && FD_ISSET(mcast_s, &fds)) { llen = sizeof(laddr); if ((rc = recvfrom(mcast_s, buf, sizeof(buf), 0, (struct sockaddr *) &laddr, &llen)) < 0) { PosixError("unable to receive trap"); continue; } for (i = 0; i < FD_SETSIZE; i++) { if (cl_addr[i] > 0) { if (! ForwardTrap(i, &laddr, buf, rc)) { cl_addr[i] = 0; close(i); } } } /* should we go on ? */ for (go_on = 0, i = 0; i < FD_SETSIZE; i++) { go_on += cl_addr[i] > 0; } } else { /* fd's connected from clients. (XXX: should check for EOF): */ for (i = 0; i < FD_SETSIZE; i++) { if (cl_addr[i] > 0 && FD_ISSET(i, &fds)) { cl_addr[i] = 0; close(i); } } /* should we go on ? */ for (go_on = 0, i = 0; i < FD_SETSIZE; i++) { go_on += cl_addr[i] > 0; } } } /* end for (;;) */ closelog(); return 0; }