Ejemplo n.º 1
0
static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
   /* we expect the form: filename */
   int ptyfd = -1, ttyfd = -1;
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
   bool useptmx = false;	/* use /dev/ptmx or equivalent */
#endif
#if HAVE_OPENPTY
   bool useopenpty = false;	/* try only openpty */
#endif	/* HAVE_OPENPTY */
   char ptyname[MAXPTYNAMELEN];
   char *tn = NULL;
   char *linkname = NULL;
   bool opt_unlink_close = true;	/* remove symlink afterwards */
   bool wait_slave = false;	/* true would be better for many platforms, but
				   some OSes cannot handle this, and for common
				   default behaviour as well as backward 
				   compatibility we choose "no" as default */
   struct timespec pollintv = { PTY_INTERVALL };

   if (argc != 1) {
      Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
   }

   xfd->stream.howtoend = END_CLOSE;

   if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0)  return -1;
   applyopts(-1, opts, PH_INIT);

   retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);

   /* trying to set user-early, perm-early etc. here might be useless because
      file system entry is eventually available only past pty creation */
   /* name not yet known; umask should not be handled with this function! */
   /* umask does not affect resulting mode, on Linux 2.4 */
   applyopts_named("", opts, PH_EARLY);	/* umask! */

#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
   retropt_bool(opts, OPT_PTMX, &useptmx);
#endif
#if HAVE_OPENPTY
   retropt_bool(opts, OPT_OPENPTY, &useopenpty);
#endif

#if (defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC))
#  if  HAVE_OPENPTY
   useopenpty = !useptmx;
#  else /* !HAVE_OPENPTY */
   useptmx = true;
#  endif /* !HAVE_OPENPTY */
#else
# if HAVE_OPENPTY
   useopenpty = true;
# endif /* HAVE_OPENPTY */
#endif /* ! (defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)) */

#if HAVE_POLL
   retropt_bool(opts, OPT_PTY_WAIT_SLAVE, &wait_slave);
   retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv);
#endif /* HAVE_POLL */

   if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0)  return -1;
   applyopts2(-1, opts, PH_INIT, PH_EARLY);

   applyopts(-1, opts, PH_PREBIGEN);

#if defined(HAVE_DEV_PTMX)
#  define PTMX "/dev/ptmx"	/* Linux */
#elif HAVE_DEV_PTC
#  define PTMX "/dev/ptc"	/* AIX 4.3.3 */
#endif
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
   if (useptmx) {
      if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
	 Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
	       strerror(errno));
	 /*!*/
      } else {
	 ;/*0 Info1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620) -> %d", ptyfd);*/
      }
      if (ptyfd >= 0 && ttyfd < 0) {
	 /* we used PTMX before forking */
	 /*0 extern char *ptsname(int);*/
#if HAVE_GRANTPT	/* AIX, not Linux */
	 if (Grantpt(ptyfd)/*!*/ < 0) {
	    Warn2("grantpt(%d): %s", ptyfd, strerror(errno));
	 }
#endif /* HAVE_GRANTPT */
#if HAVE_UNLOCKPT
	 if (Unlockpt(ptyfd)/*!*/ < 0) {
	    Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
	 }
#endif /* HAVE_UNLOCKPT */
#if HAVE_PROTOTYPE_LIB_ptsname	/* AIX, not Linux */
	 if ((tn = Ptsname(ptyfd)) == NULL) {
	    Warn2("ptsname(%d): %s", ptyfd, strerror(errno));
	 } else {
	    Notice1("PTY is %s", tn);
	 }
#endif /* HAVE_PROTOTYPE_LIB_ptsname */
	 if (tn == NULL) {
	    if ((tn = Ttyname(ptyfd)) == NULL) {
	       Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
	    }
	 }
	 ptyname[0] = '\0'; strncat(ptyname, tn, MAXPTYNAMELEN-1);
      }
   }
#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
#if HAVE_OPENPTY
   if (ptyfd < 0) {
      int result;
      if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
	 Error4("openpty(%p, %p, %p, NULL, NULL): %s",
		&ptyfd, &ttyfd, ptyname, strerror(errno));
	 return -1;
      }
      Notice1("PTY is %s", ptyname);
   }
#endif /* HAVE_OPENPTY */

   if (!retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname)) {
      if (Unlink(linkname) < 0 && errno != ENOENT) {
	 Error2("unlink(\"%s\"): %s", linkname, strerror(errno));
      }
      if (Symlink(ptyname, linkname) < 0) {
	 Error3("symlink(\"%s\", \"%s\"): %s",
		ptyname, linkname, strerror(errno));
      }
      if (opt_unlink_close) {
	 if ((xfd->stream.unlink_close = strdup(linkname)) == NULL) {
	    Error1("strdup(\"%s\"): out of memory", linkname);
	 }
	 xfd->stream.opt_unlink_close = true;
      }
   }

   applyopts_named(ptyname, opts, PH_PASTOPEN);
   applyopts_named(ptyname, opts, PH_FD);

   applyopts_cloexec(ptyfd, opts);/*!*/
   xfd->stream.dtype    = XIODATA_PTY;

   applyopts(ptyfd, opts, PH_FD);

   {
      /* special handling of user-late etc.; with standard behaviour (up to
	 1.7.1.1) they affected /dev/ptmx instead of /dev/pts/N */
      uid_t uid = -1, gid = -1;
      mode_t perm;

      bool dont;
      dont = retropt_uid(opts, OPT_USER_LATE, &uid);
      dont &= retropt_gid(opts, OPT_GROUP_LATE, &gid);

      if (!dont) {
	 if (Chown(ptyname, uid, gid) < 0) {
	    Error4("chown(\"%s\", %d, %d): %s",
		   ptyname, uid, gid, strerror(errno));
	 }
      }

      if (retropt_mode(opts, OPT_PERM_LATE, &perm) == 0) {
	 if (Chmod(ptyname, perm) < 0) {
	    Error3("chmod(\"%s\", %03o): %s",
		   ptyname, perm, strerror(errno));
	 }
      }

   }

   xfd->stream.fd = ptyfd;
   applyopts(ptyfd, opts, PH_LATE);
   if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0)  return -1;

#if HAVE_POLL
   /* if you can and wish: */
   if (wait_slave) {
      /* try to wait until someone opens the slave side of the pty */
      /* we want to get a HUP (hangup) condition on the pty */
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
      if (useptmx) {
	 ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620);
	 Close(ttyfd);
      }
#endif
#if HAVE_OPENPTY
      if (useopenpty) {
	 Close(ttyfd);
      }
#endif /* HAVE_OPENPTY */

      /* now we poll until the HUP vanishes - this indicates a slave conn. */
      while (true) {
	 struct pollfd ufd;
	 ufd.fd = ptyfd;
	 ufd.events = (POLLHUP);
	 if (Poll(&ufd, 1, 0) < 0) {
	    Error3("poll({%d, 0x%04hu,}, 1, 0): %s",
		   ufd.fd, ufd.events, strerror(errno));
	    /*! close something */
	    return -1;
	 }
	 if (!(ufd.revents & POLLHUP)) {
	    break;
	 }
	 Nanosleep(&pollintv, NULL);
	 continue;
      }
   }
#endif /* HAVE_POLL */

   return STAT_OK;
}
Ejemplo n.º 2
0
int procan(FILE *outfile) {

   /*filan(0, outfile);*/

   /* controlling terminal */
   fprintf(outfile, "process id = "F_pid"\n", Getpid());
   fprintf(outfile, "process parent id = "F_pid"\n", Getppid());
   {
      int fd;
      if ((fd = Open("/dev/tty", O_NOCTTY, 0)) < 0) {
	 fprintf(outfile, "controlling terminal: -\n");
      } else {
#if 1
	 fprintf(outfile, "controlling terminal: \"%s\"\n", Ttyname(fd));
#else
	 char procpath[PATH_MAX], devpath[PATH_MAX+1];
	 int devlen;
	 sprintf(procpath, "/proc/"F_pid"/fd/%d", Getpid(), 0 /*! fd*/);
	 if ((devlen = Readlink(procpath, devpath, sizeof(devpath))) < 0) {
	    ;
	 } else {
	    devpath[devlen] = '\0';
	    fprintf(outfile, "controlling terminal: \"%s\"\n", devpath);
	 }
#endif
      }
   }
   fprintf(outfile, "process group id = "F_pid"\n", Getpgrp());
#if HAVE_GETSID
   fprintf(outfile, "process session id = "F_pid"\n", Getsid(0));
#endif
   fprintf(outfile, "process group id if fg process / stdin = "F_pid"\n", Tcgetpgrp(0));
   fprintf(outfile, "process group id if fg process / stdout = "F_pid"\n", Tcgetpgrp(1));
   fprintf(outfile, "process group id if fg process / stderr = "F_pid"\n", Tcgetpgrp(2));
   {
      int fd;
      if ((fd = Open("/dev/tty", O_RDWR, 0600)) >= 0) {
	 fprintf(outfile, "process has a controlling terminal\n");
	 Close(fd);
      } else {
	 fprintf(outfile, "process does not have a controlling terminal\n");
      }
   }

   /* process owner, groups */
   fprintf(outfile, "user id  = "F_uid"\n", Getuid());
   fprintf(outfile, "effective user id  = "F_uid"\n", Geteuid());
   fprintf(outfile, "group id = "F_gid"\n", Getgid());
   fprintf(outfile, "effective group id = "F_gid"\n", Getegid());

   {
      struct rlimit rlim;

      fprintf(outfile, "\nRESOURCE LIMITS\n");
      fprintf(outfile, "resource                         current         maximum\n");
      if (getrlimit(RLIMIT_CPU, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_CPU, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "cpu time (seconds)      %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
      if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_FSIZE, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "file size (blocks)      %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
      if (getrlimit(RLIMIT_DATA, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_DATA, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "data seg size (kbytes)  %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
      if (getrlimit(RLIMIT_STACK, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_STACK, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "stack size (blocks)     %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
      if (getrlimit(RLIMIT_CORE, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_CORE, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "core file size (blocks) %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
#ifdef RLIMIT_RSS	/* Linux, AIX; not Cygwin */
      if (getrlimit(RLIMIT_RSS, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_RSS, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "max resident set size   %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
#endif
#ifdef RLIMIT_NPROC	/* Linux, not AIX, Cygwin */
      if (getrlimit(RLIMIT_NPROC, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_NPROC, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "max user processes      %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
#endif
#ifdef RLIMIT_NOFILE	/* not AIX 4.1 */
      if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_NOFILE, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "open files              %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
#endif
#ifdef RLIMIT_MEMLOCK	/* Linux, not AIX, Cygwin */
      if (getrlimit(RLIMIT_MEMLOCK, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_MEMLOCK, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "max locked-in-memory address space %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
#endif
#ifdef RLIMIT_AS
      if (getrlimit(RLIMIT_AS, &rlim) < 0) {
	 Warn2("getrlimit(RLIMIT_AS, %p): %s", &rlim, strerror(errno));
      } else {
	 fprintf(outfile,
		 "virtual memory (kbytes) %16"F_rlim_max"%16"F_rlim_max"\n",
		 rlim.rlim_cur, rlim.rlim_max);
      }
#endif
   }

   /* file descriptors */

   /* what was this for?? */
   /*Sleep(1);*/
   return 0;
}