Exemple #1
0
int initializeClient(const char *name)
{
	int sock, rc;
	sockaddr_x dag;
	socklen_t daglen;
	char sdag[1024];
	char IP[MAX_XID_SIZE];

    // lookup the xia service 
	daglen = sizeof(dag);
    if (XgetDAGbyName(name, &dag, &daglen) < 0)
		die(-1, "unable to locate: %s\n", name);


	// create a socket, and listen for incoming connections
	if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		 die(-1, "Unable to create the listening socket\n");
    
	if (Xconnect(sock, (struct sockaddr*)&dag, daglen) < 0) {
		Xclose(sock);
		 die(-1, "Unable to bind to the dag: %s\n", dag);
	}

	
	
	rc = XreadLocalHostAddr(sock, my_ad, MAX_XID_SIZE, my_hid, MAX_XID_SIZE, IP, MAX_XID_SIZE);

	if (rc < 0) {
		Xclose(sock);
		 die(-1, "Unable to read local address.\n");
	} else{
		warn("My AD: %s, My HID: %s\n", my_ad, my_hid);
	}
	
	// save the AD and HID for later. This seems hacky
	// we need to find a better way to deal with this
	Graph g(&dag);
	strncpy(sdag, g.dag_string().c_str(), sizeof(sdag));
//   	say("sdag = %s\n",sdag);
	char *ads = strstr(sdag,"AD:");
	char *hids = strstr(sdag,"HID:");
// 	i = sscanf(ads,"%s",s_ad );
// 	i = sscanf(hids,"%s", s_hid);
	
	if(sscanf(ads,"%s",s_ad ) < 1 || strncmp(s_ad,"AD:", 3) !=0){
		die(-1, "Unable to extract AD.");
	}
		
	if(sscanf(hids,"%s", s_hid) < 1 || strncmp(s_hid,"HID:", 4) !=0 ){
		die(-1, "Unable to extract AD.");
	}

	warn("Service AD: %s, Service HID: %s\n", s_ad, s_hid);
	return sock;
}
Exemple #2
0
TEST(XreadLocalHostAddr, InvalidPointers)
{
	int sock = Xsocket(AF_XIA, XSOCK_STREAM, 0);
	int rc = XreadLocalHostAddr(sock, NULL, XID_LEN, NULL, XID_LEN, NULL, XID_LEN);
	ASSERT_EQ(-1, rc);
	Xclose(sock);
}
Exemple #3
0
//Just registering the service and openning the necessary sockets
int registerReceiver()
{
    int sock;
	say ("\n%s (%s): started\n", TITLE, VERSION);

	// create a socket, and listen for incoming connections
	if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		 die(-1, "Unable to create the listening socket\n");

    // read the localhost AD and HID
    if ( XreadLocalHostAddr(sock, myAD, sizeof(myAD), myHID, sizeof(myHID), my4ID, sizeof(my4ID)) < 0 )
    	die(-1, "Reading localhost address\n");

	struct addrinfo *ai;
    //FIXME: SID is hardcoded
	if (Xgetaddrinfo(NULL, SID, NULL, &ai) != 0)
		die(-1, "getaddrinfo failure!\n");

	sockaddr_x *dag = (sockaddr_x*)ai->ai_addr;
	//FIXME NAME is hard coded
    if (XregisterName(NAME, dag) < 0 )
    	die(-1, "error registering name: %s\n", NAME);

	if (Xbind(sock, (struct sockaddr*)dag, sizeof(dag)) < 0) {
		Xclose(sock);
		 die(-1, "Unable to bind to the dag: %s\n", dag);
	}

	Graph g(dag);
	say("listening on dag: %s\n", g.dag_string().c_str());
  return sock;
  
}
Exemple #4
0
void echo_dgram()
{
	int sock;
	char buf[XIA_MAXBUF];
	sockaddr_x cdag;
	socklen_t dlen;
	int n;

	say("Datagram service started\n");

	if ((sock = Xsocket(AF_XIA, SOCK_DGRAM, 0)) < 0)
		die(-2, "unable to create the datagram socket\n");

	struct addrinfo *ai;
	if (Xgetaddrinfo(NULL, SID_DGRAM, NULL, &ai) != 0)
		die(-1, "getaddrinfo failure!\n");

	sockaddr_x *sa = (sockaddr_x*)ai->ai_addr;

	Graph g((sockaddr_x*)ai->ai_addr);
	printf("\nDatagram DAG\n%s\n", g.dag_string().c_str());

    if (XregisterName(DGRAM_NAME, sa) < 0 )
    	die(-1, "error registering name: %s\n", DGRAM_NAME);
	say("registered name: \n%s\n", DGRAM_NAME);

	if (Xbind(sock, (sockaddr *)sa, sizeof(sa)) < 0) {
		die(-3, "unable to bind to the dag\n");
	}

	pid_t pid = 0;

	// only need to fork if doing stream echo at the same time
	if (stream == 1)
		pid = fork();

	if (pid == 0) {
		while (1) {
			say("Dgram Server waiting\n");

			dlen = sizeof(cdag);
			memset(buf, 0, sizeof(buf));
			if ((n = Xrecvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&cdag, &dlen)) < 0) {
				warn("Recv error on socket %d, closing connection\n", pid);
				break;
			}

			say("dgram received %d bytes\n", n);

			if ((n = Xsendto(sock, buf, n, 0, (struct sockaddr *)&cdag, dlen)) < 0) {
				warn("%5d send error\n", pid);
				break;
			}

			say("dgram sent %d bytes\n", n);
		}

		Xclose(sock);
	}
}
Exemple #5
0
void handler(int)
{
	timetodie = 1;
	if (sock > 0)
		Xclose(sock);
	sock = -1;
}
Exemple #6
0
/*
 * Save an array subscript - returns true if matching bracket found, false
 * if eof or newline was found.
 * (Returned string double null terminated)
 */
static bool
arraysub(char **strp)
{
	XString ws;
	char *wp, c;
	/* we are just past the initial [ */
	unsigned int depth = 1;

	Xinit(ws, wp, 32, ATEMP);

	do {
		c = getsc();
		Xcheck(ws, wp);
		*wp++ = c;
		if (c == '[')
			depth++;
		else if (c == ']')
			depth--;
	} while (depth > 0 && c && c != '\n');

	*wp++ = '\0';
	*strp = Xclose(ws, wp);

	return (tobool(depth == 0));
}
Exemple #7
0
/*
 * Save an array subscript - returns true if matching bracket found, false
 * if eof or newline was found.
 * (Returned string double null terminated)
 */
static int
arraysub(char **strp)
{
	XString ws;
	char	*wp;
	char	c;
	int	depth = 1;	/* we are just past the initial [ */

	Xinit(ws, wp, 32, ATEMP);

	do {
		c = getsc();
		Xcheck(ws, wp);
		*wp++ = c;
		if (c == '[')
			depth++;
		else if (c == ']')
			depth--;
	} while (depth > 0 && c && c != '\n');

	*wp++ = '\0';
	*strp = Xclose(ws, wp);

	return depth == 0 ? 1 : 0;
}
Exemple #8
0
int getFile(int sock, char *p_ad, char* p_hid, const char *fin, const char *fout)
{
	int chunkSock;
	int offset;
	char cmd[512];
	char reply[512];
	int status = 0;
	
	//TODO: check the arguments to be correct
	
	// send the file request
	sprintf(cmd, "get %s",  fin);
	sendCmd(sock, cmd);

	// get back number of chunks in the file
	if (getChunkCount(sock, reply, sizeof(reply)) < 1){
		warn("could not get chunk count. Aborting. \n");
		return -1;
	}

	int count = atoi(&reply[4]);

	if ((chunkSock = Xsocket(AF_XIA, XSOCK_CHUNK, 0)) < 0)
		die(-1, "unable to create chunk socket\n");

	FILE *f = fopen(fout, "w");

	offset = 0;
	while (offset < count) {
		int num = NUM_CHUNKS;
		if (count - offset < num)
			num = count - offset;

		// tell the server we want a list of <num> cids starting at location <offset>
		sprintf(cmd, "block %d:%d", offset, num);
		sendCmd(sock, cmd);

		if (getChunkCount(sock, reply, sizeof(reply)) < 1){
			warn("could not get chunk count. Aborting. \n");
			return -1;
		}
		offset += NUM_CHUNKS;
		if (getListedChunks(chunkSock, f, &reply[4], p_ad, p_hid) < 0) {
			status= -1;
			break;
		}
	}
	
	fclose(f);

	if (status < 0) {
		unlink(fin);
	}

	say("Received file %s\n", fout);
	sendCmd(sock, "done");
	Xclose(chunkSock);
	return status;
}
Exemple #9
0
static void
readhere(struct ioword *iop)
{
	int c;
	char *volatile eof;
	char *eofp;
	int skiptabs;
	XString xs;
	char *xp;
	int xpos;

	eof = evalstr(iop->delim, 0);

	if (!(iop->flag & IOEVAL))
		ignore_backslash_newline++;

	Xinit(xs, xp, 256, ATEMP);

	for (;;) {
		eofp = eof;
		skiptabs = iop->flag & IOSKIP;
		xpos = Xsavepos(xs, xp);
		while ((c = getsc()) != 0) {
			if (skiptabs) {
				if (c == '\t')
					continue;
				skiptabs = 0;
			}
			if (c != *eofp)
				break;
			Xcheck(xs, xp);
			Xput(xs, xp, c);
			eofp++;
		}
		/* Allow EOF here so commands with out trailing newlines
		 * will work (eg, ksh -c '...', $(...), etc).
		 */
		if (*eofp == '\0' && (c == 0 || c == '\n')) {
			xp = Xrestpos(xs, xp, xpos);
			break;
		}
		ungetsc(c);
		while ((c = getsc()) != '\n') {
			if (c == 0)
				yyerror("here document `%s' unclosed\n", eof);
			Xcheck(xs, xp);
			Xput(xs, xp, c);
		}
		Xcheck(xs, xp);
		Xput(xs, xp, c);
	}
	Xput(xs, xp, '\0');
	iop->heredoc = Xclose(xs, xp);

	if (!(iop->flag & IOEVAL))
		ignore_backslash_newline--;
}
/*
 * search for command with PATH
 */
const char *
search_path(const char *name, const char *lpath,
    /* R_OK or X_OK */
    int mode,
    /* set if candidate found, but not suitable */
    int *errnop)
{
	const char *sp, *p;
	char *xp;
	XString xs;
	size_t namelen;
	int ec = 0, ev;

	if (vstrchr(name, '/')) {
		if ((ec = search_access(name, mode)) == 0) {
 search_path_ok:
			if (errnop)
				*errnop = 0;
			return (name);
		}
		goto search_path_err;
	}

	namelen = strlen(name) + 1;
	Xinit(xs, xp, 128, ATEMP);

	sp = lpath;
	while (sp != NULL) {
		xp = Xstring(xs, xp);
		if (!(p = cstrchr(sp, ':')))
			p = sp + strlen(sp);
		if (p != sp) {
			XcheckN(xs, xp, p - sp);
			memcpy(xp, sp, p - sp);
			xp += p - sp;
			*xp++ = '/';
		}
		sp = p;
		XcheckN(xs, xp, namelen);
		memcpy(xp, name, namelen);
		if ((ev = search_access(Xstring(xs, xp), mode)) == 0) {
			name = Xclose(xs, xp + namelen);
			goto search_path_ok;
		}
		/* accumulate non-ENOENT errors only */
		if (ev != ENOENT && ec == 0)
			ec = ev;
		if (*sp++ == '\0')
			sp = NULL;
	}
	Xfree(xs, xp);
 search_path_err:
	if (errnop)
		*errnop = ec ? ec : ENOENT;
	return (NULL);
}
Exemple #11
0
	void integerGet(int opt, int val)
	{
		int s = Xsocket(AF_XIA, SOCK_DGRAM, 0);
		socklen_t sz = sizeof(int);
		int v = 999;
		EXPECT_EQ(0, Xsetsockopt(sock, opt, (const void *)&val, sz));
		EXPECT_EQ(0, Xgetsockopt(sock, opt, (void *)&v, &sz));
		EXPECT_EQ(sizeof(int), sz);
		EXPECT_EQ(v, val);
		Xclose(s);
	}
Exemple #12
0
/*
** get data from the client and return it
** run in a child process that was forked off from the main process.
*/
void process(int sock)
{
	char buf[XIA_MAXBUF + 1];
	int n;
	pid_t pid = getpid();

	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(sock, &fds);

#ifdef USE_SELECT
	struct timeval tv;
	tv.tv_sec = WAIT_FOR_DATA;
	tv.tv_usec = 0;
#endif
   	while (1) {
		memset(buf, 0, sizeof(buf));
#ifdef USE_SELECT
		tv.tv_sec = WAIT_FOR_DATA;
		tv.tv_usec = 0;
		 if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) {
			 warn("%5d Select failed, closing...\n", pid);
			 break;

		 } else if (n == 0) {
			 // we timed out, close the socket
			 say("%5d timed out on recv\n", pid);
			 break;
		 } else if (!FD_ISSET(sock, &fds)) {
			 // this shouldn't happen!
			 die(-4, "something is really wrong, exiting\n");
		 }
#endif

		if ((n = Xrecv(sock, buf, sizeof(buf), 0)) < 0) {
			warn("Recv error on socket %d, closing connection\n", pid);
			break;
		} else if (n == 0) {
			warn("%d client closed the connection\n", pid);
			break;
		}

		say("%5d received %d bytes\n", pid, n);

		if ((n = Xsend(sock, buf, n, 0)) < 0) {
			warn("%5d send error\n", pid);
			break;
		}

		say("%5d sent %d bytes\n", pid, n);
   	}
	say("%5d closing\n", pid);
	Xclose(sock);
}
Exemple #13
0
int sendCmd(int sock, const char *cmd)
{ 
	int n;
 	warn("Sending Command: %s \n", cmd);
	if ((n = Xsend(sock, cmd,  strlen(cmd), 0)) < 0) {
		Xclose(sock);
		 die(-1, "Unable to communicate\n");
	}

	return n;
}
Exemple #14
0
int sendCmd(int sock, const char *cmd)
{
	int n;

	if ((n = Xsend(sock, cmd,  strlen(cmd), 0)) < 0) {
		Xclose(sock);
		 die(-1, "Unable to communicate with the server\n");
	}

	return n;
}
/*
** the main loop for talking to the remote server
** when threading is enabled, one of these will run in each thread
**
** The parameter and return code are there to satisify the thread library
*/
void *mainLoop(void * /* dummy */)
{
        int ssock;
        int count = 0;
        int printcount = 1;

        // don't bother with the loop count if we are ony doing one operation
        if (loops == 1)
                printcount = 0;

        ssock = connectToServer();

        for (;;) {

                if (printcount)
                        printf("Xsock %4d loop #%d\n", ssock, count);

                if (process(ssock) != 0)
                        break;

                pausex();

                count++;
                if (reconnect) {
                        if (count % reconnect == 0) {
                                // time to close and reopen the socket
                                Xclose(ssock);
                                say("Xsock %4d closed\n", ssock);
                                ssock = connectToServer();
                        }
                }
                if (loops > 0 && count == loops)
                                break;
        }
        Xclose(ssock);
        say("Xsock %4d closed\n", ssock);

        return NULL;
}
int main(int argc, char *argv[])
{
    int sock, n;
    size_t dlen;
    char reply[128];
    char buffer[2048],theirDAG[1024];    

    //Open socket
    sock=Xsocket(XSOCK_DGRAM);
    if (sock < 0) 
	error("Opening socket");
	
    //Name query to the name server
    char * sname = (char*) malloc(snprintf(NULL, 0, "%s", SNAME) + 1);
    sprintf(sname, "%s", SNAME);      
    char * dag = XgetDAGbyName(sname);

    while(1)
    {
	printf("\nPlease enter the message (0 to exit): ");
	bzero(buffer,2048);
	fgets(buffer,2048,stdin);
	if (buffer[0]=='0'&&strlen(buffer)==2)
	    break;
	    
	//Use Xconnect() with Xsend()
	//Xsend(sock,buffer,strlen(buffer),0);
	
	//Or use Xsendto()

	Xsendto(sock,buffer,strlen(buffer),0,dag,strlen(dag)+1);
	printf("Sent\n");


	//Process reply from server
	dlen =  sizeof(theirDAG);
	n = Xrecvfrom(sock,reply,128,0,theirDAG,&dlen);
	//n = Xrecv(sock,reply,128,0);
	if (n < 0) 
	    error("recvfrom");
	//printf("Received a datagram from:%s\n",theirDAG);
	write(1,reply,n);
	printf("\n");
    }

    Xclose(sock);
    return 0;
}
Exemple #17
0
int getChunkCount(int sock, char *reply, int sz)
{
	int n;

	if ((n = Xrecv(sock, reply, sz, 0))  < 0) {
		Xclose(sock);
		 die(-1, "Unable to communicate with the server\n");
	}

	if (strncmp(reply, "OK:", 3) != 0) {
		die(-1, "%s\n", reply);
	}

	reply[n] = 0;

	return n;
}
Exemple #18
0
char *
get_phys_path(const char *path)
{
	XString xs;
	char *xp;

	Xinit(xs, xp, strlen(path) + 1, ATEMP);

	xp = do_phys_path(&xs, xp, path);

	if (!xp)
		return ((char *) 0);

	if (Xlength(xs, xp) == 0)
		Xput(xs, xp, '/');
	Xput(xs, xp, '\0');

	return (Xclose(xs, xp));
}
Exemple #19
0
void *blockingListener(void *socketid)
{
  int sock = *((int*)socketid);
  int acceptSock;
  while (1) {
		say("Waiting for a client connection\n");
   		
		if ((acceptSock = Xaccept(sock, NULL, NULL)) < 0)
			die(-1, "accept failed\n");

		say("connected\n");
		
		// handle the connection in a new thread
		pthread_t client;
	pthread_create(&client, NULL, recvCmd, (void *)&acceptSock);
	}
	
	Xclose(sock); // we should never reach here!
	return NULL;
}
Exemple #20
0
	virtual void SetUp() {
		sockaddr_x sa;

		int sock = Xsocket(AF_XIA, SOCK_STREAM, 0);
		XreadLocalHostAddr(sock, ad, XID_LEN, hid, XID_LEN, fid, XID_LEN);
		sprintf(fdag, FULL_DAG, ad, hid, SID);
		Graph gf(fdag);
		gf.fill_sockaddr(&sa);
		XregisterName(FULL_NAME, &sa);

		sprintf(hdag, HOST_DAG, ad, hid);
		Graph gh(hdag);
		gh.fill_sockaddr(&sa);
		XregisterName(HOST_NAME, &sa);
		Xclose(sock);

		nad = new Node(ad);
		nhid = new Node(hid);
		nsid = new Node(SID);

		ai = NULL;
	}
Exemple #21
0
	virtual void TearDown() {
		Xclose(sock);
	}
Exemple #22
0
/*!
** @brief Register a service or hostname with the name server.
**
** Register a host or service name with the XIA nameserver.
** By convention services are indicated by '_s' appended to the service name.
** The memory returned is dynamically allocated and should be released with a
** call to free() when the caller is done with it.
**
** This is a very simple implementation and will be replaced in a
** future release. This version does not check correctness of the name or dag,
** nor does it check to ensure that the client is allowed to bind to name.
**
** @param name - The name of an XIA service or host.
** @param DAG  - the DAG to be bound to name.
**
** @returns 0 on success
** @returns -1 on failure with errno set
**
*/
int XregisterName(const char *name, sockaddr_x *DAG) {
	int sock;
	sockaddr_x ns_dag;
	char pkt[NS_MAX_PACKET_SIZE];
	char _name[NS_MAX_DAG_LENGTH], _dag[NS_MAX_DAG_LENGTH];
	int result;

	if ((sock = Xsocket(AF_XIA, SOCK_DGRAM, 0)) < 0)
		return -1;

	//Read the nameserver DAG (the one that the name-registration will be sent to)
	if (XreadNameServerDAG(sock, &ns_dag) < 0) {
		LOG("Unable to find nameserver address");
		errno = NO_RECOVERY;
		return -1;
	}

	if (!DAG) {
		errno = EINVAL;
		return -1;
	}

	Graph g(DAG);
	if (g.num_nodes() <= 0) {
		errno = EINVAL;
		return -1;
	}

	//Construct a registration packet
	ns_pkt register_pkt;
	register_pkt.type = NS_TYPE_REGISTER;
	register_pkt.name = strdup(name);
	register_pkt.dag = strdup(g.dag_string().c_str());

	memset(pkt, 0, sizeof(pkt));
	int offset = 0;
	memcpy(pkt, &register_pkt.type, sizeof(register_pkt.type));
	offset += sizeof(register_pkt.type);
	memcpy(pkt+offset, register_pkt.name, strlen(register_pkt.name)+1);
	offset += strlen(register_pkt.name)+1;
	memcpy(pkt+offset, register_pkt.dag, strlen(register_pkt.dag)+1);
	offset += strlen(register_pkt.dag)+1;

	//Send the name registration packet to the name server
	//FIXME: use sockaddr here
	Xsendto(sock, pkt, offset, 0, (const struct sockaddr *)&ns_dag, sizeof(sockaddr_x));

	//Check the response from the name server
	memset(pkt, 0, sizeof(pkt));
	int rc = Xrecvfrom(sock, pkt, NS_MAX_PACKET_SIZE, 0, NULL, NULL);
	if (rc < 0) { perror("recvfrom"); }

	memset(_name, '\0', NS_MAX_DAG_LENGTH);
	memset(_dag, '\0', NS_MAX_DAG_LENGTH);

	ns_pkt *tmp = (ns_pkt *)pkt;
	char* tmp_name = (char*)(pkt+sizeof(tmp->type));
	char* tmp_dag = (char*)(pkt+sizeof(tmp->type)+ strlen(tmp_name)+1);
	switch (tmp->type) {
	case NS_TYPE_RESPONSE:
		sprintf(_name, "%s", tmp_name);
		sprintf(_dag, "%s", tmp_dag);
		result = 0;
		break;
	case NS_TYPE_RESPONSE_ERROR:
		result = -1;
		break;
	default:
		fprintf(stderr, "dafault\n");
		result = -1;
		break;
	 }
	free(register_pkt.name);
	free(register_pkt.dag);

	Xclose(sock);
	return result;
}
Exemple #23
0
/*!
** @brief Lookup a DAG based using a host or service name.
**
** The name should be a string such as www_s.example.xia or host.example.xia.
** By convention services are indicated by '_s' appended to the service name.
** The memory returned is dynamically allocated and should be released with a
** call to free() when the caller is done with it.
**
** This is a very simple implementation of the name query function.
** It will be replaces in a future release.
**
** @param name The name of an XIA service or host.
**
** @returns a character point to the dag on success
** @returns NULL on failure
**
*/
int XgetDAGbyName(const char *name, sockaddr_x *addr, socklen_t *addrlen)
{
	int sock;
	sockaddr_x ns_dag;
	char pkt[NS_MAX_PACKET_SIZE];
	char *dag;
	char _name[NS_MAX_DAG_LENGTH], _dag[NS_MAX_DAG_LENGTH];
	int result;

	if (!addr || !addrlen || *addrlen < sizeof(sockaddr_x)) {
		errno = EINVAL;
		return -1;
	}

	// see if name is registered in the local hosts.xia file
	if((dag = hostsLookup(name))) {

		Graph g(dag);
		free(dag);

		// check to see if the returned dag was valid
		// we may want a better check for this in the future
		if (g.num_nodes() > 0) {
			std::string s = g.dag_string();
			g.fill_sockaddr((sockaddr_x*)addr);
			*addrlen = sizeof(sockaddr_x);
			return 0;
		}
	}

	// not found locally, check the name server
	if ((sock = Xsocket(AF_XIA, SOCK_DGRAM, 0)) < 0)
		return -1;

	//Read the nameserver DAG (the one that the name-query will be sent to)
	if ( XreadNameServerDAG(sock, &ns_dag) < 0 ) {
		LOG("Unable to find nameserver address");
		errno = NO_RECOVERY;
		return -1;
	}

	//Construct a name-query packet
	ns_pkt query_pkt;
	query_pkt.type = NS_TYPE_QUERY;
	query_pkt.name = strdup(name);

	memset(pkt, 0, sizeof(pkt));
	int offset = 0;
	memcpy(pkt, &query_pkt.type, sizeof(query_pkt.type));
	offset += sizeof(query_pkt.type);
	memcpy(pkt+offset, query_pkt.name, strlen(query_pkt.name)+1);
	offset += strlen(query_pkt.name)+1;

	//Send a name query to the name server
	Xsendto(sock, pkt, offset, 0, (const struct sockaddr*)&ns_dag, sizeof(sockaddr_x));

	//Check the response from the name server
	memset(pkt, 0, sizeof(pkt));
	int rc = Xrecvfrom(sock, pkt, NS_MAX_PACKET_SIZE, 0, NULL, NULL);
	if (rc < 0) { perror("recvfrom"); }

	memset(_name, '\0', NS_MAX_DAG_LENGTH);
	memset(_dag, '\0', NS_MAX_DAG_LENGTH);

	ns_pkt *tmp = (ns_pkt *)pkt;
	char* tmp_name = (char*)(pkt+sizeof(tmp->type));
	char* tmp_dag = (char*)(pkt+sizeof(tmp->type)+ strlen(tmp_name)+1);
	switch (tmp->type) {
	case NS_TYPE_RESPONSE:
		sprintf(_name, "%s", tmp_name);
		sprintf(_dag, "%s", tmp_dag);
		result = 1;
		break;
	case NS_TYPE_RESPONSE_ERROR:
		result = -1;
		break;
	default:
		LOG("Unknown nameserver response");
		result = -1;
		break;
	}

	Xclose(sock);
	free(query_pkt.name);

	if (result < 0) {
		return result;
	}

	Graph g(_dag);
	g.fill_sockaddr(addr);

	return 0;
}
Exemple #24
0
int main(int argc, char **argv)
{
	struct addrinfo *ai;
	sockaddr_x *sa;
	int seq = 0;

// FIXME: put signal handlers back into code once Xselect is working
//	signal(SIGINT, handler);
//	signal(SIGTERM, handler);
	getConfig(argc, argv);

	if (Xgetaddrinfo(NAME, NULL, NULL, &ai) < 0)
		die("Unable to lookup address for  %s\n", NAME);
	sa = (sockaddr_x*)ai->ai_addr;

	if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		die("Unable to create a socket\n");

	say("Opening firehose: %s\n", NAME);
	if (Xconnect(sock, (struct sockaddr*)sa, sizeof(sockaddr_x)) < 0) {
		Xclose(sock);
		die("Unable to connect to %s\n", NAME);
	}

	// tell firehose how many packets we expect
	if (Xsend(sock, &fhc, sizeof(fhc), 0) < 0) {
		Xclose(sock);
		die("Unable to send config information to the firehose\n");
	}

	int count = 0;
	char  *buf = (char *)malloc(pktSize);

	while (!timetodie) {
		int n;
		fd_set fds;
		FD_ZERO(&fds);
		FD_SET(sock, &fds);

		struct timeval tv;
		tv.tv_sec = 2;
		tv.tv_usec = 0;

		if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) {
			printf("select failed\n");
			break;

		} else if (n == 0) {
			printf("recv timeout\n");
			break;
		} else if (!FD_ISSET(sock, &fds)) {
			// this shouldn't happen!
			printf("something is really wrong, exiting\n");
			break;
		}

		int rc = Xrecv(sock, buf, sizeof(buf), 0);
		if (rc < 0)
			die("Receive failure\n");
		memcpy(&seq, buf, sizeof(int));

		say("expecting %d, got %d", count, seq);
		if (count == seq)
			say("\n");
		else
			say(" lost %d\n", seq - count);
		count++;
		if (count == numPkts)
			break;
		if (delay)
			usleep(delay);
	}

	seq++;
	if (count != seq)
		printf("lost %d packets, received %d, expected %d\n", seq - count, count, seq); 
	else
		printf("success!\n");
	Xclose(sock);
}
Exemple #25
0
int
yylex(int cf)
{
	Lex_state states[STATE_BSIZE], *statep, *s2, *base;
	State_info state_info;
	int c, c2, state;
	size_t cz;
	XString ws;		/* expandable output word */
	char *wp;		/* output word pointer */
	char *sp, *dp;

 Again:
	states[0].type = SINVALID;
	states[0].ls_base = NULL;
	statep = &states[1];
	state_info.base = states;
	state_info.end = &state_info.base[STATE_BSIZE];

	Xinit(ws, wp, 64, ATEMP);

	backslash_skip = 0;
	ignore_backslash_newline = 0;

	if (cf & ONEWORD)
		state = SWORD;
	else if (cf & LETEXPR) {
		/* enclose arguments in (double) quotes */
		*wp++ = OQUOTE;
		state = SLETPAREN;
		statep->nparen = 0;
	} else {
		/* normal lexing */
		state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
		while ((c = getsc()) == ' ' || c == '\t')
			;
		if (c == '#') {
			ignore_backslash_newline++;
			while ((c = getsc()) != '\0' && c != '\n')
				;
			ignore_backslash_newline--;
		}
		ungetsc(c);
	}
	if (source->flags & SF_ALIAS) {
		/* trailing ' ' in alias definition */
		source->flags &= ~SF_ALIAS;
		/* POSIX: trailing space only counts if parsing simple cmd */
		if (!Flag(FPOSIX) || (cf & CMDWORD))
			cf |= ALIAS;
	}

	/* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */
	statep->type = state;

	/* collect non-special or quoted characters to form word */
	while (!((c = getsc()) == 0 ||
	    ((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
		if (state == SBASE &&
		    subshell_nesting_type == /*{*/ '}' &&
		    c == /*{*/ '}')
			/* possibly end ${ :;} */
			break;
		Xcheck(ws, wp);
		switch (state) {
		case SADELIM:
			if (c == '(')
				statep->nparen++;
			else if (c == ')')
				statep->nparen--;
			else if (statep->nparen == 0 && (c == /*{*/ '}' ||
			    c == (int)statep->ls_adelim.delimiter)) {
				*wp++ = ADELIM;
				*wp++ = c;
				if (c == /*{*/ '}' || --statep->ls_adelim.num == 0)
					POP_STATE();
				if (c == /*{*/ '}')
					POP_STATE();
				break;
			}
			/* FALLTHROUGH */
		case SBASE:
			if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
				/* temporary */
				*wp = EOS;
				if (is_wdvarname(Xstring(ws, wp), false)) {
					char *p, *tmp;

					if (arraysub(&tmp)) {
						*wp++ = CHAR;
						*wp++ = c;
						for (p = tmp; *p; ) {
							Xcheck(ws, wp);
							*wp++ = CHAR;
							*wp++ = *p++;
						}
						afree(tmp, ATEMP);
						break;
					} else {
						Source *s;

						s = pushs(SREREAD,
						    source->areap);
						s->start = s->str =
						    s->u.freeme = tmp;
						s->next = source;
						source = s;
					}
				}
				*wp++ = CHAR;
				*wp++ = c;
				break;
			}
			/* FALLTHROUGH */
 Sbase1:		/* includes *(...|...) pattern (*+?@!) */
			if (c == '*' || c == '@' || c == '+' || c == '?' ||
			    c == '!') {
				c2 = getsc();
				if (c2 == '(' /*)*/ ) {
					*wp++ = OPAT;
					*wp++ = c;
					PUSH_STATE(SPATTERN);
					break;
				}
				ungetsc(c2);
			}
			/* FALLTHROUGH */
 Sbase2:		/* doesn't include *(...|...) pattern (*+?@!) */
			switch (c) {
			case '\\':
 getsc_qchar:
				if ((c = getsc())) {
					/* trailing \ is lost */
					*wp++ = QCHAR;
					*wp++ = c;
				}
				break;
			case '\'':
 open_ssquote_unless_heredoc:
				if ((cf & HEREDOC))
					goto store_char;
				*wp++ = OQUOTE;
				ignore_backslash_newline++;
				PUSH_STATE(SSQUOTE);
				break;
			case '"':
 open_sdquote:
				*wp++ = OQUOTE;
				PUSH_STATE(SDQUOTE);
				break;
			case '$':
				/*
				 * processing of dollar sign belongs into
				 * Subst, except for those which can open
				 * a string: $'…' and $"…"
				 */
 subst_dollar_ex:
				c = getsc();
				switch (c) {
				case '"':
					goto open_sdquote;
				case '\'':
					goto open_sequote;
				default:
					goto SubstS;
				}
			default:
				goto Subst;
			}
			break;

 Subst:
			switch (c) {
			case '\\':
				c = getsc();
				switch (c) {
				case '"':
					if ((cf & HEREDOC))
						goto heredocquote;
					/* FALLTHROUGH */
				case '\\':
				case '$': case '`':
 store_qchar:
					*wp++ = QCHAR;
					*wp++ = c;
					break;
				default:
 heredocquote:
					Xcheck(ws, wp);
					if (c) {
						/* trailing \ is lost */
						*wp++ = CHAR;
						*wp++ = '\\';
						*wp++ = CHAR;
						*wp++ = c;
					}
					break;
				}
				break;
			case '$':
				c = getsc();
 SubstS:
				if (c == '(') /*)*/ {
					c = getsc();
					if (c == '(') /*)*/ {
						*wp++ = EXPRSUB;
						PUSH_SRETRACE(SASPAREN);
						statep->nparen = 2;
						*retrace_info->xp++ = '(';
					} else {
						ungetsc(c);
 subst_command:
						c = COMSUB;
 subst_command2:
						sp = yyrecursive(c);
						cz = strlen(sp) + 1;
						XcheckN(ws, wp, cz);
						*wp++ = c;
						memcpy(wp, sp, cz);
						wp += cz;
					}
				} else if (c == '{') /*}*/ {
					if ((c = getsc()) == '|') {
						/*
						 * non-subenvironment
						 * value substitution
						 */
						c = VALSUB;
						goto subst_command2;
					} else if (ctype(c, C_IFSWS)) {
						/*
						 * non-subenvironment
						 * "command" substitution
						 */
						c = FUNSUB;
						goto subst_command2;
					}
					ungetsc(c);
					*wp++ = OSUBST;
					*wp++ = '{'; /*}*/
					wp = get_brace_var(&ws, wp);
					c = getsc();
					/* allow :# and :% (ksh88 compat) */
					if (c == ':') {
						*wp++ = CHAR;
						*wp++ = c;
						c = getsc();
						if (c == ':') {
							*wp++ = CHAR;
							*wp++ = '0';
							*wp++ = ADELIM;
							*wp++ = ':';
							PUSH_STATE(SBRACE);
							PUSH_STATE(SADELIM);
							statep->ls_adelim.delimiter = ':';
							statep->ls_adelim.num = 1;
							statep->nparen = 0;
							break;
						} else if (ksh_isdigit(c) ||
						    c == '('/*)*/ || c == ' ' ||
						    /*XXX what else? */
						    c == '$') {
							/* substring subst. */
							if (c != ' ') {
								*wp++ = CHAR;
								*wp++ = ' ';
							}
							ungetsc(c);
							PUSH_STATE(SBRACE);
							PUSH_STATE(SADELIM);
							statep->ls_adelim.delimiter = ':';
							statep->ls_adelim.num = 2;
							statep->nparen = 0;
							break;
						}
					} else if (c == '/') {
						*wp++ = CHAR;
						*wp++ = c;
						if ((c = getsc()) == '/') {
							*wp++ = ADELIM;
							*wp++ = c;
						} else
							ungetsc(c);
						PUSH_STATE(SBRACE);
						PUSH_STATE(SADELIM);
						statep->ls_adelim.delimiter = '/';
						statep->ls_adelim.num = 1;
						statep->nparen = 0;
						break;
					}
					/*
					 * If this is a trim operation,
					 * treat (,|,) specially in STBRACE.
					 */
					if (ctype(c, C_SUBOP2)) {
						ungetsc(c);
						if (Flag(FSH))
							PUSH_STATE(STBRACEBOURNE);
						else
							PUSH_STATE(STBRACEKORN);
					} else {
						ungetsc(c);
						if (state == SDQUOTE ||
						    state == SQBRACE)
							PUSH_STATE(SQBRACE);
						else
							PUSH_STATE(SBRACE);
					}
				} else if (ksh_isalphx(c)) {
					*wp++ = OSUBST;
					*wp++ = 'X';
					do {
						Xcheck(ws, wp);
						*wp++ = c;
						c = getsc();
					} while (ksh_isalnux(c));
					*wp++ = '\0';
					*wp++ = CSUBST;
					*wp++ = 'X';
					ungetsc(c);
				} else if (ctype(c, C_VAR1 | C_DIGIT)) {
					Xcheck(ws, wp);
					*wp++ = OSUBST;
					*wp++ = 'X';
					*wp++ = c;
					*wp++ = '\0';
					*wp++ = CSUBST;
					*wp++ = 'X';
				} else {
					*wp++ = CHAR;
					*wp++ = '$';
					ungetsc(c);
				}
				break;
			case '`':
 subst_gravis:
				PUSH_STATE(SBQUOTE);
				*wp++ = COMSUB;
				/*
				 * We need to know whether we are within double
				 * quotes, since most shells translate \" to "
				 * within "…`…\"…`…". This is not done in POSIX
				 * mode (§2.2.3 Double-Quotes: “The backquote
				 * shall retain its special meaning introducing
				 * the other form of command substitution (see
				 * Command Substitution). The portion of the
				 * quoted string from the initial backquote and
				 * the characters up to the next backquote that
				 * is not preceded by a <backslash>, having
				 * escape characters removed, defines that
				 * command whose output replaces "`...`" when
				 * the word is expanded.”; §2.6.3 Command
				 * Substitution: “Within the backquoted style
				 * of command substitution, <backslash> shall
				 * retain its literal meaning, except when
				 * followed by: '$', '`', or <backslash>. The
				 * search for the matching backquote shall be
				 * satisfied by the first unquoted non-escaped
				 * backquote; during this search, if a
				 * non-escaped backquote is encountered[…],
				 * undefined results occur.”).
				 */
				statep->ls_bool = false;
				if (Flag(FPOSIX))
					break;
				s2 = statep;
				base = state_info.base;
				while (/* CONSTCOND */ 1) {
					for (; s2 != base; s2--) {
						if (s2->type == SDQUOTE) {
							statep->ls_bool = true;
							break;
						}
					}
					if (s2 != base)
						break;
					if (!(s2 = s2->ls_base))
						break;
					base = s2-- - STATE_BSIZE;
				}
				break;
			case QCHAR:
				if (cf & LQCHAR) {
					*wp++ = QCHAR;
					*wp++ = getsc();
					break;
				}
				/* FALLTHROUGH */
			default:
 store_char:
				*wp++ = CHAR;
				*wp++ = c;
			}
			break;

		case SEQUOTE:
			if (c == '\'') {
				POP_STATE();
				*wp++ = CQUOTE;
				ignore_backslash_newline--;
			} else if (c == '\\') {
				if ((c2 = unbksl(true, s_get, s_put)) == -1)
					c2 = s_get();
				if (c2 == 0)
					statep->ls_bool = true;
				if (!statep->ls_bool) {
					char ts[4];

					if ((unsigned int)c2 < 0x100) {
						*wp++ = QCHAR;
						*wp++ = c2;
					} else {
						cz = utf_wctomb(ts, c2 - 0x100);
						ts[cz] = 0;
						cz = 0;
						do {
							*wp++ = QCHAR;
							*wp++ = ts[cz];
						} while (ts[++cz]);
					}
				}
			} else if (!statep->ls_bool) {
				*wp++ = QCHAR;
				*wp++ = c;
			}
			break;

		case SSQUOTE:
			if (c == '\'') {
				POP_STATE();
				if ((cf & HEREDOC) || state == SQBRACE)
					goto store_char;
				*wp++ = CQUOTE;
				ignore_backslash_newline--;
			} else {
				*wp++ = QCHAR;
				*wp++ = c;
			}
			break;

		case SDQUOTE:
			if (c == '"') {
				POP_STATE();
				*wp++ = CQUOTE;
			} else
				goto Subst;
			break;

		/* $(( ... )) */
		case SASPAREN:
			if (c == '(')
				statep->nparen++;
			else if (c == ')') {
				statep->nparen--;
				if (statep->nparen == 1) {
					/* end of EXPRSUB */
					POP_SRETRACE();

					if ((c2 = getsc()) == /*(*/ ')') {
						cz = strlen(sp) - 2;
						XcheckN(ws, wp, cz);
						memcpy(wp, sp + 1, cz);
						wp += cz;
						afree(sp, ATEMP);
						*wp++ = '\0';
						break;
					} else {
						Source *s;

						ungetsc(c2);
						/*
						 * mismatched parenthesis -
						 * assume we were really
						 * parsing a $(...) expression
						 */
						--wp;
						s = pushs(SREREAD,
						    source->areap);
						s->start = s->str =
						    s->u.freeme = sp;
						s->next = source;
						source = s;
						goto subst_command;
					}
				}
			}
			/* reuse existing state machine */
			goto Sbase2;

		case SQBRACE:
			if (c == '\\') {
				/*
				 * perform POSIX "quote removal" if the back-
				 * slash is "special", i.e. same cases as the
				 * {case '\\':} in Subst: plus closing brace;
				 * in mksh code "quote removal" on '\c' means
				 * write QCHAR+c, otherwise CHAR+\+CHAR+c are
				 * emitted (in heredocquote:)
				 */
				if ((c = getsc()) == '"' || c == '\\' ||
				    c == '$' || c == '`' || c == /*{*/'}')
					goto store_qchar;
				goto heredocquote;
			}
			goto common_SQBRACE;

		case SBRACE:
			if (c == '\'')
				goto open_ssquote_unless_heredoc;
			else if (c == '\\')
				goto getsc_qchar;
 common_SQBRACE:
			if (c == '"')
				goto open_sdquote;
			else if (c == '$')
				goto subst_dollar_ex;
			else if (c == '`')
				goto subst_gravis;
			else if (c != /*{*/ '}')
				goto store_char;
			POP_STATE();
			*wp++ = CSUBST;
			*wp++ = /*{*/ '}';
			break;

		/* Same as SBASE, except (,|,) treated specially */
		case STBRACEKORN:
			if (c == '|')
				*wp++ = SPAT;
			else if (c == '(') {
				*wp++ = OPAT;
				/* simile for @ */
				*wp++ = ' ';
				PUSH_STATE(SPATTERN);
			} else /* FALLTHROUGH */
		case STBRACEBOURNE:
			  if (c == /*{*/ '}') {
				POP_STATE();
				*wp++ = CSUBST;
				*wp++ = /*{*/ '}';
			} else
				goto Sbase1;
			break;

		case SBQUOTE:
			if (c == '`') {
				*wp++ = 0;
				POP_STATE();
			} else if (c == '\\') {
				switch (c = getsc()) {
				case 0:
					/* trailing \ is lost */
					break;
				case '$':
				case '`':
				case '\\':
					*wp++ = c;
					break;
				case '"':
					if (statep->ls_bool) {
						*wp++ = c;
						break;
					}
					/* FALLTHROUGH */
				default:
					*wp++ = '\\';
					*wp++ = c;
					break;
				}
			} else
				*wp++ = c;
			break;

		/* ONEWORD */
		case SWORD:
			goto Subst;

		/* LETEXPR: (( ... )) */
		case SLETPAREN:
			if (c == /*(*/ ')') {
				if (statep->nparen > 0)
					--statep->nparen;
				else if ((c2 = getsc()) == /*(*/ ')') {
					c = 0;
					*wp++ = CQUOTE;
					goto Done;
				} else {
					Source *s;

					ungetsc(c2);
					/*
					 * mismatched parenthesis -
					 * assume we were really
					 * parsing a (...) expression
					 */
					*wp = EOS;
					sp = Xstring(ws, wp);
					dp = wdstrip(sp + 1, WDS_TPUTS);
					s = pushs(SREREAD, source->areap);
					s->start = s->str = s->u.freeme = dp;
					s->next = source;
					source = s;
					return ('('/*)*/);
				}
			} else if (c == '(')
				/*
				 * parentheses inside quotes and
				 * backslashes are lost, but AT&T ksh
				 * doesn't count them either
				 */
				++statep->nparen;
			goto Sbase2;

		/* << or <<- delimiter */
		case SHEREDELIM:
			/*
			 * here delimiters need a special case since
			 * $ and `...` are not to be treated specially
			 */
			switch (c) {
			case '\\':
				if ((c = getsc())) {
					/* trailing \ is lost */
					*wp++ = QCHAR;
					*wp++ = c;
				}
				break;
			case '\'':
				goto open_ssquote_unless_heredoc;
			case '$':
				if ((c2 = getsc()) == '\'') {
 open_sequote:
					*wp++ = OQUOTE;
					ignore_backslash_newline++;
					PUSH_STATE(SEQUOTE);
					statep->ls_bool = false;
					break;
				} else if (c2 == '"') {
					/* FALLTHROUGH */
			case '"':
					PUSH_SRETRACE(SHEREDQUOTE);
					break;
				}
				ungetsc(c2);
				/* FALLTHROUGH */
			default:
				*wp++ = CHAR;
				*wp++ = c;
			}
			break;

		/* " in << or <<- delimiter */
		case SHEREDQUOTE:
			if (c != '"')
				goto Subst;
			POP_SRETRACE();
			dp = strnul(sp) - 1;
			/* remove the trailing double quote */
			*dp = '\0';
			/* store the quoted string */
			*wp++ = OQUOTE;
			XcheckN(ws, wp, (dp - sp) * 2);
			dp = sp;
			while ((c = *dp++)) {
				if (c == '\\') {
					switch ((c = *dp++)) {
					case '\\':
					case '"':
					case '$':
					case '`':
						break;
					default:
						*wp++ = CHAR;
						*wp++ = '\\';
						break;
					}
				}
				*wp++ = CHAR;
				*wp++ = c;
			}
			afree(sp, ATEMP);
			*wp++ = CQUOTE;
			state = statep->type = SHEREDELIM;
			break;

		/* in *(...|...) pattern (*+?@!) */
		case SPATTERN:
			if (c == /*(*/ ')') {
				*wp++ = CPAT;
				POP_STATE();
			} else if (c == '|') {
				*wp++ = SPAT;
			} else if (c == '(') {
				*wp++ = OPAT;
				/* simile for @ */
				*wp++ = ' ';
				PUSH_STATE(SPATTERN);
			} else
				goto Sbase1;
			break;
		}
	}
 Done:
	Xcheck(ws, wp);
	if (statep != &states[1])
		/* XXX figure out what is missing */
		yyerror("no closing quote\n");

	/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
	if (state == SHEREDELIM)
		state = SBASE;

	dp = Xstring(ws, wp);
	if (state == SBASE && (
#ifndef MKSH_LEGACY_MODE
	    (c == '&' && !Flag(FSH) && !Flag(FPOSIX)) ||
#endif
	    c == '<' || c == '>')) {
		struct ioword *iop = alloc(sizeof(struct ioword), ATEMP);

		if (Xlength(ws, wp) == 0)
			iop->unit = c == '<' ? 0 : 1;
		else for (iop->unit = 0, c2 = 0; c2 < Xlength(ws, wp); c2 += 2) {
			if (dp[c2] != CHAR)
				goto no_iop;
			if (!ksh_isdigit(dp[c2 + 1]))
				goto no_iop;
			iop->unit = iop->unit * 10 + ksh_numdig(dp[c2 + 1]);
			if (iop->unit >= FDBASE)
				goto no_iop;
		}

		if (c == '&') {
			if ((c2 = getsc()) != '>') {
				ungetsc(c2);
				goto no_iop;
			}
			c = c2;
			iop->ioflag = IOBASH;
		} else
			iop->ioflag = 0;

		c2 = getsc();
		/* <<, >>, <> are ok, >< is not */
		if (c == c2 || (c == '<' && c2 == '>')) {
			iop->ioflag |= c == c2 ?
			    (c == '>' ? IOCAT : IOHERE) : IORDWR;
			if (iop->ioflag == IOHERE) {
				if ((c2 = getsc()) == '-')
					iop->ioflag |= IOSKIP;
				else if (c2 == '<')
					iop->ioflag |= IOHERESTR;
				else
					ungetsc(c2);
			}
		} else if (c2 == '&')
			iop->ioflag |= IODUP | (c == '<' ? IORDUP : 0);
		else {
			iop->ioflag |= c == '>' ? IOWRITE : IOREAD;
			if (c == '>' && c2 == '|')
				iop->ioflag |= IOCLOB;
			else
				ungetsc(c2);
		}

		iop->ioname = NULL;
		iop->delim = NULL;
		iop->heredoc = NULL;
		/* free word */
		Xfree(ws, wp);
		yylval.iop = iop;
		return (REDIR);
 no_iop:
		afree(iop, ATEMP);
	}

	if (wp == dp && state == SBASE) {
		/* free word */
		Xfree(ws, wp);
		/* no word, process LEX1 character */
		if ((c == '|') || (c == '&') || (c == ';') || (c == '('/*)*/)) {
			if ((c2 = getsc()) == c)
				c = (c == ';') ? BREAK :
				    (c == '|') ? LOGOR :
				    (c == '&') ? LOGAND :
				    /* c == '(' ) */ MDPAREN;
			else if (c == '|' && c2 == '&')
				c = COPROC;
			else if (c == ';' && c2 == '|')
				c = BRKEV;
			else if (c == ';' && c2 == '&')
				c = BRKFT;
			else
				ungetsc(c2);
#ifndef MKSH_SMALL
			if (c == BREAK) {
				if ((c2 = getsc()) == '&')
					c = BRKEV;
				else
					ungetsc(c2);
			}
#endif
		} else if (c == '\n') {
			if (cf & HEREDELIM)
				ungetsc(c);
			else {
				gethere();
				if (cf & CONTIN)
					goto Again;
			}
		}
		return (c);
	}

	/* terminate word */
	*wp++ = EOS;
	yylval.cp = Xclose(ws, wp);
	if (state == SWORD || state == SLETPAREN
	    /* XXX ONEWORD? */)
		return (LWORD);

	/* unget terminator */
	ungetsc(c);

	/*
	 * note: the alias-vs-function code below depends on several
	 * interna: starting from here, source->str is not modified;
	 * the way getsc() and ungetsc() operate; etc.
	 */

	/* copy word to unprefixed string ident */
	sp = yylval.cp;
	dp = ident;
	while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
		*dp++ = *sp++;
	if (c != EOS)
		/* word is not unquoted */
		dp = ident;
	/* make sure the ident array stays NUL padded */
	memset(dp, 0, (ident + IDENT) - dp + 1);

	if (!(cf & (KEYWORD | ALIAS)))
		return (LWORD);

	if (*ident != '\0') {
		struct tbl *p;
		uint32_t h = hash(ident);

		if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
		    (!(cf & ESACONLY) || p->val.i == ESAC ||
		    p->val.i == /*{*/ '}')) {
			afree(yylval.cp, ATEMP);
			return (p->val.i);
		}
		if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h)) &&
		    (p->flag & ISSET)) {
			/*
			 * this still points to the same character as the
			 * ungetsc'd terminator from above
			 */
			const char *cp = source->str;

			/* prefer POSIX but not Korn functions over aliases */
			while (*cp == ' ' || *cp == '\t')
				/*
				 * this is like getsc() without skipping
				 * over Source boundaries (including not
				 * parsing ungetsc'd characters that got
				 * pushed into an SREREAD) which is what
				 * we want here anyway: find out whether
				 * the alias name is followed by a POSIX
				 * function definition
				 */
				++cp;
			/* prefer functions over aliases */
			if (cp[0] != '(' || cp[1] != ')') {
				Source *s = source;

				while (s && (s->flags & SF_HASALIAS))
					if (s->u.tblp == p)
						return (LWORD);
					else
						s = s->next;
				/* push alias expansion */
				s = pushs(SALIAS, source->areap);
				s->start = s->str = p->val.s;
				s->u.tblp = p;
				s->flags |= SF_HASALIAS;
				s->next = source;
				if (source->type == SEOF) {
					/* prevent infinite recursion at EOS */
					source->u.tblp = p;
					source->flags |= SF_HASALIAS;
				}
				source = s;
				afree(yylval.cp, ATEMP);
				goto Again;
			}
		}
	} else if (cf & ALIAS) {
		/* retain typeset et al. even when quoted */
		if (assign_command((dp = wdstrip(yylval.cp, 0))))
			strlcpy(ident, dp, sizeof(ident));
		afree(dp, ATEMP);
	}

	return (LWORD);
}
Exemple #26
0
int
yylex(int cf)
{
	Lex_state states[STATE_BSIZE], *statep;
	State_info state_info;
	int c, state;
	XString ws;		/* expandable output word */
	char *wp;		/* output word pointer */
	char *sp, *dp;
	int c2;


  Again:
	states[0].ls_state = -1;
	states[0].ls_info.base = (Lex_state *) 0;
	statep = &states[1];
	state_info.base = states;
	state_info.end = &states[STATE_BSIZE];

	Xinit(ws, wp, 64, ATEMP);

	backslash_skip = 0;
	ignore_backslash_newline = 0;

	if (cf&ONEWORD)
		state = SWORD;
	else if (cf&LETEXPR) {
		*wp++ = OQUOTE;	 /* enclose arguments in (double) quotes */
		state = SLETPAREN;
		statep->ls_sletparen.nparen = 0;
	} else {		/* normal lexing */
		state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
		while ((c = getsc()) == ' ' || c == '\t')
			;
		if (c == '#') {
			ignore_backslash_newline++;
			while ((c = getsc()) != '\0' && c != '\n')
				;
			ignore_backslash_newline--;
		}
		ungetsc(c);
	}
	if (source->flags & SF_ALIAS) {	/* trailing ' ' in alias definition */
		source->flags &= ~SF_ALIAS;
		/* In POSIX mode, a trailing space only counts if we are
		 * parsing a simple command
		 */
		if (!Flag(FPOSIX) || (cf & CMDWORD))
			cf |= ALIAS;
	}

	/* Initial state: one of SBASE SHEREDELIM SWORD SASPAREN */
	statep->ls_state = state;

	/* collect non-special or quoted characters to form word */
	while (!((c = getsc()) == 0
		 || ((state == SBASE || state == SHEREDELIM)
		     && ctype(c, C_LEX1))))
	{
		Xcheck(ws, wp);
		switch (state) {
		  case SBASE:
			if (Flag(FCSHHISTORY) && (source->flags & SF_TTY) && c == '!') {
				char **replace = NULL;

				c2 = getsc();
				if (c2 == '\0')
					;
				else if (c2 == ' ' || c2 == '\t')
					ungetsc(c2);
				else if (c2 == '!')
					replace = hist_get_newest(0);
				else if (isdigit(c2) || c2 == '-' ||
				    isalpha(c2)) {
					int get = !isalpha(c2);
					char match[200], *str = match;

					*str++ = c2;
					do {
						if ((c2 = getsc()) == '\0')
							break;
						if (c2 == '\t' || c2 == ' ' ||
						    c2 == '\n') {
							ungetsc(c2);
							break;
						}
						*str++ = c2;
					} while (str < &match[sizeof(match)-1]);
					*str = '\0';

					if (get) {
						int h = findhistrel(match);
						if (h >= 0)
							replace = &history[h];
					} else {
						int h = findhist(-1, 0, match, true);
						if (h >= 0)
							replace = &history[h];
					}
				}

				/*
				 * XXX ksh history buffer saves un-expanded
				 * commands. Until the history buffer code is
				 * changed to contain expanded commands, we
				 * ignore the bad commands (spinning sucks)
				 */
				if (replace && **replace == '!')
					ungetsc(c2);
				else if (replace) {
					Source *s;

					/* do not strdup replacement via alloc */
					s = pushs(SREREAD,
					      source->areap);
					s->start = s->str = *replace;
					s->next = source;
					source = s;
					continue;
				} else
					ungetsc(c2);
			}
			if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
				*wp = EOS; /* temporary */
				if (is_wdvarname(Xstring(ws, wp), false))
				{
					char *p, *tmp;

					if (arraysub(&tmp)) {
						*wp++ = CHAR;
						*wp++ = c;
						for (p = tmp; *p; ) {
							Xcheck(ws, wp);
							*wp++ = CHAR;
							*wp++ = *p++;
						}
						afree(tmp, ATEMP);
						break;
					} else {
						Source *s;

						s = pushs(SREREAD,
							  source->areap);
						s->start = s->str
							= s->u.freeme = tmp;
						s->next = source;
						source = s;
					}
				}
				*wp++ = CHAR;
				*wp++ = c;
				break;
			}
			/* fall through.. */
		  Sbase1:	/* includes *(...|...) pattern (*+?@!) */
			if (c == '*' || c == '@' || c == '+' || c == '?'
			    || c == '!')
			{
				c2 = getsc();
				if (c2 == '(' /*)*/ ) {
					*wp++ = OPAT;
					*wp++ = c;
					PUSH_STATE(SPATTERN);
					break;
				}
				ungetsc(c2);
			}
			/* fall through.. */
		  Sbase2:	/* doesn't include *(...|...) pattern (*+?@!) */
			switch (c) {
			  case '\\':
				c = getsc();
				if (c) /* trailing \ is lost */
					*wp++ = QCHAR, *wp++ = c;
				break;
			  case '\'':
				*wp++ = OQUOTE;
				ignore_backslash_newline++;
				PUSH_STATE(SSQUOTE);
				break;
			  case '"':
				*wp++ = OQUOTE;
				PUSH_STATE(SDQUOTE);
				break;
			  default:
				goto Subst;
			}
			break;

		  Subst:
			switch (c) {
			  case '\\':
				c = getsc();
				switch (c) {
				  case '"': case '\\':
				  case '$': case '`':
					*wp++ = QCHAR, *wp++ = c;
					break;
				  default:
					Xcheck(ws, wp);
					if (c) { /* trailing \ is lost */
						*wp++ = CHAR, *wp++ = '\\';
						*wp++ = CHAR, *wp++ = c;
					}
					break;
				}
				break;
			  case '$':
				c = getsc();
				if (c == '(') /*)*/ {
					c = getsc();
					if (c == '(') /*)*/ {
						PUSH_STATE(SASPAREN);
						statep->ls_sasparen.nparen = 2;
						statep->ls_sasparen.start =
							Xsavepos(ws, wp);
						*wp++ = EXPRSUB;
					} else {
						ungetsc(c);
						PUSH_STATE(SCSPAREN);
						statep->ls_scsparen.nparen = 1;
						statep->ls_scsparen.csstate = 0;
						*wp++ = COMSUB;
					}
				} else if (c == '{') /*}*/ {
					*wp++ = OSUBST;
					*wp++ = '{'; /*}*/
					wp = get_brace_var(&ws, wp);
					c = getsc();
					/* allow :# and :% (ksh88 compat) */
					if (c == ':') {
						*wp++ = CHAR, *wp++ = c;
						c = getsc();
					}
					/* If this is a trim operation,
					 * treat (,|,) specially in STBRACE.
					 */
					if (c == '#' || c == '%') {
						ungetsc(c);
						PUSH_STATE(STBRACE);
					} else {
						ungetsc(c);
						PUSH_STATE(SBRACE);
					}
				} else if (ctype(c, C_ALPHA)) {
					*wp++ = OSUBST;
					*wp++ = 'X';
					do {
						Xcheck(ws, wp);
						*wp++ = c;
						c = getsc();
					} while (ctype(c, C_ALPHA|C_DIGIT));
					*wp++ = '\0';
					*wp++ = CSUBST;
					*wp++ = 'X';
					ungetsc(c);
				} else if (ctype(c, C_DIGIT|C_VAR1)) {
					Xcheck(ws, wp);
					*wp++ = OSUBST;
					*wp++ = 'X';
					*wp++ = c;
					*wp++ = '\0';
					*wp++ = CSUBST;
					*wp++ = 'X';
				} else {
					*wp++ = CHAR, *wp++ = '$';
					ungetsc(c);
				}
				break;
			  case '`':
				PUSH_STATE(SBQUOTE);
				*wp++ = COMSUB;
				/* Need to know if we are inside double quotes
				 * since sh/at&t-ksh translate the \" to " in
				 * "`..\"..`".
				 * This is not done in posix mode (section
				 * 3.2.3, Double Quotes: "The backquote shall
				 * retain its special meaning introducing the
				 * other form of command substitution (see
				 * 3.6.3). The portion of the quoted string
				 * from the initial backquote and the
				 * characters up to the next backquote that
				 * is not preceded by a backslash (having
				 * escape characters removed) defines that
				 * command whose output replaces `...` when
				 * the word is expanded."
				 * Section 3.6.3, Command Substitution:
				 * "Within the backquoted style of command
				 * substitution, backslash shall retain its
				 * literal meaning, except when followed by
				 * $ ` \.").
				 */
				statep->ls_sbquote.indquotes = 0;
				if (!Flag(FPOSIX)) {
					Lex_state *s = statep;
					Lex_state *base = state_info.base;
					while (1) {
						for (; s != base; s--) {
							if (s->ls_state == SDQUOTE) {
								statep->ls_sbquote.indquotes = 1;
								break;
							}
						}
						if (s != base)
							break;
						if (!(s = s->ls_info.base))
							break;
						base = s-- - STATE_BSIZE;
					}
				}
				break;
			  default:
				*wp++ = CHAR, *wp++ = c;
			}
			break;

		  case SSQUOTE:
			if (c == '\'') {
				POP_STATE();
				*wp++ = CQUOTE;
				ignore_backslash_newline--;
			} else
				*wp++ = QCHAR, *wp++ = c;
			break;

		  case SDQUOTE:
			if (c == '"') {
				POP_STATE();
				*wp++ = CQUOTE;
			} else
				goto Subst;
			break;

		  case SCSPAREN: /* $( .. ) */
			/* todo: deal with $(...) quoting properly
			 * kludge to partly fake quoting inside $(..): doesn't
			 * really work because nested $(..) or ${..} inside
			 * double quotes aren't dealt with.
			 */
			switch (statep->ls_scsparen.csstate) {
			  case 0: /* normal */
				switch (c) {
				  case '(':
					statep->ls_scsparen.nparen++;
					break;
				  case ')':
					statep->ls_scsparen.nparen--;
					break;
				  case '\\':
					statep->ls_scsparen.csstate = 1;
					break;
				  case '"':
					statep->ls_scsparen.csstate = 2;
					break;
				  case '\'':
					statep->ls_scsparen.csstate = 4;
					ignore_backslash_newline++;
					break;
				}
				break;

			  case 1: /* backslash in normal mode */
			  case 3: /* backslash in double quotes */
				--statep->ls_scsparen.csstate;
				break;

			  case 2: /* double quotes */
				if (c == '"')
					statep->ls_scsparen.csstate = 0;
				else if (c == '\\')
					statep->ls_scsparen.csstate = 3;
				break;

			  case 4: /* single quotes */
				if (c == '\'') {
					statep->ls_scsparen.csstate = 0;
					ignore_backslash_newline--;
				}
				break;
			}
			if (statep->ls_scsparen.nparen == 0) {
				POP_STATE();
				*wp++ = 0; /* end of COMSUB */
			} else
				*wp++ = c;
			break;

		  case SASPAREN: /* $(( .. )) */
			/* todo: deal with $((...); (...)) properly */
			/* XXX should nest using existing state machine
			 *     (embed "..", $(...), etc.) */
			if (c == '(')
				statep->ls_sasparen.nparen++;
			else if (c == ')') {
				statep->ls_sasparen.nparen--;
				if (statep->ls_sasparen.nparen == 1) {
					/*(*/
					if ((c2 = getsc()) == ')') {
						POP_STATE();
						*wp++ = 0; /* end of EXPRSUB */
						break;
					} else {
						char *s;

						ungetsc(c2);
						/* mismatched parenthesis -
						 * assume we were really
						 * parsing a $(..) expression
						 */
						s = Xrestpos(ws, wp,
						     statep->ls_sasparen.start);
						memmove(s + 1, s, wp - s);
						*s++ = COMSUB;
						*s = '('; /*)*/
						wp++;
						statep->ls_scsparen.nparen = 1;
						statep->ls_scsparen.csstate = 0;
						state = statep->ls_state
							= SCSPAREN;
					}
				}
			}
			*wp++ = c;
			break;

		  case SBRACE:
			/*{*/
			if (c == '}') {
				POP_STATE();
				*wp++ = CSUBST;
				*wp++ = /*{*/ '}';
			} else
				goto Sbase1;
			break;

		  case STBRACE:
			/* Same as SBRACE, except (,|,) treated specially */
			/*{*/
			if (c == '}') {
				POP_STATE();
				*wp++ = CSUBST;
				*wp++ = /*{*/ '}';
			} else if (c == '|') {
				*wp++ = SPAT;
			} else if (c == '(') {
				*wp++ = OPAT;
				*wp++ = ' ';	/* simile for @ */
				PUSH_STATE(SPATTERN);
			} else
				goto Sbase1;
			break;

		  case SBQUOTE:
			if (c == '`') {
				*wp++ = 0;
				POP_STATE();
			} else if (c == '\\') {
				switch (c = getsc()) {
				  case '\\':
				  case '$': case '`':
					*wp++ = c;
					break;
				  case '"':
					if (statep->ls_sbquote.indquotes) {
						*wp++ = c;
						break;
					}
					/* fall through.. */
				  default:
					if (c) { /* trailing \ is lost */
						*wp++ = '\\';
						*wp++ = c;
					}
					break;
				}
			} else
				*wp++ = c;
			break;

		  case SWORD:	/* ONEWORD */
			goto Subst;

		  case SLETPAREN:	/* LETEXPR: (( ... )) */
			/*(*/
			if (c == ')') {
				if (statep->ls_sletparen.nparen > 0)
				    --statep->ls_sletparen.nparen;
				/*(*/
				else if ((c2 = getsc()) == ')') {
					c = 0;
					*wp++ = CQUOTE;
					goto Done;
				} else
					ungetsc(c2);
			} else if (c == '(')
				/* parenthesis inside quotes and backslashes
				 * are lost, but at&t ksh doesn't count them
				 * either
				 */
				++statep->ls_sletparen.nparen;
			goto Sbase2;

		  case SHEREDELIM:	/* <<,<<- delimiter */
			/* XXX chuck this state (and the next) - use
			 * the existing states ($ and \`..` should be
			 * stripped of their specialness after the
			 * fact).
			 */
			/* here delimiters need a special case since
			 * $ and `..` are not to be treated specially
			 */
			if (c == '\\') {
				c = getsc();
				if (c) { /* trailing \ is lost */
					*wp++ = QCHAR;
					*wp++ = c;
				}
			} else if (c == '\'') {
				PUSH_STATE(SSQUOTE);
				*wp++ = OQUOTE;
				ignore_backslash_newline++;
			} else if (c == '"') {
				state = statep->ls_state = SHEREDQUOTE;
				*wp++ = OQUOTE;
			} else {
				*wp++ = CHAR;
				*wp++ = c;
			}
			break;

		  case SHEREDQUOTE:	/* " in <<,<<- delimiter */
			if (c == '"') {
				*wp++ = CQUOTE;
				state = statep->ls_state = SHEREDELIM;
			} else {
				if (c == '\\') {
					switch (c = getsc()) {
					  case '\\': case '"':
					  case '$': case '`':
						break;
					  default:
						if (c) { /* trailing \ lost */
							*wp++ = CHAR;
							*wp++ = '\\';
						}
						break;
					}
				}
				*wp++ = CHAR;
				*wp++ = c;
			}
			break;

		  case SPATTERN:	/* in *(...|...) pattern (*+?@!) */
			if ( /*(*/ c == ')') {
				*wp++ = CPAT;
				POP_STATE();
			} else if (c == '|') {
				*wp++ = SPAT;
			} else if (c == '(') {
				*wp++ = OPAT;
				*wp++ = ' ';	/* simile for @ */
				PUSH_STATE(SPATTERN);
			} else
				goto Sbase1;
			break;
		}
	}
Done:
	Xcheck(ws, wp);
	if (statep != &states[1])
		/* XXX figure out what is missing */
		yyerror("no closing quote\n");

	/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
	if (state == SHEREDELIM)
		state = SBASE;

	dp = Xstring(ws, wp);
	if ((c == '<' || c == '>') && state == SBASE
	    && ((c2 = Xlength(ws, wp)) == 0
	        || (c2 == 2 && dp[0] == CHAR && digit(dp[1]))))
	{
		struct ioword *iop =
				(struct ioword *) alloc(sizeof(*iop), ATEMP);

		if (c2 == 2)
			iop->unit = dp[1] - '0';
		else
			iop->unit = c == '>'; /* 0 for <, 1 for > */

		c2 = getsc();
		/* <<, >>, <> are ok, >< is not */
		if (c == c2 || (c == '<' && c2 == '>')) {
			iop->flag = c == c2 ?
				  (c == '>' ? IOCAT : IOHERE) : IORDWR;
			if (iop->flag == IOHERE) {
				if ((c2 = getsc()) == '-')
					iop->flag |= IOSKIP;
				else
					ungetsc(c2);
			}
		} else if (c2 == '&')
			iop->flag = IODUP | (c == '<' ? IORDUP : 0);
		else {
			iop->flag = c == '>' ? IOWRITE : IOREAD;
			if (c == '>' && c2 == '|')
				iop->flag |= IOCLOB;
			else
				ungetsc(c2);
		}

		iop->name = (char *) 0;
		iop->delim = (char *) 0;
		iop->heredoc = (char *) 0;
		Xfree(ws, wp);	/* free word */
		yylval.iop = iop;
		return REDIR;
	}

	if (wp == dp && state == SBASE) {
		Xfree(ws, wp);	/* free word */
		/* no word, process LEX1 character */
		switch (c) {
		  default:
			return c;

		  case '|':
		  case '&':
		  case ';':
			if ((c2 = getsc()) == c)
				c = (c == ';') ? BREAK :
				    (c == '|') ? LOGOR :
				    (c == '&') ? LOGAND :
				    YYERRCODE;
			else if (c == '|' && c2 == '&')
				c = COPROC;
			else
				ungetsc(c2);
			return c;

		  case '\n':
			gethere();
			if (cf & CONTIN)
				goto Again;
			return c;

		  case '(':  /*)*/
			if (!Flag(FSH)) {
				if ((c2 = getsc()) == '(') /*)*/
					/* XXX need to handle ((...); (...)) */
					c = MDPAREN;
				else
					ungetsc(c2);
			}
			return c;
		  /*(*/
		  case ')':
			return c;
		}
	}

	*wp++ = EOS;		/* terminate word */
	yylval.cp = Xclose(ws, wp);
	if (state == SWORD || state == SLETPAREN)	/* ONEWORD? */
		return LWORD;
	ungetsc(c);		/* unget terminator */

	/* copy word to unprefixed string ident */
	for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; )
		*dp++ = *sp++;
	/* Make sure the ident array stays '\0' padded */
	memset(dp, 0, (ident+IDENT) - dp + 1);
	if (c != EOS)
		*ident = '\0';	/* word is not unquoted */

	if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) {
		struct tbl *p;
		int h = hash(ident);

		/* { */
		if ((cf & KEYWORD) && (p = tsearch(&keywords, ident, h))
		    && (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}'))
		{
			afree(yylval.cp, ATEMP);
			return p->val.i;
		}
		if ((cf & ALIAS) && (p = tsearch(&aliases, ident, h))
		    && (p->flag & ISSET))
		{
			Source *s;

			for (s = source; s->type == SALIAS; s = s->next)
				if (s->u.tblp == p)
					return LWORD;
			/* push alias expansion */
			s = pushs(SALIAS, source->areap);
			s->start = s->str = p->val.s;
			s->u.tblp = p;
			s->next = source;
			source = s;
			afree(yylval.cp, ATEMP);
			goto Again;
		}
	}

	return LWORD;
}
Exemple #27
0
char *
do_realpath(const char *upath)
{
	char *xp, *ip, *tp, *ipath, *ldest = NULL;
	XString xs;
	size_t pos, len;
	int llen;
	struct stat sb;
#ifdef MKSH__NO_PATH_MAX
	size_t ldestlen = 0;
#define pathlen sb.st_size
#define pathcnd (ldestlen < (pathlen + 1))
#else
#define pathlen PATH_MAX
#define pathcnd (!ldest)
#endif
	/* max. recursion depth */
	int symlinks = 32;

	if (mksh_abspath(upath)) {
		/* upath is an absolute pathname */
		strdupx(ipath, upath, ATEMP);
	} else {
		/* upath is a relative pathname, prepend cwd */
		if ((tp = ksh_get_wd()) == NULL || !mksh_abspath(tp))
			return (NULL);
		ipath = shf_smprintf("%s%s%s", tp, "/", upath);
		afree(tp, ATEMP);
	}

	/* ipath and upath are in memory at the same time -> unchecked */
	Xinit(xs, xp, strlen(ip = ipath) + 1, ATEMP);

	/* now jump into the deep of the loop */
	goto beginning_of_a_pathname;

	while (*ip) {
		/* skip slashes in input */
		while (*ip == '/')
			++ip;
		if (!*ip)
			break;

		/* get next pathname component from input */
		tp = ip;
		while (*ip && *ip != '/')
			++ip;
		len = ip - tp;

		/* check input for "." and ".." */
		if (tp[0] == '.') {
			if (len == 1)
				/* just continue with the next one */
				continue;
			else if (len == 2 && tp[1] == '.') {
				/* strip off last pathname component */
				while (xp > Xstring(xs, xp))
					if (*--xp == '/')
						break;
				/* then continue with the next one */
				continue;
			}
		}

		/* store output position away, then append slash to output */
		pos = Xsavepos(xs, xp);
		/* 1 for the '/' and len + 1 for tp and the NUL from below */
		XcheckN(xs, xp, 1 + len + 1);
		Xput(xs, xp, '/');

		/* append next pathname component to output */
		memcpy(xp, tp, len);
		xp += len;
		*xp = '\0';

		/* lstat the current output, see if it's a symlink */
		if (mksh_lstat(Xstring(xs, xp), &sb)) {
			/* lstat failed */
			if (errno == ENOENT) {
				/* because the pathname does not exist */
				while (*ip == '/')
					/* skip any trailing slashes */
					++ip;
				/* no more components left? */
				if (!*ip)
					/* we can still return successfully */
					break;
				/* more components left? fall through */
			}
			/* not ENOENT or not at the end of ipath */
			goto notfound;
		}

		/* check if we encountered a symlink? */
		if (S_ISLNK(sb.st_mode)) {
#ifndef MKSH__NO_SYMLINK
			/* reached maximum recursion depth? */
			if (!symlinks--) {
				/* yep, prevent infinite loops */
				errno = ELOOP;
				goto notfound;
			}

			/* get symlink(7) target */
			if (pathcnd) {
#ifdef MKSH__NO_PATH_MAX
				if (notoktoadd(pathlen, 1)) {
					errno = ENAMETOOLONG;
					goto notfound;
				}
#endif
				ldest = aresize(ldest, pathlen + 1, ATEMP);
			}
			llen = readlink(Xstring(xs, xp), ldest, pathlen);
			if (llen < 0)
				/* oops... */
				goto notfound;
			ldest[llen] = '\0';

			/*
			 * restart if symlink target is an absolute path,
			 * otherwise continue with currently resolved prefix
			 */
			/* append rest of current input path to link target */
			tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip);
			afree(ipath, ATEMP);
			ip = ipath = tp;
			if (!mksh_abspath(ldest)) {
				/* symlink target is a relative path */
				xp = Xrestpos(xs, xp, pos);
			} else
#endif
			  {
				/* symlink target is an absolute path */
				xp = Xstring(xs, xp);
 beginning_of_a_pathname:
				/* assert: (ip == ipath)[0] == '/' */
				/* assert: xp == xs.beg => start of path */

				/* exactly two leading slashes? (SUSv4 3.266) */
				if (ip[1] == '/' && ip[2] != '/') {
					/* keep them, e.g. for UNC pathnames */
					Xput(xs, xp, '/');
				}
			}
		}
		/* otherwise (no symlink) merely go on */
	}

	/*
	 * either found the target and successfully resolved it,
	 * or found its parent directory and may create it
	 */
	if (Xlength(xs, xp) == 0)
		/*
		 * if the resolved pathname is "", make it "/",
		 * otherwise do not add a trailing slash
		 */
		Xput(xs, xp, '/');
	Xput(xs, xp, '\0');

	/*
	 * if source path had a trailing slash, check if target path
	 * is not a non-directory existing file
	 */
	if (ip > ipath && ip[-1] == '/') {
		if (stat(Xstring(xs, xp), &sb)) {
			if (errno != ENOENT)
				goto notfound;
		} else if (!S_ISDIR(sb.st_mode)) {
			errno = ENOTDIR;
			goto notfound;
		}
		/* target now either does not exist or is a directory */
	}

	/* return target path */
	if (ldest != NULL)
		afree(ldest, ATEMP);
	afree(ipath, ATEMP);
	return (Xclose(xs, xp));

 notfound:
	/* save; freeing memory might trash it */
	llen = errno;
	if (ldest != NULL)
		afree(ldest, ATEMP);
	afree(ipath, ATEMP);
	Xfree(xs, xp);
	errno = llen;
	return (NULL);

#undef pathlen
#undef pathcnd
}
Exemple #28
0
static void
readhere(struct ioword *iop)
{
	int c;
	const char *eof, *eofp;
	XString xs;
	char *xp;
	size_t xpos;

	eof = evalstr(iop->delim, 0);

	if (!(iop->ioflag & IOEVAL))
		ignore_backslash_newline++;

	Xinit(xs, xp, 256, ATEMP);

 heredoc_read_line:
	/* beginning of line */
	eofp = eof;
	xpos = Xsavepos(xs, xp);
	if (iop->ioflag & IOSKIP) {
		/* skip over leading tabs */
		while ((c = getsc()) == '\t')
			;	/* nothing */
		goto heredoc_parse_char;
	}
 heredoc_read_char:
	c = getsc();
 heredoc_parse_char:
	/* compare with here document marker */
	if (!*eofp) {
		/* end of here document marker, what to do? */
		switch (c) {
		case /*(*/ ')':
			if (!subshell_nesting_type)
				/*-
				 * not allowed outside $(...) or (...)
				 * => mismatch
				 */
				break;
			/* allow $(...) or (...) to close here */
			ungetsc(/*(*/ ')');
			/* FALLTHROUGH */
		case 0:
			/*
			 * Allow EOF here to commands without trailing
			 * newlines (mksh -c '...') will work as well.
			 */
		case '\n':
			/* Newline terminates here document marker */
			goto heredoc_found_terminator;
		}
	} else if (c == *eofp++)
		/* store; then read and compare next character */
		goto heredoc_store_and_loop;
	/* nope, mismatch; read until end of line */
	while (c != '\n') {
		if (!c)
			/* oops, reached EOF */
			yyerror("%s '%s' unclosed\n", "here document", eof);
		/* store character */
		Xcheck(xs, xp);
		Xput(xs, xp, c);
		/* read next character */
		c = getsc();
	}
	/* we read a newline as last character */
 heredoc_store_and_loop:
	/* store character */
	Xcheck(xs, xp);
	Xput(xs, xp, c);
	if (c == '\n')
		goto heredoc_read_line;
	goto heredoc_read_char;

 heredoc_found_terminator:
	/* jump back to saved beginning of line */
	xp = Xrestpos(xs, xp, xpos);
	/* terminate, close and store */
	Xput(xs, xp, '\0');
	iop->heredoc = Xclose(xs, xp);

	if (!(iop->ioflag & IOEVAL))
		ignore_backslash_newline--;
}
Exemple #29
0
void echo_stream()
{
	int acceptor, sock;

	if (signal(SIGCHLD, reaper) == SIG_ERR) {
		die(-1, "unable to catch SIGCHLD");
	}
	say("Stream service started\n");

	/* Prepare XSSL context and get SID (based on RSA key) */
	XSSL_CTX *ctx = XSSL_CTX_new();
	if (ctx == NULL) {
		die(-5, "Unable to create new XSSL_CTX\n");
	}
	char *SID = SID_from_keypair(ctx->keypair);

	/* Prepare listen socket, binding to generated SID */
	if ((acceptor = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		die(-2, "unable to create the stream socket\n");

	struct addrinfo *ai;
	if (Xgetaddrinfo(NULL, SID, NULL, &ai) != 0)
		die(-1, "getaddrinfo failure!\n");

	Graph g((sockaddr_x*)ai->ai_addr);

	sockaddr_x *sa = (sockaddr_x*)ai->ai_addr;

	printf("\nStream DAG\n%s\n", g.dag_string().c_str());

    if (XregisterName(STREAM_NAME, sa) < 0 )
    	die(-1, "error registering name: %s\n", STREAM_NAME);
	say("registered name: \n%s\n", STREAM_NAME);

	if (Xbind(acceptor, (struct sockaddr *)sa, sizeof(sockaddr_x)) < 0) {
		die(-3, "unable to bind to the dag\n");
	}

	Xlisten(acceptor, 5);

	while (1) {

		say("Xsock %4d waiting for a new connection.\n", acceptor);
		if ((sock = Xaccept(acceptor, NULL, 0)) < 0) {
			warn("Xsock %d accept failure! error = %d\n", acceptor, errno);
			// FIXME: should we die here instead or try and recover?
			continue;
		}

		say ("Xsock %4d new session\n", sock);

		pid_t pid = fork();

		if (pid == -1) {
			die(-1, "FORK FAILED\n");

		} else if (pid == 0) {
			process(sock, ctx);
			exit(0);

		} else {
			// FIXME: we need to close the socket in the main process or the file
			// descriptor limit will be hit. But if Xclose is called, the connection
			// is torn down in click as well keeping the child process from using it.
			// for now use a regular close to shut it here without affecting the child.
			close(sock);
		}
	}

	Xclose(acceptor);
	XSSL_CTX_free(ctx);
	free(SID);
}
Exemple #30
0
/*
** get data from the client and return it
** run in a child process that was forked off from the main process.
*/
void process(int sock, XSSL_CTX *ctx)
{
	char buf[XIA_MAXBUF + 1];
	int n;
	pid_t pid = getpid();

	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(sock, &fds);

	struct timeval tv;
	tv.tv_sec = WAIT_FOR_DATA;
	tv.tv_usec = 0;

	/* set up XSSL connection */
	XSSL *xssl = XSSL_new(ctx);
	if (xssl == NULL) {
		die(-6, "Error creating new XSSL object\n");
	}
	if (XSSL_set_fd(xssl, sock) != 1) {
		die(-7, "Error setting XSSL sockfd\n");
	}
	if (XSSL_accept(xssl) != 1) {
		die(-8, "Error accepting XSSL connection\n");
	}

   	while (1) {
		memset(buf, 0, sizeof(buf));

	tv.tv_sec = WAIT_FOR_DATA;
	tv.tv_usec = 0;
		 if ((n = Xselect(xssl->sockfd + 1, &fds, NULL, NULL, &tv)) < 0) {
			 warn("%5d Select failed, closing...\n", pid);
			 break;

		 } else if (n == 0) {
			 // we timed out, close the socket
			 say("%5d timed out on recv\n", pid);
			 break;
		 } else if (!FD_ISSET(xssl->sockfd, &fds)) {
			 // this shouldn't happen!
			 die(-4, "something is really wrong, exiting\n");
		 }

		if ((n = XSSL_read(xssl, buf, sizeof(buf))) < 0) {
			warn("Recv error on socket %d, closing connection\n", pid);
			break;
		}

		say("%5d received %d bytes\n", pid, n);

		if ((n = XSSL_write(xssl, buf, n)) < 0) {
			warn("%5d send error\n", pid);
			break;
		}

		say("%5d sent %d bytes\n", pid, n);
   	}
	say("%5d closing\n", pid);
	XSSL_shutdown(xssl);
	Xclose(sock);
	XSSL_free(xssl);
}