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  	  {
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  	      {
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  	
270  	    sprintf ( newpath, "/proc/%d%s", currentPid, &path [ index ] );
271  	  }
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);
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.
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 	}