 /*
  * read the services file looking for a particular service.  returns a
  * struct describing that service if found or NULL if not found (or an error
  * occurs).  format of lines in the service file are:
  * 
  * ; indicates start of a comment
  * 
  * <service name> <phone number> <baud rate> <mage page length> <multiblock>
  */

#include "memory.h"

#define TEMPLATE "NAME/A,PHONE/A,BAUD/N/A,MAXPAGELEN/N/A,MULTIBLOCK/A,PASSWORD/A,USE8N1/A"
  enum templateArgs {
	  ARG_NAME,
	  ARG_PHONE,
	  ARG_BAUD,
	  ARG_LEN,
	  ARG_MBLK,
	  ARG_PASSWORD,
	  ARG_USE8N1,
	  ARG_sizeof
  };

#define INPUT_BUFFER_SIZE (1024)

PagerService_t *__saveds __asm FindPagerService(register __a0 PagerHandle_t * ph, register __a1 STRPTR serviceName)
{
	PrivatePagerService_t *psvc;
	PagerService_t *svc;
	ULONG line = 0;
	STRPTR inputBuffer, ptr;
	struct RDArgs *ArgsPtr, *MyArgs;
	char *ArgArray[ARG_sizeof];
	BOOL leave;
	BPTR fh;

	ObtainSemaphore(&ph->ph_Sema);

	/* first look to see if we have already read this service in */

	for (psvc = (PrivatePagerService_t *) ph->ph_ServiceList.mlh_Head;
	     psvc->psvc_Node.mln_Succ;
	     psvc = (PrivatePagerService_t *) psvc->psvc_Node.mln_Succ)
		if (stricmp(serviceName, psvc->psvc_Service.svc_Name) == 0) {
			psvc->psvc_UseCount++;
			ReleaseSemaphore(&ph->ph_Sema);
			return &psvc->psvc_Service;
		}

	/*
	 * oh, well.  need to read the services file to find information on
	 * this service
	 */

	svc = NULL;

	if (inputBuffer = MyAllocVec(INPUT_BUFFER_SIZE)) {
		/* try and open the services file */

		if (fh = Open("pager:services", MODE_OLDFILE)) {
			/* loop reading lines looking for the service desired */

			leave = FALSE;

			while (leave == FALSE && FGets(fh, inputBuffer, INPUT_BUFFER_SIZE - 1)) {
				line++;

				/*
				 * check to make sure the line isn't all
				 * blank
				 */

				ptr = inputBuffer;
				while (isspace(*ptr))
					ptr++;

				if (!*ptr)
					continue;

				/*
				 * check for comment character at beginning
				 * of line
				 */

				if (*ptr == ';')
					continue;

				/* setup to call ReadArgs() to parse the line */

				if (MyArgs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, TAG_DONE)) {
					MyArgs->RDA_Flags |= RDAF_NOPROMPT;
					MyArgs->RDA_Source.CS_Buffer = inputBuffer;
					MyArgs->RDA_Source.CS_Length = strlen(inputBuffer);
					MyArgs->RDA_Source.CS_CurChr = 0L;

					memset((char *)ArgArray, 0, sizeof(ArgArray));
					if (ArgsPtr = ReadArgs(TEMPLATE, (LONG *)&ArgArray, MyArgs)) {
						if (stricmp(serviceName, ArgArray[ARG_NAME]) == 0) {

							/*
							 * we've found the
							 * service so
							 * allocate and fill
							 * in a service
							 * structure
							 */
							leave = TRUE;

							if (strlen(ArgArray[ARG_PASSWORD]) + 1 > sizeof(svc->svc_Password)) {
								ULog(ph, -1, "Password too long in services file - line %ld: %s", line, inputBuffer);
							}
							else if (psvc = (PrivatePagerService_t *) MyAllocVec(sizeof(PrivatePagerService_t) + strlen(ArgArray[ARG_NAME]) + strlen(ArgArray[ARG_PHONE]) + 2)) {
								psvc->psvc_Handle = ph;
								psvc->psvc_UseCount = 1;
								AddTail((struct List *)&ph->ph_ServiceList, (struct Node *)&psvc->psvc_Node);

								svc = &psvc->psvc_Service;

								svc->svc_Name = (STRPTR)&svc[1];
								svc->svc_Phone = svc->svc_Name + strlen(ArgArray[ARG_NAME]) + 1;

								strcpy(svc->svc_Name, ArgArray[ARG_NAME]);
								strcpy(svc->svc_Phone, ArgArray[ARG_PHONE]);
								strcpy(svc->svc_Password, ArgArray[ARG_PASSWORD]);
								svc->svc_BaudRate = *((LONG *)ArgArray[ARG_BAUD]);
								svc->svc_MaxPageLen = *((LONG *)ArgArray[ARG_LEN]);
								svc->svc_MultiBlock = PagerConfigYesNo(ArgArray[ARG_MBLK]);
								svc->svc_Use8N1 = PagerConfigYesNo(ArgArray[ARG_USE8N1]);
							}
						}

						FreeArgs(ArgsPtr);
					}
					else {
						Fault(IoErr(), NULL, inputBuffer, INPUT_BUFFER_SIZE - 1);
						ULog(ph, -1, "Error in services file - line %ld: %s", line, inputBuffer);
						leave = TRUE;
					}

					FreeDosObject(DOS_RDARGS, MyArgs);
				}
			}

			Close(fh);
		}
		else
			ULog(ph, -1, "Couldn't open services file");

		MyFreeVec(inputBuffer);
	}

	ReleaseSemaphore(&ph->ph_Sema);

	return svc;
}

void __saveds __asm FreePagerService(register __a0 PagerService_t * svc)
{
	PrivatePagerService_t *psvc;

	if (svc) {
		psvc = (PrivatePagerService_t *) ((size_t) svc - offsetof(PrivatePagerService_t, psvc_Service));

		ObtainSemaphore(&psvc->psvc_Handle->ph_Sema);

		if (--psvc->psvc_UseCount == 0) {
			Remove((struct Node *)&psvc->psvc_Node);
			MyFreeVec(svc);
		}

		ReleaseSemaphore(&psvc->psvc_Handle->ph_Sema);
	}
}
