1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2010 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3    	 *   jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu              *
4    	 *                                                                          *
5    	 *   This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src).  *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/src is free software: you can redistribute it and/or        *
8    	 *  modify it under the terms of the GNU Lesser General Public License as   *
9    	 *  published by the Free Software Foundation, either version 3 of the      *
10   	 *  License, or (at your option) any later version.                         *
11   	 *                                                                          *
12   	 *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
13   	 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14   	 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15   	 *  GNU Lesser General Public License for more details.                     *
16   	 *                                                                          *
17   	 *  You should have received a copy of the GNU Lesser General Public        *
18   	 *  License along with DMTCP:dmtcp/src.  If not, see                        *
19   	 *  <http://www.gnu.org/licenses/>.                                         *
20   	 ****************************************************************************/
21   	
22   	#include <stdarg.h>
23   	#include <stdlib.h>
24   	#include <vector>
25   	#include <list>
26   	#include <string>
27   	#include <fcntl.h>
28   	#include <signal.h>
29   	#include <sys/ipc.h>
30   	#include <sys/shm.h>
31   	#include <sys/types.h>
32   	#include <sys/socket.h>
33   	#include <unistd.h>
34   	#include <sys/syscall.h>
35   	#include <linux/version.h>
36   	#include <limits.h>
37   	#include "uniquepid.h"
38   	#include "dmtcpworker.h"
39   	#include "dmtcpmessagetypes.h"
40   	#include "protectedfds.h"
41   	#include "constants.h"
42   	#include "connectionmanager.h"
43   	#include "syscallwrappers.h"
44   	#include "sysvipc.h"
45   	#include "util.h"
46   	#include  "../jalib/jassert.h"
47   	#include  "../jalib/jconvert.h"
48   	
49   	extern "C" void exit ( int status )
50   	{
51   	  dmtcp::DmtcpWorker::setExitInProgress();
52   	  _real_exit ( status );
53   	  for (;;); // Without this, gcc emits warning:  `noreturn' fnc does return
54   	}
55   	
56   	#ifdef EXTERNAL_SOCKET_HANDLING
57   	extern dmtcp::vector <dmtcp::ConnectionIdentifier> externalTcpConnections;
58   	static void processClose(dmtcp::ConnectionIdentifier conId)
59   	{
60   	  if ( dmtcp::DmtcpWorker::waitingForExternalSocketsToClose() == true ) {
61   	    dmtcp::vector <dmtcp::ConnectionIdentifier>::iterator i = externalTcpConnections.begin();
62   	    for ( i = externalTcpConnections.begin(); i != externalTcpConnections.end(); ++i ) {
63   	      if ( conId == *i ) {
64   	        externalTcpConnections.erase(i);
65   	        break;
66   	      }
67   	    }
68   	    if ( externalTcpConnections.empty() == true ) {
69   	    }
70   	    sleep(4);
71   	  }
72   	}
73   	#endif
74   	
75   	extern "C" int close ( int fd )
76   	{
77   	  if ( dmtcp::ProtectedFDs::isProtected ( fd ) )
78   	  {
79   	    JTRACE ( "blocked attempt to close protected fd" ) ( fd );
80   	    errno = EBADF;
81   	    return -1;
82   	  }
83   	
84   	#ifdef EXTERNAL_SOCKET_HANDLING
85   	  dmtcp::ConnectionIdentifier conId;
86   	  if ( dmtcp::WorkerState::currentState() == dmtcp::WorkerState::RUNNING &&
87   	       dmtcp::DmtcpWorker::waitingForExternalSocketsToClose() == true &&
88   	       dup2(fd,fd) != -1 ) {
89   	    conId = dmtcp::KernelDeviceToConnection::instance().retrieve(fd).id();
90   	  }
91   	#endif
92   	
93   	  int rv = _real_close ( fd );
94   	
95   	#ifdef EXTERNAL_SOCKET_HANDLING
96   	  if (rv == 0) {
97   	    processClose(conId);
98   	  }
99   	#endif
100  	
101  	  return rv;
102  	}
103  	
104  	extern "C" int fclose(FILE *fp)
105  	{
106  	  int fd = fileno(fp);
107  	  if ( dmtcp::ProtectedFDs::isProtected ( fd ) )
108  	  {
109  	    JTRACE ( "blocked attempt to fclose protected fd" ) ( fd );
110  	    errno = EBADF;
111  	    return -1;
112  	  }
113  	
114  	#ifdef EXTERNAL_SOCKET_HANDLING
115  	  dmtcp::ConnectionIdentifier conId;
116  	
117  	  if ( dmtcp::WorkerState::currentState() == dmtcp::WorkerState::RUNNING &&
118  	       dmtcp::DmtcpWorker::waitingForExternalSocketsToClose() == true &&
119  	       dup2(fd,fd) != -1 ) {
120  	    conId = dmtcp::KernelDeviceToConnection::instance().retrieve(fd).id();
121  	  }
122  	#endif
123  	
124  	  int rv = _real_fclose(fp);
125  	
126  	#ifdef EXTERNAL_SOCKET_HANDLING
127  	  if (rv == 0 ) {
128  	    processClose(conId);
129  	  }
130  	#endif
131  	  return rv;
132  	}
133  	
134  	/* epoll is currently not supported by DMTCP */
135  	extern "C" int epoll_create(int size)
136  	{
137  	  JWARNING (false) .Text("epoll is currently not supported by DMTCP.");
138  	  errno = EPERM;
139  	  return -1;
140  	}
141  	
142  	extern "C" int socketpair ( int d, int type, int protocol, int sv[2] )
143  	{
144  	  WRAPPER_EXECUTION_DISABLE_CKPT();
145  	
146  	  JASSERT ( sv != NULL );
147  	  int rv = _real_socketpair ( d,type,protocol,sv );
148  	  JTRACE ( "socketpair()" ) ( sv[0] ) ( sv[1] );
149  	
150  	  dmtcp::TcpConnection *a, *b;
151  	
152  	  a = new dmtcp::TcpConnection ( d, type, protocol );
153  	  a->onConnect();
154  	  b = new dmtcp::TcpConnection ( *a, a->id() );
155  	
156  	  dmtcp::KernelDeviceToConnection::instance().create ( sv[0] , a );
157  	  dmtcp::KernelDeviceToConnection::instance().create ( sv[1] , b );
158  	
159  	  WRAPPER_EXECUTION_ENABLE_CKPT();
160  	
161  	  return rv;
162  	}
163  	
164  	extern "C" int pipe ( int fds[2] )
165  	{
166  	  JTRACE ( "promoting pipe() to socketpair()" );
167  	  //just promote pipes to socketpairs
168  	  return socketpair ( AF_UNIX, SOCK_STREAM, 0, fds );
169  	}
170  	
171  	# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
172  	// pipe2 appeared in Linux 2.6.27
173  	extern "C" int pipe2 ( int fds[2], int flags )
174  	{
175  	  JTRACE ( "promoting pipe2() to socketpair()" );
176  	  //just promote pipes to socketpairs
177  	  int newFlags = 0;
178  	# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
179  	  if (flags & O_NONBLOCK != 0) newFlags |= SOCK_NONBLOCK;
180  	  if (flags & O_CLOEXEC != 0)  newFlags |= SOCK_CLOEXEC;
181  	#endif
182  	  return socketpair ( AF_UNIX, SOCK_STREAM | newFlags, 0, fds );
183  	}
184  	#endif
185  	
186  	
187  	static int ptsname_r_work ( int fd, char * buf, size_t buflen )
188  	{
189  	  JTRACE ( "Calling ptsname_r" );
190  	
191  	  dmtcp::Connection* c = &dmtcp::KernelDeviceToConnection::instance().retrieve ( fd );
192  	  dmtcp::PtyConnection* ptyCon = (dmtcp::PtyConnection*) c;
193  	
194  	  dmtcp::string uniquePtsName = ptyCon->uniquePtsName();
195  	
196  	  JTRACE("ptsname_r") (uniquePtsName);
197  	
198  	  if ( uniquePtsName.length() >= buflen )
199  	  {
200  	    JWARNING ( false ) ( uniquePtsName ) ( uniquePtsName.length() ) ( buflen )
201  	      .Text ( "fake ptsname() too long for user buffer" );
202  	    errno = ERANGE;
203  	    return -1;
204  	  }
205  	
206  	  strcpy ( buf, uniquePtsName.c_str() );
207  	
208  	  return 0;
209  	}
210  	
211  	extern "C" char *ptsname ( int fd )
212  	{
213  	  /* No need to acquire Wrapper Protection lock since it will be done in ptsname_r */
214  	  JTRACE ( "ptsname() promoted to ptsname_r()" );
215  	  static char tmpbuf[PATH_MAX];
216  	
217  	  if ( ptsname_r ( fd, tmpbuf, sizeof ( tmpbuf ) ) != 0 )
218  	  {
219  	    return NULL;
220  	  }
221  	
222  	  return tmpbuf;
223  	}
224  	
225  	extern "C" int ptsname_r ( int fd, char * buf, size_t buflen )
226  	{
227  	  WRAPPER_EXECUTION_DISABLE_CKPT();
228  	
229  	  int retVal = ptsname_r_work(fd, buf, buflen);
230  	
231  	  WRAPPER_EXECUTION_ENABLE_CKPT();
232  	
233  	  return retVal;
234  	}
235  	
236  	#ifdef PID_VIRTUALIZATION
237  	#include <virtualpidtable.h>
238  	
239  	static void updateProcPath ( const char *path, char *newpath )
240  	{
241  	  char temp [ 10 ];
242  	  int index, tempIndex;
243  	
244  	  if (  path == "" || path == NULL )
245  	  {
Event secure_coding: [VERY RISKY]. Using "strcpy" can cause a buffer overflow when done incorrectly. If the destination string of a strcpy() is not large enough then anything might happen. Use strncpy() instead.
Also see events: [secure_coding][secure_coding][secure_coding]
246  	    strcpy(newpath, "");
247  	    return;
248  	  }
249  	
250  	  if ( dmtcp::Util::strStartsWith ( path, "/proc/" ) )
251  	  {
252  	    index = 6;
253  	    tempIndex = 0;
254  	    while ( path [ index ] != '/' )
255  	    {
256  	      if ( path [ index ] >= '0' && path [ index ] <= '9' )
257  	        temp [ tempIndex++ ] = path [ index++ ];
258  	      else
259  	      {
Event secure_coding: [VERY RISKY]. Using "strcpy" can cause a buffer overflow when done incorrectly. If the destination string of a strcpy() is not large enough then anything might happen. Use strncpy() instead.
Also see events: [secure_coding][secure_coding][secure_coding]
260  	        strcpy ( newpath, path );
261  	        return;
262  	      }
263  	    }
264  	    temp [ tempIndex ] = '\0';
265  	    pid_t originalPid = atoi ( temp );
266  	    pid_t currentPid = dmtcp::VirtualPidTable::instance().originalToCurrentPid( originalPid );
267  	    if (currentPid == -1)
268  	      currentPid = originalPid;
269  	
Event secure_coding: [VERY RISKY]. Using "sprintf" can cause a buffer overflow when done incorrectly. Because sprintf() assumes an arbitrarily long string, callers must be careful not to overflow the actual space of the destination. Use snprintf() instead, or correct precision specifiers.
Also see events: [secure_coding][secure_coding][secure_coding]
270  	    sprintf ( newpath, "/proc/%d%s", currentPid, &path [ index ] );
271  	  }
Event secure_coding: [VERY RISKY]. Using "strcpy" can cause a buffer overflow when done incorrectly. If the destination string of a strcpy() is not large enough then anything might happen. Use strncpy() instead.
Also see events: [secure_coding][secure_coding][secure_coding]
272  	  else strcpy ( newpath, path );
273  	  return;
274  	}
275  	#else
276  	void updateProcPath ( const char *path, char *newpath )
277  	{
278  	  if (  path == "" || path == NULL ) {
279  	    strcpy( newpath, "" );
280  	    return;
281  	  }
282  	  strcpy ( newpath, path );
283  	  return;
284  	}
285  	#endif
286  	
287  	// The current implementation simply increments the last count and returns it.
288  	// Although highly unlikely, this can cause a problem if the counter resets to
289  	// zero. In that case we should have some more sophisticated code which checks
290  	// to see if the value pointed by counter is in use or not.
291  	static int getNextFreeSlavePtyNum()
292  	{
293  	  static int counter = -1;
294  	  counter++;
295  	  JASSERT(counter != -1) .Text ("See the comment above");
296  	  return counter;
297  	}
298  	
299  	#define DMTCP_PTS_PREFIX_STR  "dmtcp_"
300  	#define UNIQUE_PTS_PREFIX_STR "/dev/pts/dmtcp_"
301  	//DMTCP_PTS_PREFIX_STR
302  	
303  	static int _nextPtmxId()
304  	{
305  	  static int id = 0;
306  	  return id++;
307  	}
308  	
309  	// XXX: The current implementation for handling Pseudo-Terminal Master-Slave pairs
310  	// works only if the process involved in it are restarted from the same
311  	// dmtcp_restart command.                               -- KAPIL
312  	
313  	static void processDevPtmxConnection (int fd)
314  	{
315  	  char ptsName[21];
316  	
317  	  JASSERT(_real_ptsname_r(fd, ptsName, 21) == 0) (JASSERT_ERRNO);
318  	
319  	  dmtcp::string ptsNameStr = ptsName;
320  	  dmtcp::string uniquePtsNameStr;
321  	
322  	  // glibc allows only 20 char long ptsname
323  	  // Check if there is enough room to insert the string "dmtcp_" before the
324  	  //   terminal number, if not then we ASSERT here.
325  	  JASSERT((strlen(ptsName) + strlen("dmtcp_")) <= 20)
326  	    .Text("string /dev/pts/<n> too long, can not be virtualized."
327  	          "Once possible workarong here is to replace the string"
328  	          "\"dmtcp_\" with something short like \"d_\" or even "
329  	          "\"d\" and recompile DMTCP");
330  	
331  	  // Generate new Unique ptsName
332  	  uniquePtsNameStr = UNIQUE_PTS_PREFIX_STR;
333  	  uniquePtsNameStr += jalib::XToString(getNextFreeSlavePtyNum());
334  	
335  	  dmtcp::string deviceName = "ptmx[" + ptsNameStr + "]:" + "/dev/ptmx";
336  	
337  	//   dmtcp::string deviceName = "ptmx[" + dmtcp::UniquePid::ThisProcess().toString()
338  	//                            + ":" + jalib::XToString ( _nextPtmxId() )
339  	//                            + "]:" + device;
340  	
341  	  JTRACE ( "creating ptmx connection" ) ( deviceName ) ( ptsNameStr ) ( uniquePtsNameStr );
342  	
343  	  int type = dmtcp::PtyConnection::PTY_MASTER;
344  	  dmtcp::Connection * c = new dmtcp::PtyConnection ( ptsNameStr, uniquePtsNameStr, type );
345  	
346  	  dmtcp::KernelDeviceToConnection::instance().createPtyDevice ( fd, deviceName, c );
347  	
348  	  dmtcp::UniquePtsNameToPtmxConId::instance().add ( uniquePtsNameStr, c->id() );
349  	}
350  	
351  	static void processDevPtsConnection (int fd, const char* uniquePtsName, const char* ptsName)
352  	{
353  	  dmtcp::string ptsNameStr = ptsName;
354  	  dmtcp::string uniquePtsNameStr = uniquePtsName;
355  	
356  	  dmtcp::string deviceName = "pts:" + ptsNameStr;
357  	
358  	  JTRACE ( "creating pts connection" ) ( deviceName ) ( ptsNameStr ) ( uniquePtsNameStr );
359  	
360  	  int type = dmtcp::PtyConnection::PTY_SLAVE;
361  	  dmtcp::Connection * c = new dmtcp::PtyConnection ( ptsNameStr, uniquePtsNameStr, type );
362  	
363  	  dmtcp::KernelDeviceToConnection::instance().createPtyDevice ( fd, deviceName, c );
364  	}
365  	
366  	extern "C" int getpt()
367  	{
368  	  int fd = _real_getpt();
369  	  if ( fd >= 0 ) {
370  	    processDevPtmxConnection(fd);
371  	  }
372  	  return fd;
373  	}
374  	
375  	extern "C" int open (const char *path, int flags, ... )
376  	{
377  	  va_list ap;
378  	  mode_t mode;
379  	  int rc;
380  	  char newpath [ PATH_MAX ] = {0} ;
381  	
382  	  // Handling the variable number of arguments
383  	  va_start( ap, flags );
384  	  mode = va_arg ( ap, mode_t );
385  	  va_end ( ap );
386  	
387  	  /* If DMTCP has not yet initialized, it might be that JASSERT_INIT() is
388  	   * calling this function to open jassert log files. Therefore we shouldn't be
389  	   * playing with locks etc.
390  	   *
391  	   * FIXME: The following check is not required anymore. JASSERT_INIT calls
392  	   *        libc:open directly.
393  	   */
394  	  if ( dmtcp::WorkerState::currentState() == dmtcp::WorkerState::UNKNOWN ) {
395  	    return _real_open ( path, flags, mode );
396  	  }
397  	
398  	  WRAPPER_EXECUTION_DISABLE_CKPT();
399  	
400  	  if ( dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR) ) {
401  	    dmtcp::string currPtsDevName = dmtcp::UniquePtsNameToPtmxConId::instance().retrieveCurrentPtsDeviceName(path);
402  	    strcpy(newpath, currPtsDevName.c_str());
403  	  } else {
404  	    updateProcPath ( path, newpath );
405  	  }
406  	
407  	  int fd = _real_open( newpath, flags, mode );
408  	
409  	  if ( fd >= 0 && strcmp(path, "/dev/ptmx") == 0 ) {
410  	    processDevPtmxConnection(fd);
411  	  } else if ( fd >= 0 && dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR) ) {
412  	    processDevPtsConnection(fd, path, newpath);
413  	  }
414  	
415  	  WRAPPER_EXECUTION_ENABLE_CKPT();
416  	
417  	  return fd;
418  	}
419  	
420  	extern "C" FILE *fopen (const char* path, const char* mode)
421  	{
422  	  /* If DMTCP has not yet initialized, it might be that JASSERT_INIT() is
423  	   * calling this function to open jassert log files. Therefore we shouldn't be
424  	   * playing with locks etc.
425  	   *
426  	   * FIXME: The following check is not required anymore. JASSERT_INIT calls
427  	   *        libc:open directly.
428  	   */
429  	  if ( dmtcp::WorkerState::currentState() == dmtcp::WorkerState::UNKNOWN ) {
430  	    return _real_fopen ( path, mode );
431  	  }
432  	
433  	  WRAPPER_EXECUTION_DISABLE_CKPT();
434  	
435  	  char newpath [ PATH_MAX ] = {0} ;
436  	  int fd = -1;
437  	
438  	  if ( dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR) ) {
439  	    dmtcp::string currPtsDevName = dmtcp::UniquePtsNameToPtmxConId::instance().retrieveCurrentPtsDeviceName(path);
440  	    strcpy(newpath, currPtsDevName.c_str());
441  	  } else {
442  	    updateProcPath ( path, newpath );
443  	  }
444  	
445  	  FILE *file = _real_fopen ( newpath, mode );
446  	
447  	  if (file != NULL) {
448  	    fd = fileno(file);
449  	  }
450  	
451  	  if ( fd >= 0 && strcmp(path, "/dev/ptmx") == 0 ) {
452  	    processDevPtmxConnection(fd);
453  	  } else if ( fd >= 0 && dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR) ) {
454  	    processDevPtsConnection(fd, path, newpath);
455  	  }
456  	
457  	  WRAPPER_EXECUTION_ENABLE_CKPT();
458  	
459  	  return file;
460  	}
461  	
462  	static void updateStatPath(const char *path, char *newpath)
463  	{
464  	  if ( dmtcp::WorkerState::currentState() == dmtcp::WorkerState::UNKNOWN ) {
465  	    strncpy(newpath, path, PATH_MAX);
466  	  } else if ( dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR) ) {
467  	    dmtcp::string currPtsDevName = dmtcp::UniquePtsNameToPtmxConId::instance().retrieveCurrentPtsDeviceName(path);
468  	    strcpy(newpath, currPtsDevName.c_str());
469  	  } else {
470  	    updateProcPath ( path, newpath );
471  	  }
472  	}
473  	
474  	extern "C" 
475  	int __xstat(int vers, const char *path, struct stat *buf)
476  	{
477  	  char newpath [ PATH_MAX ] = {0} ;
478  	  WRAPPER_EXECUTION_DISABLE_CKPT();
479  	  updateStatPath(path, newpath);
480  	  int rc = _real_xstat( vers, newpath, buf );
481  	  WRAPPER_EXECUTION_ENABLE_CKPT();
482  	  return rc;
483  	}
484  	
485  	extern "C" 
486  	int __xstat64(int vers, const char *path, struct stat64 *buf)
487  	{
488  	  char newpath [ PATH_MAX ] = {0} ;
489  	  WRAPPER_EXECUTION_DISABLE_CKPT();
490  	  updateStatPath(path, newpath);
491  	  int rc = _real_xstat64( vers, newpath, buf );
492  	  WRAPPER_EXECUTION_ENABLE_CKPT();
493  	  return rc;
494  	}
495  	
496  	extern "C" 
497  	int __lxstat(int vers, const char *path, struct stat *buf)
498  	{
499  	  char newpath [ PATH_MAX ] = {0} ;
500  	  WRAPPER_EXECUTION_DISABLE_CKPT();
501  	  updateStatPath(path, newpath);
502  	  int rc = _real_lxstat( vers, newpath, buf );
503  	  WRAPPER_EXECUTION_ENABLE_CKPT();
504  	  return rc;
505  	}
506  	
507  	extern "C" 
508  	int __lxstat64(int vers, const char *path, struct stat64 *buf)
509  	{
510  	  char newpath [ PATH_MAX ] = {0} ;
511  	  WRAPPER_EXECUTION_DISABLE_CKPT();
512  	  updateStatPath(path, newpath);
513  	  int rc = _real_lxstat64( vers, newpath, buf );
514  	  WRAPPER_EXECUTION_ENABLE_CKPT();
515  	  return rc;
516  	}
517  	
518  	//       int fstat(int fd, struct stat *buf);
519  	
520  	#ifdef ENABLE_MALLOC_WRAPPER
521  	# ifdef ENABLE_DLOPEN
522  	#  error "ENABLE_MALLOC_WRAPPER can't work with ENABLE_DLOPEN"
523  	# endif
524  	extern "C" void *calloc(size_t nmemb, size_t size)
525  	{
526  	  WRAPPER_EXECUTION_DISABLE_CKPT();
527  	  void *retVal = _real_calloc ( nmemb, size );
528  	  WRAPPER_EXECUTION_ENABLE_CKPT();
529  	  return retVal;
530  	}
531  	extern "C" void *malloc(size_t size)
532  	{
533  	  WRAPPER_EXECUTION_DISABLE_CKPT();
534  	  void *retVal = _real_malloc ( size );
535  	  WRAPPER_EXECUTION_ENABLE_CKPT();
536  	  return retVal;
537  	}
538  	extern "C" void free(void *ptr)
539  	{
540  	  WRAPPER_EXECUTION_DISABLE_CKPT();
541  	  _real_free ( ptr );
542  	  WRAPPER_EXECUTION_ENABLE_CKPT();
543  	}
544  	extern "C" void *realloc(void *ptr, size_t size)
545  	{
546  	  WRAPPER_EXECUTION_DISABLE_CKPT();
547  	  void *retVal = _real_realloc ( ptr, size );
548  	  WRAPPER_EXECUTION_ENABLE_CKPT();
549  	  return retVal;
550  	}
551  	#endif
552  	
553  	
554  	/*
555  	extern "C" int
556  	printf (const char *format, ...)
557  	{
558  	  va_list arg;
559  	  int done;
560  	
561  	  va_start (arg, format);
562  	  done = vfprintf (stdout, format, arg);
563  	  va_end (arg);
564  	
565  	  return done;
566  	}
567  	
568  	extern "C" int
569  	fprintf (FILE *stream, const char *format, ...)
570  	{
571  	  va_list arg;
572  	  int done;
573  	
574  	  va_start (arg, format);
575  	  done = vfprintf (stream, format, arg);
576  	  va_end (arg);
577  	
578  	  return done;
579  	}
580  	
581  	extern "C" int
582  	vprintf (const char *format, __gnuc_va_list arg)
583  	{
584  	  return vfprintf (stdout, format, arg);
585  	}
586  	
587  	extern "C" int
588  	vfprintf (FILE *s, const char *format, va_list ap)
589  	{
590  	  WRAPPER_EXECUTION_DISABLE_CKPT();
591  	  int retVal = _real_vfprintf ( s, format, ap );
592  	  WRAPPER_EXECUTION_ENABLE_CKPT();
593  	  return retVal;
594  	}
595  	
596  	
597  	extern "C" int
598  	sprintf (char *s, const char *format, ...)
599  	{
600  	  va_list arg;
601  	  int done;
602  	
603  	  va_start (arg, format);
604  	  done = vsprintf (s, format, arg);
605  	  va_end (arg);
606  	
607  	  return done;
608  	}
609  	
610  	
611  	extern "C" int
612  	snprintf (char *s, size_t maxlen, const char *format, ...)
613  	{
614  	  va_list arg;
615  	  int done;
616  	
617  	  va_start (arg, format);
618  	  done = vsnprintf (s, maxlen, format, arg);
619  	  va_end (arg);
620  	
621  	  return done;
622  	}
623  	
624  	
625  	extern "C" int vsprintf(char *str, const char *format, va_list ap);
626  	extern "C" int vsnprintf(char *str, size_t size, const char *format, va_list ap);
627  	*/
628  	
629  	extern "C"
630  	int shmget(key_t key, size_t size, int shmflg)
631  	{
632  	  int ret;
633  	  WRAPPER_EXECUTION_DISABLE_CKPT();
634  	  while (true) {
635  	    ret = _real_shmget(key, size, shmflg);
636  	    if (ret != -1 && 
637  	        dmtcp::SysVIPC::instance().isConflictingShmid(ret) == false) {
638  	      dmtcp::SysVIPC::instance().on_shmget(key, size, shmflg, ret);
639  	      break;
640  	    }
641  	    JASSERT(_real_shmctl(ret, IPC_RMID, NULL) != -1);
642  	  };
643  	  JTRACE ("Creating new Shared memory segment" ) (key) (size) (shmflg) (ret);
644  	  WRAPPER_EXECUTION_ENABLE_CKPT();
645  	  return ret;
646  	}
647  	
648  	extern "C"
649  	void *shmat(int shmid, const void *shmaddr, int shmflg)
650  	{
651  	  WRAPPER_EXECUTION_DISABLE_CKPT();
652  	  int currentShmid = dmtcp::SysVIPC::instance().originalToCurrentShmid(shmid);
653  	  JASSERT(currentShmid != -1);
654  	  void *ret = _real_shmat(currentShmid, shmaddr, shmflg);
655  	  if (ret != (void *) -1) {
656  	    dmtcp::SysVIPC::instance().on_shmat(shmid, shmaddr, shmflg, ret);
657  	    JTRACE ("Mapping Shared memory segment" ) (shmid) (shmflg) (ret);
658  	  }
659  	  WRAPPER_EXECUTION_ENABLE_CKPT();
660  	  return ret;
661  	}
662  	
663  	extern "C"
664  	int shmdt(const void *shmaddr)
665  	{
666  	  WRAPPER_EXECUTION_DISABLE_CKPT();
667  	  int ret = _real_shmdt(shmaddr);
668  	  if (ret != -1) {
669  	    dmtcp::SysVIPC::instance().on_shmdt(shmaddr);
670  	    JTRACE ("Unmapping Shared memory segment" ) (shmaddr);
671  	  }
672  	  WRAPPER_EXECUTION_ENABLE_CKPT();
673  	  return ret;
674  	}
675  	
676  	extern "C"
677  	int shmctl(int shmid, int cmd, struct shmid_ds *buf)
678  	{
679  	  WRAPPER_EXECUTION_DISABLE_CKPT();
680  	  int currentShmid = dmtcp::SysVIPC::instance().originalToCurrentShmid(shmid);
681  	  JASSERT(currentShmid != -1);
682  	  int ret = _real_shmctl(currentShmid, cmd, buf);
683  	  // Change the creater-pid of the shm object to the original so that if
684  	  // calling thread wants to use it, pid-virtualization layer can take care of
685  	  // the original to current conversion.
686  	  // TODO: Need to update uid/gid fields to support uid/gid virtualization.
687  	  if (buf != NULL) {
688  	    buf->shm_cpid = dmtcp::VirtualPidTable::instance().currentToOriginalPid(buf->shm_cpid);
689  	  }
690  	  WRAPPER_EXECUTION_ENABLE_CKPT();
691  	  return ret;
692  	}
693  	
694  	extern "C" int __clone ( int ( *fn ) ( void *arg ), void *child_stack, int flags, void *arg, int *parent_tidptr, struct user_desc *newtls, int *child_tidptr );
695  	pid_t gettid();
696  	int tkill(int tid, int sig);
697  	int tgkill(int tgid, int tid, int sig);
698  	
699  	#define SYSCALL_VA_START()                                              \
700  	  va_list ap;                                                           \
701  	  va_start(ap, sys_num)
702  	
703  	#define SYSCALL_VA_END()                                                \
704  	  va_end(ap)
705  	
706  	#define SYSCALL_GET_ARG(type,arg) type arg = va_arg(ap, type)
707  	
708  	#define SYSCALL_GET_ARGS_2(type1,arg1,type2,arg2)                       \
709  	  SYSCALL_GET_ARG(type1,arg1);                                          \
710  	  SYSCALL_GET_ARG(type2,arg2)
711  	
712  	#define SYSCALL_GET_ARGS_3(type1,arg1,type2,arg2,type3,arg3)            \
713  	  SYSCALL_GET_ARGS_2(type1,arg1,type2,arg2);                            \
714  	  SYSCALL_GET_ARG(type3,arg3)
715  	
716  	#define SYSCALL_GET_ARGS_4(type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
717  	  SYSCALL_GET_ARGS_3(type1,arg1,type2,arg2,type3,arg3);                 \
718  	  SYSCALL_GET_ARG(type4,arg4)
719  	
720  	#define SYSCALL_GET_ARGS_5(type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
721  	                           type5,arg5)                                  \
722  	  SYSCALL_GET_ARGS_4(type1,arg1,type2,arg2,type3,arg3,type4,arg4);      \
723  	  SYSCALL_GET_ARG(type5,arg5)
724  	
725  	#define SYSCALL_GET_ARGS_6(type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
726  	                           type5,arg5,type6,arg6)                        \
727  	  SYSCALL_GET_ARGS_5(type1,arg1,type2,arg2,type3,arg3,type4,arg4,       \
728  	                     type5,arg5);                                       \
729  	  SYSCALL_GET_ARG(type6,arg6)
730  	
731  	#define SYSCALL_GET_ARGS_7(type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
732  	                           type5,arg5,type6,arg6,type7,arg7)             \
733  	  SYSCALL_GET_ARGS_6(type1,arg1,type2,arg2,type3,arg3,type4,arg4,       \
734  	                     type5,arg5,type6,arg6);                             \
735  	  SYSCALL_GET_ARG(type7,arg7)
736  	
737  	/* Comments by Gene:
738  	 * Here, syscall is the wrapper, and the call to syscall would be _real_syscall
739  	 * We would add a special case for SYS_gettid, while all others default as below
740  	 * It depends on the idea that arguments are stored in registers, whose
741  	 *  natural size is:  sizeof(void*)
742  	 * So, we pass six arguments to syscall, and it will ignore any extra arguments
743  	 * I believe that all Linux system calls have no more than 7 args.
744  	 * clone() is an example of one with 7 arguments.
745  	 * If we discover system calls for which the 7 args strategy doesn't work,
746  	 *  we can special case them.
747  	 *
748  	 * XXX: DO NOT USE JTRACE/JNOTE/JASSERT in this function; even better, do not
749  	 *      use any STL here.  (--Kapil)
750  	 */
751  	extern "C" long int syscall(long int sys_num, ... )
752  	{
753  	  long int ret;
754  	  va_list ap;
755  	
756  	  va_start(ap, sys_num);
757  	
758  	  switch ( sys_num ) {
759  	    case SYS_gettid:
760  	    {
761  	      ret = gettid();
762  	      break;
763  	    }
764  	    case SYS_tkill:
765  	    {
766  	      SYSCALL_GET_ARGS_2(int, tid, int, sig);
767  	      ret = tkill(tid, sig);
768  	      break;
769  	    }
770  	    case SYS_tgkill:
771  	    {
772  	      SYSCALL_GET_ARGS_3(int, tgid, int, tid, int, sig);
773  	      ret = tgkill(tgid, tid, sig);
774  	      break;
775  	    }
776  	
777  	    case SYS_clone:
778  	    {
779  	      typedef int (*fnc) (void*);
780  	      SYSCALL_GET_ARGS_7(fnc, fn, void*, child_stack, int, flags, void*, arg,
781  	                         pid_t*, pid, struct user_desc*, tls, pid_t*, ctid);
782  	      ret = __clone(fn, child_stack, flags, arg, pid, tls, ctid);
783  	      break;
784  	    }
785  	
786  	    case SYS_execve:
787  	    {
788  	      SYSCALL_GET_ARGS_3(const char*,filename,char* const *,argv,char* const *,envp);
789  	      ret = execve(filename,argv,envp);
790  	      break;
791  	    }
792  	
793  	    case SYS_fork:
794  	    {
795  	      ret = fork();
796  	      break;
797  	    }
798  	    case SYS_exit:
799  	    {
800  	      SYSCALL_GET_ARG(int,status);
801  	      exit(status);
802  	      break;
803  	    }
804  	    case SYS_open:
805  	    {
806  	      SYSCALL_GET_ARGS_3(const char*,pathname,int,flags,mode_t,mode);
807  	      ret = open(pathname, flags, mode);
808  	      break;
809  	    }
810  	    case SYS_close:
811  	    {
812  	      SYSCALL_GET_ARG(int,fd);
813  	      ret = close(fd);
814  	      break;
815  	    }
816  	
817  	    case SYS_rt_sigaction:
818  	    {
819  	      SYSCALL_GET_ARGS_3(int,signum,const struct sigaction*,act,struct sigaction*,oldact);
820  	      ret = sigaction(signum, act, oldact);
821  	      break;
822  	    }
823  	    case SYS_rt_sigprocmask:
824  	    {
825  	      SYSCALL_GET_ARGS_3(int,how,const sigset_t*,set,sigset_t*,oldset);
826  	      ret = sigprocmask(how, set, oldset);
827  	      break;
828  	    }
829  	    case SYS_rt_sigtimedwait:
830  	    {
831  	      SYSCALL_GET_ARGS_3(const sigset_t*,set,siginfo_t*,info,
832  	                        const struct timespec*, timeout);
833  	      ret = sigtimedwait(set, info, timeout);
834  	      break;
835  	    }
836  	
837  	#ifdef __i386__
838  	    case SYS_sigaction:
839  	    {
840  	      SYSCALL_GET_ARGS_3(int,signum,const struct sigaction*,act,struct sigaction*,oldact);
841  	      ret = sigaction(signum, act, oldact);
842  	      break;
843  	    }
844  	    case SYS_signal:
845  	    {
846  	      typedef void (*sighandler_t)(int);
847  	      SYSCALL_GET_ARGS_2(int,signum,sighandler_t,handler);
848  	      // Cast needed:  signal returns sighandler_t
849  	      ret = (long int)signal(signum, handler);
850  	      break;
851  	    }
852  	    case SYS_sigprocmask:
853  	    {
854  	      SYSCALL_GET_ARGS_3(int,how,const sigset_t*,set,sigset_t*,oldset);
855  	      ret = sigprocmask(how, set, oldset);
856  	      break;
857  	    }
858  	#endif
859  	
860  	#ifdef __x86_64__
861  	// These SYS_xxx are only defined for 64-bit Linux
862  	    case SYS_socket:
863  	    {
864  	      SYSCALL_GET_ARGS_3(int,domain,int,type,int,protocol);
865  	      ret = socket(domain,type,protocol);
866  	      break;
867  	    }
868  	    case SYS_connect:
869  	    {
870  	      SYSCALL_GET_ARGS_3(int,sockfd,const struct sockaddr*,addr,socklen_t,addrlen);
871  	      ret = connect(sockfd, addr, addrlen);
872  	      break;
873  	    }
874  	    case SYS_bind:
875  	    {
876  	      SYSCALL_GET_ARGS_3(int,sockfd,const struct sockaddr*,addr,socklen_t,addrlen);
877  	      ret = bind(sockfd,addr,addrlen);
878  	      break;
879  	    }
880  	    case SYS_listen:
881  	    {
882  	      SYSCALL_GET_ARGS_2(int,sockfd,int,backlog);
883  	      ret = listen(sockfd,backlog);
884  	      break;
885  	    }
886  	    case SYS_accept:
887  	    {
888  	      SYSCALL_GET_ARGS_3(int,sockfd,struct sockaddr*,addr,socklen_t*,addrlen);
889  	      ret = accept(sockfd, addr, addrlen);
890  	      break;
891  	    }
892  	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
893  	# if __GLIBC_PREREQ(2,10)
894  	    case SYS_accept4:
895  	    {
896  	      SYSCALL_GET_ARGS_4(int,sockfd,struct sockaddr*,addr,socklen_t*,addrlen,int,flags);
897  	      ret = accept4(sockfd, addr, addrlen, flags);
898  	      break;
899  	    }
900  	# endif
901  	#endif
902  	    case SYS_setsockopt:
903  	    {
904  	      SYSCALL_GET_ARGS_5(int,s,int,level,int,optname,const void*,optval,socklen_t,optlen);
905  	      ret = setsockopt(s, level, optname, optval, optlen);
906  	      break;
907  	    }
908  	
909  	    case SYS_socketpair:
910  	    {
911  	      SYSCALL_GET_ARGS_4(int,d,int,type,int,protocol,int*,sv);
912  	      ret = socketpair(d,type,protocol,sv);
913  	      break;
914  	    }
915  	#endif
916  	
917  	    case SYS_pipe:
918  	    {
919  	      SYSCALL_GET_ARG(int*,fds);
920  	      ret = pipe(fds);
921  	      break;
922  	    }
923  	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
924  	# if __GLIBC_PREREQ(2,9)
925  	    case SYS_pipe2:
926  	    {
927  	      SYSCALL_GET_ARGS_2(int*,fds,int,flags);
928  	      ret = pipe2(fds, flags);
929  	      break;
930  	    }
931  	# endif
932  	#endif
933  	
934  	#ifdef PID_VIRTUALIZATION
935  	    case SYS_getpid:
936  	    {
937  	      ret = getpid();
938  	      break;
939  	    }
940  	    case SYS_getppid:
941  	    {
942  	      ret = getppid();
943  	      break;
944  	    }
945  	
946  	    case SYS_getpgrp:
947  	    {
948  	      ret = getpgrp();
949  	      break;
950  	    }
951  	
952  	    case SYS_getpgid:
953  	    {
954  	      SYSCALL_GET_ARG(pid_t,pid);
955  	      ret = getpgid(pid);
956  	      break;
957  	    }
958  	    case SYS_setpgid:
959  	    {
960  	      SYSCALL_GET_ARGS_2(pid_t,pid,pid_t,pgid);
961  	      ret = setpgid(pid, pgid);
962  	      break;
963  	    }
964  	
965  	    case SYS_getsid:
966  	    {
967  	      SYSCALL_GET_ARG(pid_t,pid);
968  	      ret = getsid(pid);
969  	      break;
970  	    }
971  	    case SYS_setsid:
972  	    {
973  	      ret = setsid();
974  	      break;
975  	    }
976  	
977  	    case SYS_kill:
978  	    {
979  	      SYSCALL_GET_ARGS_2(pid_t,pid,int,sig);
980  	      ret = kill(pid, sig);
981  	      break;
982  	    }
983  	
984  	    case SYS_waitid:
985  	    {
986  	      //SYSCALL_GET_ARGS_4(idtype_t,idtype,id_t,id,siginfo_t*,infop,int,options);
987  	      SYSCALL_GET_ARGS_4(int,idtype,id_t,id,siginfo_t*,infop,int,options);
988  	      ret = waitid((idtype_t)idtype, id, infop, options);
989  	      break;
990  	    }
991  	    case SYS_wait4:
992  	    {
993  	      SYSCALL_GET_ARGS_4(pid_t,pid,__WAIT_STATUS,status,int,options,
994  	                         struct rusage*,rusage);
995  	      ret = wait4(pid, status, options, rusage);
996  	      break;
997  	    }
998  	#ifdef __i386__
999  	    case SYS_waitpid:
1000 	    {
1001 	      SYSCALL_GET_ARGS_3(pid_t,pid,int*,status,int,options);
1002 	      ret = waitpid(pid, status, options);
1003 	      break;
1004 	    }
1005 	#endif
1006 	
1007 	    case SYS_setgid:
1008 	    {
1009 	      SYSCALL_GET_ARG(gid_t,gid);
1010 	      ret = setgid(gid);
1011 	      break;
1012 	    }
1013 	    case SYS_setuid:
1014 	    {
1015 	      SYSCALL_GET_ARG(uid_t,uid);
1016 	      ret = setuid(uid);
1017 	      break;
1018 	    }
1019 	#endif /* PID_VIRTUALIZATION */
1020 	
1021 	#ifndef DISABLE_SYS_V_IPC
1022 	# ifdef __x86_64__
1023 	// These SYS_xxx are only defined for 64-bit Linux
1024 	    case SYS_shmget:
1025 	    {
1026 	      SYSCALL_GET_ARGS_3(key_t,key,size_t,size,int,shmflg);
1027 	      ret = shmget(key, size, shmflg);
1028 	      break;
1029 	    }
1030 	    case SYS_shmat:
1031 	    {
1032 	      SYSCALL_GET_ARGS_3(int,shmid,const void*,shmaddr,int,shmflg);
1033 	      ret = (unsigned long) shmat(shmid, shmaddr, shmflg);
1034 	      break;
1035 	    }
1036 	    case SYS_shmdt:
1037 	    {
1038 	      SYSCALL_GET_ARG(const void*,shmaddr);
1039 	      ret = shmdt(shmaddr);
1040 	      break;
1041 	    }
1042 	    case SYS_shmctl:
1043 	    {
1044 	      SYSCALL_GET_ARGS_3(int,shmid,int,cmd,struct shmid_ds*,buf);
1045 	      ret = shmctl(shmid, cmd, buf);
1046 	      break;
1047 	    }
1048 	# endif
1049 	#endif
1050 	
1051 	    default:
1052 	    {
1053 	      SYSCALL_GET_ARGS_7(void*, arg1, void*, arg2, void*, arg3, void*, arg4,
1054 	                         void*, arg5, void*, arg6, void*, arg7);
1055 	      ret = _real_syscall(sys_num, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1056 	      break;
1057 	    }
1058 	  }
1059 	  va_end(ap);
1060 	  return ret;
1061 	}