/** * Main entry point */ int main(int argc, char **argv) { TRACE_FUNC_START(); int rc; /* accept command-line arguments */ while ( (rc = getopt(argc, argv, "a:b:hsdf:")) != -1) { switch(rc) { case 'a': pc_info.rshell_args = (int8_t *)strdup(optarg); if (NULL == pc_info.rshell_args) { TRACE_ERR("Can't strdup remote shell args!!\n"); } break; case 'b': pc_info.batch_size = atoi(optarg); TRACE_DEBUG_LOG("Taking batch_size as %d\n", pc_info.batch_size); break; case 'd': pc_info.daemonize = 1; break; case 'h': print_help(*argv); break; case 'f': pc_info.lua_startup_file = (uint8_t *)strdup(optarg); if (NULL == pc_info.lua_startup_file) { TRACE_ERR("Can't strdup string for lua_startup_file: %s\n", strerror(errno)); } TRACE_DEBUG_LOG("Taking file %s as startup\n", pc_info.lua_startup_file); load_lua_file(optarg); break; case 's': pc_info.rshell = 1; break; default: print_help(*argv); break; } } /* init_modules */ init_modules(); /* check if rshell and daemonize are both enabled */ if (pc_info.daemonize && pc_info.rshell) { fprintf(stdout, "You cannot create a daemon process and " "a remote shell at the same time!\n"); fflush(stdout); print_help(*argv); return EXIT_FAILURE; } /* warp to remote shell, if asked */ if (pc_info.rshell) { if (pc_info.rshell_args == NULL) fprintf(stdout, "Using localhost and port %d by default\n", BRICKS_LISTEN_PORT); lua_kickoff(LUA_EXE_REMOTE_SHELL, pc_info.rshell_args); return EXIT_SUCCESS; } /* daemonize, if asked */ if ((pc_info.daemonize && (rc=do_daemonize()) == 0) || !pc_info.daemonize) { if (mark_pid_file(pv.pid_file) != 0) { TRACE_FUNC_END(); TRACE_ERR("Can't lock the pid file.\n" "Is a previous bricks daemon already running??\n"); } export_global_socket(); lua_kickoff((pc_info.daemonize) ? LUA_EXE_SCRIPT : LUA_EXE_HOME_SHELL, NULL); } /* initialize file printing mini-module */ print_status_file(); /* * if the user wants to daemonize and the process * is the child, then jump to accepting requests... */ if (pc_info.daemonize && rc == 0) { start_listening_reqs(); } TRACE_FUNC_END(); clean_exit(EXIT_SUCCESS); /* control will never come here */ return EXIT_SUCCESS; }
/*---------------------------------------------------------------------*/ void start_listening_reqs() { TRACE_BACKEND_FUNC_START(); /* socket info about the listen sock */ struct sockaddr_in serv; int listen_fd, client_sock; struct kevent evlist; struct kevent chlist[KQUEUE_MAX_EVENTS]; int kq, events, n; /* zero the struct before filling the fields */ memset(&serv, 0, sizeof(serv)); /* set the type of connection to TCP/IP */ serv.sin_family = AF_INET; /* set the address to any interface */ serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set the server port number */ serv.sin_port = htons(BRICKS_LISTEN_PORT); /* create bricks socket for listening remote shell requests */ listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd == -1) { TRACE_ERR("Failed to create listening socket for bricks\n"); TRACE_BACKEND_FUNC_END(); } /* bind serv information to mysocket */ if (bind(listen_fd, (struct sockaddr *)&serv, sizeof(struct sockaddr)) == -1) { TRACE_ERR("Failed to bind listening socket to port %d for bricks\n", BRICKS_LISTEN_PORT); TRACE_BACKEND_FUNC_END(); } /* start listening, allowing a queue of up to 1 pending connection */ if (listen(listen_fd, LISTEN_BACKLOG) == -1) { TRACE_ERR("Failed to start listen on port %d (for bricks)\n", BRICKS_LISTEN_PORT); TRACE_BACKEND_FUNC_END(); } /* XXX - TODO: port this to kqueue version... */ /* set up the kqueue structure */ kq = kqueue(); EV_SET(&chlist[listen_fd], listen_fd, EVFILT_READ, EV_ADD, 0, 0, NULL); /* * Main loop that processes incoming remote shell commands * if the remote request arrives at listen_fd, it accepts connections * and creates a new 'shell' * if the remote request comes from a client request, it calls * the lua string command function to execute the command */ do { events = kevent(kq, chlist, 1, &evlist, 1, NULL); if (events == -1) { TRACE_ERR("kqueue error\n"); TRACE_BACKEND_FUNC_END(); } for (n = 0; n < events; n++) { /* the request is for a new shell */ if ((int)chlist[n].ident == listen_fd) { client_sock = accept(listen_fd, NULL, NULL); if (client_sock < 0) { TRACE_ERR("accept failed: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); } lua_kickoff(LUA_EXE_STR, &client_sock); /* add client_sock and listen_fd for kqueueing again */ EV_SET(&chlist[listen_fd], listen_fd, EVFILT_READ, EV_ADD, 0, 0, NULL); EV_SET(&chlist[client_sock], client_sock, EVFILT_READ, EV_ADD, 0, 0, NULL); } #if 0 else { /* chlist[n].ident == regular sock */ /* * if the client socket has incoming read, this means we are getting * some lua commands.... execute them */ if (events[n].events == EPOLLIN || events[n].events == EPOLLPRI) { lua_kickoff(LUA_EXE_STR, &events[n].data.fd); ev.data.fd = events[n].data.fd; ev.events = EPOLLIN; if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) { TRACE_ERR("Can't register client sock for epolling!\n"); TRACE_BACKEND_FUNC_END(); } } else { /* the only other epoll request is for error output.. close the socket then */ ev.data.fd = events[n].data.fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ev.data.fd, &ev) == -1) { TRACE_ERR("Can't register client sock for epolling!\n"); TRACE_BACKEND_FUNC_END(); } close(ev.data.fd); } } #endif } } while (1); TRACE_BACKEND_FUNC_END(); }
/*---------------------------------------------------------------------*/ void start_listening_reqs() { TRACE_BACKEND_FUNC_START(); /* socket info about the listen sock */ struct sockaddr_in serv; int listen_fd, client_sock; struct epoll_event ev, events[EPOLL_MAX_EVENTS]; int epoll_fd, nfds, n; /* zero the struct before filling the fields */ memset(&serv, 0, sizeof(serv)); /* set the type of connection to TCP/IP */ serv.sin_family = AF_INET; /* set the address to any interface */ serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set the server port number */ serv.sin_port = htons(BRICKS_LISTEN_PORT); /* create bricks socket for listening remote shell requests */ listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd == -1) { TRACE_ERR("Failed to create listening socket for bricks\n"); TRACE_BACKEND_FUNC_END(); } /* bind serv information to mysocket */ if (bind(listen_fd, (struct sockaddr *)&serv, sizeof(struct sockaddr)) == -1) { TRACE_ERR("Failed to bind listening socket to port %d for bricks\n", BRICKS_LISTEN_PORT); TRACE_BACKEND_FUNC_END(); } /* start listening, allowing a queue of up to 1 pending connection */ if (listen(listen_fd, LISTEN_BACKLOG) == -1) { TRACE_ERR("Failed to start listen on port %d (for bricks)\n", BRICKS_LISTEN_PORT); TRACE_BACKEND_FUNC_END(); } /* set up the epolling structure */ epoll_fd = epoll_create(EPOLL_MAX_EVENTS); if (epoll_fd == -1) { TRACE_ERR("BRICKS failed to create an epoll fd!\n"); TRACE_BACKEND_FUNC_END(); return; } /* register listening socket */ ev.events = EPOLLIN | EPOLLOUT; ev.data.fd = listen_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) { TRACE_LOG("BRICKS failed to exe epoll_ctl for fd: %d\n", epoll_fd); TRACE_BACKEND_FUNC_END(); return; } /* * Main loop that processes incoming remote shell commands * if the remote request arrives at listen_fd, it accepts connections * and creates a new 'shell' * if the remote request comes from a client request, it calls * the lua string command function to execute the command */ do { /* wait for new epoll requests */ nfds = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, -1); if (nfds == -1) { if (errno == EINTR) continue; TRACE_ERR("BRICKS poll error: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); } /* got some request... now process each one of them */ for (n = 0; n < nfds; n++) { /* the request is for a new shell */ if (events[n].data.fd == listen_fd) { client_sock = accept(listen_fd, NULL, NULL); if (client_sock < 0) { TRACE_ERR("accept failed: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); } lua_kickoff(LUA_EXE_STR, &client_sock); /* add client_sock and listen_fd for epolling again */ ev.data.fd = client_sock; ev.events = EPOLLIN; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) { TRACE_ERR("Can't register client sock for epolling!\n"); TRACE_BACKEND_FUNC_END(); } ev.data.fd = listen_fd; ev.events = EPOLLIN | EPOLLOUT; if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) { TRACE_ERR("Can't register client sock for epolling!\n"); TRACE_BACKEND_FUNC_END(); } } else { /* events[n].data.fd == regular sock */ /* * if the client socket has incoming read, this means we are getting * some lua commands.... execute them */ if (events[n].events == EPOLLIN || events[n].events == EPOLLPRI) { lua_kickoff(LUA_EXE_STR, &events[n].data.fd); ev.data.fd = events[n].data.fd; ev.events = EPOLLIN; if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) { TRACE_ERR("Can't register client sock for epolling!\n"); TRACE_BACKEND_FUNC_END(); } } else { /* the only other epoll request is for error output.. close the socket then */ ev.data.fd = events[n].data.fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ev.data.fd, &ev) == -1) { TRACE_ERR("Can't register client sock for epolling!\n"); TRACE_BACKEND_FUNC_END(); } close(ev.data.fd); } } } } while (1); TRACE_BACKEND_FUNC_END(); }