| 1 | /* SAMHAIN file system integrity testing                                   */
 | 
|---|
| 2 | /* Copyright (C) 2003 Rainer Wichmann                                      */
 | 
|---|
| 3 | /*                                                                         */
 | 
|---|
| 4 | /*  This program is free software; you can redistribute it                 */
 | 
|---|
| 5 | /*  and/or modify                                                          */
 | 
|---|
| 6 | /*  it under the terms of the GNU General Public License as                */
 | 
|---|
| 7 | /*  published by                                                           */
 | 
|---|
| 8 | /*  the Free Software Foundation; either version 2 of the License, or      */
 | 
|---|
| 9 | /*  (at your option) any later version.                                    */
 | 
|---|
| 10 | /*                                                                         */
 | 
|---|
| 11 | /*  This program is distributed in the hope that it will be useful,        */
 | 
|---|
| 12 | /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
 | 
|---|
| 13 | /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
 | 
|---|
| 14 | /*  GNU General Public License for more details.                           */
 | 
|---|
| 15 | /*                                                                         */
 | 
|---|
| 16 | /*  You should have received a copy of the GNU General Public License      */
 | 
|---|
| 17 | /*  along with this program; if not, write to the Free Software            */
 | 
|---|
| 18 | /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
 | 
|---|
| 19 | 
 | 
|---|
| 20 | #include "config_xor.h"
 | 
|---|
| 21 | 
 | 
|---|
| 22 | #include <stddef.h>
 | 
|---|
| 23 | #include <stdio.h>
 | 
|---|
| 24 | #include <stdlib.h>
 | 
|---|
| 25 | #include <string.h> 
 | 
|---|
| 26 | #include <errno.h>
 | 
|---|
| 27 | 
 | 
|---|
| 28 | #include <unistd.h>
 | 
|---|
| 29 | #include <fcntl.h>
 | 
|---|
| 30 | 
 | 
|---|
| 31 | #include <sys/socket.h>
 | 
|---|
| 32 | #include <sys/un.h>
 | 
|---|
| 33 | 
 | 
|---|
| 34 | #include <signal.h>
 | 
|---|
| 35 | #include <pwd.h>
 | 
|---|
| 36 | 
 | 
|---|
| 37 | #if !defined(AF_FILE)
 | 
|---|
| 38 | #define AF_FILE AF_UNIX
 | 
|---|
| 39 | #endif
 | 
|---|
| 40 | 
 | 
|---|
| 41 | #define SH_MAXMSG 209
 | 
|---|
| 42 | 
 | 
|---|
| 43 | static int    sock     = -1;
 | 
|---|
| 44 | static char * sockname = NULL;
 | 
|---|
| 45 | 
 | 
|---|
| 46 | static char   password[15] = "";
 | 
|---|
| 47 | 
 | 
|---|
| 48 | static int    verbose = 0;
 | 
|---|
| 49 | 
 | 
|---|
| 50 | #ifdef SH_STEALTH
 | 
|---|
| 51 | char * globber(const char * string);
 | 
|---|
| 52 | #define _(string) globber(string) 
 | 
|---|
| 53 | #define N_(string) string
 | 
|---|
| 54 | #else
 | 
|---|
| 55 | #define _(string)  string 
 | 
|---|
| 56 | #define N_(string) string
 | 
|---|
| 57 | #endif
 | 
|---|
| 58 | 
 | 
|---|
| 59 | #ifdef SH_STEALTH
 | 
|---|
| 60 | #ifndef SH_MAX_GLOBS
 | 
|---|
| 61 | #define SH_MAX_GLOBS 32
 | 
|---|
| 62 | #endif
 | 
|---|
| 63 | char * globber(const char * str)
 | 
|---|
| 64 | {
 | 
|---|
| 65 |   register int i, j;
 | 
|---|
| 66 |   static int  count = -1;
 | 
|---|
| 67 |   static char glob[SH_MAX_GLOBS][128];
 | 
|---|
| 68 | 
 | 
|---|
| 69 |   ++count; if (count > (SH_MAX_GLOBS-1) ) count = 0;
 | 
|---|
| 70 |   j = strlen(str);
 | 
|---|
| 71 |   if (j > 127) j = 127;
 | 
|---|
| 72 | 
 | 
|---|
| 73 |   for (i = 0; i < j; ++i)
 | 
|---|
| 74 |     {
 | 
|---|
| 75 |       if (str[i] != '\n' && str[i] != '\t') 
 | 
|---|
| 76 |         glob[count][i] = str[i] ^ XOR_CODE;
 | 
|---|
| 77 |       else
 | 
|---|
| 78 |         glob[count][i] = str[i];
 | 
|---|
| 79 |     }
 | 
|---|
| 80 |   glob[count][j] = '\0';
 | 
|---|
| 81 |   return glob[count];
 | 
|---|
| 82 | }
 | 
|---|
| 83 | #endif
 | 
|---|
| 84 | 
 | 
|---|
| 85 | #define CLIENT _("yulectl")
 | 
|---|
| 86 | 
 | 
|---|
| 87 | 
 | 
|---|
| 88 | int 
 | 
|---|
| 89 | make_named_socket (char * sockname)
 | 
|---|
| 90 | {
 | 
|---|
| 91 |   int sock;
 | 
|---|
| 92 | 
 | 
|---|
| 93 | #if 0
 | 
|---|
| 94 |   struct sockaddr_un name;
 | 
|---|
| 95 |   size_t size;
 | 
|---|
| 96 | #else
 | 
|---|
| 97 |   (void) sockname;
 | 
|---|
| 98 | #endif
 | 
|---|
| 99 | 
 | 
|---|
| 100 |   /* Create the socket. */
 | 
|---|
| 101 |   
 | 
|---|
| 102 |   sock = socket (PF_UNIX, SOCK_STREAM, 0);
 | 
|---|
| 103 |   if (sock < 0)
 | 
|---|
| 104 |     {
 | 
|---|
| 105 |       perror (_("ERROR: socket"));
 | 
|---|
| 106 |       return -1;
 | 
|---|
| 107 |     }
 | 
|---|
| 108 | 
 | 
|---|
| 109 | #if 0
 | 
|---|
| 110 |   /* Bind a name to the socket. */
 | 
|---|
| 111 |   name.sun_family = AF_FILE;
 | 
|---|
| 112 |   strcpy (name.sun_path, sockname);
 | 
|---|
| 113 | 
 | 
|---|
| 114 |   /* The size of the address is
 | 
|---|
| 115 |      the offset of the start of the filename,
 | 
|---|
| 116 |      plus its length,
 | 
|---|
| 117 |      plus one for the terminating null byte. */
 | 
|---|
| 118 |   size = (offsetof (struct sockaddr_un, sun_path)
 | 
|---|
| 119 |           + strlen (name.sun_path) + 1);
 | 
|---|
| 120 | 
 | 
|---|
| 121 |   if (bind (sock, (struct sockaddr *) &name, size) < 0)
 | 
|---|
| 122 |     {
 | 
|---|
| 123 |       perror (_("ERROR: bind"));
 | 
|---|
| 124 |       return -1;
 | 
|---|
| 125 |     }
 | 
|---|
| 126 | #endif
 | 
|---|
| 127 | 
 | 
|---|
| 128 |   return sock;
 | 
|---|
| 129 | }
 | 
|---|
| 130 | 
 | 
|---|
| 131 | void
 | 
|---|
| 132 | termination_handler (int signum)
 | 
|---|
| 133 | {
 | 
|---|
| 134 |   /* Clean up. */
 | 
|---|
| 135 |   if (signum != 0)
 | 
|---|
| 136 |     {
 | 
|---|
| 137 |       if (verbose)
 | 
|---|
| 138 |         fprintf(stdout, _("# Terminated on signal %d\n"), signum);
 | 
|---|
| 139 |     }
 | 
|---|
| 140 | #if 0
 | 
|---|
| 141 |   if (sockname != NULL) unlink (sockname);
 | 
|---|
| 142 | #endif
 | 
|---|
| 143 |   if (sock   >= 0 ) close  (sock);
 | 
|---|
| 144 | 
 | 
|---|
| 145 |   return;
 | 
|---|
| 146 | }
 | 
|---|
| 147 | 
 | 
|---|
| 148 | 
 | 
|---|
| 149 | int send_to_server (char * serversock, char * message)
 | 
|---|
| 150 | {
 | 
|---|
| 151 |   struct sockaddr_un name;
 | 
|---|
| 152 |   /* size_t size; */
 | 
|---|
| 153 |   int size;
 | 
|---|
| 154 |   int nbytes;
 | 
|---|
| 155 | 
 | 
|---|
| 156 |   /* Initialize the server socket address. 
 | 
|---|
| 157 |    */
 | 
|---|
| 158 |   name.sun_family = AF_UNIX;
 | 
|---|
| 159 |   strncpy (name.sun_path, serversock, sizeof(name.sun_path) - 1);
 | 
|---|
| 160 |   size = (offsetof (struct sockaddr_un, sun_path)
 | 
|---|
| 161 |           + strlen (name.sun_path) + 1);
 | 
|---|
| 162 | 
 | 
|---|
| 163 |   nbytes = connect(sock, (struct sockaddr *) & name, size);
 | 
|---|
| 164 |   if (nbytes < 0)
 | 
|---|
| 165 |     {
 | 
|---|
| 166 |       perror (_("ERROR: connect"));
 | 
|---|
| 167 |       return -1;
 | 
|---|
| 168 |     }
 | 
|---|
| 169 | 
 | 
|---|
| 170 |   /* Send the datagram. 
 | 
|---|
| 171 |   nbytes = sendto (sock, message, strlen (message) + 1, 0,
 | 
|---|
| 172 |                    (struct sockaddr *) & name, size);
 | 
|---|
| 173 |    */
 | 
|---|
| 174 |   nbytes = send (sock, message, strlen (message) + 1, 0);
 | 
|---|
| 175 | 
 | 
|---|
| 176 |   if (nbytes < 0)
 | 
|---|
| 177 |     {
 | 
|---|
| 178 |       perror (_("ERROR: send"));
 | 
|---|
| 179 |       return -1;
 | 
|---|
| 180 |     }
 | 
|---|
| 181 |   return 0;
 | 
|---|
| 182 | }
 | 
|---|
| 183 | 
 | 
|---|
| 184 | static int getline_from_server (int sock, char * buf, int size)
 | 
|---|
| 185 | {
 | 
|---|
| 186 |   int nbytes = 0;
 | 
|---|
| 187 |   int status = 0;
 | 
|---|
| 188 |   char * p   = buf;
 | 
|---|
| 189 | 
 | 
|---|
| 190 |   do {
 | 
|---|
| 191 |     status = read (sock, p, 1);
 | 
|---|
| 192 |     if (status <= 0)
 | 
|---|
| 193 |       {
 | 
|---|
| 194 |         buf[nbytes] = '\0';
 | 
|---|
| 195 |         return ((status == 0) ? nbytes : status);
 | 
|---|
| 196 |       }
 | 
|---|
| 197 |     else if (*p == '\0')
 | 
|---|
| 198 |       {
 | 
|---|
| 199 |         return nbytes;
 | 
|---|
| 200 |       }
 | 
|---|
| 201 |     ++nbytes; ++p;
 | 
|---|
| 202 |   } while (nbytes < size);
 | 
|---|
| 203 |   buf[size-1] = '\0';
 | 
|---|
| 204 |   return 0;
 | 
|---|
| 205 | }
 | 
|---|
| 206 | 
 | 
|---|
| 207 | int recv_from_server (char * message)
 | 
|---|
| 208 | {
 | 
|---|
| 209 |   int nbytes = 0;
 | 
|---|
| 210 |   char recvmsg[SH_MAXMSG];
 | 
|---|
| 211 |   int  num = 0;
 | 
|---|
| 212 |   int  good = -1;
 | 
|---|
| 213 |   int  islist = 0;
 | 
|---|
| 214 |   char * p;
 | 
|---|
| 215 | 
 | 
|---|
| 216 |   if (password[0] == '\0')
 | 
|---|
| 217 |     {
 | 
|---|
| 218 |       if (message[0] == 'L' && message[1] == 'I' &&
 | 
|---|
| 219 |           message[2] == 'S' && message[3] == 'T')
 | 
|---|
| 220 |         {
 | 
|---|
| 221 |           islist = 1;
 | 
|---|
| 222 |         }
 | 
|---|
| 223 |       if (message[0] == 'P' && message[1] == 'R' &&
 | 
|---|
| 224 |           message[2] == 'O' && message[3] == 'B' && message[4] == 'E' )
 | 
|---|
| 225 |         {
 | 
|---|
| 226 |           islist = 1;
 | 
|---|
| 227 |         }
 | 
|---|
| 228 |     }
 | 
|---|
| 229 |   else
 | 
|---|
| 230 |     {
 | 
|---|
| 231 |       p = &message[strlen(password)+1];
 | 
|---|
| 232 |       if (p[0] == 'L' && p[1] == 'I' &&
 | 
|---|
| 233 |           p[2] == 'S' && p[3] == 'T')
 | 
|---|
| 234 |         {
 | 
|---|
| 235 |           islist = 1;
 | 
|---|
| 236 |         }
 | 
|---|
| 237 |       if (p[0] == 'P' && p[1] == 'R' &&
 | 
|---|
| 238 |           p[2] == 'O' && p[3] == 'B' && p[4] == 'E' )
 | 
|---|
| 239 |         {
 | 
|---|
| 240 |           islist = 1;
 | 
|---|
| 241 |         }
 | 
|---|
| 242 |     }
 | 
|---|
| 243 | 
 | 
|---|
| 244 |   if (islist == 1)
 | 
|---|
| 245 |     {
 | 
|---|
| 246 |       do {
 | 
|---|
| 247 |         /*
 | 
|---|
| 248 |         nbytes = recvfrom (sock, recvmsg, SH_MAXMSG, 0, NULL, 0);
 | 
|---|
| 249 |         */
 | 
|---|
| 250 |         nbytes = getline_from_server (sock, recvmsg, SH_MAXMSG);
 | 
|---|
| 251 |         if (nbytes < 0)
 | 
|---|
| 252 |           {
 | 
|---|
| 253 |             if (errno == EAGAIN)
 | 
|---|
| 254 |               {
 | 
|---|
| 255 |                 return 0;
 | 
|---|
| 256 |               }
 | 
|---|
| 257 |             else
 | 
|---|
| 258 |               {
 | 
|---|
| 259 |                 perror (_("ERROR: recv"));
 | 
|---|
| 260 |                 return -1;
 | 
|---|
| 261 |               }
 | 
|---|
| 262 |           }
 | 
|---|
| 263 |         else if (nbytes == 0)
 | 
|---|
| 264 |           {
 | 
|---|
| 265 |             return 0;
 | 
|---|
| 266 |           }
 | 
|---|
| 267 |         if (recvmsg[0] == 'E' && recvmsg[1] == 'N' && recvmsg[2] == 'D')
 | 
|---|
| 268 |           {
 | 
|---|
| 269 |             if (verbose && (num == 0))
 | 
|---|
| 270 |               fprintf (stdout, _("# There are no pending commands.\n"));
 | 
|---|
| 271 |             return 0;
 | 
|---|
| 272 |           }
 | 
|---|
| 273 |         ++num;
 | 
|---|
| 274 |         fprintf (stdout, _("%03d: %s\n"), num, recvmsg);
 | 
|---|
| 275 |       } while (nbytes >= 0);
 | 
|---|
| 276 |     }
 | 
|---|
| 277 |   else
 | 
|---|
| 278 |     {
 | 
|---|
| 279 |       /*
 | 
|---|
| 280 |       nbytes = recvfrom (sock, recvmsg, SH_MAXMSG, 0, NULL, 0);
 | 
|---|
| 281 |       */
 | 
|---|
| 282 |       nbytes = recv (sock, recvmsg, SH_MAXMSG, 0);
 | 
|---|
| 283 |       if (nbytes < 0)
 | 
|---|
| 284 |         {
 | 
|---|
| 285 |           perror (_("ERROR: recv"));
 | 
|---|
| 286 |           return -1;
 | 
|---|
| 287 |         }
 | 
|---|
| 288 |     }
 | 
|---|
| 289 | 
 | 
|---|
| 290 |   /* Print a diagnostic message. */
 | 
|---|
| 291 |   if (password[0] == '\0')
 | 
|---|
| 292 |     {
 | 
|---|
| 293 |       good = strcmp (message, recvmsg);
 | 
|---|
| 294 |     }
 | 
|---|
| 295 |   else
 | 
|---|
| 296 |     {
 | 
|---|
| 297 |       good = strcmp (&message[strlen(password)+1], recvmsg);
 | 
|---|
| 298 |     }
 | 
|---|
| 299 | 
 | 
|---|
| 300 |   if (0 != good)
 | 
|---|
| 301 |     {
 | 
|---|
| 302 |       fprintf (stderr, _("ERROR: Bounced message != original message.\n"));
 | 
|---|
| 303 |       return -1;
 | 
|---|
| 304 |     }
 | 
|---|
| 305 |   else
 | 
|---|
| 306 |     {
 | 
|---|
| 307 |       if (verbose)
 | 
|---|
| 308 |         fprintf (stdout, _("# Message received by server.\n"));
 | 
|---|
| 309 |     }
 | 
|---|
| 310 | 
 | 
|---|
| 311 |   return 0;
 | 
|---|
| 312 | }
 | 
|---|
| 313 | 
 | 
|---|
| 314 | void usage(char * name)
 | 
|---|
| 315 | {
 | 
|---|
| 316 |   printf(_("\nUsage : %s [-v][-s server_socket] -c command <client_hostname>\n\n"), 
 | 
|---|
| 317 |          name);
 | 
|---|
| 318 | 
 | 
|---|
| 319 |   printf(_("Purpose : send commands to the server via a socket,\n"));
 | 
|---|
| 320 |   printf(_("          in particular commands that the server would\n"));
 | 
|---|
| 321 |   printf(_("          transfer to the client <client_hostname> when\n"));
 | 
|---|
| 322 |   printf(_("          this client connects to deliver a message.\n\n"));
 | 
|---|
| 323 | 
 | 
|---|
| 324 |   printf(_("Commands: RELOAD    <reload configuration>\n"));
 | 
|---|
| 325 |   printf(_("          STOP      <terminate>\n"));
 | 
|---|
| 326 |   printf(_("          CANCEL    <cancel previous command>\n"));
 | 
|---|
| 327 |   printf(_("          LIST      <list queued commands>\n"));
 | 
|---|
| 328 |   printf(_("          LISTALL   <list queued and last sent commands>\n"));
 | 
|---|
| 329 |   printf(_("          PROBE     <probe all clients for necessity of reload>\n"));
 | 
|---|
| 330 |   return;
 | 
|---|
| 331 | }
 | 
|---|
| 332 | 
 | 
|---|
| 333 | void fixup_message (char * message)
 | 
|---|
| 334 | {
 | 
|---|
| 335 |   char message2[SH_MAXMSG];
 | 
|---|
| 336 |   char home[4096];
 | 
|---|
| 337 |   FILE * fp;
 | 
|---|
| 338 |   struct passwd * pwent;
 | 
|---|
| 339 | 
 | 
|---|
| 340 |   
 | 
|---|
| 341 |   pwent = getpwuid(geteuid());
 | 
|---|
| 342 |   if ((pwent == 0) || (pwent->pw_dir == NULL))
 | 
|---|
| 343 |     {
 | 
|---|
| 344 |       if (verbose)
 | 
|---|
| 345 |         fprintf (stderr, _("WARNING: no home directory for euid %ld\n"), 
 | 
|---|
| 346 |                  (long) geteuid()); 
 | 
|---|
| 347 |       if (NULL != getenv(_("HOME")))
 | 
|---|
| 348 |         {
 | 
|---|
| 349 |           strncpy(home, getenv(_("HOME")), 4096);
 | 
|---|
| 350 |           home[4095] = '\0';
 | 
|---|
| 351 |         }
 | 
|---|
| 352 |       else
 | 
|---|
| 353 |         {
 | 
|---|
| 354 |           fprintf (stderr, _("ERROR: no home directory for euid %ld (tried $HOME and password database).\n"), (long) geteuid());
 | 
|---|
| 355 |           exit(EXIT_FAILURE);
 | 
|---|
| 356 |         }
 | 
|---|
| 357 |     }
 | 
|---|
| 358 |   else
 | 
|---|
| 359 |     {
 | 
|---|
| 360 |       strncpy(home, pwent->pw_dir, 4096);
 | 
|---|
| 361 |       home[4095] = '\0';
 | 
|---|
| 362 |     }
 | 
|---|
| 363 | 
 | 
|---|
| 364 |   if ( (strlen(home) + strlen(_("/.yulectl_cred")) + 1) > 4096)
 | 
|---|
| 365 |     {
 | 
|---|
| 366 |       fprintf (stderr, _("ERROR: path for $HOME is too long.\n"));
 | 
|---|
| 367 |       exit(EXIT_FAILURE);
 | 
|---|
| 368 |     }
 | 
|---|
| 369 |   strcat(home, _("/.yulectl_cred"));
 | 
|---|
| 370 |   fp = fopen(home, "r");
 | 
|---|
| 371 |   if (fp == NULL)
 | 
|---|
| 372 |     {
 | 
|---|
| 373 |       if (verbose && (errno == ENOENT))
 | 
|---|
| 374 |         fprintf (stdout, 
 | 
|---|
| 375 |                  _("# Password file (%s) missing\n"),
 | 
|---|
| 376 |                  home);
 | 
|---|
| 377 |       else if (verbose)
 | 
|---|
| 378 |         fprintf (stdout, 
 | 
|---|
| 379 |                  _("# Password file (%s) not accessible for euid %ld uid %ld\n"),
 | 
|---|
| 380 |                  home, (long)geteuid(), (long)getuid());
 | 
|---|
| 381 |       return;
 | 
|---|
| 382 |     }
 | 
|---|
| 383 |   if (NULL == fgets(message2, SH_MAXMSG, fp))
 | 
|---|
| 384 |     {
 | 
|---|
| 385 |       fprintf (stderr, 
 | 
|---|
| 386 |                _("ERROR: empty or unreadable password file (%s).\n"),
 | 
|---|
| 387 |                home);
 | 
|---|
| 388 |       exit(EXIT_FAILURE);
 | 
|---|
| 389 |     }
 | 
|---|
| 390 |   if (strlen(message2) > 15)
 | 
|---|
| 391 |     {
 | 
|---|
| 392 |       fprintf (stderr, 
 | 
|---|
| 393 |                _("ERROR: Password too long (max. 14 characters).\n"));
 | 
|---|
| 394 |       exit(EXIT_FAILURE);
 | 
|---|
| 395 |     }
 | 
|---|
| 396 | 
 | 
|---|
| 397 |   if ( (0 != strlen(message2)) && ('\n' == message2[strlen(message2)-1]))
 | 
|---|
| 398 |     {
 | 
|---|
| 399 |       message2[strlen(message2)-1] = '\0';
 | 
|---|
| 400 |     }
 | 
|---|
| 401 |   strcpy(password, message2);
 | 
|---|
| 402 |   strcat(message2, "@");
 | 
|---|
| 403 |   fclose(fp);
 | 
|---|
| 404 | 
 | 
|---|
| 405 |   strncat(message2, message, SH_MAXMSG - strlen(message2) -1);
 | 
|---|
| 406 |   message2[SH_MAXMSG-1] = '\0';
 | 
|---|
| 407 |   strcpy(message, message2);
 | 
|---|
| 408 |   return;
 | 
|---|
| 409 | }
 | 
|---|
| 410 | 
 | 
|---|
| 411 | 
 | 
|---|
| 412 | int
 | 
|---|
| 413 | main (int argc, char * argv[])
 | 
|---|
| 414 | {
 | 
|---|
| 415 | 
 | 
|---|
| 416 |   char   message[SH_MAXMSG] = "";
 | 
|---|
| 417 |   char   clientcd[1024];
 | 
|---|
| 418 |   char   serversock[256];
 | 
|---|
| 419 |   int    status, size;
 | 
|---|
| 420 |   int    num = 1;
 | 
|---|
| 421 |   int    flag = 0;
 | 
|---|
| 422 |   
 | 
|---|
| 423 | #ifdef HAVE_VSNPRINTF
 | 
|---|
| 424 |   status = snprintf(serversock, 256, _("%s/%s.sock"), 
 | 
|---|
| 425 |                     DEFAULT_PIDDIR, SH_INSTALL_NAME);
 | 
|---|
| 426 | #else
 | 
|---|
| 427 |   if ((strlen(DEFAULT_PIDDIR) + strlen(SH_INSTALL_NAME) + 1 + 6) > 256)
 | 
|---|
| 428 |     {
 | 
|---|
| 429 |       status = -1;
 | 
|---|
| 430 |     }
 | 
|---|
| 431 |   else
 | 
|---|
| 432 |     {
 | 
|---|
| 433 |       status = sprintf (serversock, _("%s/%s.sock"), 
 | 
|---|
| 434 |                         DEFAULT_PIDDIR, SH_INSTALL_NAME);
 | 
|---|
| 435 |     }
 | 
|---|
| 436 | #endif
 | 
|---|
| 437 | 
 | 
|---|
| 438 |   if ((status < 0) || (status > 255))
 | 
|---|
| 439 |     {
 | 
|---|
| 440 |       fprintf(stderr, _("ERROR: Path too long (maximum 255): %s/%s.sock\n"), 
 | 
|---|
| 441 |               DEFAULT_PIDDIR, SH_INSTALL_NAME);
 | 
|---|
| 442 |       return (EXIT_FAILURE);
 | 
|---|
| 443 |     }
 | 
|---|
| 444 | 
 | 
|---|
| 445 |   while (argc > 1 && argv[num][0] == '-')
 | 
|---|
| 446 |     {
 | 
|---|
| 447 |       switch (argv[num][1]) 
 | 
|---|
| 448 |         {
 | 
|---|
| 449 |           case 'h':
 | 
|---|
| 450 |             usage(argv[0]);
 | 
|---|
| 451 |             return (EXIT_SUCCESS);
 | 
|---|
| 452 | 
 | 
|---|
| 453 |           case 'v':
 | 
|---|
| 454 |             ++verbose;
 | 
|---|
| 455 |             break;
 | 
|---|
| 456 | 
 | 
|---|
| 457 |           case 's':
 | 
|---|
| 458 |             --argc; ++num;
 | 
|---|
| 459 |             if (argv[num] == NULL || argv[num][0] == '\0') {
 | 
|---|
| 460 |               usage(argv[0]);
 | 
|---|
| 461 |               fprintf(stderr, _("ERROR: -s: argument missing\n"));
 | 
|---|
| 462 |               return (EXIT_FAILURE);
 | 
|---|
| 463 |             } else {
 | 
|---|
| 464 |               if (strlen(argv[num]) > 255) 
 | 
|---|
| 465 |                 {
 | 
|---|
| 466 |                   fprintf(stderr, _("ERROR: Path too long: %s\n"), argv[num]);
 | 
|---|
| 467 |                   return (EXIT_FAILURE);
 | 
|---|
| 468 |                 }
 | 
|---|
| 469 |               strncpy (serversock, argv[num], 256);
 | 
|---|
| 470 |               serversock[255] = '\0';
 | 
|---|
| 471 |             }
 | 
|---|
| 472 |             break;
 | 
|---|
| 473 | 
 | 
|---|
| 474 |           case 'c':
 | 
|---|
| 475 |             --argc; ++num;
 | 
|---|
| 476 |             if (argv[num] == NULL || argv[num][0] == '\0') {
 | 
|---|
| 477 |               usage(argv[0]);
 | 
|---|
| 478 |               fprintf(stderr, _("ERROR: -c: argument missing\n"));
 | 
|---|
| 479 |               return (EXIT_FAILURE);
 | 
|---|
| 480 |             } else {
 | 
|---|
| 481 |               if (strlen(argv[num]) >= SH_MAXMSG) 
 | 
|---|
| 482 |                 {
 | 
|---|
| 483 |                   fprintf(stderr, _("ERROR: Command too long: %s\n"), 
 | 
|---|
| 484 |                           argv[num]);
 | 
|---|
| 485 |                   return (EXIT_FAILURE);
 | 
|---|
| 486 |                 }
 | 
|---|
| 487 |               strncpy (message, argv[num], SH_MAXMSG);
 | 
|---|
| 488 |               message[SH_MAXMSG-1] = '\0';
 | 
|---|
| 489 |               strncat(message, ":", SH_MAXMSG-strlen(message)-1);
 | 
|---|
| 490 |               message[SH_MAXMSG-1] = '\0';
 | 
|---|
| 491 |               flag = 1;
 | 
|---|
| 492 |             }
 | 
|---|
| 493 |             break;
 | 
|---|
| 494 | 
 | 
|---|
| 495 |           default:
 | 
|---|
| 496 |             usage(argv[0]);
 | 
|---|
| 497 |             fprintf(stderr, _("ERROR: unknown option -%c\n"), argv[num][1]);
 | 
|---|
| 498 |             return (EXIT_FAILURE);
 | 
|---|
| 499 |         }
 | 
|---|
| 500 |       --argc; ++num;
 | 
|---|
| 501 |     }
 | 
|---|
| 502 | 
 | 
|---|
| 503 |   if (flag == 0) /* no command given */
 | 
|---|
| 504 |     {
 | 
|---|
| 505 |       usage(argv[0]);
 | 
|---|
| 506 |       return (EXIT_FAILURE);
 | 
|---|
| 507 |     }
 | 
|---|
| 508 | 
 | 
|---|
| 509 |   if (argc > 1)
 | 
|---|
| 510 |     {
 | 
|---|
| 511 |       if (strlen(argv[num]) > (SH_MAXMSG - strlen(message) -1)) 
 | 
|---|
| 512 |         {
 | 
|---|
| 513 |           fprintf(stderr, _("ERROR: Hostname too long: %s\n"), argv[num]);
 | 
|---|
| 514 |           return (EXIT_FAILURE);
 | 
|---|
| 515 |         }
 | 
|---|
| 516 |       strncat (message, argv[num], SH_MAXMSG -strlen(message) - 1);
 | 
|---|
| 517 |       message[SH_MAXMSG-1] = '\0';
 | 
|---|
| 518 |     }
 | 
|---|
| 519 |   else
 | 
|---|
| 520 |     {
 | 
|---|
| 521 |       if (message[0] == 'P' && message[1] == 'R' &&
 | 
|---|
| 522 |           message[2] == 'O' && message[3] == 'B' && message[4] == 'E' )
 | 
|---|
| 523 |         {
 | 
|---|
| 524 |           strncat (message, _("dummy"), SH_MAXMSG -strlen(message) - 1);
 | 
|---|
| 525 |           message[SH_MAXMSG-1] = '\0';
 | 
|---|
| 526 |         }
 | 
|---|
| 527 |       else if (message[0] == 'L' && message[1] == 'I' &&
 | 
|---|
| 528 |                message[2] == 'S' && message[3] == 'T')
 | 
|---|
| 529 |         {
 | 
|---|
| 530 |           strncat (message, _("dummy"), SH_MAXMSG -strlen(message) - 1);
 | 
|---|
| 531 |           message[SH_MAXMSG-1] = '\0';
 | 
|---|
| 532 |         }
 | 
|---|
| 533 |       else
 | 
|---|
| 534 |         {
 | 
|---|
| 535 |           fprintf(stderr, "ERROR: this command requires a hostname\n");
 | 
|---|
| 536 |           usage(argv[0]);
 | 
|---|
| 537 |           return (EXIT_FAILURE);
 | 
|---|
| 538 |         }
 | 
|---|
| 539 |     }
 | 
|---|
| 540 | 
 | 
|---|
| 541 |   fixup_message(message);
 | 
|---|
| 542 | 
 | 
|---|
| 543 |   /* OpenBSD wants >= 1024
 | 
|---|
| 544 |    */
 | 
|---|
| 545 |   if (NULL == getcwd(clientcd, 1024))
 | 
|---|
| 546 |     {
 | 
|---|
| 547 |       perror(_("ERROR: getcwd"));
 | 
|---|
| 548 |       return (EXIT_FAILURE);
 | 
|---|
| 549 |     }
 | 
|---|
| 550 |   size = strlen(clientcd) + 1 + strlen(CLIENT) + 6;
 | 
|---|
| 551 |   sockname = malloc (size);
 | 
|---|
| 552 |   if (!sockname)
 | 
|---|
| 553 |     {
 | 
|---|
| 554 |       perror(_("ERROR: main: malloc"));
 | 
|---|
| 555 |       return (EXIT_FAILURE);
 | 
|---|
| 556 |     }
 | 
|---|
| 557 |   sprintf(sockname, _("%s/%s.sock"), clientcd, CLIENT);
 | 
|---|
| 558 | 
 | 
|---|
| 559 | 
 | 
|---|
| 560 |   /* Make the socket.
 | 
|---|
| 561 |    */
 | 
|---|
| 562 |   sock = make_named_socket (sockname);
 | 
|---|
| 563 |   if (sock < 0)
 | 
|---|
| 564 |     {
 | 
|---|
| 565 |       return (EXIT_FAILURE);
 | 
|---|
| 566 |     }
 | 
|---|
| 567 | 
 | 
|---|
| 568 |   /* Set up termination handler.
 | 
|---|
| 569 |    */
 | 
|---|
| 570 |   signal (SIGINT,  termination_handler);
 | 
|---|
| 571 |   signal (SIGHUP,  termination_handler);
 | 
|---|
| 572 |   signal (SIGTERM, termination_handler);
 | 
|---|
| 573 |   signal (SIGQUIT, termination_handler);
 | 
|---|
| 574 | 
 | 
|---|
| 575 |   /* Send the datagram. 
 | 
|---|
| 576 |    */
 | 
|---|
| 577 |   status = send_to_server (serversock, message);
 | 
|---|
| 578 |   if (status < 0)
 | 
|---|
| 579 |     {
 | 
|---|
| 580 |       fprintf(stderr, _("ERROR: sending command to server failed\n"));
 | 
|---|
| 581 |       (void) termination_handler(0);
 | 
|---|
| 582 |       return (EXIT_FAILURE);
 | 
|---|
| 583 |     }
 | 
|---|
| 584 | 
 | 
|---|
| 585 |   /* Wait for a reply. 
 | 
|---|
| 586 |    */
 | 
|---|
| 587 |   if (message[0] == 'L' && message[1] == 'I' &&
 | 
|---|
| 588 |       message[2] == 'S' && message[3] == 'T')
 | 
|---|
| 589 |     {
 | 
|---|
| 590 |       if (verbose)
 | 
|---|
| 591 |         fprintf(stdout, _("# Waiting for listing.\n"));
 | 
|---|
| 592 |     }
 | 
|---|
| 593 |   else
 | 
|---|
| 594 |     {
 | 
|---|
| 595 |       if (verbose)
 | 
|---|
| 596 |         fprintf(stdout, _("# Waiting for confirmation.\n"));
 | 
|---|
| 597 |     }
 | 
|---|
| 598 |   status = recv_from_server (message);
 | 
|---|
| 599 | 
 | 
|---|
| 600 |   if (status < 0)
 | 
|---|
| 601 |     {
 | 
|---|
| 602 |       fprintf(stderr, _("ERROR: receiving data from server failed.\n"));
 | 
|---|
| 603 |       (void) termination_handler(0);
 | 
|---|
| 604 |       return (EXIT_FAILURE);
 | 
|---|
| 605 |     }
 | 
|---|
| 606 | 
 | 
|---|
| 607 |   /* Clean up. */
 | 
|---|
| 608 |   (void) termination_handler(0);
 | 
|---|
| 609 |   return (EXIT_SUCCESS);
 | 
|---|
| 610 | }
 | 
|---|
| 611 | 
 | 
|---|