Business IT - Technology for your business

No. 1 Story

Mobile operators get fixed price spectrum renewal in $3b Government windfall

The Government has offered Australia's three mobile operators, and vividwireless, renewal of their existing spectrum allocated on 15 year licences in the late 90s and early 2000s at set prices, while the Government expects to rake in $3 billion.

read more

Write your own Linux server part one

Business IT - Open Source

dwserv.cpp


/*
 *  DWSERV
 */

#include "dwserv.h"
#include <unistd.h>

#define VERSION "1.2\n"

bool logging = false;
bool verbose = false;
char FileName [PATH_MAX];

// ---------------------------------------------------------------------------
int main (int argc, char *argv [])
{
  struct sockaddr_in sin, fsin;
  struct protoent *ppe;
  int sock, ssock;
  socklen_t alen;
  int port = 6000;
  int qlen = 5;
  int pid;
  int fd;
  char nowtime [26];
  char Remote [80];
  int connections = 0;
  FILE *logfp = NULL;

  if (geteuid () != 0)
  {
    printf ("\n%s must be run with super-user privileges.\n", argv [0]);
    return 0;
  }

  FileName [0] = '\0';

// Process command line arguments.

  for (int i = 1; i < argc; i++)
  {
    if (strncmp (argv[i], "-p", 2) == 0)
      port = atoi (argv[i] + 2);

    else if (strncmp (argv[i], "-q", 2) == 0)
      qlen = atoi (argv[i] + 2);

    else if (strncmp (argv[i], "-f", 2) == 0)
    {
      strcpy (FileName, argv[i] + 2);
      logging = true;
    }
    else if (strncmp (argv[i], "-v", 2) == 0)
      verbose = logging = true;

    else if (strncmp (argv[i], "-l", 2) == 0)
      logging = true;

    else
    {
      DisplayHelpMessage (port, qlen);
      return 0;
    }
  }

// Set up the socket.

  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_port = htons (port);

  if ((ppe = getprotobyname ("tcp")) == 0)
    errexit ("Can't find tcp: %s\n", strerror (errno));

  if ((sock = socket (PF_INET, SOCK_STREAM, ppe->p_proto)) < 0)
    errexit ("Can't create socket: %s\n", strerror (errno));

  if (bind (sock, (struct sockaddr *) &sin, sizeof (sin)) < 0)
    errexit ("Can't bind to port: %s\n", strerror (errno));

  if (listen (sock, qlen) < 0)
    errexit ("Can't listen on port: %s\n", strerror (errno));

// Print a welcome banner.

  printf ("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
                  "   DWServ Server\n"
                  "      Port: %4d\n"
                  "   Version: %s"
                  "-----------------------------\n"
                  "by  David M. Williams\n"
                  "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n", port, VERSION);

  log ("Listening on port %d (qlen = %d).\n", port, qlen);

// Set up the server safely.

// 1. Run the server in the background ...

  if ((pid = fork ()) < 0)
    errexit ("Error setting up server: %s\n", strerror (errno));

  if (pid)  // Non-zero is parent.
  {
    printf ("Server pid is %d.\n", pid);
    if (strlen (FileName) > 0)
      log ("Server pid is %d.\n\n", pid);
    exit (0);
  }

// 2. Detach from controlling tty ...

  fd = open ("/dev/tty", O_RDWR);
  ioctl (fd, TIOCNOTTY, 0);
  close (fd);

// 3. Miscellaneous commands ...

  umask (027);
  chdir ("/tmp");

// Be the server !

  while (1)
  {
// Wait for connections. If one is made, then get a slave socket to
// process it, in a child process. This way the server remains free
// to accept more connections.

    alen = sizeof (fsin);
    ssock = accept (sock, (struct sockaddr *) &fsin, &alen);
    if (ssock < 0)
    {
      if (errno == EINTR)
        continue;
      else
        errexit ("accept: %s\n", strerror (errno));
    }

    strcpy (Remote, IPtoAddress (fsin.sin_addr));
    log ("%s: connect from %s\n", CurrentDateTime (nowtime), Remote);

    signal (SIGCHLD, reaper);
    connections++;
    if (fork () == 0)
    {
      process (ssock, Remote, connections);
      exit (0);
    }
    else
      close (ssock);
  }
}

// ---------------------------------------------------------------------------
void DisplayHelpMessage (int port, int qlen)
{
  printf ("\nDWServ Server\n\n");
  printf ("\t\tSyntax:\tdwserv [flags]\n\n");
  printf ("\t-pPORT\t\tto specify the port to use.\n");
  printf ("\t\t\t(default = %d)\n", port);
  printf ("\t-qQLEN\t\tto specify the queue length.\n");
  printf ("\t\t\t(default = %d)\n", qlen);
  printf ("\t-l\t\tto perform logging.\n");
  printf ("\t-fFILENAME\tto specify a log file.\n");
  printf ("\t\t\t(default = stdout)\n");
  printf ("\t-v\t\tto specify verbose logging.\n");
  printf ("\t\t\t(default = off)\n\n");
}

// ---------------------------------------------------------------------------
char *CurrentDateTime (char *nowtime)
{
  time_t now;

  time (&now);
  strcpy (nowtime, ctime (&now));
  nowtime [strlen (nowtime) - 1] = '\0';

  return nowtime;
}

// ---------------------------------------------------------------------------
void WriteToFD (int filedesc, char *s)
{
  write (filedesc, s, strlen (s));
}

// ---------------------------------------------------------------------------
void log (const char *format, ...)
{
  va_list  args;
  FILE  *fp;

  if (logging)
  {
    fp = stdout;

    if (strlen (FileName) > 0)
    {
      if ((fp = fopen (FileName, "a")) < 0)
        fp = stdout;
    }

    va_start (args, format);
    vfprintf (fp, format, args);
    va_end (args);

    if (fp != stdout)
      fclose (fp);
  }
}

// ---------------------------------------------------------------------------
int errexit (const char *format, ...)
{
  va_list args;
  char errstr [255];

  va_start (args, format);
  vsprintf (errstr, format, args);
  log (errstr);
  fprintf (stderr, errstr);
  va_end (args);

  exit (1);
}

// ---------------------------------------------------------------------------
const char *IPtoAddress (struct in_addr ipA)
{
  unsigned long hostname;
  struct hostent *ip;

  hostname = inet_addr (inet_ntoa (ipA));

  if ((ip = gethostbyaddr ((char *) &hostname, sizeof (long), AF_INET))<0)
    return "unknown";
  else
    return ip->h_name;
}

// ---------------------------------------------------------------------------
void reaper (int sig)
// The reaper cleans up zombie children processes.
// In Unix, when a child process terminates it sends a message back to
// the parent process.  Unless this message is handled, the child process
// will wait around forever taking up resources.
{
  int status;

  wait3 (&status, WNOHANG, (struct rusage *) 0);
}

// ---------------------------------------------------------------------------
void process (int ssock, char *Remote, int connections)
// This function handles the processing of a socket connection.
{
  StringVector *svec = new StringVector;
  int count = 0, n;
  char TmpBuf [LINELEN], InMsg [LINELEN];
  char OutMsg [MAX_STRING];
  char Command [5], Data [97];
  char nowtime [26];
  bool keepgoing = true;

// Display an innocent banner (anything to hide the real purpose).

  while (count < 3)
  {
    sprintf (OutMsg, "%s\n", CurrentDateTime (nowtime));
    WriteToFD (ssock, OutMsg);

    if ((n = read (ssock, InMsg, LINELEN - 1)) > 0)
    {
      InMsg [n] = '\0';

// Strip CR's and LF's
      if ((InMsg [strlen (InMsg) - 1] == 10) ||
         (InMsg [strlen (InMsg) - 1] == 13))
        InMsg [strlen (InMsg) - 1] = '\0';
      if ((InMsg [strlen (InMsg) - 1] == 10) ||
         (InMsg [strlen (InMsg) - 1] == 13))
        InMsg [strlen (InMsg) - 1] = '\0';

      if (strcmp (InMsg, SECRET_PASSWORD) == 0)
        count = 999;
    }

    count++;
  }

  if (count < 900)
  {
    close (ssock);
    return;
  }

// Loop until exit or connection lost.

  keepgoing = true;
  while (keepgoing)
  {

// Read input.
    WriteToFD (ssock, "");      // Send no prompt.

    if ((n = read (ssock, InMsg, LINELEN - 1)) <= 0)
      keepgoing = false;  // No more.
    else
      InMsg [n] = '\0';

// Process input.
    strcpy (OutMsg, "");

    if (keepgoing)
    {
      StripString (InMsg, Command, Data);

// Here are the main functions ...

// Aliases
      if (strcmp (Command, "ALIA") == 0)
        GetAliases (Data, OutMsg);

// Groups
      else if (strcmp (Command, "GROU") == 0)
        GetGroup (Data, OutMsg);

// Make new account
      else if (strcmp (Command, "MAKE") == 0)
        CreateAccount (Data, OutMsg);

// Start a process
      else if (strcmp (Command, "STRT") == 0)
        StartProcess (Data, OutMsg);

// Return the version number
      else if (strcmp (Command, "VERS") == 0)
        strcpy (OutMsg, VERSION);

// Miscellaneous commands ...

      else if (strcmp (Command, "QUIT") == 0)
      {
        keepgoing = false;
        strcpy (OutMsg, "");
      }

      else if (strcmp (Command, "STAT") == 0)
        sprintf (OutMsg, "%d connections.\n", connections);

      else
        sprintf (OutMsg, "");

      if (strlen (OutMsg) > 0)
        WriteToFD (ssock, OutMsg);

      if (verbose)
        log ("%d  %s\t%s\t%s\t%s\n", connections, Remote, Command,
                  Data, OutMsg);
    }

// And loop again!
  }

// Close the socket and finish !
  close (ssock);
}

// ---------------------------------------------------------------------------
void StripString (char *InMsg, char *Command, char *Data)
{
  int i, count;

  while (strlen (InMsg) < 4)
    strcat (InMsg, " ");

  for (i = 0; i < 4; i++)
    Command [i] = toupper (InMsg [i]);
  Command [i] = '\0';

  while ((InMsg [i] != ' ') && (InMsg [i] != '\0'))
    i++;

  while ((InMsg [i] == ' ') && (InMsg [i] != '\0'))
    i++;

  count = 0;
  while ((InMsg [i] != '\0') && (InMsg [i] != 13) && (InMsg [i] != 10))
    Data [count++] = InMsg [i++];
  Data [count] = '\0';
}

Loading comments ...



- sponsored feature -

The Death of Traditional BI: What’s Next?

How to Make Business Discovery Work for Your Business IP PABX BUYING GUIDE

Business Discovery takes its cues from consumer apps. Like Google, it encourages us- ers to hunt for and explore data without worrying about or even noticing the underly- ing technology. Their entire experience is working within an intuitive interface to get real-time, self-service results with only minimal training. ...more