TweetFollow Us on Twitter

MacSockets
Volume Number:7
Issue Number:12
Column Tag:Com Workshop

Related Info: Device Manager

Library for UNIX-based Clients

By Frank Storbeck, The Netherlands

Introduction.

From the moment that Apple Computer, Inc. came with its UDP-TCP/IP driver for the Macintosh, there was suddenly an increased potential for use of client-server programs as developed in the UNIX-world. Alas, Apple came with its own calls for addressing their UDP-TCP/IP driver (“.IPP”). The calls are essentially the standard low level PBOpen, PBControl and PBClose calls from the DeviceManager. The software includes a file named “TCPPB.h”, in which one finds the definitions for the various DeviceManager calls for the .IPP-driver. However it would be easy if one could use the standard UNIX calls for socket-based communication instead. This gives you the opportunity to port the UNIX software to the Mac. So I started to write a small library with the .IPP equivalents for the client-functions close, connect, recv, recvfrom, recvmsg, send, sendto, sendmsg, shutdown, and socket. To use the Mac as a server, you also need the equivalents of the functions accept, bind, listen and select, but, as I only needed the client-software, I left them out of the project. There are also some other constraints. These will be addressed in the next paragraph. To use the MacTCP software you need a Mac-512E or better and the appropriate LocalTalk- or Ethernet-compatible hardware.

The MacTCP package is available as a single-user developer kit (APDA™ # M0230LL/D). It contains the MacTCP software, a programmers guide and an administrator guide. A licence is required to redistribute the software.

Sockets.

In the manual titled “Network Programming Guide” from SUN®-microsystems (part number 800-3850-10) you can find a good explanation of the in’s and out’s of “Socket-Based Interprocess Communication”. Here only a short summary will follow.

Normally some host sets up a particular service. A client that wants to communicate with this server has to know the address of the host and what is called the port-number of the service. For the standard UNIX-services these port-numbers are “well known” (here I quoted from the manual pages), but if you want to start to offer a new service there is a range of numbers from which you can choose. In the example given here for the use of the code I choose the value 31768 (in a UNIX-system these values for the port-numbers can be found in the file /etc/services).

A socket-pair is a “two way communication channel between two processes”. Each of these processes has a socket that can be used both for sending and receiving of data to and from the other process. The processes may reside on the same or different hosts, but they have to use the same address domains, the same communication method and the same protocol. As I had to use the software for a special project for communication on board of a research vessel, I allowed some more constraints to the software: only internet addressing mode (AF_INET), stream-sockets (SOCK_STREAM) and of course the TCP-IP protocol are supported.

Normally a server-program runs on a host for as long as possible (i.e. between start-up and shut-down). It then waits for the action of some client-program. The client tries to connect to the server, sends a message that it wants some service and then waits for the answer from the server. This can go on for as long as the service is needed. Then the connection is closed down and the server waits for the next client to be served. It is also possible that a server works for more than one client simultaneously. In this case it has a socket for each of the various clients to be served.

The client and server programs

This scheme shows up in the sample code for client.c and server.c that can be found in the listing. They are examples of how to use the calls to the functions for the socket-based communication. After the server has been activated, the client can be started, and it sends the following message to the server:

From: client

To: server

Mssg: Hello server!

Then the server replies with another message:

From: server

To: client

Mssg: Hello client!\n

The server has to be run on some SUN workstation (because of the call bcopy, replace it eventually with the ANSI-C call memcpy, but beware, the order of the parameters is different; also there is a function bzero to clear the memory locations over some range - if not present, deactivate it: the locations will be overwritten by the message anyhow!) The client has been compiled with THINK-C (4.0) compiler. The THINK-C project must also contain the ANSI, MacTraps and UNIX libraries.

The client-program can also be run on a SUN workstation. Just activate the SUN_C macro.

Of course you can change client and server as you like. You can maintain the connection until the client sends some bye-bye message, messages can be sent in chunks etc. etc. Do as you like.

Diagram 1: Sequence for communication between some server and one or more clients.

Some notes on the library

MacTCP provides the use of an asynchronous notification routine. This means that when some exception occurs, a user specified function can be activated. This is here implemented by the function SockNotify, which is hidden to the user. It calls the function DoAlert that draws an alert box on the screen displaying the appropriate massage for some time. The default showing time is 4 seconds, but can be changed with the function SetDialogShowTime. When the time is zero or negative, no DialogBox will be shown. The function DoAlert is also used by the function perror. In this case a stopIcon and an OK-button are added. The DialogBox shows the error message until the user clicks on the OK-button. As the function cannot be sure that a resource for the DialogBox and its DialogItemList is available, it is built up in memory. Note that to use it, you must initialize the DialogManager etc., otherwise your Mac behaves like the mother of all field-battles. All this can be switched off by deactivating the MAC_APPL macro. In this case the messages will be shown on stderr, using the console-library from THINK-C.

There are some extra routines added: close_MacSocket, exit_MacSocket, perror_MacSocket, and strerror_MacSocket,. They are used to prevent direct calls to their UNIX and ANSI-C equivalents close, exit, perror and strerror. In the file MacSocket.h there are macros that make sure that these calls will be diverted to their equivalents in the MacSocket library. e.g., if you call close, close_MacSocket first tries to close a socket-based connection. If the socket doesn’t exist, it calls the standard function close. This is a particular noteworthy example: you might have a file descriptor with number 5 and a socket with number 5. The only way to close the file with file-descriptor 5 while keeping the socket with number 5 in good shape is calling close directly:

/* 1 */

#undef close /* to dactivate a call to close_MacSocket */
close(5);
#define close close_MacSocket /* to reactivate it */

The program includes some files that are not provided here: “types.h”, “socket.h, “in.h”, “netdb.h” and “TCPPB.h”. The first four come from the SUNOS 4.1 operating system and are copyrighted by the Regents of the University of California I am not sure if I can redistribute them, so they are not included. But if you want to port software from a UNIX-platform to the Mac, you must have access to them anyhow. The file “TCPPB.h” is copyrighted by Apple Computer, Inc.

Last note: the program was written using SUNOS 4.0. Now we are using version 4.1. There they don’t speak about “address families” but about “address protocols”. Hence the macro AF_INET has been renamed to AP_INET, but AF_INET still works.

Listings server.c:
/***
 ***
 *** To send data between stream sockets (having communication 
 *** style SOCK_STREAM)
 *** Code based on an example taken from SUN® Network Program
 *** ming Guide,chapter 10, A Socket-Based Interprocess 
 *** Communications Tutorial,Revision A, of 27 March 1990, 
 *** Fig. 10-11, pp. 270-271.
 ***/
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/time.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#define TRUE(1)
#define DATA“\nFrom: server\nTo:   client\nMssg: Hello client!\n”
#define Port(31768)

main()
{
 int    sock, length;
 struct sockaddr_in server;
 int    msgsock;
 char buf[1024];
 fd_set ready;
 struct timeval  to;

 /* Create socket. */
 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock < 0)
 {
 perror(“Server--> opening stream socket”);
 exit(1);
 }
 /* Name socket using wildcards. */
 server.sin_family = AF_INET;
 server.sin_addr.s_addr = INADDR_ANY;
 server.sin_port = Port;
 if (bind(sock, (struct sockadd *)&server, sizeof server) < 0)
 {
 perror(“Server--> getting socket name”);
 exit(1);
 }
 printf(“Server--> Socket port #%d\n”, ntohs(server.sin_port));

 /* Start accepting connections. */
 listen(sock, 5);
 do
 {
 FD_ZERO(&ready);
 FD_SET(sock, &ready);
 to.tv_sec = 5;
 if (select(sock + 1, &ready, (fd_set *)0, (fd_set *)0, &to) < 0)
 {
 perror(“Server--> select”);
 continue;
 }
 if (FD_ISSET(sock, &ready))
 {
 msgsock = accept(sock, (struct sockaddr *) 0, (int *) 0);
 if (msgsock == -1)
 {
 perror(“Server--> accept”);
 }
 else
 {
 bzero(buf, sizeof buf);
 if ((length = recv(msgsock, buf, 1024, 0)) < 0)
 {
 perror(“Server--> reading stream message”);
 }
 else
 {
 buf[length] = ‘\0’;
 printf(“Server-->%s\n”, buf);
 }
 if (send(msgsock, DATA, sizeof DATA, 0) < 0)
 {
 perror(“Server--> sending steam message”);
 }
 }
 close(msgsock);
 }
 else
 {
 /* Do something else. */
 }
 } while (TRUE);
 exit(0);
}
Listing:  socket.h
/***
 *** Copyright (c) 1990 Rijksinstituut voor Visserijonderzoek.
 *** All rights reserved.
 ***
 *** Redistribution and use in source and binary forms are 
 *** permitted provided that this notice is preserved and that 
 *** due credit is given to the Rijksinstituut voor Visserijonderzoek 
at IJmuiden.
 *** This software is provided “as is” without express or implied warranty.
 ***
 *** @(#)MacSocket.h 1.2 91/01/25
 ***/

#ifndef _MacSocket_H_
#define _MacSocket_H_

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unix.h>
#include<DeviceMgr.h>

#include“types.h”
#include“socket.h”
#include“in.h”
#include“netdb.h”
#include“TCPPB.h”

#ifdef  LAB_VIEW

/* to prevent the use of the malloc() call in a LabVIEW CIN */
#define SockElmnttheSockElmnt
#define SizeOf(x)x
#define malloc(x)&x

#else

#define SizeOf sizeof

#endif  LAB_VIEW

#ifndef NIL
#define NIL ((void*) 0L)
#endif  NIL
#ifndef InFrontOfAll
#define InFrontOfAll ((Ptr) -1L)
#endif  InFrontOfAll
#ifndef True
#define True(1)
#endif  True
#ifndef False
#define False    (0)
#endif  False
#define Abort    True
#define ReportIt False
#define Asynchronous True
#define SynchronousFalse
#define ConnectTimeout  (15)
#define SendTimeout(15)
#define RecvTimeout(15)
#define CloseTimeout (15)
#define SockBufSize(16384)
#define UserDataSize (128)

#define noTCPDriver(-1)
#define invalidArgument (2)
#define nonSOCK_STREAM  (13)
#define nonSocket(38)
#define nonAF_INET (43)
#define noBufSpace (55)
#define commandInProgress (1)

/* to force the application first to use the MacSocket versions */
#define perror   perror_MacSocket
#define exitexit_MacSocket
#define close    close_MacSocket
#define strerror strerror_MacSocket

/* Prototypes */
intaccept(int s, struct sockaddr *addr, int addrlen);
intbind(int s, struct sockaddr *name, int namelen);
intclose_MacSocket(int s);
intconnect(int s, struct sockaddr_in *name, int namelen);
void  exit_MacSocket(int status);
intlisten(int s, int backlog);
void  perror_MacSocket(char *s);
intrecv(int s, char *msg, int len, int flags);
intrecvfrom(int s, char *msg, int len, int flags, struct sockaddr_in 
*from,
 int *fromlen);
intrecvmsg(int s, struct msghdr *msg, int flags);
intsend(int s, char *msg, int len, int flags);
intsendto(int s, char *msg, int len, int flags, struct sockaddr_in *to,
 int tolen);
intsendmsg(int s, struct msghdr *msg, int flags);
intshutdown(int s, int how);
#ifdef  MAC_APPL
void  SetDialogShowTime(int sec);
#endif  MAC_APPL
intsocket(int domain, int type, int protocol);
char* strerror_MacSocket(int errnum);

#endif _MacSocket_H_
Listing:  client.c
/***
 ***
 *** To send data between stream sockets (having communication style
 *** SOCK_STREAM)
 *** Code based on an example taken from SUN® Network Programming Guide,
 *** chapter 10, A Socket-Based Interprocess Communications Tutorial,
 *** Revision A, of 27 March 1990, Fig. 10-9, pp. 266-267.
 ***
 ***/

#ifdef  SUN_C
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#else SUN_C
/*
#define MAC_APPL
*/
#include<console.h>
#include“MacSocket.h”
#define bcopy(s1, s2, n)  memcpy((s2), (s1), (n))
#endif  SUN_C

#define Port(31768)
#define DATA“\nFrom: client\nTo:   server\nMssg: Hello server!\n”

main()
{
 int    sock, mssgSize;
 struct sockaddr_in server;
 union
 {
 long   address;
 unsigned char domain[4];
 } host;
 char buf[1024];
 
#ifdef  MAC_APPL
 /* prevent showing informative MacTCP/IP messages */
 SetDialogShowTime(0);
#endif  MAC_APPL
 
 /* Create socket. */
 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock < 0)
 {
 perror(“opening stream socket”);
 exit(1);
 }
 /* Connect socket using address 192.6.1.30 and port# */
 server.sin_family = AF_INET;
 host.domain[0] = 192;
 host.domain[1] = 6;
 host.domain[2] = 1;
 host.domain[3] = 30;
 bcopy((char*)&host.address, (char*)&server.sin_addr, 4);
 server.sin_port = Port;

 if (connect(sock, (struct sockaddr_in *)&server, sizeof server) < 0)
 {
 perror(“connecting stream socket”);
 exit(1);
 }
 if (send(sock, DATA, sizeof DATA, 0) < 0)
 {
 perror(“writing on stream socket”);
 exit(1);
 }
 if ((mssgSize = recv(sock, buf, sizeof buf, 0)) < 0)
 {
 perror(“reading on stream socket”);
 exit(1);
 }
 buf[mssgSize] = ‘\0’;
 printf(“Client--> %s\n”, buf);
 close(sock);
 exit(0);
}
Listing:  MacSocket.c
/***
 *** Copyright (c) 1990 Rijksinstituut voor Visserijonderzoek, IJmuiden.
 *** All rights reserved.
 ***
 *** Redistribution and use in source and binary forms are permitted
 *** provided that this notice is preserved and that due credit is given
 *** to the Rijksinstituut voor Visserijonderzoek at IJmuiden.
 *** This software is provided “as is” without express or implied warranty.
 ***
 *** @(#)MacSocket.c 1.7 91/04/04
 ***/

/*
#define MAC_APPL
*/
#include“MacSocket.h”

#define Connected(0x01)

typedef struct SockElmnt
{
 int    number;
 struct SockElmnt*next;
 TCPiopbthePB;
 char   sockBuf[SockBufSize];
} SockElmnt, *SockElmntPtr, **SockElmntHdl;

#ifdef  MAC_APPL

#define LineLength (350)
#define AMargin  (13)
#define BMargin  (23)
#define IconSize (32)
#define DlogTop  (66)
#define DlogLeft (50)
#define ButtonHeight (22)
#define ButtonLength (59)

typedef struct AlertDitl
{
 unsigned short  nItems;
 Handle textHandle;
 Rect   textRect;
 unsigned char text;
 unsigned char textSize;
 char   textString[8];
 Handle buttonHandle;
 Rect   buttonRect;
 unsigned char button;
 unsigned char buttonSize;
 char   buttonString[2];
 Handle iconHandle;
 Rect   iconRect;
 unsigned char icon;
 unsigned char iconSize;
 unsigned short  iconId;
 Handle outlineHandle;
 Rect   outlineRect;
 unsigned char outline;
 unsigned char outlineSize;
} AlertDitl, *AlertDitlPtr, **AlertDitlHdl;

#endif  MAC_APPL

#ifdef  close
#undef  close
#endif  close

#ifdef  exit
#undef  exit
#ifdef  MAC_APPL
#define exit(s)  ExitToShell()
#endif  MAC_APPL
#endif  exit

#ifdef  perror
#undef  perror
#endif  perror

#ifdef  strerror
#undef  strerror
#endif  strerror

/**
 **
 ** local prototypes
 **
 **/
static  voidDoAlert(int alertId, char* s1, char* s2, char* s3, char* 
s4);
static  SockElmntPtr CreateSocketStruct(void);
static  SockElmntPtr FindSocketStruct(int);
static  int OpenTCPDriver(void);
static  pascal voidOutlineProc(DialogPtr thePtr, int theItem);
static  voidPollTCPDriver(TCPiopb *thePB);
static  int RemoveSocketStruct(int);
static  pascal voidSockNotify(StreamPtr tcpStream,
 unsigned short eventCode,
 Ptr userDataPtr,
 unsigned short terminReason,
 struct ICMPReport *icmpMsg);

/**
 **
 ** local variables
 **
 **/
static  int errno_MacSocket = noErr;
static  int ioRefNumTCP;
static  charmacSocketErrorMssg[128] = “no error!”;
static  int showTime = 4;
static  int sockNumber = 4;
static  SockElmntPtr theHeadPtr = NIL;
static  charTCPDriverName[] = “\p.IPP”;
static  chartheUserData[UserDataSize];
static  charTCPDriverNotOpened = True;

#ifdef  LAB_VIEW

static  SockElmnttheSockElmnt;

#endif  LAB_VIEW

/***
 ***
 *** Mac versions the standard Socket-based internet communication protocol:
 ***
 ***/

/**
 **
 ** Local functions
 **
 **/

/*
 *
 * CreateSocketStruct - creates a data structure for a particular socket 
into a
 * linked list
 *
 */
static  SockElmntPtr CreateSocketStruct()
{
 register SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = (SockElmntPtr)malloc(SizeOf(SockElmnt))) == NIL)
 {
 errno_MacSocket = noBufSpace;
 return (NIL);
 }
 theSockPtr->next = theHeadPtr;
 theHeadPtr = theSockPtr;
 theSockPtr->number = ++sockNumber;
 return (theSockPtr);
}

#ifdef  MAC_APPL
/*
 *
 * DoAlert - shows an alert message on the screen. When alertId is negative,
 * no icon and OK-button are displayed. The Alert message is then “showTime”
 * seconds visible.
 *
 */
static void DoAlert(int alertId, char* s1, char* s2, char* s3, char* 
s4)
{
 AlertDitlPtr  theAlertDitlPtr;
 AlertDitlHdl  theAlertDitlHdl;
 DialogRecord  dlogRecord;
 DialogPtrtheDlogPtr;
 Rect   theBounds;
 int    theItem;
 int    textHeight;
 int    nChars;
 FontInfo theFont;
 
 if ((alertId < 0) && (showTime <= 0))
 {
 return;
 }
 
 theAlertDitlHdl = (AlertDitlHdl)NewHandle(sizeof(AlertDitl));
 if (theAlertDitlHdl != NIL)
 {
 HLock(theAlertDitlHdl);
 theAlertDitlPtr = * theAlertDitlHdl;
 
 nChars = (int)((unsigned char)*s1) +
 (int)((unsigned char)*s2) +
 (int)((unsigned char)*s3) +
 (int)((unsigned char)*s4);
 
 GetFontInfo(&theFont);
 textHeight = ((nChars * theFont.widMax) / LineLength + 1) *
 (theFont.ascent + theFont.descent + theFont.leading);
 if ((textHeight < IconSize) && (alertId >= 0))
 {
 textHeight = IconSize;
 }
 
 theAlertDitlPtr->nItems = (alertId >= 0) ? 3 : 0;
 
 theAlertDitlPtr->textHandle = ((void*) 0L);
 theAlertDitlPtr->textRect.top = AMargin - 3;
 theAlertDitlPtr->textRect.left = BMargin - 3;
 if (alertId >= 0)
 {
 theAlertDitlPtr->textRect.left += IconSize + BMargin;
 }
 theAlertDitlPtr->textRect.bottom =
 theAlertDitlPtr->textRect.top + textHeight;
 theAlertDitlPtr->textRect.right =
 theAlertDitlPtr->textRect.left + LineLength;
 theAlertDitlPtr->text = statText + itemDisable;
 theAlertDitlPtr->textSize = 8;
 theAlertDitlPtr->textString[0] = ‘^’;
 theAlertDitlPtr->textString[1] = ‘0’;
 theAlertDitlPtr->textString[2] = ‘^’;
 theAlertDitlPtr->textString[3] = ‘1’;
 theAlertDitlPtr->textString[4] = ‘^’;
 theAlertDitlPtr->textString[5] = ‘2’;
 theAlertDitlPtr->textString[6] = ‘^’;
 theAlertDitlPtr->textString[7] = ‘3’;
 
 if (alertId >= 0)
 {
 theAlertDitlPtr->buttonHandle = ((void*) 0L);
 theAlertDitlPtr->buttonRect.top =
 theAlertDitlPtr->textRect.bottom + AMargin;
 theAlertDitlPtr->buttonRect.right =
 theAlertDitlPtr->textRect.right;
 theAlertDitlPtr->buttonRect.bottom =
 theAlertDitlPtr->buttonRect.top + ButtonHeight;
 theAlertDitlPtr->buttonRect.left =
 theAlertDitlPtr->buttonRect.right - ButtonLength;
 theAlertDitlPtr->button = ctrlItem + btnCtrl;
 theAlertDitlPtr->buttonSize = 2;
 theAlertDitlPtr->buttonString[0] = ‘O’;
 theAlertDitlPtr->buttonString[1] = ‘K’;
 
 theAlertDitlPtr->iconHandle = ((void*) 0L);
 theAlertDitlPtr->iconRect.top = theAlertDitlPtr->textRect.top;
 theAlertDitlPtr->iconRect.left = BMargin - 3;
 theAlertDitlPtr->iconRect.bottom =
 theAlertDitlPtr->iconRect.top + IconSize;
 theAlertDitlPtr->iconRect.right =
 theAlertDitlPtr->iconRect.left + IconSize;
 theAlertDitlPtr->icon = iconItem + itemDisable;
 theAlertDitlPtr->iconSize = 2;
 theAlertDitlPtr->iconId = alertId;
 
 theAlertDitlPtr->outlineHandle = (Handle)&OutlineProc;
 theAlertDitlPtr->outlineRect.top = theAlertDitlPtr->buttonRect.top;
 theAlertDitlPtr->outlineRect.left = theAlertDitlPtr->buttonRect.left;
 theAlertDitlPtr->outlineRect.bottom =
 theAlertDitlPtr->buttonRect.bottom;
 theAlertDitlPtr->outlineRect.right = theAlertDitlPtr->buttonRect.right;
 theAlertDitlPtr->outline = userItem + itemDisable;
 theAlertDitlPtr->outlineSize = 0;
 }
 
 theBounds.top = DlogTop;
 theBounds.left = DlogLeft;
 theBounds.bottom = DlogTop + AMargin - 3;
 theBounds.bottom += (alertId >= 0) ?
 theAlertDitlPtr->buttonRect.bottom :
 theAlertDitlPtr->textRect.bottom;
 theBounds.right = DlogLeft + theAlertDitlPtr->textRect.right + AMargin 
- 3;
 
 HUnlock(theAlertDitlHdl);
 
 ParamText(s1, s2, s3, s4);
 theDlogPtr = NewDialog(&dlogRecord, &theBounds, “\p”, True, dBoxProc,
 InFrontOfAll, False, 0L, theAlertDitlHdl);
 if (alertId >= 0)
 {
 ModalDialog(NIL, &theItem);
 }
 else
 {
 DrawDialog(theDlogPtr);
 sleep(showTime);
 }
 CloseDialog(theDlogPtr);
 DisposHandle(theAlertDitlHdl);
 }
};
#endif MAC_APPL

/*
 *
 * FindSocketStruct - finds a data structure for a particular socket 
in a linked list
 *
 */
static SockElmntPtrFindSocketStruct(int sock)
{
 register SockElmntPtr  theSockPtr;

 for (theSockPtr = theHeadPtr; theSockPtr != NIL;
   theSockPtr = (SockElmntPtr)theSockPtr->next)
 {
 if (theSockPtr->number == sock)
 {
 errno_MacSocket = noErr;
 return (theSockPtr);
 }
 }
 errno_MacSocket = nonSocket;
 return (NIL);
}

/*
 *
 * OpenTCPDriver - loads and opens UDP-TCP/IP driver (“.IPP”)
 *
 */
static  int OpenTCPDriver()
{
 ParamBlockRec thePB;
 
 thePB.ioParam.ioCompletion = NIL;
 thePB.ioParam.ioNamePtr = (StringPtr)TCPDriverName;
 thePB.ioParam.ioPermssn = fsCurPerm;
 PBOpen(&thePB, Asynchronous);
 PollTCPDriver((TCPiopb *)&thePB);
 if (errno_MacSocket == noErr)
 {
 TCPDriverNotOpened = False;
 ioRefNumTCP = thePB.ioParam.ioRefNum;
 return(1);
 }
 else
 {
 errno_MacSocket = noTCPDriver;
 return(0);
 }
}

#ifdef MAC_APPL
/*
 *
 * OutlineProc - Outlines an item in a dialogbox
 *
 */
static pascal void OutlineProc(WindowPtr thePtr, int theItem)
{
 int    theItemType;
 GrafPtrcurrentPort;
 Handle theItemHdl;
 Rect theBox;

 GetDItem (thePtr, theItem, &theItemType, &theItemHdl, &theBox);
 GetPort(&currentPort);
 SetPort(thePtr);
 PenSize(3, 3);
 InsetRect(&theBox, -4, -4);
 FrameRoundRect (&theBox, 16, 16);
 PenNormal();
 SetPort(currentPort);
};
#endif  MAC_APPL

/*
 *
 * PollTCPDriver - polls the UDP-TCP/IP driver until an action is completed
 *
 */
static  voidPollTCPDriver(TCPiopb *theTCPPtr)
{
 while((errno_MacSocket = theTCPPtr->ioResult) > 0)
 {
 SystemTask();
 }
}

/*
 *
 * RemoveSocketStruct - removes a data structure for a particular socket 
from a
 * linked list
 *
 */
static intRemoveSocketStruct(int sock)
{
 register SockElmntPtr  theSockPtr, thePrevOne = NIL;

 for (theSockPtr = theHeadPtr; theSockPtr != NIL;
   thePrevOne = theSockPtr, theSockPtr = (SockElmntPtr)theSockPtr->next)
 {
 if (theSockPtr->number == sock)
 {
 if (thePrevOne == NIL)
 {
 theHeadPtr = theSockPtr->next;
 }
 else
 {
 thePrevOne->next = theSockPtr->next;
 }
 free(theSockPtr);
 errno_MacSocket = noErr;
 return (1);
 }
 }
 errno_MacSocket = nonSocket;
 return(0);
}

/*
 *
 * SockNotify - prints notification messages for the UDP-TCP/IP driver
 *
 */
static pascal void SockNotify(StreamPtr tcpStream, unsigned short eventCode,
  Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg)
{
 char theErrorMsg[128];
 char *errStrPtr1 = “\0”, *errStrPtr2 = “\0”;
#ifdef  MAC_APPL
 char errNoStr[32];
#endif  MAC_APPL
 
 strcpy(theErrorMsg, “MacSocket: “);
 switch (eventCode)
 {
 case TCPClosing:
 errStrPtr1 = “all data has been received and delivered”;
 break;
 case TCPULPTimeout:
 errStrPtr1 = “time out”;
 break;
 case TCPTerminate:
 errStrPtr1 = “connection terminated, “;
 switch(terminReason)
 {
 case TCPRemoteAbort:
 errStrPtr2 = “connection reset by peer”;
 break;
 case TCPNetworkFailure:
 errStrPtr2 = “network failure”;
 break;
 case TCPSecPrecMismatch:
 errStrPtr2 = “invallid security option or precedence level”;
 break;
 case TCPULPTimeoutTerminate:
 errStrPtr2 = “ULP time out”;
 break;
 case TCPULPAbort:
 errStrPtr2 = “connection aborted”;
 break;
 case TCPULPClose:
 errStrPtr2 = “connection closed gracefully”;
 break;
 case TCPServiceError:
 errStrPtr2 = “unexpected connection initiation segment read”;
 break;
 default:
 errStrPtr2 = “unknown reason”;
 break;
 }
 break;
 case TCPDataArrival:
 errStrPtr1 = “data arrived, no receive outstanding”;
 break;
 case TCPUrgent:
 errStrPtr1 = “urgent data arrived”;
 break;
 case TCPICMPReceived:
 errStrPtr1 = “Internet Control Message arrived”;
 /* still to be printed */
 break;
 default:
 errStrPtr1 = “unknown eventcode”;
 break;
 }
 strcat(theErrorMsg, errStrPtr1);
 strcat(theErrorMsg, errStrPtr2);
#ifndef MAC_APPL
 fprintf(stderr, “%s (%d).\n”, theErrorMsg, eventCode);
#else MAC_APPL
 NumToString(eventCode, errNoStr);
 DoAlert(-1, CtoPstr(theErrorMsg), “\p(“, errNoStr, “\p)”);
#endif  MAC_APPL
};

/**
 **
 ** Global functions
 **
 **/

/**
 **
 ** Functions that substitute relevant UNIX-system calls on the Mac
 **
 **/

/*
 *
 * close_MacSocket - delete a (socket) descriptor if present, else do 
close(int s)
 *
 */
int close_MacSocket(int s)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr, thePrevPtr = NIL;

 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return(close(s));
 }
 
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPClose;
 theTCPPtr->csParam.close.ulpTimeoutValue = CloseTimeout;
 theTCPPtr->csParam.close.ulpTimeoutAction = Abort;
 theTCPPtr->csParam.close.validityFlags = (byte)(timeoutValue | timeoutAction);
 theTCPPtr->csParam.close.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 theSockPtr->number = -1;
 if (errno_MacSocket == noErr)
 {
 return(0);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * exit_MacSocket - substitute for exit(int status)
 *
 */
void exit_MacSocket(int status)
{
 ParamBlockRec thePB;

 while (theHeadPtr != NIL)
 {
 shutdown(theHeadPtr->number, 2);
 }
 
 if (!TCPDriverNotOpened)
 {
 thePB.ioParam.ioCompletion = NIL;
 thePB.ioParam.ioRefNum = ioRefNumTCP;
 PBClose(&thePB, Asynchronous);
 /*
 PollTCPDriver(&thePB);
 */
 }
 exit(status);
}

/*
 *
 * perror_MacSocket - substitute for void perror(char *s)
 *
 */
void perror_MacSocket(char *s)
{
 char theErrorMsg[128];
#ifdef  MAC_APPL
 char errNoStr[32];
#endif  MAC_APPL
 
 strcpy(theErrorMsg, s);
 strcat(theErrorMsg, “: “);
 strcat(theErrorMsg, strerror_MacSocket(errno_MacSocket));
#ifndef MAC_APPL
 fprintf(stderr, “%s (%d).\n”, theErrorMsg, errno_MacSocket);
#else MAC_APPL
 NumToString(errno_MacSocket, errNoStr);
 DoAlert(stopIcon, CtoPstr(theErrorMsg), “\p (“, errNoStr, “\p).”);
#endif  MAC_APPL
}

/*
 *
 * strerror_MacSocket - substitute for strerror(int errnum)
 *
 */
char* strerror_MacSocket(int errnum)
{
 char *errStrPtr;
 
 switch (errnum)
 {
 case noTCPDriver:
 errStrPtr = “UDP-TCP/IP driver (\”.IPP\”) not available”;
 break;
 case invalidArgument:
 errStrPtr = “invalid address argument”;
 break;
 case nonSOCK_STREAM:
 errStrPtr = “socket type not supported”;
 break;
 case nonSocket:
 errStrPtr = “invalid socket descriptor”;
 break;
 case nonAF_INET:
 errStrPtr = “domain not supported”;
 break;
 case noBufSpace:
 errStrPtr = “no memory for buffers available”;
 break;
 case ipBadLapErr:
 errStrPtr = “bad network configuration”;
 break;
 case ipBadCnfgErr:
 errStrPtr = “bad IP configuration error”;
 break;
 case ipNoCnfgErr:
 errStrPtr = “missing IP or LAP configuration error”;
 break;
 case ipLoadErr:
 errStrPtr = “error in MacTCP load”;
 break;
 case ipBadAddr:
 errStrPtr = “error in getting address”;
 break;
 case streamAlreadyOpen:
 errStrPtr = “an open stream is already using this receive buffer area”;
 break;
 case invalidLength:
 errStrPtr = “the buffer is too small or too large”;
 break;
 case invalidBufPtr:
 errStrPtr = “illegal buffer pointer”;
 break;
 case insufficientResources:
 errStrPtr = “there are already 64 TCP streams open”;
 break;
 case invalidStreamPtr:
 errStrPtr = “the specified TCP stream is not open”;
 break;
 case connectionExists:
 errStrPtr = “this TCP stream has an open connection”;
 break;
 case duplicateSocket:
 errStrPtr = “a connection already exists on this link”;
 break;
 case commandTimeout:
 errStrPtr =
 “no connection attempt was received in the specified time-out period”;
 break;
 case openFailed:
 errStrPtr = “the connection came halfway up and then failed”;
 break;
 case connectionDoesntExist:
 errStrPtr = “there is no open connection on this stream”;
 break;
 case connectionClosing:
 errStrPtr = “a TCP close command was already issued”;
 break;
 case connectionTerminated:
 errStrPtr = “the connection went down”;
 break;
 case invalidRDS:
 errStrPtr = “trying to release wrong buffer”;
 break;
 default:
 errStrPtr = strerror(errnum);;
 break;
 }
 strcpy(macSocketErrorMssg, errStrPtr);
 return(macSocketErrorMssg);
}

/**
 **
 ** MacSocket calls
 **
 **/

/*
 *
 * connect - initiate a connection on a socket
 *
 */
int connect(int s, struct sockaddr_in *name, int namelen)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;
 
 if (namelen != sizeof(struct sockaddr_in))
 {
 errno_MacSocket = invalidArgument;
 return (-1);
 }

 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return (-1);
 }
 
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPActiveOpen;
 theTCPPtr->csParam.open.ulpTimeoutValue = ConnectTimeout;
 theTCPPtr->csParam.open.ulpTimeoutAction = Abort;
 theTCPPtr->csParam.open.validityFlags =
 (byte)(timeoutValue | timeoutAction | typeOfService | precedence);
 memcpy((void *)&theTCPPtr->csParam.open.remoteHost, (void *)&name->sin_addr,
 sizeof(name->sin_addr));
 theTCPPtr->csParam.open.remotePort = name->sin_port;
 theTCPPtr->csParam.open.localPort = 0;
 theTCPPtr->csParam.open.tosFlags = (byte)(reliability | lowDelay);
 theTCPPtr->csParam.open.precedence = 0;
 theTCPPtr->csParam.open.dontFrag = False;
 theTCPPtr->csParam.open.timeToLive = (byte)60;
 theTCPPtr->csParam.open.security = False;
 theTCPPtr->csParam.open.optionCnt = (byte)0;
 theTCPPtr->csParam.open.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return (0);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * recv - receive a message from a socket
 *
 */
int recv(int s, char *msg, int len, int flags)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return (-1);
 }
 
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPRcv;
 theTCPPtr->csParam.receive.commandTimeoutValue = RecvTimeout;
 theTCPPtr->csParam.receive.rcvBuff = msg;
 theTCPPtr->csParam.receive.rcvBuffLen = len;
 theTCPPtr->csParam.receive.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return (theTCPPtr->csParam.receive.rcvBuffLen);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * recvfrom - receive a message from a socket
 *
 */
int recvfrom(int s, char *msg, int len, int flags, struct sockaddr_in 
*from, int *fromlen)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (from != NULL)
 {
 *fromlen = sizeof(from);
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, from, *fromlen))
 {
 return(-1);
 }
 }
 }
 return(recv(s, msg, len, flags));
};

/*
 *
 * recvmsg - receive a message from a socket
 *
 */
int recvmsg(int s, struct msghdr *msg, int flags)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (msg->msg_name != NULL)
 {
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, (struct sockaddr_in *)msg->msg_name, msg->msg_namelen))
 {
 return(-1);
 }
 }
 }
 return(recv(s, (char *)msg->msg_iov, msg->msg_iovlen, flags));
};

/*
 *
 * send - send a message from a socket
 *
 */
int send(int s, char *msg, int len, int flags)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;

 struct theWDS
 {
 short  length;
 Ptr  theDataPtr;
 short  end;
 } theWDS;
 

 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return (-1);
 }
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPSend;
 theTCPPtr->csParam.send.ulpTimeoutValue = SendTimeout;
 theTCPPtr->csParam.send.ulpTimeoutAction = True;
 theTCPPtr->csParam.send.validityFlags = (byte)(timeoutValue | timeoutAction);
 theTCPPtr->csParam.send.pushFlag = True; /* May be false ?? */
 theTCPPtr->csParam.send.urgentFlag = False;
 theWDS.length = len;
 theWDS.theDataPtr = msg;
 theWDS.end = 0;
 theTCPPtr->csParam.send.wdsPtr = (Ptr)&theWDS;
 theTCPPtr->csParam.send.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return(len);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * sendto - send a message to a socket
 *
 */
int sendto(int s, char *msg, int len, int flags, struct sockaddr_in *to, 
int *tolen)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (to != NULL)
 {
 *tolen = sizeof(struct sockaddr_in);
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, to, *tolen))
 {
 return(-1);
 }
 }
 }
 return(send(s, msg, len, flags));
};

/*
 * sendmsg - send a message to a socket
 */
int sendmsg(int s, struct msghdr *msg, int flags)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (msg->msg_name != NULL)
 {
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, (struct sockaddr_in *)msg->msg_name, msg->msg_namelen))
 {
 return(-1);
 }
 }
 }
 return(send(s, (char *)msg->msg_iov, msg->msg_iovlen, flags));
};

#ifdef  MAC_APPL
/*
 *
 * SetDialogShowTime - sets the time that an MacTCP/IP info DialogBox 
is vissible.
 * when sec <= 0, no message will be displayed.
 *
 */
void SetDialogShowTime(int sec)
{
 showTime = sec;
}
#endif  MAC_APPL

/*
 *
 * shutdown - shut down part of a full-duplex connection
 *
 */
int shutdown(int s, int how)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;

 switch (how)
 {
 case 1: /* further sends disalowed */
 return (close_MacSocket(s));
 break;
 case 2: /* further sends and receives disalowed */
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return(-1);
 }
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPRelease;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 return (RemoveSocketStruct(s));
 break;
 case 0: /* further receives disalowed */
 default:
 errno_MacSocket = invalidArgument;
 return(-1);
 break;
 }
};

/*
 * socket - create an endpoint for communication
 */
intsocket(int domain, int type, int protocol)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;
 
 if (domain != AF_INET)
 {
 errno_MacSocket = nonAF_INET;
 return (-1);
 }
 if (protocol != 0)
 {
 errno_MacSocket = invalidArgument;
 return (-1);
 }
 if (type != SOCK_STREAM)
 {
 errno_MacSocket = nonSOCK_STREAM;
 return (-1);
 }
 if ((theSockPtr = (SockElmntPtr)CreateSocketStruct()) == NIL)
 {
 errno_MacSocket = noBufSpace;
 return (-1);
 }

 if (TCPDriverNotOpened)
 {
 if (!OpenTCPDriver())
 {
 return(-1);;
 }
 }
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->ioCompletion = NIL;
 theTCPPtr->ioRefNum = ioRefNumTCP;
 theTCPPtr->csCode = TCPCreate;
 theTCPPtr->csParam.create.rcvBuff = theSockPtr->sockBuf;
 theTCPPtr->csParam.create.rcvBuffLen = SockBufSize;
 theTCPPtr->csParam.create.notifyProc = SockNotify;
 theTCPPtr->csParam.create.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return (theSockPtr->number);
 }
 else
 {
 RemoveSocketStruct(theSockPtr->number);
 return (-1);
 };
}
 
AAPL
$99.59
Apple Inc.
-1.17
MSFT
$46.17
Microsoft Corpora
-0.20
GOOG
$569.92
Google Inc.
-7.44

MacTech Search:
Community Search:

Software Updates via MacUpdate

Cocktail 8.0 Beta 2 - General maintenanc...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
QuickBooks 2015 16.0.0.1352 R1 - Financi...
QuickBooks 2015 helps you manage your business easily and efficiently. Organize your finances all in one place, track money going in and out of your business, and spot areas where you can save.... Read more
Mac DVDRipper Pro 5.0.1 - Copy, backup,...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
Apple OS X bash Update 1.0 - Fix for sec...
The OS X bash Update fixes a security flaw in the bash UNIX shell on OS X 10.9.5 (also on OS X 10.8 and 10.7 [see Related Links below]). OS X 10.9.5 or later Downloads for OS X 10.8 and OS X 10.7 in... Read more
SyncTwoFolders 2.0.5 - Syncs two user-sp...
SyncTwoFolders simply synchronizes two folders. It supports synchronization across mounted network drives and it is a possibility to run a simulation showing in a log what will be done. Please visit... Read more
FinderPop 2.5.7 - Classic Mac utility, n...
FinderPop is a Universal preference pane that extends OS X's contextual menus using a FinderPop Items folder much as the Apple Menu Items folder used to do for the Apple menu. It has other features... Read more
VueScan 9.4.45 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
LibreOffice 4.3.2.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
calibre 2.4 - Complete e-library managem...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital... Read more
Default Folder X 4.6.9b1 - Enhances Open...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more

Latest Forum Discussions

See All

Nexticy Review
Nexticy Review By Jennifer Allen on October 1st, 2014 Our Rating: :: IDEAL FORM CREATIONiPad Only App - Designed for the iPad Nexticy allows you to make your own forms for research purposes or to organize your business better. It’s... | Read more »
HeroCraft Introduces Unlimited Sequel to...
HeroCraft Introduces Unlimited Sequel to WW2: Sandbox. Strategy & Tactics Posted by Jessica Fisher on October 1st, 2014 [ permalink ] | Read more »
RGB Express Review
RGB Express Review By Jennifer Allen on October 1st, 2014 Our Rating: :: DELIGHTFUL PUZZLINGUniversal App - Designed for iPhone and iPad Guide trucks along their delivery routes in RGB Express, a testing but charming puzzle game... | Read more »
The Sagas of Fire*Wolf (Games)
The Sagas of Fire*Wolf 1.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0 (iTunes) Description: | Read more »
BuggyFun Review
BuggyFun Review By Amy Solomon on October 1st, 2014 Our Rating: iPad Only App - Designed for the iPad BuggyFun allows children to create their own tracks for bugs to interact with for a unique open-ended experience.   | Read more »
Fold the Adventure Review
Fold the Adventure Review By Jennifer Allen on October 1st, 2014 Our Rating: :: AWKWARD FOLDSUniversal App - Designed for iPhone and iPad Fold pieces of paper to create platforms for a princely rabbit in this puzzle game; something... | Read more »
WW2: Sandbox. Strategy & Tactics (G...
WW2: Sandbox. Strategy & Tactics 1.0.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0.0 (iTunes) Description: ***NOTE: Compatible with iPhone 4s and up, iPad 2 and up - may not work properly on earlier devices... | Read more »
apeFilter (Music)
apeFilter 1.0 Device: iOS Universal Category: Music Price: $6.99, Version: 1.0 (iTunes) Description: | Read more »
Shred It! Review
Shred It! Review By Jennifer Allen on September 30th, 2014 Our Rating: :: GORGEOUS BUT BASICUniversal App - Designed for iPhone and iPad It might look lovely, but Shred It! is a pretty shallow endless runner/snowboarding game.   | Read more »
Check Out the New Teaser Trailer forGAME...
Check Out the New Teaser Trailer forGAMEVIL’s Darkness Reborn Posted by Jessica Fisher on September 30th, 2014 [ permalink ] Darkness Reborn, by GAMEVIL< | Read more »

Price Scanner via MacPrices.net

Apple resting On Its iPhone Laurels? – The ‘B...
Apple calls its new iPhone 6 and 6 Plus “The Biggest Advancements in iPhone History,” but does reality live up to the hype? “Seldom have so many waited so breathlessly for so little,” tweeted veteran... Read more
Roundup of Apple Mac and iPad Education disco...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more
Apple Boycotts German Magazine Computer Bild...
Apple has revoked its PR accreditation of Germany’s Computer Bild, Europe’s best-selling PC magazine, in reaction to Bild’s posting of a “#Bentgate” YouTube video. Axel Telzerow, editor in chief of... Read more
iPhone 6 & iPhone 6 Plus Available in Chi...
Apple has announced that iPhone 6 and iPhone 6 Plus will be available in China beginning Friday, October 17 from the Apple Online Store (http://www.apple.com), Apple’s retail stores, and an expansive... Read more
MacBook Airs on sale for $100 off MSRP, start...
Best Buy has the new 2014 MacBook Airs on sale for $100 off MSRP on their online store. Choose free home shipping or free local store pickup (if available). Prices valid for online orders only, in-... Read more
Apple Releases OS X Mavericks bash Update 1.0...
Apple has released a patch update for OS X Mavericks users to address the recently-detected “Shellshock” security bug in BSD UNIX’s bash shell. Apple says only a few Mac users who had manually... Read more
Pivotal Payments Ready for Apple Pay – FlexPo...
Pivotal Payments, a provider of merchant services and global payment processing solutions, has announced its proprietary FlexPoint platform will support credit and debit transactions through Apple’s... Read more
iStabilizer Announces Tabarm — First Friction...
iStabilizer, a specialist in universal lightweight compact tripods, steady cams, dollies, mounts, and remotes for smartphones, tablets, and cameras, announced today the iStabilizer tabArm, the first... Read more
IStabilizer Flex Smartphone Tripod Wins Usa T...
iStabilizer, a specialist in universal lightweight compact tripods, steady cams, and other products for smartphones, tablets, and cameras, has announced today that its iStabilizer Flex smartphone... Read more
13-inch 2.8GHz Retina MacBook Pro on sale for...
B&H Photo has the new 2014 13″ 2.8GHz Retina MacBook Pro on sale for $1699.99 including free shipping plus NY sales tax only. They’ll also include free copies of Parallels Desktop and LoJack for... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.