From: shulick@navajo.ucs.indiana.edu (Sam Hulick)
Subject: Enough talk.  FILE: server.c
Originator: shulick@navajo
Reply-To: shulick@navajo.ucs.indiana.edu
Organization: Vallen Software
Date: Fri, 8 Jan 1993 07:35:28 GMT


Well, I've complained enough about memory leaks.  =u)  Here's the server
I wrote that is faulty.  About 8k bytes are not freed, and I can't
figure out why.

Compiling instructions (SAS 5.10b)
lc1 server
lc2 server
blink lib:c.o server.o lib lib:lc.lib lib:amiga.lib DEFINE __main=__tinymain
(6.0/6.1 users, I think NOSTDOUT is what you do to make it detach)

Note, there's a sleep() function in here.  sorry.  =u)  It's in one of
my custom libraries.  sleep(x) = Delay(50*x), that's all.  PLEASE
contact me if you find out why this program leaks.  Thank you.

(two files below: server.c foomsg.h)
-----cut here-------------------------------------------
/*** BEGIN SERVER.C ***/
/* This code is free.  Sell it, change it, erase it, distribute it, puke on
it.  I don't care!! :)  I'll try to comment this as best I can.. */
/* oh, keep in mind, this was done w/ SAS/C 5.10b. */

#include <stdio.h>
#include <exec/exec.h>
#include <exec/ports.h>
#include <exec/types.h>
#include <exec/alerts.h>
#include <clib/exec_protos.h>
#include <intuition/intuition.h>
#include "foomsg.h"

#define SERVER_RUNNING  0
#define SERVER_OK       1
#define SERVER_FULL     2

void FlushPort(struct MsgPort *);
struct Library *IntuitionBase = NULL, *GfxBase = NULL;
struct Window *win;
struct MsgPort *myport;
struct NewWindow newwin = {
   0, 0, 320, 50, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   0, 0, 0, 0, WBENCHSCREEN
};
struct EasyStruct ereq[3] = {
   {
      sizeof(struct EasyStruct), 0, "Problem",
      "Server already running!\nShut down?",
      "Yes|No"
   },
   {
      sizeof(struct EasyStruct), 0, "Confirmation",
      "Server is now running!",
      "Groovy"
   },
   {
      sizeof(struct EasyStruct), 0, "Problem",
      "*grunt* This string is getting too big!\nShall I reset it?",
      "Sure|No, just quit"
   }
};

void shutdown(struct MsgPort *);

void main(int ac, char **av)
{
   char catmsg[30+1] = {0};
   struct FooMessage *msg;
   int done = FALSE;

   if (!(IntuitionBase = (struct Library *)
     OpenLibrary("intuition.library", 37)))
   {
      Alert(AG_OpenLib | AO_Intuition);
      exit(0);
   }
   if (!(GfxBase = (struct Library *)OpenLibrary("graphics.library", 37)))
   {
      Alert(AG_OpenLib | AO_GraphicsLib);
      exit(0);
   }
   Forbid();
   myport = FindPort("Foobar!");  /*Is the server already running..? */
   Permit();
   if (myport)  /* Yup */
   {
      if (EasyRequest(NULL, &ereq[SERVER_RUNNING], NULL))
         shutdown(myport);  /* Either shut down */
      else  /* Or remain running */
      {
         CloseLibrary(GfxBase);
         CloseLibrary(IntuitionBase);
         exit(0);
      }
   }                                   /* If we don't exist, */
   if (!(myport = CreateMsgPort()))  /* Create the port.. */
   {
      Alert(AN_CreatePort);
      exit(0);
   }
   myport->mp_Node.ln_Name = "Foobar!";
   myport->mp_Node.ln_Pri = 0;
   AddPort(myport);  /* Now we're a public port, anyone can access us */

   EasyRequest(NULL, &ereq[SERVER_OK], NULL);  /* Tell user we're up! */

   while (!done) {
      WaitPort(myport); /* Wait for an incoming message. */
      while ((msg = (struct FooMsg *)GetMsg(myport)))  /* Got one...! */
      {
  /* Ignore the catmsg stuff.  I have a 'send' program where you */
  /* can send strings to the server, which keeps concatenating them. */
  /* In this case, the 'send' client is irrelevant. */
         if (strlen(catmsg) + strlen(msg->message) > 30)
         {
            if (EasyRequest(NULL, &ereq[SERVER_FULL], NULL))
               strcpy(catmsg, "\0");
            else
               done = TRUE;
         }
         else
         {
            if (!(win = (struct Window *)OpenWindow(&newwin)))
            {
               Alert(AN_OpenWindow);
               exit(0);
            }
            strcat(catmsg, msg->message);
            Move(win->RPort, 10, 20);
            Text(win->RPort, catmsg, strlen(catmsg));
            sleep(3);
            CloseWindow(win);
            if (!strcmp(msg->message, "QUIT"))
               done = TRUE;
         }
      }
  }
  shutdown(myport);
}

void shutdown(struct MsgPort *victim)
{
  FlushPort(victim);  /* Empty the queue (see func below) */
  RemPort(victim);  /* We're no longer public.. */
  DeleteMsgPort(victim); /* And now we don't exist. :) */
  CloseLibrary(IntuitionBase);
  CloseLibrary(GfxBase);
  exit(0);
}

void FlushPort(struct MsgPort *thePort)
{
   struct Message *mesg;

   while ((mesg = GetMsg(thePort)))  /* There's a message here.. */
      ReplyMsg(mesg);              /* Kiss it goodbye */
}
/*** END OF SERVER.C ***/

/*** BEGIN FOOMSG.H ***/
struct FooMessage
{
   struct Message msg;
   char message[50];   /* so we can pass strings to the server */
};                  /* and so the server can interpret them. */
/* end */
-- 
    // Amiga 3000   ___ \ Sam Hulick: shulick@indiana.edu (NeXTmail OK!)
   // 68030 25 MHz /__/\ \ My opinions wear combat boots.  Or whatever.
\\// OS 2.04       \__\/ / "Walk!  Not bloody likely.  I am going in a
 \/                     / taxi."  --George Bernard Shaw
Newsgroups: comp.sys.amiga.programmer