mirror of
https://github.com/tbamud/tbamud.git
synced 2026-02-19 10:01:45 +01:00
Setting up 3.5.0 as trunk
This commit is contained in:
159
src/util/sign.c
Executable file
159
src/util/sign.c
Executable file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* sign.c: a program to present text on a TCP port
|
||||
*
|
||||
* Author: Jeremy Elson (jelson@circlemud.org)
|
||||
* Usage: sign <port> <filename> or
|
||||
* sign <port> -
|
||||
*
|
||||
* '-' indicates file should be read from stdin.
|
||||
*
|
||||
* This program is in the public domain. It may be copied, redistributed,
|
||||
* reused, modified, etc., but a notice of my authorship must be maintained.
|
||||
*
|
||||
* This program comes with no warranty of any kind, expressed or implied.
|
||||
*/
|
||||
|
||||
#define MAX_FILESIZE 8192
|
||||
#define LINEBUF_SIZE 128
|
||||
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
|
||||
/*
|
||||
* init_socket sets up the mother descriptor - creates the socket, sets
|
||||
* its options up, binds it, and listens.
|
||||
*/
|
||||
int init_socket(int port)
|
||||
{
|
||||
int s, opt;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
/*
|
||||
* Should the first argument to socket() be AF_INET or PF_INET? I don't
|
||||
* know, take your pick. PF_INET seems to be more widely adopted, and
|
||||
* Comer (_Internetworking with TCP/IP_) even makes a point to say that
|
||||
* people erroneously use AF_INET with socket() when they should be using
|
||||
* PF_INET. However, the man pages of some systems indicate that AF_INET
|
||||
* is correct; some such as ConvexOS even say that you can use either one.
|
||||
* All implementations I've seen define AF_INET and PF_INET to be the same
|
||||
* number anyway, so ths point is (hopefully) moot.
|
||||
*/
|
||||
|
||||
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
perror("Create socket");
|
||||
exit(1);
|
||||
}
|
||||
#if defined(SO_REUSEADDR)
|
||||
opt = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)) < 0) {
|
||||
perror("setsockopt REUSEADDR");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SO_LINGER)
|
||||
{
|
||||
struct linger ld;
|
||||
|
||||
ld.l_onoff = 0;
|
||||
ld.l_linger = 0;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld)) < 0) {
|
||||
perror("setsockopt LINGER");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
listen(s, 5);
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
char *get_text(char *fname)
|
||||
{
|
||||
static char t[MAX_FILESIZE];
|
||||
char tmp[LINEBUF_SIZE + 2];
|
||||
FILE *fl = NULL;
|
||||
|
||||
*t = '\0';
|
||||
|
||||
if (!strcmp(fname, "-")) {
|
||||
fl = stdin;
|
||||
if (isatty(STDIN_FILENO))
|
||||
fprintf(stderr, "Enter sign text; terminate with Ctrl-D.\n");
|
||||
} else {
|
||||
if (!(fl = fopen(fname, "r"))) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
while (fgets(tmp, LINEBUF_SIZE, fl)) {
|
||||
if (strlen(tmp) + strlen(t) < MAX_FILESIZE - 1)
|
||||
strcat(t, strcat(tmp, "\r"));
|
||||
else {
|
||||
fprintf(stderr, "String too long. Truncated.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (t);
|
||||
}
|
||||
|
||||
|
||||
/* clean up our zombie kids to avoid defunct processes */
|
||||
RETSIGTYPE reap(int sig)
|
||||
{
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
|
||||
signal(SIGCHLD, reap);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *txt;
|
||||
int desc, remaining, bytes_written, len, s, port, child;
|
||||
|
||||
if (argc != 3 || (port = atoi(argv[1])) < 1024) {
|
||||
fprintf(stderr, "usage: %s <portnum> <\"-\" | filename>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
s = init_socket(port);
|
||||
len = strlen(txt = get_text(argv[2]));
|
||||
|
||||
if ((child = fork()) > 0) {
|
||||
fprintf(stderr, "Sign started on port %d (pid %d).\n", port, child);
|
||||
exit(0);
|
||||
}
|
||||
signal(SIGCHLD, reap);
|
||||
|
||||
for (;;) {
|
||||
if ((desc = accept(s, (struct sockaddr *) NULL, 0)) < 0)
|
||||
continue;
|
||||
|
||||
if (fork() == 0) {
|
||||
remaining = len;
|
||||
do {
|
||||
if ((bytes_written = write(desc, txt, remaining)) < 0)
|
||||
exit(0);
|
||||
else {
|
||||
txt += bytes_written;
|
||||
remaining -= bytes_written;
|
||||
}
|
||||
} while (remaining > 0);
|
||||
exit(0);
|
||||
}
|
||||
close(desc);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user