⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socdemon.c

📁 一个可以执行Client端传来的Shell命令的服务器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
 *   - Most of the socket setup stuff is taken from Stevens *     (the socket(), bind(), listen() and accept() stuff), *     the rest is mine.*/main(argc, argv) int   argc;char *argv[];{ int     client_address_len; t_parms parms; int i;   silent_mode = false;   debug_mode  = false;   port_to_use = SOCDEMON_PORT;   /* get the name of the executable for use in the print_usage() */   /* call so that the "usage: XXX [options]" will be correct     */   strcpy(program_name,argv[0]);#ifdef LOG_TO_DEATH   log_to_file = false;   command_log = false;   strcpy(log_file,program_name);   strcat(log_file,".log");   strcpy(cmd_log_file,program_name);   strcat(cmd_log_file,".log");#endif   if (argc > 1) {      /* Collect and process the program arguments */      for (i=1;i<argc;i++) {         if ((!strcmp(argv[i],parm_table[parm_help1]))           || (!strcmp(argv[i],parm_table[parm_help2]))) {            print_usage();            exit(0);         } else if ((!strcmp(argv[i],parm_table[parm_silent1]))                  || (!strcmp(argv[i],parm_table[parm_silent2]))) {            silent_mode = true;         } else if ((!strcmp(argv[i],parm_table[parm_debug1]))                 || (!strcmp(argv[i],parm_table[parm_debug2]))) {            debug_mode = true;         } else if ((!strcmp(argv[i],parm_table[parm_port1]))                 || (!strcmp(argv[i],parm_table[parm_port2]))) {            i++;            if (i == argc) {               fprintf(stderr,"ERROR(%d): You must specify a port number.\n",                       BAD_PARAMETERS);               exit(BAD_PARAMETERS);            }             if (sscanf(argv[i],"%d",&port_to_use) <= 0) {               soc_fprintf(stderr,out_table[bad_port_use_def]);               port_to_use = SOCDEMON_PORT;               /* they prob. forgot to put the port number in and */               /* tried to read the next parm, back up the index  */               /* and we'll take a peep at what was there..       */               i--;            }#ifdef LOG_TO_DEATH         } else if ((!strcmp(argv[i],parm_table[parm_log1]))                  || (!strcmp(argv[i],parm_table[parm_log2]))) {            log_to_file = true;            i++;            if (i == argc) {               soc_fprintf(stderr, out_table[no_log_use_def]);            } else {               if (argv[i][0] == '-') {                  soc_fprintf(stderr, out_table[no_log_use_def]);                  i--;               } else {                  strcpy(log_file,argv[i]);               }            }         } else if ((!strcmp(argv[i],parm_table[parm_cmds1]))                 || (!strcmp(argv[i],parm_table[parm_cmds2]))) {            command_log = true;            i++;            if (i == argc) {               soc_fprintf(stderr, out_table[no_cmd_log_use_def]);            } else {               if (argv[i][0] == '-') {                  soc_fprintf(stderr, out_table[no_cmd_log_use_def]);                  i--;               } else {                  strcpy(cmd_log_file,argv[i]);               }            }#endif         } else {            fprintf(stderr,"ERROR(%d): Unknown switch \"%s\".\n",                    BAD_PARAMETERS, argv[i]);            print_usage();            exit(BAD_PARAMETERS);         }      }   }   soc_fprintf(stdout,"%s ver %s.\n",SOCDEMON_NAME,SOCDEMON_VER);   soc_fprintf(stdout,"%s: Initializing.\n",SOCDEMON_NAME);   if (getuid() != geteuid()) {      /* Our user id is *not* equal to our effective user id */      /* This means that we are a setuid program.. so, let's */      /* Enjoy all the priviledges that we can, call setuid  */      /* to set our user id to our effective userid          */      soc_fprintf(stdout,"%s: Running setuid.\n",SOCDEMON_NAME);      setuid(geteuid());   }   if (getgid() != getegid()) {      soc_fprintf(stdout,"%s: Running setgid.\n",SOCDEMON_NAME);      setgid(getegid());   }   soc_fprintf(stdout,"%s: Creating internet socket...",SOCDEMON_NAME);   /* create a socket */   socket_address_family = AF_INET;   socket_type           = SOCK_STREAM;   socket_protocol       = IPPROTO_TCP;      socket_descriptor = socket(socket_address_family,                               socket_type,                               socket_protocol);   if (socket_descriptor == -1) {      soc_fprintf(stdout,"\n");      soc_fprintf(stderr,"ERROR(%d): Unable to create socket [%d].\n",                  CANT_MAKE_SOCKET, errno);      exit(CANT_MAKE_SOCKET);   }   soc_fprintf(stdout,"done.\n");   soc_fprintf(stdout,"%s: Binding socket to port %d ...",               SOCDEMON_NAME, port_to_use);   /* now bind it to the port, if the program was just run   */   /* this call will fail, because it takes about 45 seconds */   /* after a process exits for the port to be unbound       */   bzero((char *) &server_address, sizeof(server_address));   server_address.sin_family      = AF_INET;   server_address.sin_addr.s_addr = htonl(INADDR_ANY);   server_address.sin_port        = htons(port_to_use);   socket_rc = bind(socket_descriptor,                    (struct sockaddr *) &server_address,                    sizeof(server_address));   if (socket_rc != 0) {      soc_fprintf(stdout,"\n");      soc_fprintf(stderr,"ERROR(%d): Cannot bind internet socket to specified address and port. [%d]\n",                  CANT_BIND_SOCKET, errno);      if (errno == EADDRINUSE) {         soc_fprintf(stderr,"            This address is inuse. Waiting 15 seconds then re-trying.\n");         /* The following status message is to stderr instead of to stdout  */         /* because stdout doesn't flush (at least on HP-UX) until a C/R    */         /* but stderr flushes right away, so that way we can have the dots */         /* print one at a time instead of all at once                      */         soc_fprintf(stderr,"%s: Waiting",SOCDEMON_NAME);         for (i=1;i<=15;i++) {            sleep(1);            soc_fprintf(stderr,".");         }         soc_fprintf(stderr,"done.\n");         soc_fprintf(stdout,"%s: Retrying..",SOCDEMON_NAME);         socket_rc = bind(socket_descriptor,                          (struct sockaddr *) &server_address,                          sizeof(server_address));         if (socket_rc != 0) {            soc_fprintf(stdout, " failed.\n");            soc_fprintf(stderr, "ERROR(%d): This port is inuse, either wait a few moments, or use\n",                        CANT_BIND_SOCKET);            soc_fprintf(stderr, "            a different port.\n");            socket_demon_shutdown();            exit(CANT_BIND_SOCKET);         }       } else {         socket_demon_shutdown();         exit(CANT_BIND_SOCKET);      }   }   soc_fprintf(stdout,"done.\n");   /* now my favorite part, convert to a daemon.. */   if (fork() != 0) {      /* we let the parent die off.. this means that our real parent   */      /* will not be the shell, as was this thread right here, but     */      /* because this thread is exiting, I believe that the new parent */      /* becomes the process group leader, which may be the shell, but */      /* I think it's the login instead.. whoever to process group     */      /* is...                                                         */      if (silent_mode == false) {         /* now, we hold for a sec, so that the user doesn't get their */         /* shell back until we've completely started up.. this is so  */         /* the program doesn't print out it's init messages to the    */         /* tty when the user has recieved thier prompt again.. if     */         /* we're in silent mode, however, we don't need to pause      */         /* because there is no output                                 */         sleep(SOCDEMON_PAUSE);      }      exit(0);   }   /* now we dis-associate from our process group leader by creating   */   /* our own process group.                                           */   setpgrp();   /* now we ignore hang up signals, so we are effectively nohup-ing   */   /* the process now                                                  */   signal(SIGHUP,SIG_IGN);    /* fork once again to get rid of our parent (the new process group  */   /* leader) and now our parent is init(1) so we are now a daemon     */   /* (rejoice)                                                        */   if (fork() != 0) {      exit(0);   }   soc_fprintf(stdout,"%s: Binding signal handlers to shutdown routines...",                SOCDEMON_NAME);   /* now bind our shutdown routines to catch the TERMINATE and KILL   */   /* I don't think that the KILL signals are caught however, but i'm  */   /* not entirely sure.. all I know is that when i kill -9 the daemon */   /* I don't get the shutdown messages, but that doesn't necessarily  */   /* mean it's not catching it.. so don't kill with the -9 option and */   /* all will be well..                                               */   signal(SIGTERM,socket_demon_death_action);   signal(SIGKILL,socket_demon_death_action);   soc_fprintf(stdout,"done.\n");   /* hokey dokey, now listen to the internet socket... */   socket_rc = listen(socket_descriptor,SOCDEMON_MAX_BACKLOG);   if (socket_rc != 0) {      soc_fprintf(stderr,"ERROR(%d): Listen failed on internet socket [%d].\n",                  LISTEN_FAILED, errno);      socket_demon_shutdown();      exit(LISTEN_FAILED);   }     for (;;) {      client_address_len = sizeof(client_address);      /* now we sit and wait for someone to connect to us...           */      /* this will not take up any CPU at all, because the process is  */      /* blocked waiting for a connect... what I might do if there's   */      /* some need, is to send the process wake up signals every now   */      /* and then to change it's process ID, or hide or something, but */      /* until all other little bugs are resolved, that will have to   */      /* wait                                                          */      client_descriptor = accept(socket_descriptor,                                  (struct sockaddr *) &client_address,                                 &client_address_len);      if (client_descriptor < 0) {         soc_fprintf(stderr,"ERROR(%d): accept() call failed on internet socket [%d]\n",                     ACCEPT_FAILED, errno);         exit(ACCEPT_FAILED);      }#ifdef LOG_TO_DEATH      /* ok, now to convert the address to a dotted quad, I guess i */      /* could just cast it on top of the dotted_quad structure, I  */      /* dunno if that'd work, so to be safe and portable, let's    */      /* do it manually... oh, and note the bit shifts, yeah, it's  */      /* messy, but I couldn't think of anything more elegant at the*/      /* time.. same with the leading zeros in the bitwise 'and's   */      client_dotted_q.class    = (client_address.sin_addr.s_addr >> 24);      client_dotted_q.netid    = (client_address.sin_addr.s_addr >> 16) & 0x00ff;      client_dotted_q.subnetid = (client_address.sin_addr.s_addr >> 8) & 0x0000ff;      client_dotted_q.hostid   = client_address.sin_addr.s_addr & 0x000000ff;      sprintf(dotted_4_str, "%d.%d.%d.%d",              client_dotted_q.class, client_dotted_q.netid,              client_dotted_q.subnetid, client_dotted_q.hostid);#endif      if (fork() != 0) {         /* let the parent process handle the user comming in, and       */         /* make the shild go on to wait for more requests - this        */         /* will avoid defunct processes and have an added bonus side-   */         /* effect of having the main daemon have it's process ID change */         /* periodically.                                                */#ifdef LOG_TO_DEATH         log_stuff(accepting_connection);#endif              /* direct stdin, stdout and stderr to the socket */         dup2(client_descriptor,0);         dup2(client_descriptor,1);         dup2(client_descriptor,2);         if (soc_demon_welcome()) {            soc_demon_main_proc();         }          shutdown(client_descriptor, 2);         close(client_descriptor);#ifdef LOG_TO_DEATH         log_stuff(connection_closed);#endif         exit(0);      }      close(client_descriptor);   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -