{\scriptsize \begin{lstlisting}
     1	/**
     2	   @file
     3	
     4	   Main part of libcomm.
     5	*/
     6	
     7	/*
     8	  Copyright (c) Andreas Hofmeier
     9	  (www.an-h.de, www.an-h.de.vu, www.lgut.uni-bremen.de/an-h/)
    10	  
    11	  This program is free software; you can redistribute it and/or modify
    12	  it under the terms of the GNU General Public License as published by
    13	  the Free Software Foundation; either version 2 of the License, or
    14	  (at your option) any later version.
    15	
    16	  This program is distributed in the hope that it will be useful, but
    17	  WITHOUT ANY WARRANTY; without even the implied warranty of
    18	  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    19	  General Public License for more details.
    20	
    21	  You should have received a copy of the GNU General Public License
    22	  along with this program; if not, write to the Free Software
    23	  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    24	*/
    25	
    26	
    27	#include <stdio.h>
    28	#include <stdlib.h>
    29	#include <sys/types.h>
    30	#include <sys/socket.h>
    31	#include <sys/time.h>
    32	#include <unistd.h>
    33	#include <sys/poll.h>
    34	#include <string.h>
    35	
    36	
    37	#include "libcomm.h"
    38	#include "md5.h"
    39	
    40	#ifndef nothread
    41	  #include <pthread.h>
    42	#endif
    43	
    44	
    45	#ifndef nothread
    46	/**
    47	   This is a part of socket_accept() and must not called from the
    48	   user. This function is the thread which is started from
    49	   socket_accept() and runs in background.
    50	*/
    51	void socket_accept_thread(struct LIBCOMMPTHREADP *libcommpthreadp) {
    52	  char *buf;
    53	  unsigned int type;
    54	  unsigned int size;
    55	  /* connector's address information */
    56	  struct sockaddr_in their_addr;
    57	  int sin_size;
    58	  int fd;
    59	
    60	  while (1) {
    61	    // wait and accept a incomming connection
    62	    sin_size = sizeof(struct sockaddr_in);
    63	    if ((fd = accept(libcommpthreadp -> sockport,
    64			     (struct sockaddr *) &their_addr,
    65			     &sin_size)) != -1) {
    66	      char *pip = inet_ntoa(their_addr.sin_addr);
    67	
    68	      libcommpthreadp -> socket_accept_do(fd,
    69						  libcommpthreadp -> id,
    70						  pip, their_addr);
    71	    }
    72	  }
    73	  //  pthread_exit(NULL);
    74	}
    75	
    76	
    77	/**
    78	   Start a new thread, wait for connections and start
    79	   socket_accept_do() when someone connects.
    80	
    81	   @param sockport (int) descriptor of a tcp socket/port from
    82	   socket_bind()
    83	
    84	   @param id (int) arbitrary id of background process / thread. (May
    85	   be it is a good idea to use the portnumber.)
    86	
    87	   @param aocket_accept_do(int fd, int id, char *pip, struct
    88	   sockaddr_in their_addr) (function) this function is called if
    89	   somebody connects.  fd is the descriptor of the new socket to the
    90	   connected tcp-tream. id is the same as in socket_accept(). pip
    91	   contains the ip-address of the connected client. The structure
    92	   their_addr contails all known information about the connected
    93	   client.
    94	
    95	   @return If all right zero otherwise non zero.
    96	*/
    97	int socket_accept(int sockport, int id,
    98		   void (*socket_accept_do)(int fd, int id, char *pip,
    99					    struct sockaddr_in their_addr)) {
   100	
   101	  // allocate memory for thread configuration
   102	  struct LIBCOMMPTHREADP *libcommpthreadp; 
   103	  libcommpthreadp = (struct LIBCOMMPTHREADP *)
   104	    malloc(sizeof(struct LIBCOMMPTHREADP));
   105	  if (libcommpthreadp == NULL) {
   106	    perror("malloc()");
   107	    return -1;
   108	  }
   109	
   110	  // store all necessary data in it
   111	  libcommpthreadp -> sockport = sockport;
   112	  libcommpthreadp -> id = id;
   113	  libcommpthreadp -> socket_accept_do = socket_accept_do;
   114	
   115	  // starting thread
   116	  pthread_attr_init(&(libcommpthreadp -> thrd_2_attr));
   117	  return pthread_create(&(libcommpthreadp -> thrd_2),
   118				&(libcommpthreadp -> thrd_2_attr),
   119				(void *) socket_accept_thread,
   120				libcommpthreadp);
   121	
   122	}
   123	
   124	#endif
   125	
   126	
   127	/** Bind a socket to a port (Server side). This function creates a
   128	    socket and binds it to a local port.
   129	
   130	   @param port an integer which specifies the port
   131	
   132	   @param cqueue an integer how many pending connections queue will
   133	   hold in the waiting queue.
   134	
   135	   @return The File Descriptor (FD) which allows access to the bound
   136	   port.
   137	*/
   138	
   139	#include <netinet/in.h>
   140	
   141	int socket_bind(int port, int cqueue) {
   142	  // FD of the new socket to the bound port
   143	  int sock;
   144	  // address information
   145	  struct sockaddr_in ad;
   146	
   147	  // create a socket
   148	  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
   149	    // cannot created socket, return error
   150	    perror("socket");
   151	    return -1;
   152	  }
   153	
   154	  // make ensure that the memory is initiated
   155	  memset(&ad, 0, sizeof(ad));
   156	
   157	  // address family: AF_INET: IPv4 Internet protocols
   158	  ad.sin_family = AF_INET;
   159	  // convert and copy port in structure
   160	  ad.sin_port = htons(port);
   161	  // bind to all interfaces -- the port will accept connections to all
   162	  // addresses of the local machine
   163	  ad.sin_addr.s_addr = INADDR_ANY;
   164	  // bind socket
   165	  if (bind(sock, (struct sockaddr *) &ad, sizeof(struct sockaddr)) == -1) {
   166	    // cannot bind, return error
   167	    perror("bind");
   168	    return -1;
   169	  }
   170	  // listen for connections on bound port
   171	  if (listen(sock, cqueue) == -1) {
   172	    // cannot listen, return error
   173	    perror("listen");
   174	    return -1;
   175	  }
   176	  // all right, port is listening. Return the FD as
   177	  // reference for use.
   178	  return sock;
   179	}
   180	
   181	
   182	#include <netinet/in.h>
   183	#include <netdb.h>
   184	#include <sys/types.h>
   185	#include <sys/socket.h>
   186	#include <arpa/inet.h>
   187	
   188	
   189	
   190	/**
   191	  Connect a TCP-stream to a server (Client side). Creates a socket and
   192	  connect it over a TCP-stream to the specified port on the specified
   193	  server.
   194	
   195	  @param host a string (char *) which specifies the name or the
   196	  IP-address of the server.
   197	
   198	  @param port an integer which specifies the port on the server.
   199	
   200	  @return The File Descriptor (FD) which allows access to the
   201	  TCP-stream-socket or -1 if the connection fails.
   202	*/
   203	int socket_connect(char *host, int port) {
   204	  // FD of the new socket to the TCP-stream
   205	  int sock;
   206	  // The IP address in binary form
   207	  in_addr_t inaddr;
   208	  // address information to connect other side (syscall: connect() )
   209	  struct sockaddr_in ad;
   210	  // contains the result of the resolution of a network-name.
   211	  struct hostent *hp;
   212	  
   213	  // make ensure that the memory is initiated
   214	  memset(&ad, 0, sizeof(ad));
   215	  // address family: AF_INET: IPv4 Internet protocols
   216	  ad.sin_family = AF_INET;
   217	  // Try to convert the given IP-address into binary data...
   218	  inaddr = inet_addr(host);
   219	  if (inaddr != INADDR_NONE) {
   220	    // if the IP address was converted copy it in the parameter
   221	    // structure (ad) for later use
   222	    memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
   223	  } else {
   224	    // if this is not possible (the name and not the IP address is
   225	    // given), try to resolve the name to a binary IP address
   226	    hp = gethostbyname(host);
   227	    if (hp == NULL) {
   228	      // name cannot resolved, return error
   229	      perror("gethostbyname()");
   230	      return -1;
   231	    }
   232	    // copy address in the parameter structure (ad) for later use
   233	    memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
   234	  }
   235	  // convert and copy port-number in the parameter structure (ad) for
   236	  // later use
   237	  ad.sin_port = htons(port);
   238	  // create a socket
   239	  sock = socket(AF_INET, SOCK_STREAM, 0);
   240	  if (sock < 0) {
   241	    // cannot created socket, return error
   242	    perror("socket()");
   243	    return -1;
   244	  }
   245	  // connect the socket over an TCP-stream to the port and the server,
   246	  // which are stored in ad.
   247	  if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0) {
   248	    // connection is not possible, return error
   249	    perror("connect()");
   250	    return -1;
   251	  }
   252	  // all right, socket is connected an can be used. Return the FD as
   253	  // reference for use.
   254	  return sock;
   255	}
   256	
   257	
   258	/**
   259	   Get random numbers/bytes. This function reads random numbers/bytes
   260	   from /dev/urandom and stores this bytes in a buffer.
   261	
   262	   @param buf (char *) in which the bytes will be stored. If this
   263	   parameter is equal to NULL dynamic memory will be allocated.
   264	
   265	   @param size an integer, specifies ths size of the buffer (the
   266	   number of the random bytes). WARNING: If buf is not equal to null,
   267	   n*(size) bytes will be stored in this buffer without any check of
   268	   ths size of this buf.
   269	
   270	   @return (char *) a pointer to the buffer in which the random bytes
   271	   are stored.
   272	*/
   273	char *block_random(char *buf, int size) {
   274	  FILE *f;
   275	
   276	  // If no momory allocated, allocate memory
   277	  if (buf == NULL) {
   278	    if ((buf = malloc(size)) == NULL) {
   279	      perror("malloc");
   280	      return NULL;
   281	    }
   282	  }
   283	
   284	  // Read Random numbers from /dev/urandom and stroe this these in the
   285	  // buffer
   286	
   287	  if ((f = fopen("/dev/urandom", "ro")) == NULL) {
   288	    perror("fopen(/dev/urandom)");
   289	    return NULL;
   290	  }
   291	
   292	  fread(buf, 1, size, f);
   293	
   294	  fclose(f);
   295	
   296	  return buf;
   297	}
   298	
   299	
   300	
   301	
   302	
   303	
   304	#ifndef nothread
   305	/**
   306	   This is a part of block_call() and must not called from the
   307	   user. This function is the thread which is started from
   308	   block_call() and runs in background.
   309	
   310	   @param libcommpthreads (struct LIBCOMMPTHREADS *) holds pointers to
   311	   the functions to be call, fd (socket discriptor) and id.
   312	*/
   313	void thread1(struct LIBCOMMPTHREADS *libcommpthreads) {
   314	  char *buf;
   315	  unsigned int type;
   316	  unsigned int size;
   317	
   318	  while (1) {
   319	    // try to receive a datablock...
   320	    buf = block_receive(libcommpthreads -> fd, &type, NULL, &size, 0, 
   321				libcommpthreads -> term);
   322	    // failed: call block_call_term() and terminate thread
   323	    if (buf == NULL) {
   324	      libcommpthreads -> block_call_term(libcommpthreads -> fd,
   325						 libcommpthreads -> id);
   326	      break;
   327	    }
   328	    // datablock OK: call block_call_do(), after this wait for the
   329	    // next datablock
   330	    libcommpthreads -> block_call_do(libcommpthreads -> fd,
   331					     libcommpthreads -> id,
   332					     type, buf, size,
   333					     libcommpthreads -> term);
   334	  }
   335	  pthread_exit(NULL);
   336	}
   337	
   338	
   339	/**
   340	   Waits in a new thread for a datablock to be received and calls the
   341	   function block_call_do() if this event occurs or block_call_term()
   342	   when the connection terminates.
   343	
   344	   @param fd (int) descriptor of socket
   345	
   346	   @param id (int) arbitrary id of background process / thread
   347	
   348	   @param term (int) 0: do not terminate the buffer, 1: terminate the
   349	   buffer by appending a 0x00.
   350	
   351	   @param block_call_do(int fd, int id, unsigned int type, char *buf,
   352	   unsigned int size, int term) (function) this function is called if
   353	   a datablock was received. fd, id and term are the same as in
   354	   block_call(). type describes the type of the received datablock,
   355	   buf is a pointer to this datablock and size is the number of bytes
   356	   of the datablock
   357	
   358	   @param block_call_term(int fd, int id) (function) this function is
   359	   called if the connection terminates. fd and id are the same as in
   360	   block_call().
   361	
   362	   @return If all right zero otherwise non zero.
   363	*/
   364	int block_call(int fd, int id, int term,
   365		   void (*block_call_do)(int fd, int id, unsigned int type,
   366					 char *buf, unsigned int size,
   367					 int term),
   368		   void (*block_call_term)(int fd, int id)) {
   369	
   370	  // allocate memory for thread configuration
   371	  struct LIBCOMMPTHREADS *libcommpthreads; 
   372	  libcommpthreads = (struct LIBCOMMPTHREADS *)
   373	    malloc(sizeof(struct LIBCOMMPTHREADS));
   374	  if (libcommpthreads == NULL) {
   375	    perror("malloc()");
   376	    return -1;
   377	  }
   378	
   379	  // store all necessary data in it
   380	  libcommpthreads -> fd = fd;
   381	  libcommpthreads -> id = id;
   382	  libcommpthreads -> block_call_do = block_call_do;
   383	  libcommpthreads -> block_call_term = block_call_term;
   384	
   385	  // starting thread
   386	  pthread_attr_init(&(libcommpthreads -> thrd_1_attr));
   387	  return pthread_create(&(libcommpthreads -> thrd_1),
   388				&(libcommpthreads -> thrd_1_attr),
   389				(void *) thread1, libcommpthreads);
   390	}
   391	
   392	#endif
   393	
   394	
   395	
   396	/**
   397	   This function tests if new data is available to read on a stream.
   398	
   399	   @param fd (int) discriptor of stream to test
   400	
   401	   @return (int) 1: Data to read; 0: No data to read
   402	*/
   403	int block_ifdata(int fd) {
   404	  struct pollfd polld;
   405	
   406	  polld.fd = fd;
   407	  polld.events = POLLIN | POLLPRI;
   408	
   409	  if (poll(&polld, 1, 0)) {
   410	    return 1;
   411	  }
   412	  return 0;
   413	}
   414	
   415	
   416	/**
   417	   Test if is there data available on the socket's input buffer and
   418	   starts receiving a block if there is. WARNING: The integers (type
   419	   and size; excluding fd) are only 16 bit values (0 - 65535).
   420	
   421	   @param fd (int) descriptor of socket
   422	
   423	   @param type (unsigned int *) pointer to integer, this value can be
   424	   used as buyer's option
   425	
   426	   @param buf (char *) buffer for datablock. Memory will be allocated
   427	   if this parameter is equal to null.
   428	
   429	   @param size (unsigned int *) pointer to integer in which the size
   430	   of the received datablock is saved.
   431	
   432	   @param maxsize (unsigned int *) describes size of buf. This
   433	   parameter will be ignored if buf is equal to null.
   434	
   435	   @param term (int) 0: do not terminate the buffer, 1: terminate the
   436	   buffer by appending a 0x00.
   437	
   438	   @return (char *) pointer to buffer which contains the received
   439	   datablock; NULL if fail; 1 if no data available.
   440	
   441	*/
   442	char *block_receive_poll(int fd, unsigned int *type, char *buf,
   443				 unsigned int *size, unsigned int maxsize,
   444				 int term) {
   445	  // new data available
   446	  if (block_ifdata(fd)) {
   447	    return block_receive(fd, type, buf, size, maxsize, term);
   448	  } else {
   449	  // no new data available
   450	    return (char *) 1L;
   451	  }
   452	}
   453	
   454	
   455	
   456	/**
   457	   Receive a block (composition of: type, size of datablock and
   458	   datablock) from a socket. Waits for a block to be received
   459	   completely. WARNING: The integers (type and size; excluding fd) are
   460	   only 16 bit values (0 - 65535).
   461	
   462	   @param fd (int) descriptor of socket   
   463	
   464	   @param type (unsigned int *) pointer to integer, this value can be
   465	   used as buyer's option
   466	
   467	   @param buf (char *) buffer for datablock. Memory will be allocated
   468	   if this parameter is equal to null.
   469	
   470	   @param size (unsigned int *) pointer to integer in which the size
   471	   of the received datablock is saved.
   472	
   473	   @param maxsize (unsigned int *) describes size of buf. This
   474	   parameter will be ignored if buf is equal to null.
   475	
   476	   @param term (int) 0: do not terminate the buffer, 1: terminate the
   477	   buffer by appending a 0x00.
   478	
   479	   @return (char *) pointer to buffer which contains the received
   480	   datablock; NULL if fail.
   481	
   482	*/
   483	char *block_receive(int fd, unsigned int *type, char *buf,
   484			    unsigned int *size, unsigned int maxsize, 
   485			    int term) {
   486	  // do not trust any user!
   487	  if (term > 1) {
   488	    term = 1;
   489	  }
   490	  if (term < 0) {
   491	    term = 0;
   492	  }
   493	
   494	  // receiving type
   495	  if (block_receive_integer(fd, type) < 0) {
   496	    return NULL;
   497	  }
   498	  // receiving size
   499	  if (block_receive_integer(fd, size) < 0) {
   500	    return NULL;
   501	  }
   502	
   503	  if (buf == NULL) {
   504	    if ((buf = (char *) malloc(*size + term)) == NULL) {
   505	      perror("malloc()");
   506	      return NULL;
   507	    }
   508	  } else {
   509	    if ((*size + term) > maxsize) {
   510	      fprintf(stderr, "Try to receive more than fit in the buffer\n");
   511	      return NULL;
   512	    }
   513	  }
   514	  // receiving data
   515	  if (block_receive_nbytes(fd, buf, *size) < 0) {
   516	    return NULL;
   517	  }
   518	
   519	  if (term) {
   520	    buf[*size] = 0;
   521	  }
   522	
   523	  return buf;
   524	}
   525	
   526	
   527	
   528	
   529	/**
   530	   Receive an integer (two bytes; 16Bit) from the socket. 
   531	
   532	   @param fd (int) descriptor of socket
   533	
   534	   @param recvi (unsigned int *) pointer to integer in which the
   535	   received integer is saved.
   536	
   537	   @return (int) 2: OK; -1: fail
   538	*/
   539	int block_receive_integer(int fd, unsigned int *recvi) {
   540	  int i, r;
   541	  //  unsigned int recvi;
   542	  int sizeofint = 2; /* sizeof(int); */
   543	
   544	  // reset value
   545	  *recvi = 0;
   546	
   547	  // receive value
   548	  if (recv(fd, ((char *) recvi), sizeofint, MSG_WAITALL) != sizeofint) {
   549	    perror("recv()");
   550	    return -1;
   551	  }
   552	
   553	  return 2; //recvi;
   554	}
   555	
   556	
   557	
   558	
   559	/**
   560	   Receive n bytes from socket.
   561	
   562	   @param fd (integer) descriptor of socket
   563	
   564	   @param buf (char *) buffer for saving the received bytes
   565	
   566	   @param n (integer) number of bytes to receive
   567	
   568	   @return (integer) n: OK; -1 fial
   569	*/
   570	int block_receive_nbytes(int fd, char *buf, int n) {
   571	  int i, r;
   572	  unsigned int recvi;
   573	  int sizeofint = 2; /* sizeof(int); */
   574	
   575	  // receive n bytes to buffer
   576	  if (recv(fd, buf, n, MSG_WAITALL) != n) {
   577	    perror("recv()");
   578	    return -1;
   579	  }
   580	
   581	  return n;
   582	}
   583	
   584	
   585	
   586	/**
   587	   Send a block (composition of: type, size of datablock and datablock
   588	   (buf)) to a socket. The function blocks until the whole block is
   589	   transfered to the buffer. If the buffer is full, data has to be
   590	   sent first. WARNING: The integers (type and size; excluding fd) are
   591	   only 16 bit values (0 - 65535).
   592	
   593	   @param fd (int) descriptor of the socket to which buf should send
   594	
   595	   @param type (unsigned int) This value can be used as buyer's option
   596	
   597	   @param buf (char *) which should be send
   598	
   599	   @return number of sent bytes, -1 if an error is occurt.
   600	*/
   601	
   602	int block_send(int fd, unsigned int type, char *buf,
   603		       unsigned int size) {
   604	  // add up the number of sent byte, for checking.
   605	  int i, r;
   606	
   607	  // send the type of the data
   608	  i = r = 0;
   609	  while (r < 2) {
   610	    if ((i = send(fd, (void *) &type + r, 2 - r, 0)) < 0) {
   611	      return -1;
   612	    }
   613	    r += i;
   614	  }
   615	  // send the size of the buffer
   616	  i = r = 0;
   617	  while (r < 2) {
   618	    if ((i = send(fd, (void *) &size + r, 2 - r, 0)) < 0) {
   619	      return -1;
   620	    }
   621	    r += i;
   622	  }
   623	  // send the data in the buffer it self
   624	  i = r = 0;
   625	  while (r < size) {
   626	    if ((i = send(fd, (void *) buf + r, size - r, 0)) < 0) {
   627	      return -1;
   628	    }
   629	    r += i;
   630	  }
   631	
   632	  /*
   633	  // send the type of the data
   634	  if ((r = send(fd, (void *) &type, 2, 0)) < 0) {
   635	    return -1;
   636	  }
   637	  // send the size of the buffer
   638	  if ((i = send(fd, (void *) &size, 2, 0)) < 0) {
   639	    perror("send0()");
   640	    return -1;
   641	  }
   642	  r += i;
   643	  // send the data in the buffer it self
   644	  if ((i = send(fd, buf, size, 0)) < 0) {
   645	    perror("send1()");
   646	    return -1;
   647	  }
   648	  r += i;
   649	
   650	  // not the comlete messages was sent.
   651	  if (r = (size + 4)) {
   652	    perror("send2()");
   653	    return -1;
   654	  }
   655	  */
   656	
   657	  return r;
   658	}
   659	
   660	
   661	
   662	
   663	
   664	
   665	/**
   666	   Free the memory space which is used by an AUTHINFO structure.
   667	
   668	   @param (struct AUTHINFO *) pointer to structure to destroy.
   669	*/
   670	void free_authinfo(struct AUTHINFO *destroy) {
   671	  free(destroy -> netname);
   672	  free(destroy -> name);
   673	  free(destroy -> passwd);
   674	  free(destroy -> keyencrypt);
   675	  free(destroy -> keydecrypt);
   676	  free(destroy);
   677	}
   678	
   679	
   680	
   681	/**
   682	   Do both side authentification. This function is usually called
   683	   just after a socket stream is established. The function must be
   684	   called on both sides.
   685	
   686	   WARNING: This authentication can be bypassed simply by using the
   687	   multiple session attack if multiple session are allowd and the same
   688	   password is used for both sides.
   689	
   690	   Both sides following these steps:
   691	
   692	   1. get auth info ([login] name, passwd) by using getauthinfo() from
   693	   name or netname for remote login
   694	
   695	   2. generate random numbers
   696	
   697	   3. exchange (first send, then receive) login names
   698	
   699	   4. exchange random numbers
   700	
   701	   5. calculate md5 checksum over the random numbers (received from other
   702	   side) and the remote passwd.
   703	
   704	   6. exchange md5 checksums
   705	
   706	   7. get auth info from name (received from other side) for local login
   707	
   708	   8. calculate md5 checksum over the local random numbers and the
   709	   local passwd.
   710	
   711	   9. check login -- compare the received md5sum (6.) with the
   712	   generated one (8.); send acknowledgement
   713	   
   714	   10. receive remote acknowledgement
   715	
   716	   11. return suitable values
   717	
   718	   @param fd (int) describes the socket on which the authentication
   719	   has to be done
   720	
   721	   @param netname (char *) use netname to resolve [login] name and
   722	   passwd of the remote machine (NULL: not specified)
   723	
   724	   @param netname (char *) use [login] name to resolve passwd of the
   725	   remote machine (NULL: not specified; both NULL use first entry in
   726	   file, see getauthinfo())
   727	
   728	   @param plocallogin (struct AUTHINFO **) (pointer to pointer to an
   729	   AUTHINFO struct) in this (double pointed) struct the local authinfo
   730	   will be loaded, if the parameter is not null.
   731	
   732	   @param premotelogin (struct AUTHINFO **) in this (double pointed)
   733	   struct the remote authinfo will be loaded, if the parameter is not
   734	   null.
   735	
   736	   @return (int) 0: Authentication/Login OK; -1: remote login error;
   737	   -2: login error on both sides; -3: local login error; -4: other
   738	   (network) error; -5: cannot load remote auth info; -6: cannot load
   739	   local auth info; 
   740	*/
   741	int socket_md5auth(int fd, char *netname, char *name,
   742			   struct AUTHINFO **plocallogin,
   743			   struct AUTHINFO **premotelogin) {
   744	  char rstr0[authrandomstringsize], rstr1[authrandomstringsize];
   745	  char rstr0sum[35], rstr1sum[35];
   746	
   747	  int otype;
   748	  char *oname;
   749	  int onamesize;
   750	  char *randblock;
   751	  char *orandblock;
   752	  int orandblocksize;
   753	
   754	  struct MD5Context context;
   755	  unsigned char md5_prs[16];
   756	  unsigned char omd5_prs[16];
   757	
   758	  int login_ok = 0;
   759	
   760	  struct AUTHINFO *locallogin;
   761	  // 1.
   762	  struct AUTHINFO *remotelogin = getauthinfo(netname, name);
   763	  if (remotelogin == NULL) {
   764	    return -5;
   765	  }
   766	  if (premotelogin != NULL) {
   767	    *premotelogin = remotelogin;
   768	  }
   769	  
   770	  // 2. generate random block for local login
   771	  if ((randblock = block_random(NULL, authrandomstringsize))
   772	      == NULL) {
   773	    if (premotelogin == NULL) {
   774	      free_authinfo(remotelogin);
   775	    }
   776	    return -4;
   777	  }
   778	
   779	  // 3. exchange login name
   780	  if (block_send(fd, authmessagetype, remotelogin -> name,
   781			 strlen(remotelogin -> name)) <= 0) {
   782	    if (premotelogin == NULL) {
   783	      free_authinfo(remotelogin);
   784	    }
   785	    free(randblock);
   786	    return -4;
   787	  }
   788	  oname = block_receive(fd, &otype, NULL, &onamesize, 0, true);
   789	  if ((oname == NULL) ||
   790	      (otype != authmessagetype)) {
   791	    if (premotelogin == NULL) {
   792	      free_authinfo(remotelogin);
   793	    }
   794	    free(randblock);
   795	    return -4;
   796	  }
   797	
   798	
   799	  // 4. exchange random block
   800	  if (block_send(fd, authmessagetype, randblock,
   801			 authrandomstringsize)
   802	      <= 0) {
   803	    if (premotelogin == NULL) {
   804	      free_authinfo(remotelogin);
   805	    }
   806	    free(randblock);
   807	    free(oname);
   808	    return -4;
   809	  }
   810	  orandblock = block_receive(fd, &otype, NULL, 
   811				     &orandblocksize, 0, false);
   812	  if ((orandblock == NULL) ||
   813	      (otype != authmessagetype)) {
   814	    if (premotelogin == NULL) {
   815	      free_authinfo(remotelogin);
   816	    }
   817	    free(randblock);
   818	    free(oname);
   819	    free(orandblock);
   820	    return -4;
   821	  }
   822	
   823	  // 5. calculate md5 checksum over the random numbers (received from
   824	  // other side) and the remote passwd.
   825	  MD5Init(&context);
   826	  MD5Update(&context, orandblock, orandblocksize);
   827	  MD5Update(&context, remotelogin -> passwd,
   828		    strlen(remotelogin -> passwd));
   829	  MD5Final(md5_prs, &context);
   830	
   831	  // 6. exchange md5 checkumms
   832	  if (block_send(fd, authmessagetype, md5_prs, 16) <= 0) {
   833	    if (premotelogin == NULL) {
   834	      free_authinfo(remotelogin);
   835	    }
   836	    free(randblock);
   837	    free(oname);
   838	    free(orandblock);
   839	    return -4;
   840	  }
   841	  if ((block_receive(fd, &otype, omd5_prs, &orandblocksize,
   842			     16, false)
   843	      == NULL) ||
   844	    (otype != authmessagetype) ||
   845	    (orandblocksize != 16)) {
   846	    if (premotelogin == NULL) {
   847	      free_authinfo(remotelogin);
   848	    }
   849	    free(randblock);
   850	    free(oname);
   851	    free(orandblock);
   852	    return -4;
   853	  }
   854	  usleep(1);
   855	
   856	  // 7. get auth info from name (received from other side) for local login
   857	  locallogin = getauthinfo(NULL, oname);
   858	  if (locallogin == NULL) {
   859	    if (premotelogin == NULL) {
   860	      free_authinfo(remotelogin);
   861	    }
   862	    free(randblock);
   863	    free(oname);
   864	    free(orandblock);
   865	    return -6;
   866	  }
   867	  if (plocallogin != NULL) {
   868	    *plocallogin = locallogin;
   869	  }
   870	
   871	  // 8. calculate md5 checksum over the local random numbers and the
   872	  // local passwd.
   873	  MD5Init(&context);
   874	  MD5Update(&context, randblock, authrandomstringsize);
   875	  MD5Update(&context, locallogin -> passwd,
   876		    strlen(locallogin -> passwd));
   877	  MD5Final(md5_prs, &context);
   878	  
   879	  // 9. check login -- compare the received md5sum (6.) with the
   880	  // generated one (8.); send acknowledgement
   881	  if (memcmp(md5_prs, omd5_prs, 16) == 0) {
   882	    login_ok = 1;
   883	    if (block_send(fd, authmessagetype, "OK", 2) <= 0) {
   884	      if (plocallogin == NULL) {
   885		free_authinfo(locallogin);
   886	      }
   887	      if (premotelogin == NULL) {
   888		free_authinfo(remotelogin);
   889	      }
   890	      free(randblock);
   891	      free(oname);
   892	      free(orandblock);
   893	      return -4;
   894	    }
   895	  } else {
   896	    if (block_send(fd, authmessagetype, "FAIL", 4) <= 0) {
   897	      if (plocallogin == NULL) {
   898		free_authinfo(locallogin);
   899	      }
   900	      if (premotelogin == NULL) {
   901		free_authinfo(remotelogin);
   902	      }
   903	      free(randblock);
   904	      free(oname);
   905	      free(orandblock);
   906	      return -4;
   907	    }
   908	  }
   909	
   910	  // 10. receive remote acknowledgement
   911	  free(orandblock);
   912	  orandblock = block_receive(fd, &otype, NULL, &orandblocksize,
   913				     0, true);
   914	  if ((orandblock == NULL) ||
   915	      (otype != authmessagetype) ||
   916	      (orandblocksize != 2) ||
   917	      (strcmp(orandblock, "OK") != 0)) {
   918	    if (login_ok) {
   919	      if (plocallogin == NULL) {
   920		free_authinfo(locallogin);
   921	      }
   922	      if (premotelogin == NULL) {
   923		free_authinfo(remotelogin);
   924	      }
   925	      free(randblock);
   926	      free(oname);
   927	      return -1;
   928	    } else {
   929	      if (plocallogin == NULL) {
   930		free_authinfo(locallogin);
   931	      }
   932	      if (premotelogin == NULL) {
   933		free_authinfo(remotelogin);
   934	      }
   935	      free(randblock);
   936	      free(oname);
   937	      return -2;
   938	    }
   939	  }
   940	
   941	
   942	  if (plocallogin == NULL) {
   943	    free_authinfo(locallogin);
   944	  }
   945	  if (premotelogin == NULL) {
   946	    free_authinfo(remotelogin);
   947	  }
   948	  free(randblock);
   949	  free(oname);
   950	  free(orandblock);
   951	  
   952	  if (!login_ok) {
   953	    return -3;
   954	  }
   955	
   956	  // all right!
   957	  return 0;
   958	}
   959	
   960	
   961	
   962	/**
   963	   Load authentication informations (netname, name, passwd,
   964	   keyencrypt, keydecrypt) from authfile.
   965	
   966	   @param netname (char *) specify the network name (may IP). NULL not
   967	   specified.
   968	
   969	   @param name (char *) specity the login name. NULL not
   970	   specified.
   971	
   972	   @return (struct AUTHINFO *) the first entry from authfile which
   973	   matches network name OR login name. If both values are NULL, the
   974	   first entry of the authfile is given back.
   975	*/
   976	struct AUTHINFO *getauthinfo(char *netname, char *name) {
   977	  // Descriptor for authfile
   978	  FILE *f;
   979	  // buffer for reading one line of the authfile
   980	  char buf[authfilemaxlinelenght];
   981	  // number of fields in the authfile
   982	  int fields = 5;
   983	  // pointer buffer for the five parts of the line
   984	  char *bufsplit[fields];
   985	  // char **bufsplit;
   986	  // control variable, count variable for field
   987	  int i, j;
   988	  struct AUTHINFO *load;
   989	  // temporary pointer
   990	  char *s;
   991	
   992	  //  bufsplit = (char **) malloc(sizeof(char *) * fields);
   993	
   994	  // allocate memory for auth-structure
   995	  load = (struct AUTHINFO *) malloc(sizeof(struct AUTHINFO));
   996	  if (load == NULL) {
   997	    perror("malloc(sizeof(struct AUTHINFO))");
   998	    return NULL;
   999	  }
  1000	
  1001	  // open authfile
  1002	  if ((f = fopen(authfile0, "ro")) == NULL) {
  1003	    perror(authfile0);
  1004	    if ((f = fopen(authfile1, "ro")) == NULL) {
  1005	      perror(authfile0);
  1006	      free(load);
  1007	      return NULL;
  1008	    }
  1009	  }
  1010	
  1011	  // read as long as ther is no more data
  1012	  while (!feof(f)) {
  1013	    // read one line
  1014	    fgets(buf, authfilemaxlinelenght - 1, f);
  1015	
  1016	    // split the line into it five components
  1017	    j = 0;
  1018	    bufsplit[j++] = buf;
  1019	    //    load -> netname = buf;
  1020	    for (i = 0; i < authfilemaxlinelenght; i++) {
  1021	      if (buf[i] == authfilefieldseperator) {
  1022		buf[i] = 0;
  1023		if (j == fields) {
  1024		  break;
  1025		}
  1026		bufsplit[j++] = buf + i + 1;
  1027	      }
  1028	    }
  1029	
  1030	    // if this the right entry? Compare with parameter.
  1031	    if (
  1032		((   name != NULL) && (strcmp(   name, bufsplit[1]) == 0))
  1033		||
  1034		((netname != NULL) && (strcmp(netname, bufsplit[0]) == 0))
  1035		||
  1036		((netname == NULL) && (name == NULL))
  1037	       ) {
  1038	      
  1039	      // allocate Memory
  1040	      for (i = 0; i < fields; i++) {
  1041		s = NULL;
  1042		s = (char *) malloc(strlen(bufsplit[i]) + 1);
  1043		if (s == NULL) {
  1044		  perror("malloc()");
  1045		  free(load);
  1046		  return NULL;
  1047		}
  1048		strcpy(s, bufsplit[i]);
  1049		bufsplit[i] = s;
  1050	      }
  1051	
  1052	      // store the pointers in the struct
  1053	      load -> netname =    bufsplit[0];
  1054	      load -> name =       bufsplit[1];
  1055	      load -> passwd =     bufsplit[2];
  1056	      load -> keyencrypt = bufsplit[3];
  1057	      load -> keydecrypt = bufsplit[4];
  1058	
  1059	      // return the pointer to this struct
  1060	      return load;
  1061	    }
  1062	  }
  1063	  free(load);
  1064	  return NULL;
  1065	}
  1066	
  1067	
  1068	
  1069	
  1070	/**
  1071	   Thread used by linemonitor_server() NOT for direct usage.
  1072	*/
  1073	void linemonitor_server_thread(struct LINEMONITOR_THREAD_DATA
  1074				       *linemonitor_thread_data) {
  1075	  unsigned char buf;
  1076	
  1077	  // configuration of poll -- waiting for an event of the socket.
  1078	  struct pollfd polld;
  1079	  polld.fd = linemonitor_thread_data -> sock;
  1080	  polld.events = POLLIN | POLLPRI;
  1081	
  1082	  while (1) {
  1083	    // Receive a Ping/Byte
  1084	    if (recv(linemonitor_thread_data -> sock, ((char *) &buf), 1,
  1085		     MSG_WAITALL) != 1) {
  1086	      linemonitor_thread_data -> linemonitor_exception(
  1087			       linemonitor_thread_data -> server,
  1088			       linemonitor_thread_data -> port, 0);
  1089	      break;
  1090	    }
  1091	    // And Send it Back
  1092	    if (send(linemonitor_thread_data -> sock, &buf, 1, 0) != 1) {
  1093	      linemonitor_thread_data -> linemonitor_exception(
  1094			       linemonitor_thread_data -> server,
  1095			       linemonitor_thread_data -> port, 0);
  1096	      break;
  1097	    }
  1098	
  1099	    // Test, if next Ping is received within the reload-time plus
  1100	    // soft-timeout
  1101	    if (poll(&polld, 1, linemonitor_thread_data -> wait_msec)
  1102		<= 0) {
  1103	
  1104	      if (poll(&polld, 1, linemonitor_thread_data -> soft_msec)
  1105		  <= 0) {
  1106		// If not, call exception-function
  1107		linemonitor_thread_data -> linemonitor_exception(
  1108				    linemonitor_thread_data -> server,
  1109				    linemonitor_thread_data -> port, 1);
  1110	
  1111		// and test if the data is received within the hard-timeout
  1112		if (poll(&polld, 1, linemonitor_thread_data -> hard_msec)
  1113		    <= 0) {
  1114		  // If not, call exception-function
  1115		  linemonitor_thread_data -> linemonitor_exception(
  1116	                              linemonitor_thread_data -> server,
  1117				      linemonitor_thread_data -> port, 2);
  1118		}
  1119	      }
  1120	    }
  1121	  }
  1122	
  1123	  pthread_exit(NULL);
  1124	}
  1125	
  1126	
  1127	
  1128	/**
  1129	   Monitor if the "line" is fast enough: Server Application. This
  1130	   function opens a port and wait for the first connection on this
  1131	   port. All data/pings which is sent by this first connection will
  1132	   be sent back. The soft-timeout will called after wait_msec AND
  1133	   soft_msec is timeouted. The hard-timeout will called after
  1134	   soft-timeout was called AND hard_msec is timeouted.
  1135	
  1136	   @param port (int) port which should be listend
  1137	
  1138	   @param soft_msec (int) timeout in milliseconds which causes
  1139	   soft-real-time exception.
  1140	
  1141	   @param hard_msec (int) timeout in milliseconds which causes
  1142	   hard-real-time exception.
  1143	
  1144	   @param wait_msec (int) timeout for resent -- sending of the next
  1145	   ping.
  1146	
  1147	   @param linemonitor_exception (pointer to function) This function
  1148	   will be called if an exception occurs. It becomes the following
  1149	   parameters: server name (char *) which is always null, port (int):
  1150	   listend port and type (int) of exception which can be: 0: Connicion
  1151	   Fault, 1: Soft Real Time Exception, 2: HARD Real Time Exception.
  1152	
  1153	   @return (int) Filediscriptor to the used socket. Only for usage
  1154	   with linemonitor_emergencystop().
  1155	*/
  1156	int linemonitor_server(int port,
  1157			   int soft_msec, int hard_msec, int wait_msec,
  1158			   void (*linemonitor_exception)(char *server, int port,
  1159							 int type)) {
  1160	  int  sock;
  1161	
  1162	  /* connector's address information */
  1163	  struct sockaddr_in their_addr;
  1164	  int sin_size;
  1165	  int fd;
  1166	
  1167	  // ID and atributes for the threads
  1168	  pthread_t        thrd_2;
  1169	  pthread_attr_t   thrd_2_attr;
  1170	
  1171	  // allocate memory to store parameter for the
  1172	  // linemonitor_server_thread() function.
  1173	  struct LINEMONITOR_THREAD_DATA *linemonitor_thread_data;
  1174	  linemonitor_thread_data = (struct LINEMONITOR_THREAD_DATA *)
  1175	    malloc(sizeof(struct LINEMONITOR_THREAD_DATA));
  1176	  if (linemonitor_thread_data == NULL) {
  1177	    perror("malloc()");
  1178	    return -1;
  1179	  }
  1180	
  1181	  // store all necessary parameters in this memory
  1182	  linemonitor_thread_data -> server = NULL;
  1183	  linemonitor_thread_data -> port = port;
  1184	  linemonitor_thread_data -> soft_msec = soft_msec;
  1185	  linemonitor_thread_data -> hard_msec = hard_msec;
  1186	  linemonitor_thread_data -> wait_msec = wait_msec;
  1187	  linemonitor_thread_data -> linemonitor_exception =
  1188	    linemonitor_exception;
  1189	
  1190	  // Bind a port
  1191	  sock = socket_bind(port, 10);
  1192	
  1193	  // wait for the first connection
  1194	  // only accept the first connection
  1195	  sin_size = sizeof(struct sockaddr_in);
  1196	  if ((fd = accept(sock, (struct sockaddr *) &their_addr,
  1197			   &sin_size)) != -1) {
  1198	    char *pip = inet_ntoa(their_addr.sin_addr);
  1199	    
  1200	    linemonitor_thread_data -> sock = fd;
  1201	  
  1202	    // starting linemonitor_server_thread()
  1203	    pthread_attr_init(&thrd_2_attr);
  1204	    if (pthread_create(&thrd_2,
  1205			       &thrd_2_attr,
  1206			       (void *) linemonitor_server_thread,
  1207			       linemonitor_thread_data) != 0) {
  1208	      return -1;
  1209	    }
  1210	
  1211	    return fd;
  1212	  }
  1213	
  1214	  return -1;
  1215	}
  1216	
  1217	
  1218	
  1219	/**
  1220	   Sends an "Emergency Stop" to the client's side, linemonitor() will
  1221	   produce an "Emergency Stop" exception (type 4).
  1222	*/
  1223	void linemonitor_emergencystop(int sock) {
  1224	  unsigned char data = 254;
  1225	  send(sock, &data, 1, 0);
  1226	}
  1227	
  1228	
  1229	
  1230	/**
  1231	   Thread used by linemonitor() NOT for direct usage.
  1232	*/
  1233	int linemonitor_thread(struct LINEMONITOR_THREAD_DATA
  1234			       *linemonitor_thread_data) {
  1235	  // buffer for sending a ping
  1236	  unsigned char counter;
  1237	  // buffer for receiving a ping
  1238	  unsigned char rcounter;
  1239	  
  1240	  // configuration of poll -- waiting for an event of the socket.
  1241	  struct pollfd polld;
  1242	  polld.fd = linemonitor_thread_data -> sock;
  1243	  polld.events = POLLIN | POLLPRI;
  1244	
  1245	
  1246	  while (1) {
  1247	    // increase counter, prevent "Emergency Stop"-Code 254
  1248	    counter++;
  1249	    if (counter == 254) {
  1250	      counter = 0;
  1251	    }
  1252	
  1253	    // send a ping
  1254	    if (send(linemonitor_thread_data -> sock, &counter, 1, 0) != 1) {
  1255	      linemonitor_thread_data -> linemonitor_exception(
  1256	                            linemonitor_thread_data -> server,
  1257				    linemonitor_thread_data -> port, 0);
  1258	      break;
  1259	    }
  1260	
  1261	    // Test, if Ping returns within the soft-timeout time, if not
  1262	    // cause exception
  1263	    if (poll(&polld, 1, linemonitor_thread_data -> soft_msec) <= 0) {
  1264	      linemonitor_thread_data -> linemonitor_exception(
  1265				    linemonitor_thread_data -> server,
  1266				    linemonitor_thread_data -> port, 1);
  1267	      // Test, if Ping returns within the soft-timeout plus
  1268	      // hard-timeout time, if not cause exception
  1269	      if (poll(&polld, 1, linemonitor_thread_data -> hard_msec) <= 0) {
  1270		linemonitor_thread_data -> linemonitor_exception(
  1271	                              linemonitor_thread_data -> server,
  1272				      linemonitor_thread_data -> port, 2);
  1273	      }
  1274	    }
  1275	
  1276	    // receive the ping
  1277	    if (recv(linemonitor_thread_data -> sock, ((char *) &rcounter), 1,
  1278		     MSG_WAITALL) != 1) {
  1279	      linemonitor_thread_data -> linemonitor_exception(
  1280				    linemonitor_thread_data -> server,
  1281				    linemonitor_thread_data -> port, 0);
  1282	      break;
  1283	    }
  1284	
  1285	    // If "Emergency Stop" code was received, call "Emergency Stop"
  1286	    // exception and retry to receive a ping
  1287	    if (rcounter == 254) {
  1288	      linemonitor_thread_data -> linemonitor_exception(
  1289				    linemonitor_thread_data -> server,
  1290				    linemonitor_thread_data -> port, 4);
  1291	
  1292	      if (recv(linemonitor_thread_data -> sock, ((char *) &rcounter),
  1293		       1, MSG_WAITALL) != 1) {
  1294		linemonitor_thread_data -> linemonitor_exception(
  1295				    linemonitor_thread_data -> server,
  1296				    linemonitor_thread_data -> port, 0);
  1297		break;
  1298	      }
  1299	    }
  1300	
  1301	    // Test on right transmission code and call "Transmission Fault"
  1302	    // exception if the data is currupted
  1303	    if (counter != rcounter) {
  1304	      linemonitor_thread_data -> linemonitor_exception(
  1305				    linemonitor_thread_data -> server,
  1306				    linemonitor_thread_data -> port, 3);
  1307	    }
  1308	
  1309	    // Wait before sendin next ping
  1310	    if (poll(&polld, 1, linemonitor_thread_data -> wait_msec) <= 0) {
  1311	    }
  1312	  }
  1313	
  1314	  pthread_exit(NULL);
  1315	}
  1316	
  1317	
  1318	
  1319	/**
  1320	   Monitor if the "line" is fast enough: Client/Robot Application. This
  1321	   function opens a socket stream, sents pings/bytes and wait for them
  1322	   to come back. The soft-timeout will called after soft_msec is
  1323	   timeouted. The hard-timeout will called after soft-timeout was
  1324	   called AND hard_msec is timeouted. wait_msec specifies the time
  1325	   which is waited after a ping is received befor the next one will be
  1326	   launched.
  1327	
  1328	   @param server (char *) server to be connected
  1329	
  1330	   @param port (int) port to be connected
  1331	
  1332	   @param soft_msec (int) timeout in milliseconds which causes
  1333	   soft-real-time exception.
  1334	
  1335	   @param hard_msec (int) timeout in milliseconds which causes
  1336	   hard-real-time exception.
  1337	
  1338	   @param wait_msec (int) timeout for resent -- sending of the next
  1339	   ping.
  1340	
  1341	   @param linemonitor_exception (pointer to function) This function
  1342	   will be called if an exception occurs. It becomes the following
  1343	   parameters: server name (char *) which is always null, port (int):
  1344	   listend port and type (int) of exception which can be: 0: Connicion
  1345	   Fault, 1: Soft Real Time Exception, 2: HARD Real Time Exception, 3:
  1346	   Transmission Fault, 4: Emergency Stop.
  1347	*/
  1348	int linemonitor(char *server, int port,
  1349			int soft_msec, int hard_msec, int wait_msec,
  1350			void (*linemonitor_exception)(char *server, int port,
  1351						      int type)) {
  1352	
  1353	  // ID and atributes for the threads
  1354	  pthread_t        thrd_2;
  1355	  pthread_attr_t   thrd_2_attr;
  1356	
  1357	  // allocate memory to store parameter for the
  1358	  // linemonitor_thread() function.
  1359	  struct LINEMONITOR_THREAD_DATA *linemonitor_thread_data;
  1360	  linemonitor_thread_data = (struct LINEMONITOR_THREAD_DATA *)
  1361	    malloc(sizeof(struct LINEMONITOR_THREAD_DATA));
  1362	  if (linemonitor_thread_data == NULL) {
  1363	    perror("malloc()");
  1364	    return -1;
  1365	  }
  1366	
  1367	  // connect to server
  1368	  linemonitor_thread_data -> sock = socket_connect(server, port);
  1369	  if (linemonitor_thread_data -> sock <= 0) {
  1370	    linemonitor_exception(server, port, 0);
  1371	    return -1;
  1372	  }
  1373	
  1374	  // store all necessary parameters in this memory
  1375	  linemonitor_thread_data -> server = server;
  1376	  linemonitor_thread_data -> port = port;
  1377	  linemonitor_thread_data -> soft_msec = soft_msec;
  1378	  linemonitor_thread_data -> hard_msec = hard_msec;
  1379	  linemonitor_thread_data -> wait_msec = wait_msec;
  1380	  linemonitor_thread_data -> linemonitor_exception =
  1381	    linemonitor_exception;
  1382	
  1383	  // launch linemonitor_thread()
  1384	  pthread_attr_init(&thrd_2_attr);
  1385	  return pthread_create(&thrd_2,
  1386				&thrd_2_attr,
  1387				(void *) linemonitor_thread,
  1388				linemonitor_thread_data);
  1389	}
  1390	
\end{lstlisting}}
