server.c
上传用户:mei_mei897
上传日期:2007-01-05
资源大小:82k
文件大小:8k
- /* -------------------------------------------------------------------- */
- /* SMS Client, send messages to mobile phones and pagers */
- /* */
- /* server.c */
- /* */
- /* Copyright (C) 1997,1998 Angelo Masci */
- /* */
- /* This library is free software; you can redistribute it and/or */
- /* modify it under the terms of the GNU Library General Public */
- /* License as published by the Free Software Foundation; either */
- /* version 2 of the License, or (at your option) any later version. */
- /* */
- /* This library is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
- /* Library General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU Library General Public */
- /* License along with this library; if not, write to the Free */
- /* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* */
- /* You can contact the author at this e-mail address: */
- /* */
- /* angelo@styx.demon.co.uk */
- /* */
- /* --------------------------------------------------------------------
- $Id$
- -------------------------------------------------------------------- */
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdarg.h>
- #include <pwd.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <netdb.h>
- #include "server.h"
- #include "logfile.h"
- #include "common.h"
- /* -------------------------------------------------------------------- */
- #if !defined(WNOHANG)
- #define WNOHANG 0
- #endif
- /* -------------------------------------------------------------------- */
- /* Read a complete 'n' terminated string from socket */
- /* upto maxlen characters will be read and a ' ' is appended */
- /* -------------------------------------------------------------------- */
- char *hgets(char *buf, int maxlen, int fd)
- {
- int result,
- i;
- /* NOTE - */
- /* As this function now uses recv instead of read */
- /* it probably makes sense to use the MSG_PEEK functionality */
- /* to read a block of data find the newline and then */
- /* make another call to receive with the correct length */
- /* of the line. */
- i = 0;
- buf[0] = ' ';
- while (i < (maxlen -1))
- {
- result = read(fd, &buf[i], 1);
- if (result < 0)
- { if (errno != EINTR)
- { lprintf(LOG_ERROR, "read() failed");
- exit(-1);
- }
- }
- else
- if (result == 0)
- {
- buf[i+1] = ' ';
- if (i == 0)
- { return NULL;
- }
- break;
- }
- else
- { if (buf[i] == 'n')
- { i++;
- break;
- }
- i++;
- }
- }
-
- buf[i] = ' ';
- return buf;
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- void hprintf(int fd, char *fmt, ...)
- {
- va_list args;
- int line_len,
- len;
- static char line[MAX_STRING_LEN];
- char *line_ptr;
- /* ---------------------------- */
- va_start(args, fmt);
- vsprintf(line, fmt, args);
- va_end(args);
- line_len = sms_strlen(line);
- line_ptr = line;
- while ((len = write(fd, line_ptr, line_len)) != line_len)
- {
- if (len < 0)
- { if (errno == EINTR)
- { continue;
- }
- else
- { lprintf(LOG_ERROR, "write() failed");
- exit(-1);
- }
- }
- line_ptr += len;
- line_len -= len;
- }
- }
- /* -------------------------------------------------------------------- */
- /* Reap child processes on receipt of SIGCHLD */
- /* -------------------------------------------------------------------- */
- #if defined(LINUX) || defined(SOLARIS)
- void sigchld_handler(int signum)
- {
- while (waitpid((pid_t)-1, NULL, WNOHANG) > 0)
- {
- /* Reap children */
- }
- signal(SIGCHLD, sigchld_handler); /* Re-establish signal */
- /* handler */
- }
- #endif
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- int server_init(int server_port)
- {
- int sockfd; /* listen on sock_fd */
- struct sockaddr_in
- server_addr; /* my address information */
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- { lprintf(LOG_ERROR, "socket() failedn");
- return(-1);
- }
- server_addr.sin_family = AF_INET; /* host byte order */
- server_addr.sin_port = htons(server_port); /* short, network byte order */
- server_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
- memset(&(server_addr.sin_zero), 0, 8); /* zero rest of struct */
- if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
- {
- switch (errno)
- {
- case EADDRINUSE:
- lprintf(LOG_ERROR, "bind() - Socket %d allready in usen", server_port);
- break;
- case EACCES:
- lprintf(LOG_ERROR, "bind() - Socket %d protected port and not superusern", server_port);
- break;
- default:
- lprintf(LOG_ERROR, "bind() failedn");
- }
- return(-1);
- }
- if (listen(sockfd, MAX_BACKLOG) < 0)
- { lprintf(LOG_ERROR, "listen() failedn");
- return(-1);
- }
- lprintf(LOG_STANDARD, "Listening on port %dn", server_port);
- return sockfd;
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- int server_main(int server_port, void (*handle_child)(int new_fd))
- {
- pid_t pid;
- int sockfd,
- sin_size,
- new_fd;
- struct sockaddr_in
- client_addr; /* connector's address information */
- sockfd = server_init(server_port);
- if (sockfd == -1)
- { return(1);
- }
- if (deamon_init() != 0)
- { return(1);
- }
- #if defined(LINUX) || defined(SOLARIS)
- signal(SIGCHLD, sigchld_handler);
- #else
- signal(SIGCHLD, SIG_IGN); /* Automagically reap zombies */
- /* under SYSV */
- #endif
- set_consolelog(FALSE); /* No more login output */
- /* to be sent to the console */
- while(TRUE)
- {
- /* main accept() loop */
- sin_size = sizeof(struct sockaddr_in);
- if ((new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size)) < 0)
- {
- if (errno == EINTR)
- { continue;
- }
- else
- { lprintf(LOG_ERROR, "accept failedn");
- exit(-1);
- }
- }
- pid = fork();
- if (pid == 0)
- {
- (*handle_child)(new_fd);
- close(new_fd);
- exit(0);
- }
- else if (pid < 0)
- { lprintf(LOG_ERROR, "Trying to fork child processn");
- exit(-1);
- }
- close(new_fd);
- }
- return 0;
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- void default_echo(int new_fd)
- {
- char buf[MAX_STRING_LEN];
- while (hgets(buf, MAX_STRING_LEN, new_fd) != NULL)
- { printf("Received Data +%s+n", buf);
- hprintf(new_fd, "Echo: +%s+n", buf);
- }
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- int deamon_init(void)
- {
- pid_t pid;
-
- pid = fork();
- if (pid < 0)
- { return -1;
- }
- else
- if (pid != 0)
- { exit(0); /* Parent Exits */
- }
- if (setsid() < 0) /* Become session leader */
- {
- lprintf(LOG_ERROR, "setsid failedn");
- exit(-1);
- }
- if (chdir("/") < 0) /* Change working directory */
- {
- lprintf(LOG_ERROR, "chdir failedn");
- exit(-1);
- }
- return 0;
- }
- /* -------------------------------------------------------------------- */
- /* -------------------------------------------------------------------- */
- int get_client_information(int fd, char *host_name, char *ip_address)
- {
- int sin_size;
- struct sockaddr_in
- client_addr; /* connector's address information */
- struct hostent
- *host;
- u_long addr;
-
- sin_size = sizeof(struct sockaddr_in);
- if ((getpeername(fd, (struct sockaddr *)&client_addr, &sin_size)) < 0)
- { return -1;
- }
- sms_strcpy(ip_address, inet_ntoa(client_addr.sin_addr));
- addr = inet_addr(ip_address);
- host = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
- if (host != NULL)
- { sms_strcpy(host_name, host->h_name);
- }
- else
- { sms_strcpy(host_name, "");
- }
- return 0;
- }