/* (C) Spiros Ioannou 1999 */ #include #include #include #include #include #include #include #include #include #include #include #include int serve_client(int); int serve_client(int Asd) { fd_set inout_fds; char buff[1024]; char outbuff[1024]; int r,i,s; FILE *pfp; for (;;) { FD_ZERO(&inout_fds); FD_SET(Asd, &inout_fds); i=0; do { s = select(64, &inout_fds, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); } while (s == EINTR && i++<10); buff[0] = 0; outbuff[0] = 0; if (FD_ISSET(Asd, &inout_fds)) { r = read(Asd, buff, 1024); buff[r] = 0; /* chop */ if (r > 2 && buff[r - 1] == '\n') { buff[r-1] = 0; #ifdef DEBUG printf("serve_client[%d]:read:#%s#\n", getpid(), buff); #endif } if (r <= 0) { shutdown(Asd, 2); close(Asd); #ifdef DEBUG printf("serve_child:socket closed,returning\n"); #endif return 1; } else { /* parse input here */ if (!strcmp(buff, "daemon_stop")) { #ifdef DEBUG printf("\nserve_child:exiting\n"); #endif return (0); } else if (!strcmp(buff, "quit")) { shutdown(Asd, 2); close(Asd); return 2; } else if (!strcmp(buff, "calc_checksums")) { #ifdef DEBUG printf("serve_child:calculating checksums\n"); #endif if ((pfp=popen("md5sum *","r"))!=NULL) { while (fgets(buff,1024,pfp)) if (write(Asd,buff,strlen(buff))<=0) { pclose(pfp); break; } pclose(pfp); //disconnect client shutdown(Asd, 2); close(Asd); } else { perror("statusd:popen"); } } else { sprintf(outbuff, "%s:invalid command\n", buff); write(Asd, outbuff, strlen(outbuff)); } } } else printf("serve_client:select interrupted(?)\n"); } } int main(int argc, char **argv) { int one = 1,r, i; struct sockaddr_in sa; int Asd, len, lsd; fd_set inout_fds; char buff[1024]; int port; if (argc != 2) { fprintf(stderr, "statusd version 0.1\n"); fprintf(stderr, "Usage: statusd \n"); exit(0); } port = atoi(argv[1]); if ((lsd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } setsockopt(lsd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)); sa.sin_family = AF_INET; sa.sin_port = htons((u_short) port); sa.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(lsd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("bind"); exit(2); } if (listen(lsd, 1) < 0) { perror("listen"); exit(3); } len = sizeof(sa); printf("statusd:listening on port %d\n",port); for (;;) { FD_ZERO(&inout_fds); FD_SET(lsd, &inout_fds); do { i = select(64, &inout_fds,(fd_set *)0,(fd_set *)0,(struct timeval *)0); } while (i == EINTR); if (i < 0) { perror("statusd:select"); exit(4); } if (FD_ISSET(lsd, &inout_fds)) { if ((Asd = accept(lsd, (struct sockaddr *) &sa, &len)) < 0) { perror("accept"); exit(5); } printf("\nstatusd:accepted connection from %s [port:%d]\n", inet_ntoa(sa.sin_addr) , ntohs(sa.sin_port)); // show some help strcpy(buff, "\navailable commands\n------------------\n"); strcat(buff, "calc_checksums \t\t\t//calculate them\n"); strcat(buff, "quit \t\t\t\t//close current connection\n"); strcat(buff, "daemon_stop \t\t\t//stop the daemon\n\n"); write(Asd, buff, strlen(buff)); if ((r=serve_client(Asd))==0) { printf("statusd:process %d shuting down by request\n", getpid()); exit(6); } else if (r==1) { Asd=-1; printf("statusd:client disconnected\n"); } else if (r==2) { Asd=-1; printf("statusd:client requested disconnect\n"); } } } return -1; }