]> mj.ucw.cz Git - nwho.git/blobdiff - nwhod.c
gethostbyname() does not set errno
[nwho.git] / nwhod.c
diff --git a/nwhod.c b/nwhod.c
index e0f158e8d91d98e20f3932039571a3b96a038875..05e73a91a23eece788753f5cd1d5696bfbcb2bef 100644 (file)
--- a/nwhod.c
+++ b/nwhod.c
@@ -1,10 +1,7 @@
 /*
- *     The Remote User Information Daemon 1.8
+ *     The Remote User Information Daemon
  *
- *     (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU General Public License. See file COPYING in any of the GNU packages.
+ *     (c) 1997--2010 Martin Mares <mj@ucw.cz>
  */
 
 #include <stdio.h>
 #include <arpa/inet.h>
 #include <syslog.h>
 #include <sys/stat.h>
+#include <time.h>
 #include <utmp.h>
 #include <signal.h>
 #include <dirent.h>
+#include <errno.h>
 
 #include "net.h"
 
@@ -29,7 +28,7 @@ struct hostrec {
   struct hostrec *next;
   char name[32];
   time_t last_rec;                     /* 0=down */
-  __u32 addr;
+  u32 addr;
 };
 
 static int sock, port;
@@ -55,29 +54,21 @@ net_init(char *name)
 {
   struct hostent *h;
   struct sockaddr_in sa;
-  struct servent *se;
-  int one;
 
   if (name)
     {
       if (! (h = gethostbyname(name)))
-       die("%s: %m", name);
+       die("Failed to resolve %s", name);
     }
   else
     h = NULL;
 
-  if (! (se = getservbyname("nwho", "udp")))
-    die("Unknown service `nwho/udp'");
-
   sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
   if (sock < 0)
     die("socket: %m");
 
-  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
-    die("setsockopt: %m");
-
   sa.sin_family = AF_INET;
-  sa.sin_port = port = se->s_port;
+  sa.sin_port = port = htons(NWHO_PORT);
   sa.sin_addr.s_addr = INADDR_ANY;
   if (bind(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0)
     die("bind: %m");
@@ -91,7 +82,7 @@ net_init(char *name)
 }
 
 static void
-scan_utmp(struct rywho_pkt *p, time_t now)
+scan_utmp(struct nwho_pkt *p, time_t now)
 {
   struct utmp *u;
   int cnt = 0;
@@ -110,25 +101,10 @@ scan_utmp(struct rywho_pkt *p, time_t now)
        name[9] = 0;
        strcpy(h->name, name);
        h->login_time = htonl(now - u->ut_time);
-       if (u->ut_id[0])
-         {
-           h->con[0] = u->ut_id[0];
-           h->con[1] = u->ut_id[1];
-           h->con[2] = 0;
-         }
-       else
-         {
-           char *z = u->ut_line;
-           if (!strncmp(z, "tty", 3))
-             z += 3;
-           sprintf(h->con, "%.3s", z);
-         }
+       sprintf(h->con, "%.7s", u->ut_line);
        sprintf(device, "/dev/%s", u->ut_line);
        if (stat(device, &st) < 0)
-         {
-           fprintf(stderr, "stat(%s): %m", device);
-           continue;
-         }
+         continue;
        h->mesg_y = !!(S_IWGRP & st.st_mode);
        last = st.st_atime;
        if (st.st_mtime > last)
@@ -144,7 +120,7 @@ scan_utmp(struct rywho_pkt *p, time_t now)
 }
 
 static void
-scan_load(struct rywho_pkt *p)
+scan_load(struct nwho_pkt *p)
 {
   int n, i, j[6];
   char buf[256];
@@ -173,9 +149,10 @@ scan_load(struct rywho_pkt *p)
 }
 
 static void
-make_pkt(struct rywho_pkt *pkt)
+make_pkt(struct nwho_pkt *pkt)
 {
   bzero(pkt, sizeof(pkt));
+  pkt->magic = htonl(NWHO_MAGIC);
   pkt->local_time = htonl(now);
   scan_utmp(pkt, now);
   scan_load(pkt);
@@ -197,7 +174,7 @@ cleanup(void)
 }
 
 static void
-save_pkt(char *name, struct rywho_pkt *pkt, int len)
+save_pkt(char *name, struct nwho_pkt *pkt, int len)
 {
   int fd = open(name, O_WRONLY | O_CREAT, 0666);
   if (fd < 0)
@@ -213,7 +190,7 @@ save_pkt(char *name, struct rywho_pkt *pkt, int len)
 }
 
 static inline int                      /* Validation checks not implemented yet */
-is_valid(__u32 ipa)
+is_valid(u32 ipa)
 {
   return 1;
 }
@@ -221,16 +198,16 @@ is_valid(__u32 ipa)
 static void
 receive(void)
 {
-  int r, al;
-  struct rywho_pkt pkt;
+  int r;
+  struct nwho_pkt pkt;
   struct sockaddr_in sa;
-  int n = sizeof(struct rywho_pkt) - MAX_USERS * sizeof(struct userinfo);
+  socklen_t al = sizeof(sa);
+  int n = sizeof(struct nwho_pkt) - MAX_USERS * sizeof(struct userinfo);
   struct hostrec *e;
   struct hostent *h;
   char *c;
 
   alarm(DEFAULT_PRUNE_TIME);
-  al = sizeof(sa);
   r = recvfrom(sock, &pkt, sizeof(pkt), 0, (struct sockaddr *) &sa, &al);
   alarm(0);
   now = time(NULL);
@@ -255,6 +232,12 @@ receive(void)
       return;
     }
 
+  if (pkt.magic != htonl(NWHO_MAGIC))
+    {
+      syslog(LOG_WARNING, "Received ancient nwho packet from %s", inet_ntoa(sa.sin_addr));
+      return;
+    }
+
   for(e=first_host; e; e=e->next)
     if (e->addr == sa.sin_addr.s_addr)
       break;
@@ -296,7 +279,7 @@ receive(void)
 static void
 local_scan(void)
 {
-  struct rywho_pkt pkt;
+  struct nwho_pkt pkt;
   static char hostname[64];
 
   make_pkt(&pkt);
@@ -325,19 +308,40 @@ do_tick(void)
 }
 
 static void
-tick(int unused)
+daemonize(void)
 {
+  pid_t pid = fork();
+  if (pid < 0)
+    die("Fork failed: %m");
+  if (pid)
+    exit(0);
+
+  close(0);
+  close(1);
+  close(2);
+  open("/dev/null", O_RDONLY);
+  dup(0);
+  dup(0);
+  setsid();
 }
 
-static struct sigaction sigact = { tick, 0, 0, NULL };
+static void
+tick(int unused)
+{
+}
 
 static void
 server(void)
 {
+  static struct sigaction sigact;
+
   net_init(NULL);
-  if (chdir(YWHO_SPOOL_DIR) < 0)
-    die("chdir(" YWHO_SPOOL_DIR "): %m");
+  if (chdir(NWHO_SPOOL_DIR) < 0)
+    die("chdir(" NWHO_SPOOL_DIR "): %m");
   cleanup();
+  daemonize();
+  bzero(&sigact, sizeof(sigact));
+  sigact.sa_handler = tick;
   sigaction(SIGALRM, &sigact, NULL);
   now = time(NULL);
   for(;;)
@@ -350,10 +354,11 @@ server(void)
 static void
 client(char *serv)
 {
-  struct rywho_pkt pkt;
+  struct nwho_pkt pkt;
 
   net_init(serv);
   utmpname(UTMP_FILE);
+  daemonize();
   for(;;)
     {
       now = time(NULL);
@@ -367,24 +372,14 @@ client(char *serv)
 int
 main(int argc, char **argv)
 {
-  int pid;
-
-  if (argc != 1 && argc != 2)
-    {
-      fprintf(stderr, "Usage: nwhod [<server>]\n");
-      return 1;
-    }
-  pid = fork();
-  if (pid < 0)
-    {
-      perror("fork");
-      return 1;
-    }
-  if (pid)
-    return 0;
   if (argc == 2)
     client(argv[1]);
   else if (argc == 1)
     server();
-  return 1;
+  else
+    {
+      fprintf(stderr, "Usage: nwhod [<server>]\n");
+      return 1;
+    }
+  return 0;
 }