From: Joshua Kwan Date: Sun, 22 Feb 2004 05:57:36 +0000 (+0000) Subject: Committing this, currently broken, shouldn't be within 5 minutes X-Git-Tag: v1.6.1-roc-dev~452 X-Git-Url: https://skyeroc.xyz/gitweb/?a=commitdiff_plain;h=901a5ea38af33ff161678e41996f683ef486f4db;p=dgamelaunch Committing this, currently broken, shouldn't be within 5 minutes git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@248 db0b04b0-f4d1-0310-9a6d-de3e77497b0e --- diff --git a/.cvsignore b/.cvsignore index 9e0d075..e5d53f5 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,4 +1,5 @@ dgamelaunch +dgl-wall nethackstub tags cscope.out diff --git a/Makefile b/Makefile index c07ccf1..64c223b 100644 --- a/Makefile +++ b/Makefile @@ -41,18 +41,23 @@ LDFLAGS = CFLAGS = -g3 $(optimize) -Wall -Wno-unused $(DEFS) INSTALL = install -c DEFS = -DVERSION=\"$(VERSION)\" -DDEFCONFIG=\"$(DEFCONFIG)\" -SRCS = $(EDITOR) ttyrec.c dgamelaunch.c io.c ttyplay.c mygetnstr.c stripgfx.c strlcpy.c strlcat.c y.tab.c lex.yy.c +SRCS = $(EDITOR) dgl-common.c ttyrec.c dgamelaunch.c io.c ttyplay.c mygetnstr.c stripgfx.c strlcpy.c strlcat.c y.tab.c lex.yy.c +EXTRA_SRCS = nethackstub.c OBJS = $(SRCS:.c=.o) +WALL_OBJS = y.tab.o lex.yy.o dgl-common.o dgl-wall.o strlcat.o strlcpy.o LIBS = -lcurses -lcrypt $(LUTIL) -ll -all: $(NAME) +all: $(NAME) dgl-wall $(NAME): $(OBJS) $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) +dgl-wall: $(WALL_OBJS) + $(CC) $(CFLAGS) -o $@ $(WALL_OBJS) $(LIBS) + clean: - rm -f $(NAME) nethackstub - rm -f editors/*.o *.o .#* *~ y.tab.* lex.yy.c + rm -f $(NAME) nethackstub dgl-wall + rm -f editors/*.o *.o .#* *~ y.tab.* lex.yy.c Makefile.dep install: $(INSTALL) -m 755 $(NAME) $(SBINDIR) @@ -70,24 +75,30 @@ y.tab.c y.tab.h: config.y lex.yy.o: lex.yy.c y.tab.o: y.tab.c -dist: clean +dist: dep clean rm -rf $(NAME)-$(VERSION) (cd .. && ln -sf $(CURDIR) $(NAME)-$(VERSION)) (cd .. && tar $(addprefix --exclude ,$(exclusions)) -chzf $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION)) rm -f ../$(NAME)-$(VERSION) @echo "Created source release $(NAME)-$(VERSION).tar.gz" - -# Dependencies - we may auto-generate later + +dep: y.tab.c lex.yy.c + @sed -e '/^# Source code dependencies/,$$d' < Makefile > Makefile.dep + @echo "# Source code dependencies" >> Makefile.dep + $(CC) -MM $(SRCS) $(EXTRA_SRCS) >> Makefile.dep + mv Makefile.dep Makefile + +# Source code dependencies ee.o: ee.c +dgl-common.o: dgl-common.c dgamelaunch.h +ttyrec.o: ttyrec.c dgamelaunch.h ttyrec.h io.h +dgamelaunch.o: dgamelaunch.c dgamelaunch.h ttyplay.h ttyrec.h y.tab.h io.o: io.c ttyrec.h -last_char_is.o: last_char_is.c +ttyplay.o: ttyplay.c dgamelaunch.h ttyplay.h ttyrec.h io.h stripgfx.h mygetnstr.o: mygetnstr.c -nethackstub.o: nethackstub.c stripgfx.o: stripgfx.c stripgfx.h -strlcat.o: strlcat.c strlcpy.o: strlcpy.c -ttyplay.o: ttyplay.c dgamelaunch.h ttyplay.h ttyrec.h io.h stripgfx.h -ttyrec.o: ttyrec.c dgamelaunch.h ttyrec.h io.h -virus.o: virus.c last_char_is.c +strlcat.o: strlcat.c y.tab.o: y.tab.c dgamelaunch.h -dgamelaunch.o: dgamelaunch.c dgamelaunch.h ttyplay.h ttyrec.h y.tab.h +lex.yy.o: lex.yy.c y.tab.h dgamelaunch.h +nethackstub.o: nethackstub.c diff --git a/dgamelaunch.h b/dgamelaunch.h index 147a72e..8a5583d 100644 --- a/dgamelaunch.h +++ b/dgamelaunch.h @@ -13,6 +13,10 @@ # define NOSTREAMS #endif +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + struct dg_user { char *username; @@ -89,6 +93,11 @@ extern void writefile(int requirenew); extern void graceful_exit(int status); extern int purge_stale_locks(void); extern void menuloop(void); +#if !defined(BSD) && !defined(__linux__) +extern int mysetenv (const char* name, const char* value, int overwrite); +#else +# define mysetenv setenv +#endif /* strlcpy.c */ extern size_t strlcpy (char *dst, const char *src, size_t siz); diff --git a/dgl-common.c b/dgl-common.c new file mode 100644 index 0000000..72278c6 --- /dev/null +++ b/dgl-common.c @@ -0,0 +1,230 @@ +/* Functions common to both dgamelaunch itself and dgl-wall. */ + +#include "dgamelaunch.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern FILE* yyin; +extern int yyparse (); + +/* Data structures */ +struct dg_config *myconfig = NULL; +struct dg_config defconfig = { + /* chroot = */ "/var/lib/dgamelaunch/", + /* nethack = */ "/bin/nethack", + /* dglroot = */ "/dgldir/", + /* lockfile = */ "/dgl-lock", + /* passwd = */ "/dgl-login", + /* banner = */ "/dgl-banner", + /* rcfile = */ "/dgl-default-rcfile", + /* spool = */ "/var/mail/", + /* shed_user = */ "games", + /* shed_group = */ "games", + /* shed_uid = */ 5, + /* shed_gid = */ 60, /* games:games in Debian */ + /* max = */ 64000 +}; + +char* config = NULL; +int silent = 0; +int set_max = 0; /* XXX */ +int loggedin = 0; +char *chosen_name; + +struct dg_game ** +populate_games (int *l) +{ + int fd, len; + DIR *pdir; + struct dirent *pdirent; + struct stat pstat; + char fullname[130], ttyrecname[130]; + char *replacestr, *dir; + struct dg_game **games = NULL; + struct flock fl = { 0 }; + size_t slen; + + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + + len = 0; + + slen = strlen(myconfig->dglroot) + ARRAY_SIZE("inprogress/") + 1; + dir = malloc(slen); + snprintf(dir, slen, "%sinprogress/", myconfig->dglroot); + + if (!(pdir = opendir (dir))) + graceful_exit (140); + + while ((pdirent = readdir (pdir))) + { + if (!strcmp (pdirent->d_name, ".") || !strcmp (pdirent->d_name, "..")) + continue; + + snprintf (fullname, 130, "%sinprogress/%s", myconfig->dglroot, pdirent->d_name); + + fd = 0; + /* O_RDWR here should be O_RDONLY, but we need to test for + * an exclusive lock */ + fd = open (fullname, O_RDWR); + if ((fd > 0) && fcntl (fd, F_SETLK, &fl) == -1) + { + + /* stat to check idle status */ + snprintf (ttyrecname, 130, "%sttyrec/%s", myconfig->dglroot, pdirent->d_name); + replacestr = strchr (ttyrecname, ':'); + if (!replacestr) + graceful_exit (145); + replacestr[0] = '/'; + if (!stat (ttyrecname, &pstat)) + { + /* now it's a valid game for sure */ + games = realloc (games, sizeof (struct dg_game) * (len + 1)); + games[len] = malloc (sizeof (struct dg_game)); + games[len]->ttyrec_fn = strdup (pdirent->d_name); + + if (!(replacestr = strchr (pdirent->d_name, ':'))) + graceful_exit (146); + else + *replacestr = '\0'; + + games[len]->name = malloc (strlen (pdirent->d_name) + 1); + strlcpy (games[len]->name, pdirent->d_name, + strlen (pdirent->d_name) + 1); + + games[len]->date = malloc (11); + strlcpy (games[len]->date, replacestr + 1, 11); + + games[len]->time = malloc (9); + strlcpy (games[len]->time, replacestr + 12, 9); + + games[len]->idle_time = pstat.st_mtime; + + len++; + } + } + else + { + /* clean dead ones */ + unlink (fullname); + } + fl.l_type = F_UNLCK; + + fcntl (fd, F_SETLK, &fl); + + fl.l_type = F_WRLCK; + + close (fd); + } + + closedir (pdir); + *l = len; + return games; +} + +void +create_config () +{ + FILE *config_file = NULL; + + if (config) + { + if ((config_file = fopen(config, "r")) != NULL) + { + yyin = config_file; + yyparse(); + fclose(config_file); + free (config); + } + else + { + fprintf(stderr, "ERROR: can't find or open %s for reading\n", config); + graceful_exit(104); + return; + } + + if (!myconfig) /* a parse error occurred */ + { + myconfig = &defconfig; + return; + } + /* Fill the rest with defaults */ + if (!myconfig->shed_user && myconfig->shed_uid == -1) + { + struct passwd *pw; + if ((pw = getpwnam(defconfig.shed_user))) + myconfig->shed_uid = pw->pw_uid; + else + myconfig->shed_uid = defconfig.shed_uid; + } + + if (!myconfig->shed_group && myconfig->shed_gid == -1) + { + struct group *gr; + if ((gr = getgrnam(defconfig.shed_group))) + myconfig->shed_gid = gr->gr_gid; + else + myconfig->shed_gid = defconfig.shed_gid; + } + + if (myconfig->max == 0 && !set_max) myconfig->max = defconfig.max; + if (!myconfig->banner) myconfig->banner = defconfig.banner; + if (!myconfig->chroot) myconfig->chroot = defconfig.chroot; + if (!myconfig->nethack) myconfig->nethack = defconfig.nethack; + if (!myconfig->dglroot) myconfig->dglroot = defconfig.dglroot; + if (!myconfig->rcfile) myconfig->rcfile = defconfig.rcfile; + if (!myconfig->spool) myconfig->spool = defconfig.spool; + if (!myconfig->passwd) myconfig->passwd = defconfig.passwd; + if (!myconfig->lockfile) myconfig->lockfile = defconfig.lockfile; + } + else + { + myconfig = &defconfig; + } +} + +#if !defined(BSD) && !defined(__linux__) +int +mysetenv (const char* name, const char* value, int overwrite) +{ + int retval; + char *buf = NULL; + + if (getenv(name) == NULL || overwrite) + { + size_t len = strlen(name) + 1 + strlen(value) + 1; /* NAME=VALUE\0 */ + buf = malloc(len); + snprintf(buf, len, "%s=%s", name, value); + retval = putenv(buf); + } + else + retval = -1; + + return retval; +} +#endif + +void +graceful_exit (int status) +{ + /*FILE *fp; + if (status != 1) + { + fp = fopen ("/crash.log", "a"); + char buf[100]; + sprintf (buf, "graceful_exit called with status %d", status); + fputs (buf, fp); + } + This doesn't work. Ever. + */ + exit (status); +} diff --git a/dgl-wall.c b/dgl-wall.c new file mode 100644 index 0000000..47dea17 --- /dev/null +++ b/dgl-wall.c @@ -0,0 +1,126 @@ +/* dgl-wall sends a message to all logged in users. If you specified a + * configuration file to dgamelaunch, you must do so as well for dgl-wall, + * or else the message won't be sent. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dgamelaunch.h" + +int +main (int argc, char** argv) +{ + int c, i, len; + char* config = NULL, buf[80], *ptr = buf, *from = NULL; + struct dg_game ** games = NULL; + struct flock fl = { 0 }; + struct passwd* pw = getpwuid(getuid()); + FILE* spool = NULL; + + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + + *ptr = '\0'; + + while ((c = getopt(argc, argv, "f:F:")) != -1) + { + switch (c) + { + case 'f': + config = strdup(optarg); + break; + case 'F': + from = strdup(optarg); + break; + } + } + + if (from == NULL) + from = pw->pw_name; + + while (optind < argc) + { + if (strlen(buf) >= 80) + { + fprintf(stderr, "Error: Message is too long! (80 chars max)\n"); + return 1; + } + else if (strlen(buf) != 0) + strlcat (buf, " ", 80); + strlcat (buf, argv[optind++], 80); + } + + if (strlen(buf) == 0) + { + fprintf(stderr, "Error: no message?\n"); + return 1; + } + + create_config(); + + if (chroot (myconfig->chroot)) + { + perror("Couldn't change root directory"); + return 1; + } + + if (chdir ("/")) + { + perror("Couldn't chdir to root directory"); + return 1; + } + + games = populate_games (&len); + + if (len == 0) + { + fprintf(stderr, "Error: no one's logged in!\n"); + return 1; + } + + for (i = 0; i < len; i++) + { + char* fname = NULL; + size_t len; + + len = strlen(myconfig->spool) + strlen(games[i]->name) + 2; + fname = malloc (len + 1); + + snprintf(fname, len, "%s/%s", myconfig->spool, games[i]->name); + + if ((spool = fopen(fname, "a")) == NULL) + { + fprintf (stderr, "Warning: couldn't open mailbox for %s.\n", games[i]->name); + free (fname); + continue; + } + + while (fcntl (fileno(spool), F_SETLK, &fl) == -1) + { + if (errno != EAGAIN) + fprintf (stderr, "Warning: fcntl errored out trying to lock mailbox for %s\n", + games[i]->name); + sleep(1); + } + + /* Now that we have the lock, begin the write */ + + fprintf(spool, "%s:%s\n", from, buf); + fclose(spool); + free(fname); + } + + puts("Message sent successfully."); + return 0; +} +