miscd.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 436 行
C
436 行
#ifndef lintstatic char *sccsid = "@(#)miscd.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//*----------------------------------------------------------------------- * Modification History * * 6/8/88 -- map * Changed signal handlers to void. * * 4/5/85 -- jrs * Created to serve under inetd to implement some of * the cheap internet services. Based on a concept by * Marshall Rose of UC Irvine and Chris Kent of Purdue. * *----------------------------------------------------------------------- */#include <stdio.h>#include <signal.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <netdb.h>#include <syslog.h>#define TIMEOUT 120#define BUFFERCNT 4096#define LINECNT 80char *daemoname;void timeout();FILE *popen();/* * This program performs some of the small internet utility functions. * It runs subservient to inetd. * * The main routine determines the port and protocol. We look it * up in the /etc/services table and then call the action switcher */main(argc, argv) int argc; char **argv;{ int on = 1, socklen; int tcpsock; struct sockaddr_in sock; struct servent *serv; char servnam[16]; /* This is a real hack to try and find if we are tcp or udp. If a better way can be found this should be replaced */ socklen = sizeof (sock); if (getpeername(0, &sock, &socklen) < 0) { tcpsock = 0; } else { tcpsock = 1; } socklen = sizeof (sock); if (getsockname(0, &sock, &socklen) < 0) { openlog(argv[0], LOG_PID); syslog(LOG_ERR, "getsockname: %m"); closelog(); exit(1); } serv = getservbyport(sock.sin_port, tcpsock? "tcp": "udp"); if (serv == NULL) { openlog(argv[0], LOG_PID); syslog(LOG_ERR, "getservbyport failed"); closelog(); exit(1); } (void) signal(SIGALRM, timeout); if (tcpsock == 0) { (void) alarm(TIMEOUT); } else { if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { openlog(argv[0], LOG_PID); syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); closelog(); } } (void) strcpy(servnam, serv->s_name); daemoname = argv[0]; doit(0, servnam, tcpsock);}/* * This routine acts as the main switcher for all functionality * Note that the code is designed to handle both tcp and udp * sockets. When invoked on tcp sockets, the server will terminate * immediately when the connection is closed. For the udp case, * we will stay alive until two minutes go by without incoming * packets. */doit(f, servnam, tcpsock) int f; char *servnam; int tcpsock;{ int count; char buffer[BUFFERCNT]; char line[LINECNT]; struct sockaddr from; int fromlen; int rotate; struct timeval nowtime; struct timezone nowzone; unsigned long nowbias; /* simple echo of recieved packet */ if (strcmp(servnam, "echo") == 0) { if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } if (sendto(f, buffer, count, 0, &from, fromlen) < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "sendto: %m"); closelog(); exit(1); } } } else { while ((count = read(f, buffer, sizeof(buffer))) > 0) { (void) alarm(TIMEOUT); if (write(f, buffer, count) != count) { break; } (void) alarm(0); } } /* throw away imcoming data (without error) */ } else if (strcmp(servnam, "discard") == 0) { if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } } } else { while ((count = read(f, buffer, sizeof(buffer))) > 0) { ; } } /* return ascii text giving our list of users */ } else if (strcmp(servnam, "systat") == 0) { if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } count = invoke("who", buffer, BUFFERCNT); if (sendto(f, buffer, count, 0, &from, fromlen) < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "sendto: %m"); closelog(); exit(1); } } } else { count = invoke("who", buffer, BUFFERCNT); (void) alarm(TIMEOUT); (void) write(f, buffer, count); (void) alarm(0); } /* return ascii string giving our idea of time */ } else if (strcmp(servnam, "daytime") == 0) { if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } count = invoke("date", buffer, BUFFERCNT); if (sendto(f, buffer, count, 0, &from, fromlen) < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "sendto: %m"); closelog(); exit(1); } } } else { count = invoke("date", buffer, BUFFERCNT); (void) alarm(TIMEOUT); (void) write(f, buffer, count); (void) alarm(0); } /* return ascii text buffer of short length - we use fortune to gen */ } else if (strcmp(servnam, "quote") == 0) { if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } count = invoke("/usr/games/fortune", buffer, BUFFERCNT); if (sendto(f, buffer, count, 0, &from, fromlen) < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "sendto: %m"); closelog(); exit(1); } } } else { count = invoke("/usr/games/fortune", buffer, BUFFERCNT); (void) alarm(TIMEOUT); (void) write(f, buffer, count); (void) alarm(0); } /* generate character pattern (silly for udp, but..) */ } else if (strcmp(servnam, "chargen") == 0) { (void) strcpy(line, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); (void) strcat(line, "abcdefghijklmnopqrstuvwxyz"); (void) strcat(line, "0123456789"); (void) strcat(line, "!@#$%^&*()-=+[]{}"); rotate = 0; if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } *buffer = '\0'; for (count = 0; count < 8; count++) { (void) strcat(buffer, &line[rotate]); (void) strncat(buffer, line, rotate); (void) strcat(buffer, "\r\n"); rotate = (rotate + 1) % strlen(line); } count = strlen(buffer); if (sendto(f, buffer, count, 0, &from, fromlen) < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "sendto: %m"); closelog(); exit(1); } } } else { while (1) { (void) strcpy(buffer, &line[rotate]); (void) strncat(buffer, line, rotate); (void) strcat(buffer, "\r\n"); rotate = (rotate + 1) % strlen(line); count = strlen(buffer); (void) alarm(TIMEOUT); if (write(f, buffer, count) != count) { break; } (void) alarm(0); } } /* return longword giving biased time in seconds since 1900 */ } else if (strcmp(servnam, "time") == 0) { if (tcpsock == 0) { while (1) { fromlen = sizeof(from); count = recvfrom(f, buffer, sizeof(buffer), 0, &from, &fromlen); (void) alarm(TIMEOUT); if (count < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "recvfrom: %m"); closelog(); exit(1); } (void) gettimeofday(&nowtime, &nowzone); nowbias = htonl(nowtime.tv_sec + 2208988800l); if (sendto(f, &nowbias, sizeof(nowbias), 0, &from, fromlen) < 0) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "sendto: %m"); closelog(); exit(1); } } } else { (void) gettimeofday(&nowtime, &nowzone); nowbias = htonl(nowtime.tv_sec + 2208988800l); (void) alarm(TIMEOUT); (void) write(f, &nowbias, sizeof(nowbias)); (void) alarm(0); } /* we have been called to do something we don't know how */ } else { openlog(daemoname, LOG_PID); syslog(LOG_WARNING, "unimplemented service: %s/%s", servnam, tcpsock? "tcp": "udp"); closelog(); }}/* * Gracefully handle final alarm for udp shutdown */voidtimeout(){ exit(0);}/* * Invoke given command and return buffer full of output. * Add carriage returns to each line as that's how internet * likes to see things. */invoke(command, buffer, size)char *command;char *buffer;int size;{ int count; register char *bp; FILE *cmd; if ((cmd = popen(command, "r")) == NULL) { openlog(daemoname, LOG_PID); syslog(LOG_ERR, "command failure: %m"); closelog(); exit(1); } count = 0; bp = buffer; while (fgets(bp, size - count - 1, cmd) != NULL) { bp = buffer + strlen(buffer) - 1; if (*bp != '\n') { break; } *bp++ = '\r'; *bp++ = '\n'; *bp = '\0'; count = bp - buffer; } (void) pclose(cmd); return(count);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?