Example #1
0
int main (int argc, char * argv[])
{
	/*Set up some Variables*/
	int parent_PCB_id = argc;
	int fid;
	caddr_t mmap_ptr;
	inputbuf *in_mem_p;
	char c[MAX_CHAR];

	// If parent tells us to terminate, then clean up first
	sigset(SIGINT,in_die);
	
	//Gets id of parents (to signal) and the file id of mmap.
	sscanf(argv[1], "%d", &parent_PCB_id);
	sscanf(argv[2], "%d", &kfid );

	kmmap_ptr =     
		mmap((caddr_t) 0,
		bufsize,
		PROT_READ | PROT_WRITE,
		MAP_SHARED,
		kfid,
		(off_t) 0);
  
	if (kmmap_ptr == MAP_FAILED){
		printf("Child memory map has failed, KB is aborting! Error <%s> ...\n", strerror(errno));
		in_die(0);
	}
	in_mem_p = (inputbuf *) kmmap_ptr;
	buf_index = 0;
	in_mem_p->flag = MEM_EMPTY; // Set the flag to “Buffer Empty”

	do { 
		fgets(c, MAX_CHAR, stdin);  // This only returns when <cr> is pressed
		strcpy(in_mem_p->data, c); // Read in data from buffer
		in_mem_p->flag = MEM_FULL;  // Set the flag
		kill(parent_PCB_id ,SIGUSR1);  // Signal the parent
		buf_index = 0;
		while(in_mem_p->flag == MEM_FULL){
			usleep(100000); // Sleep until the RTX has read the data
		}
	} while(1); // Loops Forever
}
Example #2
0
int main()
{
	struct sigaction act;
	act.sa_flags = 0;
	act.sa_handler = myhandler;
	sigemptyset(&act.sa_mask);

	if (sigaction(SIGUSR1, &act, 0) != 0) {
                perror("Unexpected error while using sigaction()");
               	return PTS_UNRESOLVED;
        }

        if (sigset(SIGUSR1,SIG_DFL) != myhandler) {
		printf("Test FAILED: sigset didn't return myhandler even though it was SIGUSR1's original disposition\n");
               	return PTS_FAIL;
        }

	return PTS_PASS;
} 
Example #3
0
/*
 * _tt_sigset sets up a signal handler in such a way that the handler
 * is *not* unregistered when the signal handler is entered.  If
 * returns 0 if an error occurs, else 1, and leaves errno set according
 * to the underlying system call (sigaction, signal, sigset.)
 */
int
_tt_sigset(
	int	sig,
	SIG_PF	handler )
{
#if defined(OPT_POSIX_SIGNAL)
/* 
 * There seems to be some controversy over the type of sa_handler in
 * C++ programs.  Everybody\'s man page seems to say it is of type
 * "void (*)()", and that\'s what Solaris does, and I think that\'s what
 * POSIX says, but both HP and IBM define it as the arguably much more
 * useful "void (*)(int)", a/k/a SIG_PF.
 * 
 * [4 Apr 95] Solaris 2.5 has switched to use void (*)(int), which
 * is nice for the long run but causes us some short-run problems
 * as we want this level of the source to compile both on
 * Solaris 2.4 and Solaris 2.5 for a while. To solve this, we use
 * the "sa_sigaction" element of the sigaction structure, which is the
 * three-argument flavor of the function pointer.  This is, strictly, 
 * a lie, but it's safe since our signal handlers never look at the
 * arguments anyway.  sa_sigaction is, fortunately, the same on all
 * Solaris versions.
 * Once the requirement to compile on Solaris 2.4 goes away, we can
 * simply remove the OPT_BUG_SUNOS_5 ifdefs here, leaving only the
 * UnixWare one.
 */
        struct sigaction act;
#if defined(OPT_BUG_SUNOS_5)	
	act.sa_sigaction = (void (*)(int, siginfo_t *, void *)) handler;
#elif defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
	act.sa_handler = (void (*)()) handler;
#else
        act.sa_handler = handler;
#endif	
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	return 0==sigaction(sig, &act, NULL);
#elif defined(OPT_BSD_SIGNAL)
	return SIG_ERR!=signal(sig, handler);
#else
	return SIG_ERR!=sigset(sig, handler);
#endif
}
Example #4
0
int
main(int argc, char * argv[])
{
    if(argc!=2)
    {
        printf("usage: sleep <sleep in seconds>\n");
        printf("used to test sleep() and sending a alarm signal -14 affects process\n");
        printf("the signal will wakeup a process doing sleep and should return");
        printf(" number of seconds left to sleep\n");

        exit(0);
    }

    // set the alaram signal
    //
    sigset(SIGALRM, SIG_IGN);

    unsigned int sleepTime = atoi(argv[1]);

    unsigned int timeSlept;

    time_t currTime = time(NULL);
    struct tm currStruct;
    localtime_r(&currTime, &currStruct);
    printf("current time: %s\n", asctime(&currStruct));

    timeSlept = sleepTime;
    while ((timeSlept = sleep(timeSlept)) != 0)
    {
        // woke up early
        //
        printf("woke up early need to sleep: %u more\n", timeSlept);
        currTime = time(NULL);
        localtime_r(&currTime, &currStruct);
        printf("current time: %s\n", asctime(&currStruct));
    }

    currTime = time(NULL);
    localtime_r(&currTime, &currStruct);
    printf("end time: %s\n", asctime(&currStruct));

    return 0;
}
Example #5
0
void pipeback_shell_close (FILE *file)
{
#ifndef NOCLDWAIT
    int wait_status = 0;
#endif
    int cresult = fclose (file);
    if (cresult) fprintf (stderr, "Warning.  Error closing pipeback file.\n");
    if (0 == --Usage)
    {
	if (SIG_ERR == sigset (SIGCHLD, SIG_DFL))
	{
	    fprintf (stderr, 
		 "Warning.  Error resetting SIGCHLD action after pipeback.\n");
	}
#ifndef NOCLDWAIT
    wait (&wait_status);
#endif
    }
}
Example #6
0
static void setup(void)
{
	char wdbuf[MAXPATHLEN];

	/*
	 * Make a directory to do this in; ignore error if already exists.
	 * Save starting directory.
	 */
	tst_tmpdir();

	if (getcwd(homedir, sizeof(homedir)) == NULL) {
		tst_brkm(TBROK | TERRNO, NULL, "getcwd() failed");
	}

	parent_pid = getpid();

	if (!fuss[0])
		sprintf(fuss, "%s/ftest03.%d", getcwd(wdbuf, sizeof(wdbuf)),
			getpid());

	mkdir(fuss, 0755);

	if (chdir(fuss) < 0) {
		tst_resm(TBROK, "\tCan't chdir(%s), error %d.", fuss, errno);
		tst_exit();
	}

	/*
	 * Default values for run conditions.
	 */
	iterations = 10;
	nchild = 5;
	csize = K_2;		/* should run with 1, 2, and 4 K sizes */
	max_size = K_1 * K_1;
	misc_intvl = 10;

	if (sigset(SIGTERM, term) == SIG_ERR) {
		perror("sigset failed");
		tst_resm(TBROK, " sigset failed: signo = 15");
		tst_exit();
	}
}
Example #7
0
File: sspsh2.c Project: DontL/ssp
int main(void)
{
    char buf[LINE_LEN];
    pid_t pid;
    int status;

 if(sigset(SIGINT, sigint)== SIG_ERR) 
   perror("sigint"); 

    printf("->:");
    
    for(;;)
    {
        while(fgets(buf,LINE_LEN,stdin)!=NULL)
        {
            if(*buf != '\0')
                buf[strlen(buf)-1]='\0';
            printf("->:");
            continue;
        }
        
    switch (pid = fork()){
        case -1:
            perror("fork failed");
            break;
        case 0:
            execlp(buf,buf,NULL);
            perror("cannot execlp");
            break;
        default :
            if(waitpid(pid,&status,0)==-1)
                perror("waitpid");
                break;
    }
    printf("->:");
    
    if(errno != EINTR)
        break;
    errno = 0;
    }
    return (0);
}
Example #8
0
void
doinput()
{
	char ibuf[BUFSIZ];
	int cc;

	(void) fclose(fscript);
	sigset(SIGWINCH, sigwinch);

	while ((cc = read(0, ibuf, BUFSIZ)) != 0) {
		if (cc == -1) {
			if (errno == EINTR) {   /* SIGWINCH probably */
				continue;
			} else {
				break;
			}
		}
		(void) write(master, ibuf, cc);
	}
	done();
}
Example #9
0
int main()
{
	sigset_t mask;
	sigemptyset(&mask);

	sigprocmask(SIG_SETMASK, &mask, NULL);

	if (sigset(SIGCHLD, myhandler) == SIG_ERR) {
                perror("Unexpected error while using sigset()");
               	return PTS_UNRESOLVED;
        }

	raise(SIGCHLD);
	sigprocmask(SIG_SETMASK, NULL, &mask);

	if (is_empty(&mask) != 1) {
		printf("Test FAILED: signal mask should be empty\n");
		return PTS_FAIL;
	}
	return PTS_PASS;
} 
static int
returnTest2 (void)
{
  sighandler_t prev;

  printf ("\n===== TEST 2 =====\n");

  printf ("About to use sigset() to set SIG_HOLD\n");
  prev = sigset (TEST_SIG, SIG_HOLD);
  if (prev == SIG_ERR)
    error (1, errno, "sigset");

  printf ("Previous disposition: ");
  printDisposition (prev);
  printf (" (should be SIG_DFL)\n");
  if (prev != SIG_DFL)
    {
      printf("TEST FAILED!!!\n");
      return 1;
    }
  return 0;
} /* returnTest2 */
Example #11
0
static void
ktrsigaction(const struct sigaction *sa)
{
	/*
	 * note: ktrstruct() has already verified that sa points to a
	 * buffer exactly sizeof(struct sigaction) bytes long.
	 */
	printf("struct sigaction { ");
	if (sa->sa_handler == SIG_DFL)
		printf("handler=SIG_DFL");
	else if (sa->sa_handler == SIG_IGN)
		printf("handler=SIG_IGN");
	else if (sa->sa_flags & SA_SIGINFO)
		printf("sigaction=%p", (void *)sa->sa_sigaction);
	else
		printf("handler=%p", (void *)sa->sa_handler);
	printf(", mask=");
	sigset(sa->sa_mask);
	printf(", flags=");
	sigactionflagname(sa->sa_flags);
	printf(" }\n");
}
Example #12
0
void BSP_Reset(void)
{
    pid_t pid = getpid();
    char cmdline_file[200];
    char cmdline[1024];
    int cfd, r;
    snprintf(cmdline_file, 200, CMDLINE_FILE, pid);
    cfd = open(cmdline_file, O_RDONLY);
    if (cfd < 0) {
        printf("Reboot failed: Cannot access %s: %s\n", cmdline_file, strerror(errno));
        exit(2);
    }
    r = read(cfd, cmdline, 1024);

    if (r < 0) {
        printf("Reboot failed: Cannot read cmdline from proc file\n");
        exit(2);
    }
    printf("############ Rebooting...\n\n\n");
    sigset(SIGALRM, SIG_IGN);
    execl(cmdline, cmdline, NULL);
}
Example #13
0
static void init(void)
{
	int fd;
	char wdbuf[MAXPATHLEN];

	parent_pid = getpid();
	tst_tmpdir();

	/*
	 * Make a filename for the test.
	 */
	if (!filename[0])
		sprintf(filename, "%s/ftest08.%d", getcwd(wdbuf, MAXPATHLEN),
			getpid());

	fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);

	if (fd < 0) {
		tst_resm(TBROK, "Error %d creating file %s", errno, filename);
		tst_exit();
	}

	close(fd);

	/*
	 * Default values for run conditions.
	 */
	iterations = 10;
	nchild = 5;
	csize = K_2;		/* should run with 1, 2, and 4 K sizes */
	max_size = K_1 * K_1;
	misc_intvl = 10;

	if (sigset(SIGTERM, term) == SIG_ERR) {
		tst_brkm(TBROK | TERRNO, NULL, "first sigset failed");
	}

}
Example #14
0
File: 6-1.c Project: kraj/ltp
int main(void)
{
	sigset_t pendingset;
	struct sigaction act;
	act.sa_handler = myhandler;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	int rc;

	rc = sigaction(SIGCHLD, &act, 0);
	if (rc) {
		ERR_MSG("sigaction()", rc);
		return PTS_UNRESOLVED;
	}

	if (sigset(SIGCHLD, SIG_HOLD) == SIG_ERR) {
		perror("Unexpected error while using sigset()");
		return PTS_UNRESOLVED;
	}

	raise(SIGCHLD);

	rc = sigpending(&pendingset);
	if (rc) {
		ERR_MSG("sigpending()", rc);
		return PTS_UNRESOLVED;
	}

	if (sigismember(&pendingset, SIGCHLD) != 1) {
		printf("Test FAILED: Signal SIGCHLD wasn't hold.\n");
		return PTS_FAIL;
	}

	printf("Test PASSED\n");
	return PTS_PASS;
}
Example #15
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments (6 or 7) */
     char *argv[])			/* I - Command-line arguments */
{
  const char	*device_uri;		/* Device URI */
  char		scheme[255],		/* Scheme in URI */
		hostname[1024],		/* Hostname */
		username[255],		/* Username info (not used) */
		resource[1024],		/* Resource info (not used) */
		*options,		/* Pointer to options */
		*name,			/* Name of option */
		*value,			/* Value of option */
		sep;			/* Option separator */
  int		print_fd;		/* Print file */
  int		copies;			/* Number of copies to print */
  time_t	start_time;		/* Time of first connect */
#ifdef __APPLE__
  time_t	current_time,		/* Current time */
		wait_time;		/* Time to wait before shutting down socket */
#endif /* __APPLE__ */
  int		contimeout;		/* Connection timeout */
  int		waiteof;		/* Wait for end-of-file? */
  int		port;			/* Port number */
  char		portname[255];		/* Port name */
  int		delay;			/* Delay for retries... */
  int		device_fd;		/* AppSocket */
  int		error;			/* Error code (if any) */
  http_addrlist_t *addrlist,		/* Address list */
		*addr;			/* Connected address */
  char		addrname[256];		/* Address name */
  int		snmp_fd,		/* SNMP socket */
		start_count,		/* Page count via SNMP at start */
		page_count,		/* Page count via SNMP */
		have_supplies;		/* Printer supports supply levels? */
  ssize_t	bytes = 0,		/* Initial bytes read */
		tbytes;			/* Total number of bytes written */
  char		buffer[1024];		/* Initial print buffer */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Make sure status messages are not buffered...
  */

  setbuf(stderr, NULL);

 /*
  * Ignore SIGPIPE signals...
  */

#ifdef HAVE_SIGSET
  sigset(SIGPIPE, SIG_IGN);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &action, NULL);
#else
  signal(SIGPIPE, SIG_IGN);
#endif /* HAVE_SIGSET */

 /*
  * Check command-line...
  */

  if (argc == 1)
  {
    printf("network socket \"Unknown\" \"%s\"\n",
           _cupsLangString(cupsLangDefault(), _("AppSocket/HP JetDirect")));
    return (CUPS_BACKEND_OK);
  }
  else if (argc < 6 || argc > 7)
  {
    _cupsLangPrintf(stderr,
                    _("Usage: %s job-id user title copies options [file]"),
                    argv[0]);
    return (CUPS_BACKEND_FAILED);
  }

 /*
  * If we have 7 arguments, print the file named on the command-line.
  * Otherwise, send stdin instead...
  */

  if (argc == 6)
  {
    print_fd = 0;
    copies   = 1;
  }
  else
  {
   /*
    * Try to open the print file...
    */

    if ((print_fd = open(argv[6], O_RDONLY)) < 0)
    {
      _cupsLangPrintError("ERROR", _("Unable to open print file"));
      return (CUPS_BACKEND_FAILED);
    }

    copies = atoi(argv[4]);
  }

 /*
  * Extract the hostname and port number from the URI...
  */

  while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
  {
    _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
    sleep(10);

    if (getenv("CLASS") != NULL)
      return (CUPS_BACKEND_FAILED);
  }

  httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
                  username, sizeof(username), hostname, sizeof(hostname), &port,
		  resource, sizeof(resource));

  if (port == 0)
    port = 9100;	/* Default to HP JetDirect/Tektronix PhaserShare */

 /*
  * Get options, if any...
  */

  waiteof    = 1;
  contimeout = 7 * 24 * 60 * 60;

  if ((options = strchr(resource, '?')) != NULL)
  {
   /*
    * Yup, terminate the device name string and move to the first
    * character of the options...
    */

    *options++ = '\0';

   /*
    * Parse options...
    */

    while (*options)
    {
     /*
      * Get the name...
      */

      name = options;

      while (*options && *options != '=' && *options != '+' && *options != '&')
        options ++;

      if ((sep = *options) != '\0')
        *options++ = '\0';

      if (sep == '=')
      {
       /*
        * Get the value...
	*/

        value = options;

	while (*options && *options != '+' && *options != '&')
	  options ++;

        if (*options)
	  *options++ = '\0';
      }
      else
        value = (char *)"";

     /*
      * Process the option...
      */

      if (!_cups_strcasecmp(name, "waiteof"))
      {
       /*
        * Set the wait-for-eof value...
	*/

        waiteof = !value[0] || !_cups_strcasecmp(value, "on") ||
		  !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
      }
      else if (!_cups_strcasecmp(name, "contimeout"))
      {
       /*
        * Set the connection timeout...
	*/

	if (atoi(value) > 0)
	  contimeout = atoi(value);
      }
    }
  }

 /*
  * Then try finding the remote host...
  */

  start_time = time(NULL);

  sprintf(portname, "%d", port);

  fputs("STATE: +connecting-to-device\n", stderr);
  fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);

  while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
  {
    _cupsLangPrintFilter(stderr, "INFO",
                         _("Unable to locate printer \"%s\"."), hostname);
    sleep(10);

    if (getenv("CLASS") != NULL)
    {
      fputs("STATE: -connecting-to-device\n", stderr);
      return (CUPS_BACKEND_STOP);
    }
  }

 /*
  * See if the printer supports SNMP...
  */

  if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0)
  {
    have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
                                         &start_count, NULL);
  }
  else
    have_supplies = start_count = 0;

 /*
  * Wait for data from the filter...
  */

  if (print_fd == 0)
  {
    if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 1, backendNetworkSideCB))
      return (CUPS_BACKEND_OK);
    else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0)
      return (CUPS_BACKEND_OK);
  }

 /*
  * Connect to the printer...
  */

  fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
  _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));

  for (delay = 5;;)
  {
    if ((addr = httpAddrConnect(addrlist, &device_fd)) == NULL)
    {
      error     = errno;
      device_fd = -1;

      if (getenv("CLASS") != NULL)
      {
       /*
        * If the CLASS environment variable is set, the job was submitted
	* to a class and not to a specific queue.  In this case, we want
	* to abort immediately so that the job can be requeued on the next
	* available printer in the class.
	*/

        _cupsLangPrintFilter(stderr, "INFO",
			     _("Unable to contact printer, queuing on next "
			       "printer in class."));

       /*
        * Sleep 5 seconds to keep the job from requeuing too rapidly...
	*/

	sleep(5);

        return (CUPS_BACKEND_FAILED);
      }

      fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));

      if (error == ECONNREFUSED || error == EHOSTDOWN ||
          error == EHOSTUNREACH)
      {
        if (contimeout && (time(NULL) - start_time) > contimeout)
	{
	  _cupsLangPrintFilter(stderr, "ERROR",
	                       _("The printer is not responding."));
	  return (CUPS_BACKEND_FAILED);
	}

	switch (error)
	{
	  case EHOSTDOWN :
	      _cupsLangPrintFilter(stderr, "WARNING",
				   _("The printer may not exist or "
				     "is unavailable at this time."));
	      break;

	  case EHOSTUNREACH :
	      _cupsLangPrintFilter(stderr, "WARNING",
				   _("The printer is unreachable at this "
				     "time."));
	      break;

	  case ECONNREFUSED :
	  default :
	      _cupsLangPrintFilter(stderr, "WARNING",
	                           _("The printer is in use."));
	      break;
        }

	sleep(delay);

	if (delay < 30)
	  delay += 5;
      }
      else
      {
	_cupsLangPrintFilter(stderr, "ERROR",
	                     _("The printer is not responding."));
	sleep(30);
      }
    }
    else
      break;
  }

  fputs("STATE: -connecting-to-device\n", stderr);
  _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));

  fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
	  httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
	  _httpAddrPort(&(addr->addr)));

 /*
  * Print everything...
  */

  tbytes = 0;

  if (bytes > 0)
    tbytes += write(device_fd, buffer, bytes);

  while (copies > 0 && tbytes >= 0)
  {
    copies --;

    if (print_fd != 0)
    {
      fputs("PAGE: 1 1\n", stderr);
      lseek(print_fd, 0, SEEK_SET);
    }

    tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1,
                            0, backendNetworkSideCB);

    if (print_fd != 0 && tbytes >= 0)
      _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
  }

#ifdef __APPLE__
 /*
  * Wait up to 5 seconds to get any pending back-channel data...
  */

  wait_time = time(NULL) + 5;
  while (wait_time >= time(&current_time))
    if (wait_bc(device_fd, wait_time - current_time) <= 0)
      break;
#endif /* __APPLE__ */

  if (waiteof)
  {
   /*
    * Shutdown the socket and wait for the other end to finish...
    */

    _cupsLangPrintFilter(stderr, "INFO", _("Waiting for printer to finish."));

    shutdown(device_fd, 1);

    while (wait_bc(device_fd, 90) > 0);
  }

 /*
  * Collect the final page count as needed...
  */

  if (have_supplies &&
      !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &page_count, NULL) &&
      page_count > start_count)
    fprintf(stderr, "PAGE: total %d\n", page_count - start_count);

 /*
  * Close the socket connection...
  */

  close(device_fd);

  httpAddrFreeList(addrlist);

 /*
  * Close the input file and return...
  */

  if (print_fd != 0)
    close(print_fd);

  return (CUPS_BACKEND_OK);
}
Example #16
0
int
main(int argc, char *argv[])
{
	int i, n;
	struct interface *ifp;
	int c;
	struct timeval waittime;
	int timeout;
	boolean_t daemon = _B_TRUE;	/* Fork off a detached daemon */
	FILE *pidfp;
	mode_t pidmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* 0644 */

	rip6_port = htons(IPPORT_ROUTESERVER6);
	allrouters.sin6_family = AF_INET6;
	allrouters.sin6_port = rip6_port;
	allrouters.sin6_addr = allrouters_in6;

	while ((c = getopt(argc, argv, "nsqvTtdgPp:")) != EOF) {
		switch (c) {
		case 'n':
			install = _B_FALSE;
			break;
		case 's':
			supplier = _B_TRUE;
			break;
		case 'q':
			supplier = _B_FALSE;
			break;
		case 'v':
			tracing |= ACTION_BIT;
			break;
		case 'T':
			daemon = _B_FALSE;
			break;
		case 't':
			tracepackets = _B_TRUE;
			daemon = _B_FALSE;
			tracing |= (INPUT_BIT | OUTPUT_BIT);
			break;
		case 'd':
			break;
		case 'P':
			dopoison = _B_FALSE;
			break;
		case 'p':
			rip6_port = htons(atoi(optarg));
			allrouters.sin6_port = rip6_port;
			break;
		default:
			usage(argv[0]);
			/* NOTREACHED */
		}
	}

	/*
	 * Any extra argument is considered
	 * a tracing log file.
	 */
	if (optind < argc) {
		traceon(argv[optind]);
	} else if (tracing && !daemon) {
		traceonfp(stdout);
	} else if (tracing) {
		(void) fprintf(stderr, "Need logfile with -v\n");
		usage(argv[0]);
		/* NOTREACHED */
	}

	if (daemon) {
		int t;

		if (fork())
			exit(EXIT_SUCCESS);
		for (t = 0; t < 20; t++) {
			if (!tracing || (t != fileno(ftrace)))
				(void) close(t);
		}
		(void) open("/", 0);
		(void) dup2(0, 1);
		(void) dup2(0, 2);
		(void) setsid();
	}

	/* Store our process id, blow away any existing file if it exists. */
	if ((pidfp = fopen(PATH_PID, "w")) == NULL) {
		(void) fprintf(stderr, "%s: unable to open " PATH_PID ": %s\n",
		    argv[0], strerror(errno));
	} else {
		(void) fprintf(pidfp, "%ld\n", getpid());
		(void) fclose(pidfp);
		(void) chmod(PATH_PID, pidmode);
	}


	iocsoc = socket(AF_INET6, SOCK_DGRAM, 0);
	if (iocsoc < 0) {
		syslog(LOG_ERR, "main: socket: %m");
		exit(EXIT_FAILURE);
	}

	setup_rtsock();

	/*
	 * Allocate the buffer to hold the RIPng packet.  In reality, it will be
	 * smaller than IPV6_MAX_PACKET octets due to (at least) the IPv6 and
	 * UDP headers but IPV6_MAX_PACKET is a convenient size.
	 */
	packet = (char *)malloc(IPV6_MAX_PACKET);
	if (packet == NULL) {
		syslog(LOG_ERR, "main: malloc: %m");
		exit(EXIT_FAILURE);
	}
	msg = (struct rip6 *)packet;

	/*
	 * Allocate the buffer to hold the ancillary data.  This data is used to
	 * insure that the incoming hop count of a RIPCMD6_RESPONSE message is
	 * IPV6_MAX_HOPS which indicates that it came from a direct neighbor
	 * (namely, no intervening router decremented it).
	 */
	control = (char *)malloc(IPV6_MAX_PACKET);
	if (control == NULL) {
		syslog(LOG_ERR, "main: malloc: %m");
		exit(EXIT_FAILURE);
	}

	openlog("in.ripngd", LOG_PID | LOG_CONS, LOG_DAEMON);

	(void) gettimeofday(&now, (struct timezone *)NULL);

	initifs();
	solicitall(&allrouters);

	if (supplier)
		supplyall(&allrouters, 0, (struct interface *)NULL, _B_TRUE);

	(void) sigset(SIGALRM, (void (*)(int))timer);
	(void) sigset(SIGHUP, (void (*)(int))initifs);
	(void) sigset(SIGTERM, (void (*)(int))term);
	(void) sigset(SIGUSR1, (void (*)(int))if_dump);
	(void) sigset(SIGUSR2, (void (*)(int))rtdump);

	/*
	 * Seed the pseudo-random number generator for GET_RANDOM().
	 */
	srandom((uint_t)gethostid());

	timer();

	for (;;) {
		if (needupdate) {
			waittime = nextmcast;
			timevalsub(&waittime, &now);
			if (waittime.tv_sec < 0) {
				timeout = 0;
			} else {
				timeout = TIME_TO_MSECS(waittime);
			}
			if (tracing & ACTION_BIT) {
				(void) fprintf(ftrace,
				    "poll until dynamic update in %d msec\n",
				    timeout);
				(void) fflush(ftrace);
			}
		} else {
			timeout = INFTIM;
		}

		if ((n = poll(poll_ifs, poll_ifs_num, timeout)) < 0) {
			if (errno == EINTR)
				continue;
			syslog(LOG_ERR, "main: poll: %m");
			exit(EXIT_FAILURE);
		}
		(void) sighold(SIGALRM);
		(void) sighold(SIGHUP);
		/*
		 * Poll timed out.
		 */
		if (n == 0) {
			if (needupdate) {
				TRACE_ACTION("send delayed dynamic update",
				    (struct rt_entry *)NULL);
				(void) gettimeofday(&now,
				    (struct timezone *)NULL);
				supplyall(&allrouters, RTS_CHANGED,
				    (struct interface *)NULL, _B_TRUE);
				lastmcast = now;
				needupdate = _B_FALSE;
				nextmcast.tv_sec = 0;
			}
			(void) sigrelse(SIGHUP);
			(void) sigrelse(SIGALRM);
			continue;
		}
		(void) gettimeofday(&now, (struct timezone *)NULL);
		for (i = 0; i < poll_ifs_num; i++) {
			/*
			 * This case should never happen.
			 */
			if (poll_ifs[i].revents & POLLERR) {
				syslog(LOG_ERR,
				    "main: poll returned a POLLERR event");
				continue;
			}
			if (poll_ifs[i].revents & POLLIN) {
				for (ifp = ifnet; ifp != NULL;
				    ifp = ifp->int_next) {
					if (poll_ifs[i].fd == ifp->int_sock)
						in_data(ifp);
				}
			}
		}
		(void) sigrelse(SIGHUP);
		(void) sigrelse(SIGALRM);
	}

	return (0);
}
Example #17
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int			i;		/* Looping var */
  char			*opt;		/* Option character */
  int			fg;		/* Run in the foreground */
  int			fds;		/* Number of ready descriptors */
  cupsd_client_t	*con;		/* Current client */
  cupsd_job_t		*job;		/* Current job */
  cupsd_listener_t	*lis;		/* Current listener */
  time_t		current_time,	/* Current time */
			activity,	/* Client activity timer */
			senddoc_time,	/* Send-Document time */
			expire_time,	/* Subscription expire time */
			report_time,	/* Malloc/client/job report time */
			event_time;	/* Last event notification time */
  long			timeout;	/* Timeout for cupsdDoSelect() */
  struct rlimit		limit;		/* Runtime limit */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction	action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
#ifdef __sgi
  cups_file_t		*fp;		/* Fake lpsched lock file */
  struct stat		statbuf;	/* Needed for checking lpsched FIFO */
#endif /* __sgi */
  int			run_as_child = 0;
					/* Needed for background fork/exec */
#ifdef __APPLE__
  int			use_sysman = !getuid();
					/* Use system management functions? */
#else
  time_t		netif_time = 0;	/* Time since last network update */
#endif /* __APPLE__ */
#if HAVE_LAUNCHD
  int			launchd_idle_exit;
					/* Idle exit on select timeout? */
#endif	/* HAVE_LAUNCHD */


#ifdef HAVE_GETEUID
 /*
  * Check for setuid invocation, which we do not support!
  */

  if (getuid() != geteuid())
  {
    fputs("cupsd: Cannot run as a setuid program\n", stderr);
    return (1);
  }
#endif /* HAVE_GETEUID */

 /*
  * Check for command-line arguments...
  */

  fg = 0;

#ifdef HAVE_LAUNCHD
  if (getenv("CUPSD_LAUNCHD"))
  {
    Launchd = 1;
    fg      = 1;
  }
#endif /* HAVE_LAUNCHD */

  for (i = 1; i < argc; i ++)
    if (argv[i][0] == '-')
      for (opt = argv[i] + 1; *opt != '\0'; opt ++)
        switch (*opt)
	{
	  case 'C' : /* Run as child with config file */
              run_as_child = 1;
	      fg           = -1;

	  case 'c' : /* Configuration file */
	      i ++;
	      if (i >= argc)
	      {
	        _cupsLangPuts(stderr, _("cupsd: Expected config filename "
		                        "after \"-c\" option."));
	        usage(1);
	      }

              if (argv[i][0] == '/')
	      {
	       /*
	        * Absolute directory...
		*/

		cupsdSetString(&ConfigurationFile, argv[i]);
              }
	      else
	      {
	       /*
	        * Relative directory...
		*/

                char *current;		/* Current directory */


	       /*
	        * Allocate a buffer for the current working directory to
		* reduce run-time stack usage; this approximates the
		* behavior of some implementations of getcwd() when they
		* are passed a NULL pointer.
	        */

                if ((current = malloc(1024)) == NULL)
		{
		  _cupsLangPuts(stderr,
		                _("cupsd: Unable to get current directory."));
                  return (1);
		}

		if (!getcwd(current, 1024))
		{
		  _cupsLangPuts(stderr,
		                _("cupsd: Unable to get current directory."));
                  free(current);
		  return (1);
		}

		cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]);
		free(current);
              }
	      break;

          case 'f' : /* Run in foreground... */
	      fg = 1;
	      break;

          case 'F' : /* Run in foreground, but disconnect from terminal... */
	      fg = -1;
	      break;

          case 'h' : /* Show usage/help */
	      usage(0);
	      break;

          case 'l' : /* Started by launchd... */
#ifdef HAVE_LAUNCHD
	      Launchd = 1;
	      fg      = 1;
#else
	      _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled "
	                              "in, running in normal mode."));
              fg = 0;
#endif /* HAVE_LAUNCHD */
	      break;

          case 'p' : /* Stop immediately for profiling */
              fputs("cupsd: -p (startup profiling) is for internal testing "
                    "use only!\n", stderr);
	      stop_scheduler = 1;
	      fg             = 1;
	      break;

          case 'P' : /* Disable security profiles */
              fputs("cupsd: -P (disable security profiles) is for internal "
                    "testing use only!\n", stderr);
	      UseProfiles = 0;
	      break;

#ifdef __APPLE__
          case 'S' : /* Disable system management functions */
              fputs("cupsd: -S (disable system management) for internal "
                    "testing use only!\n", stderr);
	      use_sysman = 0;
	      break;
#endif /* __APPLE__ */

          case 't' : /* Test the cupsd.conf file... */
	      TestConfigFile = 1;
	      fg             = 1;
	      break;

	  default : /* Unknown option */
              _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - "
	                                "aborting."), *opt);
	      usage(1);
	      break;
	}
    else
    {
      _cupsLangPrintf(stderr, _("cupsd: Unknown argument \"%s\" - aborting."),
                      argv[i]);
      usage(1);
    }

  if (!ConfigurationFile)
    cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");

 /*
  * If the user hasn't specified "-f", run in the background...
  */

  if (!fg)
  {
   /*
    * Setup signal handlers for the parent...
    */

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
    sigset(SIGUSR1, parent_handler);
    sigset(SIGCHLD, parent_handler);

    sigset(SIGHUP, SIG_IGN);
#elif defined(HAVE_SIGACTION)
    memset(&action, 0, sizeof(action));
    sigemptyset(&action.sa_mask);
    sigaddset(&action.sa_mask, SIGUSR1);
    action.sa_handler = parent_handler;
    sigaction(SIGUSR1, &action, NULL);
    sigaction(SIGCHLD, &action, NULL);

    sigemptyset(&action.sa_mask);
    action.sa_handler = SIG_IGN;
    sigaction(SIGHUP, &action, NULL);
#else
    signal(SIGUSR1, parent_handler);
    signal(SIGCLD, parent_handler);

    signal(SIGHUP, SIG_IGN);
#endif /* HAVE_SIGSET */

    if (fork() > 0)
    {
     /*
      * OK, wait for the child to startup and send us SIGUSR1 or to crash
      * and the OS send us SIGCHLD...  We also need to ignore SIGHUP which
      * might be sent by the init script to restart the scheduler...
      */

      for (; parent_signal == 0;)
        sleep(1);

      if (parent_signal == SIGUSR1)
        return (0);

      if (wait(&i) < 0)
      {
        perror("cupsd");
	return (1);
      }
      else if (WIFEXITED(i))
      {
        fprintf(stderr, "cupsd: Child exited with status %d\n",
	        WEXITSTATUS(i));
	return (2);
      }
      else
      {
        fprintf(stderr, "cupsd: Child exited on signal %d\n", WTERMSIG(i));
	return (3);
      }
    }

#ifdef __OpenBSD__
   /*
    * Call _thread_sys_closefrom() so the child process doesn't reset the
    * parent's file descriptors to be blocking.  This is a workaround for a
    * limitation of userland libpthread on OpenBSD.
    */

    _thread_sys_closefrom(0);
#endif /* __OpenBSD__ */

   /*
    * Since CoreFoundation and DBUS both create fork-unsafe data on execution of
    * a program, and since this kind of really unfriendly behavior seems to be
    * more common these days in system libraries, we need to re-execute the
    * background cupsd with the "-C" option to avoid problems.  Unfortunately,
    * we also have to assume that argv[0] contains the name of the cupsd
    * executable - there is no portable way to get the real pathname...
    */

    execlp(argv[0], argv[0], "-C", ConfigurationFile, (char *)0);
    exit(errno);
  }

  if (fg < 1)
  {
   /*
    * Make sure we aren't tying up any filesystems...
    */

    chdir("/");

#ifndef DEBUG
   /*
    * Disable core dumps...
    */

    getrlimit(RLIMIT_CORE, &limit);
    limit.rlim_cur = 0;
    setrlimit(RLIMIT_CORE, &limit);

   /*
    * Disconnect from the controlling terminal...
    */

    setsid();

   /*
    * Close all open files...
    */

    getrlimit(RLIMIT_NOFILE, &limit);

    for (i = 0; i < limit.rlim_cur && i < 1024; i ++)
      close(i);

   /*
    * Redirect stdin/out/err to /dev/null...
    */

    if ((i = open("/dev/null", O_RDONLY)) != 0)
    {
      dup2(i, 0);
      close(i);
    }

    if ((i = open("/dev/null", O_WRONLY)) != 1)
    {
      dup2(i, 1);
      close(i);
    }

    if ((i = open("/dev/null", O_WRONLY)) != 2)
    {
      dup2(i, 2);
      close(i);
    }
#endif /* DEBUG */
  }

 /*
  * Set the timezone info...
  */

  tzset();

#ifdef LC_TIME
  setlocale(LC_TIME, "");
#endif /* LC_TIME */

 /*
  * Set the maximum number of files...
  */

  getrlimit(RLIMIT_NOFILE, &limit);

#if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE)
  if (limit.rlim_max > FD_SETSIZE)
    MaxFDs = FD_SETSIZE;
  else
#endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */
#ifdef RLIM_INFINITY
  if (limit.rlim_max == RLIM_INFINITY)
    MaxFDs = 16384;
  else
#endif /* RLIM_INFINITY */
    MaxFDs = limit.rlim_max;

  limit.rlim_cur = MaxFDs;

  setrlimit(RLIMIT_NOFILE, &limit);

  cupsdStartSelect();

 /*
  * Read configuration...
  */

  if (!cupsdReadConfiguration())
  {
    if (TestConfigFile)
      printf("%s contains errors\n", ConfigurationFile);
    else
      syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
	     ConfigurationFile);
    return (1);
  }
  else if (TestConfigFile)
  {
    printf("%s is OK\n", ConfigurationFile);
    return (0);
  }

 /*
  * Clean out old temp files and printer cache data.
  */

  if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)))
    cupsdCleanFiles(TempDir, NULL);

  cupsdCleanFiles(CacheDir, "*.ipp");

#if HAVE_LAUNCHD
  if (Launchd)
  {
   /*
    * If we were started by launchd get the listen sockets file descriptors...
    */

    launchd_checkin();
    launchd_checkout();
  }
#endif /* HAVE_LAUNCHD */

 /*
  * Startup the server...
  */

  httpInitialize();

  cupsdStartServer();

 /*
  * Catch hangup and child signals and ignore broken pipes...
  */

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGCHLD, sigchld_handler);
  sigset(SIGHUP, sighup_handler);
  sigset(SIGPIPE, SIG_IGN);
  sigset(SIGTERM, sigterm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  sigaddset(&action.sa_mask, SIGTERM);
  sigaddset(&action.sa_mask, SIGCHLD);
  action.sa_handler = sigchld_handler;
  sigaction(SIGCHLD, &action, NULL);

  sigemptyset(&action.sa_mask);
  sigaddset(&action.sa_mask, SIGHUP);
  action.sa_handler = sighup_handler;
  sigaction(SIGHUP, &action, NULL);

  sigemptyset(&action.sa_mask);
  action.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &action, NULL);

  sigemptyset(&action.sa_mask);
  sigaddset(&action.sa_mask, SIGTERM);
  sigaddset(&action.sa_mask, SIGCHLD);
  action.sa_handler = sigterm_handler;
  sigaction(SIGTERM, &action, NULL);
#else
  signal(SIGCLD, sigchld_handler);	/* No, SIGCLD isn't a typo... */
  signal(SIGHUP, sighup_handler);
  signal(SIGPIPE, SIG_IGN);
  signal(SIGTERM, sigterm_handler);
#endif /* HAVE_SIGSET */

#ifdef __sgi
 /*
  * Try to create a fake lpsched lock file if one is not already there.
  * Some Adobe applications need it under IRIX in order to enable
  * printing...
  */

  if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL)
  {
    syslog(LOG_LPR, "Unable to create fake lpsched lock file "
                    "\"/var/spool/lp/SCHEDLOCK\"\' - %s!",
           strerror(errno));
  }
  else
  {
    fchmod(cupsFileNumber(fp), 0644);
    fchown(cupsFileNumber(fp), User, Group);

    cupsFileClose(fp);
  }
#endif /* __sgi */

 /*
  * Initialize authentication certificates...
  */

  cupsdInitCerts();

 /*
  * If we are running in the background, signal the parent process that
  * we are up and running...
  */

  if (!fg || run_as_child)
  {
   /*
    * Send a signal to the parent process, but only if the parent is
    * not PID 1 (init).  This avoids accidentally shutting down the
    * system on OpenBSD if you CTRL-C the server before it is up...
    */

    i = getppid();	/* Save parent PID to avoid race condition */

    if (i != 1)
      kill(i, SIGUSR1);
  }

#ifdef __APPLE__
 /*
  * Start power management framework...
  */

  if (use_sysman)
    cupsdStartSystemMonitor();
#endif /* __APPLE__ */

 /*
  * Send server-started event...
  */

#ifdef HAVE_LAUNCHD
  if (Launchd)
    cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL,
                  "Scheduler started via launchd.");
  else
#endif /* HAVE_LAUNCHD */
  if (fg)
    cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL,
                  "Scheduler started in foreground.");
  else
    cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL,
                  "Scheduler started in background.");

 /*
  * Start any pending print jobs...
  */

  cupsdCheckJobs();

 /*
  * Loop forever...
  */

  current_time  = time(NULL);
  event_time    = current_time;
  expire_time   = current_time;
  fds           = 1;
  report_time   = 0;
  senddoc_time  = current_time;

  while (!stop_scheduler)
  {
   /*
    * Check if there are dead children to handle...
    */

    if (dead_children)
      process_children();

   /*
    * Check if we need to load the server configuration file...
    */

    if (NeedReload)
    {
     /*
      * Close any idle clients...
      */

      if (cupsArrayCount(Clients) > 0)
      {
	for (con = (cupsd_client_t *)cupsArrayFirst(Clients);
	     con;
	     con = (cupsd_client_t *)cupsArrayNext(Clients))
	  if (con->http.state == HTTP_WAITING)
	    cupsdCloseClient(con);
	  else
	    con->http.keep_alive = HTTP_KEEPALIVE_OFF;

        cupsdPauseListening();
      }

     /*
      * Restart if all clients are closed and all jobs finished, or
      * if the reload timeout has elapsed...
      */

      if ((cupsArrayCount(Clients) == 0 &&
           (cupsArrayCount(PrintingJobs) == 0 || NeedReload != RELOAD_ALL)) ||
          (time(NULL) - ReloadTime) >= ReloadTimeout)
      {
       /*
	* Shutdown the server...
	*/

        DoingShutdown = 1;

	cupsdStopServer();

       /*
	* Read configuration...
	*/

        if (!cupsdReadConfiguration())
        {
          syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
		 ConfigurationFile);
          break;
	}

#if HAVE_LAUNCHD
	if (Launchd)
	{
	 /*
	  * If we were started by launchd, get the listen socket file
	  * descriptors...
	  */

	  launchd_checkin();
	  launchd_checkout();
	}
#endif /* HAVE_LAUNCHD */

       /*
        * Startup the server...
        */

        DoingShutdown = 0;

        cupsdStartServer();

       /*
        * Send a server-restarted event...
	*/

        cupsdAddEvent(CUPSD_EVENT_SERVER_RESTARTED, NULL, NULL,
                      "Scheduler restarted.");
      }
    }

   /*
    * Check for available input or ready output.  If cupsdDoSelect()
    * returns 0 or -1, something bad happened and we should exit
    * immediately.
    *
    * Note that we at least have one listening socket open at all
    * times.
    */

    if ((timeout = select_timeout(fds)) > 1 && LastEvent)
      timeout = 1;

#if HAVE_LAUNCHD
   /*
    * If no other work is scheduled and we're being controlled by
    * launchd then timeout after 'LaunchdTimeout' seconds of
    * inactivity...
    */

    if (timeout == 86400 && Launchd && LaunchdTimeout &&
        !cupsArrayCount(ActiveJobs) &&
	(!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers)))
    {
      timeout		= LaunchdTimeout;
      launchd_idle_exit = 1;
    }
    else
      launchd_idle_exit = 0;
#endif	/* HAVE_LAUNCHD */

    if ((fds = cupsdDoSelect(timeout)) < 0)
    {
     /*
      * Got an error from select!
      */

#ifdef HAVE_DNSSD
      cupsd_printer_t	*p;		/* Current printer */
#endif /* HAVE_DNSSD */


      if (errno == EINTR)		/* Just interrupted by a signal */
        continue;

     /*
      * Log all sorts of debug info to help track down the problem.
      */

      cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!",
                      strerror(errno));

      for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients);
	   con;
	   i ++, con = (cupsd_client_t *)cupsArrayNext(Clients))
        cupsdLogMessage(CUPSD_LOG_EMERG,
	                "Clients[%d] = %d, file = %d, state = %d",
	                i, con->http.fd, con->file, con->http.state);

      for (i = 0, lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
           lis;
	   i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
        cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd);

      cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]);

#ifdef __APPLE__
      cupsdLogMessage(CUPSD_LOG_EMERG, "SysEventPipes[0] = %d",
                      SysEventPipes[0]);
#endif /* __APPLE__ */

      for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
	   job;
	   job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
        cupsdLogMessage(CUPSD_LOG_EMERG, "Jobs[%d] = %d < [%d %d] > [%d %d]",
	        	job->id,
			job->status_buffer ? job->status_buffer->fd : -1,
			job->print_pipes[0], job->print_pipes[1],
			job->back_pipes[0], job->back_pipes[1]);

#ifdef HAVE_DNSSD
      for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
	   p;
	   p = (cupsd_printer_t *)cupsArrayNext(Printers))
        cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] reg_name=\"%s\"", p->name,
	                p->reg_name ? p->reg_name : "(null)");
#endif /* HAVE_DNSSD */

      break;
    }

    current_time = time(NULL);

   /*
    * Write dirty config/state files...
    */

    if (DirtyCleanTime && current_time >= DirtyCleanTime)
      cupsdCleanDirty();

#ifdef __APPLE__
   /*
    * If we are going to sleep and still have pending jobs, stop them after
    * a period of time...
    */

    if (SleepJobs > 0 && current_time >= SleepJobs &&
        cupsArrayCount(PrintingJobs) > 0)
    {
      SleepJobs = 0;
      cupsdStopAllJobs(CUPSD_JOB_DEFAULT, 5);
    }
#endif /* __APPLE__ */

#ifndef __APPLE__
   /*
    * Update the network interfaces once a minute...
    */

    if ((current_time - netif_time) >= 60)
    {
      netif_time  = current_time;
      NetIFUpdate = 1;
    }
#endif /* !__APPLE__ */

#if HAVE_LAUNCHD
   /*
    * If no other work was scheduled and we're being controlled by launchd
    * then timeout after 'LaunchdTimeout' seconds of inactivity...
    */

    if (!fds && launchd_idle_exit)
    {
      cupsdLogMessage(CUPSD_LOG_INFO,
                      "Printer sharing is off and there are no jobs pending, "
		      "will restart on demand.");
      stop_scheduler = 1;
      break;
    }
#endif /* HAVE_LAUNCHD */

   /*
    * Resume listening for new connections as needed...
    */

    if (ListeningPaused && ListeningPaused <= current_time &&
        cupsArrayCount(Clients) < MaxClients)
      cupsdResumeListening();

   /*
    * Expire subscriptions and unload completed jobs as needed...
    */

    if (current_time > expire_time)
    {
      if (cupsArrayCount(Subscriptions) > 0)
        cupsdExpireSubscriptions(NULL, NULL);

      cupsdUnloadCompletedJobs();

      expire_time = current_time;
    }

#ifndef HAVE_AUTHORIZATION_H
   /*
    * Update the root certificate once every 5 minutes if we have client
    * connections...
    */

    if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration &&
        !RunUser && cupsArrayCount(Clients))
    {
     /*
      * Update the root certificate...
      */

      cupsdDeleteCert(0);
      cupsdAddCert(0, "root", NULL);
    }
#endif /* !HAVE_AUTHORIZATION_H */

   /*
    * Check for new data on the client sockets...
    */

    for (con = (cupsd_client_t *)cupsArrayFirst(Clients);
	 con;
	 con = (cupsd_client_t *)cupsArrayNext(Clients))
    {
     /*
      * Process pending data in the input buffer...
      */

      if (con->http.used)
      {
        cupsdReadClient(con);
	continue;
      }

     /*
      * Check the activity and close old clients...
      */

      activity = current_time - Timeout;
      if (con->http.activity < activity && !con->pipe_pid)
      {
        cupsdLogMessage(CUPSD_LOG_DEBUG,
	                "Closing client %d after %d seconds of inactivity...",
	                con->http.fd, Timeout);

        cupsdCloseClient(con);
        continue;
      }
    }

   /*
    * Update any pending multi-file documents...
    */

    if ((current_time - senddoc_time) >= 10)
    {
      cupsdCheckJobs();
      senddoc_time = current_time;
    }

   /*
    * Clean job history...
    */

    if (JobHistoryUpdate && current_time >= JobHistoryUpdate)
      cupsdCleanJobs();

   /*
    * Log statistics at most once a minute when in debug mode...
    */

    if ((current_time - report_time) >= 60 && LogLevel >= CUPSD_LOG_DEBUG)
    {
      size_t		string_count,	/* String count */
			alloc_bytes,	/* Allocated string bytes */
			total_bytes;	/* Total string bytes */
#ifdef HAVE_MALLINFO
      struct mallinfo	mem;		/* Malloc information */


      mem = mallinfo();
      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-arena=%lu", mem.arena);
      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-used=%lu",
                      mem.usmblks + mem.uordblks);
      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-free=%lu",
		      mem.fsmblks + mem.fordblks);
#endif /* HAVE_MALLINFO */

      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: clients=%d",
                      cupsArrayCount(Clients));
      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs=%d",
                      cupsArrayCount(Jobs));
      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs-active=%d",
                      cupsArrayCount(ActiveJobs));
      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d",
                      cupsArrayCount(Printers));

      string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes);
      cupsdLogMessage(CUPSD_LOG_DEBUG,
                      "Report: stringpool-string-count=" CUPS_LLFMT,
		      CUPS_LLCAST string_count);
      cupsdLogMessage(CUPSD_LOG_DEBUG,
                      "Report: stringpool-alloc-bytes=" CUPS_LLFMT,
		      CUPS_LLCAST alloc_bytes);
      cupsdLogMessage(CUPSD_LOG_DEBUG,
                      "Report: stringpool-total-bytes=" CUPS_LLFMT,
		      CUPS_LLCAST total_bytes);

      report_time = current_time;
    }

   /*
    * Handle OS-specific event notification for any events that have
    * accumulated.  Don't send these more than once a second...
    */

    if (LastEvent && (current_time - event_time) >= 1)
    {
#ifdef HAVE_NOTIFY_POST
      if (LastEvent & (CUPSD_EVENT_PRINTER_ADDED |
                       CUPSD_EVENT_PRINTER_DELETED |
                       CUPSD_EVENT_PRINTER_MODIFIED))
      {
        cupsdLogMessage(CUPSD_LOG_DEBUG2,
	                "notify_post(\"com.apple.printerListChange\")");
	notify_post("com.apple.printerListChange");
      }

      if (LastEvent & CUPSD_EVENT_PRINTER_STATE_CHANGED)
      {
        cupsdLogMessage(CUPSD_LOG_DEBUG2,
	                "notify_post(\"com.apple.printerHistoryChange\")");
	notify_post("com.apple.printerHistoryChange");
      }

      if (LastEvent & (CUPSD_EVENT_JOB_STATE_CHANGED |
                       CUPSD_EVENT_JOB_CONFIG_CHANGED |
                       CUPSD_EVENT_JOB_PROGRESS))
      {
        cupsdLogMessage(CUPSD_LOG_DEBUG2,
	                "notify_post(\"com.apple.jobChange\")");
	notify_post("com.apple.jobChange");
      }
#endif /* HAVE_NOTIFY_POST */

     /*
      * Reset the accumulated events...
      */

      LastEvent  = CUPSD_EVENT_NONE;
      event_time = current_time;
    }
  }

 /*
  * Log a message based on what happened...
  */

  if (stop_scheduler)
  {
    cupsdLogMessage(CUPSD_LOG_INFO, "Scheduler shutting down normally.");
    cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL,
                  "Scheduler shutting down normally.");
  }
  else
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Scheduler shutting down due to program error.");
    cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL,
                  "Scheduler shutting down due to program error.");
  }

 /*
  * Close all network clients...
  */

  DoingShutdown = 1;

  cupsdStopServer();

#ifdef HAVE_LAUNCHD
 /*
  * Update the launchd KeepAlive file as needed...
  */

  if (Launchd)
    launchd_checkout();
#endif /* HAVE_LAUNCHD */

 /*
  * Stop all jobs...
  */

  cupsdFreeAllJobs();

#ifdef __APPLE__
 /*
  * Stop monitoring system event monitoring...
  */

  if (use_sysman)
    cupsdStopSystemMonitor();
#endif /* __APPLE__ */

#ifdef HAVE_GSSAPI
 /*
  * Free the scheduler's Kerberos context...
  */

#  ifdef __APPLE__
 /*
  * If the weak-linked GSSAPI/Kerberos library is not present, don't try
  * to use it...
  */

  if (krb5_init_context != NULL)
#  endif /* __APPLE__ */
  if (KerberosContext)
    krb5_free_context(KerberosContext);
#endif /* HAVE_GSSAPI */

#ifdef __sgi
 /*
  * Remove the fake IRIX lpsched lock file, but only if the existing
  * file is not a FIFO which indicates that the real IRIX lpsched is
  * running...
  */

  if (!stat("/var/spool/lp/FIFO", &statbuf))
    if (!S_ISFIFO(statbuf.st_mode))
      unlink("/var/spool/lp/SCHEDLOCK");
#endif /* __sgi */

  cupsdStopSelect();

  return (!stop_scheduler);
}
Example #18
0
int					/* O - Process ID or 0 */
cupsdStartProcess(
    const char  *command,		/* I - Full path to command */
    char        *argv[],		/* I - Command-line arguments */
    char        *envp[],		/* I - Environment */
    int         infd,			/* I - Standard input file descriptor */
    int         outfd,			/* I - Standard output file descriptor */
    int         errfd,			/* I - Standard error file descriptor */
    int         backfd,			/* I - Backchannel file descriptor */
    int         sidefd,			/* I - Sidechannel file descriptor */
    int         root,			/* I - Run as root? */
    void        *profile,		/* I - Security profile to use */
    cupsd_job_t *job,			/* I - Job associated with process */
    int         *pid)			/* O - Process ID */
{
  int		i;			/* Looping var */
  const char	*exec_path = command;	/* Command to be exec'd */
  char		*real_argv[110],	/* Real command-line arguments */
		cups_exec[1024],	/* Path to "cups-exec" program */
		user_str[16],		/* User string */
		group_str[16],		/* Group string */
		nice_str[16];		/* FilterNice string */
  uid_t		user;			/* Command UID */
  cupsd_proc_t	*proc;			/* New process record */
#if USE_POSIX_SPAWN
  posix_spawn_file_actions_t actions;	/* Spawn file actions */
  posix_spawnattr_t attrs;		/* Spawn attributes */
  sigset_t	defsignals;		/* Default signals */
#elif defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* POSIX signal handler */
#endif /* USE_POSIX_SPAWN */
#if defined(__APPLE__)
  char		processPath[1024],	/* CFProcessPath environment variable */
		linkpath[1024];		/* Link path for symlinks... */
  int		linkbytes;		/* Bytes for link path */
#endif /* __APPLE__ */


  *pid = 0;

 /*
  * Figure out the UID for the child process...
  */

  if (RunUser)
    user = RunUser;
  else if (root)
    user = 0;
  else
    user = User;

 /*
  * Check the permissions of the command we are running...
  */

  if (_cupsFileCheck(command, _CUPS_FILE_CHECK_PROGRAM, !RunUser,
                     cupsdLogFCMessage, job ? job->printer : NULL))
    return (0);

#if defined(__APPLE__)
  if (envp)
  {
   /*
    * Add special voodoo magic for OS X - this allows OS X programs to access
    * their bundle resources properly...
    */

    if ((linkbytes = readlink(command, linkpath, sizeof(linkpath) - 1)) > 0)
    {
     /*
      * Yes, this is a symlink to the actual program, nul-terminate and
      * use it...
      */

      linkpath[linkbytes] = '\0';

      if (linkpath[0] == '/')
	snprintf(processPath, sizeof(processPath), "CFProcessPath=%s",
		 linkpath);
      else
	snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
		 dirname((char *)command), linkpath);
    }
    else
      snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);

    envp[0] = processPath;		/* Replace <CFProcessPath> string */
  }
#endif	/* __APPLE__ */

 /*
  * Use helper program when we have a sandbox profile...
  */

#if !USE_POSIX_SPAWN
  if (profile)
#endif /* !USE_POSIX_SPAWN */
  {
    snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin);
    snprintf(user_str, sizeof(user_str), "%d", user);
    snprintf(group_str, sizeof(group_str), "%d", Group);
    snprintf(nice_str, sizeof(nice_str), "%d", FilterNice);

    real_argv[0] = cups_exec;
    real_argv[1] = (char *)"-g";
    real_argv[2] = group_str;
    real_argv[3] = (char *)"-n";
    real_argv[4] = nice_str;
    real_argv[5] = (char *)"-u";
    real_argv[6] = user_str;
    real_argv[7] = profile ? profile : "none";
    real_argv[8] = (char *)command;

    for (i = 0;
         i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 10) && argv[i];
	 i ++)
      real_argv[i + 9] = argv[i];

    real_argv[i + 9] = NULL;

    argv      = real_argv;
    exec_path = cups_exec;
  }

  if (LogLevel == CUPSD_LOG_DEBUG2)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Preparing to start \"%s\", arguments:", command);

    for (i = 0; argv[i]; i ++)
      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: argv[%d] = \"%s\"", i, argv[i]);
  }

#if USE_POSIX_SPAWN
 /*
  * Setup attributes and file actions for the spawn...
  */

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting spawn attributes.");
  sigemptyset(&defsignals);
  sigaddset(&defsignals, SIGTERM);
  sigaddset(&defsignals, SIGCHLD);
  sigaddset(&defsignals, SIGPIPE);

  posix_spawnattr_init(&attrs);
  posix_spawnattr_setflags(&attrs, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF);
  posix_spawnattr_setpgroup(&attrs, 0);
  posix_spawnattr_setsigdefault(&attrs, &defsignals);

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting file actions.");
  posix_spawn_file_actions_init(&actions);
  if (infd != 0)
  {
    if (infd < 0)
      posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_RDONLY, 0);
    else
      posix_spawn_file_actions_adddup2(&actions, infd, 0);
  }

  if (outfd != 1)
  {
    if (outfd < 0)
      posix_spawn_file_actions_addopen(&actions, 1, "/dev/null", O_WRONLY, 0);
    else
      posix_spawn_file_actions_adddup2(&actions, outfd, 1);
  }

  if (errfd != 2)
  {
    if (errfd < 0)
      posix_spawn_file_actions_addopen(&actions, 2, "/dev/null", O_WRONLY, 0);
    else
      posix_spawn_file_actions_adddup2(&actions, errfd, 2);
  }

  if (backfd != 3 && backfd >= 0)
    posix_spawn_file_actions_adddup2(&actions, backfd, 3);

  if (sidefd != 4 && sidefd >= 0)
    posix_spawn_file_actions_adddup2(&actions, sidefd, 4);

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Calling posix_spawn.");

  if (posix_spawn(pid, exec_path, &actions, &attrs, argv, envp ? envp : environ))
  {
    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command, strerror(errno));

    *pid = 0;
  }
  else
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: pid=%d", (int)*pid);

  posix_spawn_file_actions_destroy(&actions);
  posix_spawnattr_destroy(&attrs);

#else
 /*
  * Block signals before forking...
  */

  cupsdHoldSignals();

  if ((*pid = fork()) == 0)
  {
   /*
    * Child process goes here; update stderr as needed...
    */

    if (errfd != 2)
    {
      if (errfd < 0)
        errfd = open("/dev/null", O_WRONLY);

      if (errfd != 2)
      {
        dup2(errfd, 2);
	close(errfd);
      }
    }

   /*
    * Put this process in its own process group so that we can kill any child
    * processes it creates.
    */

#  ifdef HAVE_SETPGID
    if (!RunUser && setpgid(0, 0))
      exit(errno + 100);
#  else
    if (!RunUser && setpgrp())
      exit(errno + 100);
#  endif /* HAVE_SETPGID */

   /*
    * Update the remaining file descriptors as needed...
    */

    if (infd != 0)
    {
      if (infd < 0)
        infd = open("/dev/null", O_RDONLY);

      if (infd != 0)
      {
        dup2(infd, 0);
	close(infd);
      }
    }

    if (outfd != 1)
    {
      if (outfd < 0)
        outfd = open("/dev/null", O_WRONLY);

      if (outfd != 1)
      {
        dup2(outfd, 1);
	close(outfd);
      }
    }

    if (backfd != 3 && backfd >= 0)
    {
      dup2(backfd, 3);
      close(backfd);
      fcntl(3, F_SETFL, O_NDELAY);
    }

    if (sidefd != 4 && sidefd >= 0)
    {
      dup2(sidefd, 4);
      close(sidefd);
      fcntl(4, F_SETFL, O_NDELAY);
    }

   /*
    * Change the priority of the process based on the FilterNice setting.
    * (this is not done for root processes...)
    */

    if (!root)
      nice(FilterNice);

   /*
    * Reset group membership to just the main one we belong to.
    */

    if (!RunUser && setgid(Group))
      exit(errno + 100);

    if (!RunUser && setgroups(1, &Group))
      exit(errno + 100);

   /*
    * Change user to something "safe"...
    */

    if (!RunUser && user && setuid(user))
      exit(errno + 100);

   /*
    * Change umask to restrict permissions on created files...
    */

    umask(077);

   /*
    * Unblock signals before doing the exec...
    */

#  ifdef HAVE_SIGSET
    sigset(SIGTERM, SIG_DFL);
    sigset(SIGCHLD, SIG_DFL);
    sigset(SIGPIPE, SIG_DFL);
#  elif defined(HAVE_SIGACTION)
    memset(&action, 0, sizeof(action));

    sigemptyset(&action.sa_mask);
    action.sa_handler = SIG_DFL;

    sigaction(SIGTERM, &action, NULL);
    sigaction(SIGCHLD, &action, NULL);
    sigaction(SIGPIPE, &action, NULL);
#  else
    signal(SIGTERM, SIG_DFL);
    signal(SIGCHLD, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
#  endif /* HAVE_SIGSET */

    cupsdReleaseSignals();

   /*
    * Execute the command; if for some reason this doesn't work, log an error
    * exit with a non-zero value...
    */

    if (envp)
      execve(exec_path, argv, envp);
    else
      execv(exec_path, argv);

    exit(errno + 100);
  }
  else if (*pid < 0)
  {
   /*
    * Error - couldn't fork a new process!
    */

    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command,
                    strerror(errno));

    *pid = 0;
  }

  cupsdReleaseSignals();
#endif /* USE_POSIX_SPAWN */

  if (*pid)
  {
    if (!process_array)
      process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL);

    if (process_array)
    {
      if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL)
      {
        proc->pid    = *pid;
	proc->job_id = job ? job->id : 0;
	_cups_strcpy(proc->name, command);

	cupsArrayAdd(process_array, proc);
      }
    }
  }

  cupsdLogMessage(CUPSD_LOG_DEBUG2,
		  "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
		  "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
		  "profile=%p, job=%p(%d), pid=%p) = %d",
		  command, argv, envp, infd, outfd, errfd, backfd, sidefd,
		  root, profile, job, job ? job->id : 0, pid, *pid);

  return (*pid);
}
Example #19
0
int
main(int argc, char **argv)
{
	int c;
	int err;
	const char *ofields = NULL;
	ofmt_status_t ofmterr;
	ofmt_field_t *fields = NULL;
	uint_t ofmtflags = 0;
	ipmp_handle_t ih;
	ipmp_qcontext_t qcontext = IPMP_QCONTEXT_SNAP;
	ipmpstat_cbfunc_t *cbfunc;
	ipmpstat_walker_t *walker;
	char errbuf[OFMT_BUFSIZE];

	if ((progname = strrchr(argv[0], '/')) == NULL)
		progname = argv[0];
	else
		progname++;

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	while ((c = getopt(argc, argv, "nLPo:agipt")) != EOF) {
		if (fields != NULL && strchr("agipt", c) != NULL)
			die("only one output format may be specified\n");

		switch (c) {
		case 'n':
			opt |= IPMPSTAT_OPT_NUMERIC;
			break;
		case 'L':
			/* Undocumented option: for testing use ONLY */
			qcontext = IPMP_QCONTEXT_LIVE;
			break;
		case 'P':
			opt |= IPMPSTAT_OPT_PARSABLE;
			ofmtflags |= OFMT_PARSABLE;
			break;
		case 'o':
			ofields = optarg;
			break;
		case 'a':
			walker = walk_addr;
			cbfunc = info_output_cbfunc;
			fields = addr_fields;
			break;
		case 'g':
			walker = walk_group;
			cbfunc = info_output_cbfunc;
			fields = group_fields;
			break;
		case 'i':
			walker = walk_if;
			cbfunc = info_output_cbfunc;
			fields = if_fields;
			break;
		case 'p':
			fields = probe_fields;
			break;
		case 't':
			walker = walk_if;
			cbfunc = targinfo_output_cbfunc;
			fields = targ_fields;
			break;
		default:
			usage();
			break;
		}
	}

	if (argc > optind || fields == NULL)
		usage();

	/*
	 * Open a handle to the formatted output engine.
	 */
	ofmterr = ofmt_open(ofields, fields, ofmtflags, IPMPSTAT_NCOL, &ofmt);
	if (ofmterr != OFMT_SUCCESS) {
		/*
		 * If some fields were badly formed in human-friendly mode, we
		 * emit a warning and continue.  Otherwise exit immediately.
		 */
		(void) ofmt_strerror(ofmt, ofmterr, errbuf, sizeof (errbuf));
		if (ofmterr != OFMT_EBADFIELDS || (opt & IPMPSTAT_OPT_PARSABLE))
			die("%s\n", errbuf);
		else
			warn("%s\n", errbuf);
	}

	/*
	 * Obtain the window size and monitor changes to the size.  This data
	 * is used to redisplay the output headers when necessary.
	 */
	(void) sigset(SIGWINCH, sighandler);

	if ((err = ipmp_open(&ih)) != IPMP_SUCCESS)
		die_ipmperr(err, "cannot create IPMP handle");

	if (ipmp_ping_daemon(ih) != IPMP_SUCCESS)
		die("cannot contact in.mpathd(1M) -- is IPMP in use?\n");

	/*
	 * If we've been asked to display probes, then call the probe output
	 * function.  Otherwise, snapshot IPMP state (or use live state) and
	 * invoke the specified walker with the specified callback function.
	 */
	if (fields == probe_fields) {
		probe_output(ih, ofmt);
	} else {
		if ((err = ipmp_setqcontext(ih, qcontext)) != IPMP_SUCCESS) {
			if (qcontext == IPMP_QCONTEXT_SNAP)
				die_ipmperr(err, "cannot snapshot IPMP state");
			else
				die_ipmperr(err, "cannot use live IPMP state");
		}
		(*walker)(ih, cbfunc, ofmt);
	}

	ofmt_close(ofmt);
	ipmp_close(ih);

	return (EXIT_SUCCESS);
}
Example #20
0
File: main.c Project: wnr/os13-lab2
void registerSignalToHandle(int sig) {
    /* Register the new action to handle the signal sig. */
    CHECK(sigset(sig, signalHandler));
}
Example #21
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments (6 or 7) */
     char *argv[])			/* I - Command-line arguments */
{
  int		ipv4,			/* SNMP IPv4 socket */
		ipv6;			/* SNMP IPv6 socket */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Check command-line options...
  */

  if (argc > 2)
  {
    _cupsLangPuts(stderr, _("Usage: snmp [host-or-ip-address]"));
    return (1);
  }

 /*
  * Set the password callback for IPP operations...
  */

  cupsSetPasswordCB(password_cb);

 /*
  * Catch SIGALRM signals...
  */

#ifdef HAVE_SIGSET
  sigset(SIGALRM, alarm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  sigaddset(&action.sa_mask, SIGALRM);
  action.sa_handler = alarm_handler;
  sigaction(SIGALRM, &action, NULL);
#else
  signal(SIGALRM, alarm_handler);
#endif /* HAVE_SIGSET */

 /*
  * Open the SNMP socket...
  */

  if ((ipv4 = _cupsSNMPOpen(AF_INET)) < 0)
    return (1);

#ifdef AF_INET6
  if ((ipv6 = _cupsSNMPOpen(AF_INET6)) < 0)
    perror("DEBUG: Unable to create IPv6 socket");
#else
  ipv6 = -1;
#endif /* AF_INET6 */

 /*
  * Read the configuration file and any cache data...
  */

  read_snmp_conf(argv[1]);

  _cupsSNMPSetDebug(DebugLevel);

  Devices = cupsArrayNew((cups_array_func_t)compare_cache, NULL);

 /*
  * Scan for devices...
  */

  scan_devices(ipv4, ipv6);

 /*
  * Close, free, and return with no errors...
  */

  _cupsSNMPClose(ipv4);
  if (ipv6 >= 0)
    _cupsSNMPClose(ipv6);

  free_array(Addresses);
  free_array(Communities);
  free_cache();

  return (0);
}
Example #22
0
File: main.c Project: msantl/PARPRO
int main(int argc, char **argv) {
    int myid, n_workers, status, n_thread, i;

    if (argc == 2) {
        sscanf(argv[1], "%d", &g_max_depth);
    } else {
        g_max_depth = MAX_DEPTH;
    }

    if (MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &status) != MPI_SUCCESS) {
        errx(1, "MPI_Init_thread failed!");
    }

    if (status != MPI_THREAD_MULTIPLE) {
        errx(1, "MPI_Init_thread failed to provide thread support!");
    }

    thread_functions[0] = worker;
    thread_functions[1] = master;
    thread_functions[2] = user_input;

    pthread_mutex_init(&m_board, NULL);
    pthread_cond_init(&u_human, NULL);
    pthread_cond_init(&u_computer, NULL);

    sigset(SIGINT, Exit);

    MPI_Comm_size(MPI_COMM_WORLD, &n_workers);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);

    /* init processes */
    if (myid == 0) {
        ListConstruct(&q_worker_ready);

        for (i = 0; i < n_workers; ++i) {
            ListInsert(&q_worker_ready, i);
        }

        BoardInit(&board);
        BoardPrint(&board);

        n_thread = 3;
    } else {
        n_thread = 1;
    }

    /* start the game */
    RUNNING = 1;
    CURRENT_PLAYER = HUMAN;

    for (i = 0; i < n_thread; ++i) {
        if (pthread_create(&threads[i], NULL, thread_functions[i], NULL) != 0) {
            errx(1, "pthread_create(): failed to create a new thread!");
        }
    }

    /* end the game */
    for (i = 0; i < n_thread; ++i) {
        pthread_join(threads[i], NULL);
    }

    Exit(0);
    return 0;
}
Example #23
0
int
main(int ac, char *av[])
{
	char *dir = "/";
	int allflag = 0;
	int df_allflag = 0;
	int opt_cnt = 0;
	int maxservers = 1;	/* zero allows inifinte number of threads */
	int maxservers_set = 0;
	int logmaxservers = 0;
	int pid;
	int i;
	char *provider = (char *)NULL;
	char *df_provider = (char *)NULL;
	struct protob *protobp0, *protobp;
	NETSELDECL(proto) = NULL;
	NETSELDECL(df_proto) = NULL;
	NETSELPDECL(providerp);
	char *defval;
	boolean_t can_do_mlp;
	uint_t dss_npaths = 0;
	char **dss_pathnames = NULL;
	sigset_t sgset;
	char name[PATH_MAX], value[PATH_MAX];
	int ret, bufsz;

	int pipe_fd = -1;

	MyName = *av;

	/*
	 * Initializations that require more privileges than we need to run.
	 */
	(void) _create_daemon_lock(NFSD, DAEMON_UID, DAEMON_GID);
	svcsetprio();

	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS,
	    can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
		(void) fprintf(stderr, "%s should be run with"
		    " sufficient privileges\n", av[0]);
		exit(1);
	}

	(void) enable_extended_FILE_stdio(-1, -1);

	/*
	 * Read in the values from SMF first before we check
	 * command line options so the options override SMF values.
	 */
	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("max_connections", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		max_conns_allowed = strtol(value, (char **)NULL, 10);
		if (errno != 0)
			max_conns_allowed = -1;
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("listen_backlog", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		listen_backlog = strtol(value, (char **)NULL, 10);
		if (errno != 0) {
			listen_backlog = 32;
		}
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("protocol", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if ((ret == SA_OK) && strlen(value) > 0) {
		df_proto = strdup(value);
		opt_cnt++;
		if (strncasecmp("ALL", value, 3) == 0) {
			free(df_proto);
			df_proto = NULL;
			df_allflag = 1;
		}
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("device", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if ((ret == SA_OK) && strlen(value) > 0) {
		df_provider = strdup(value);
		opt_cnt++;
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("servers", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		maxservers = strtol(value, (char **)NULL, 10);
		if (errno != 0)
			maxservers = 1;
		else
			maxservers_set = 1;
	}

	bufsz = 4;
	ret = nfs_smf_get_prop("server_versmin", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK)
		nfs_server_vers_min = strtol(value, (char **)NULL, 10);

	bufsz = 4;
	ret = nfs_smf_get_prop("server_versmax", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK)
		nfs_server_vers_max = strtol(value, (char **)NULL, 10);

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("server_delegation", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if (ret == SA_OK)
		if (strncasecmp(value, "off", 3) == 0)
			nfs_server_delegation = FALSE;

	/*
	 * Conflict options error messages.
	 */
	if (opt_cnt > 1) {
		(void) fprintf(stderr, "\nConflicting options, only one of "
		    "the following options can be specified\n"
		    "in SMF:\n"
		    "\tprotocol=ALL\n"
		    "\tprotocol=protocol\n"
		    "\tdevice=devicename\n\n");
		usage();
	}
	opt_cnt = 0;

	while ((i = getopt(ac, av, "ac:p:s:t:l:")) != EOF) {
		switch (i) {
		case 'a':
			free(df_proto);
			df_proto = NULL;
			free(df_provider);
			df_provider = NULL;

			allflag = 1;
			opt_cnt++;
			break;

		case 'c':
			max_conns_allowed = atoi(optarg);
			break;

		case 'p':
			proto = optarg;
			df_allflag = 0;
			opt_cnt++;
			break;

		/*
		 * DSS: NFSv4 distributed stable storage.
		 *
		 * This is a Contracted Project Private interface, for
		 * the sole use of Sun Cluster HA-NFS. See PSARC/2006/313.
		 */
		case 's':
			if (strlen(optarg) < MAXPATHLEN) {
				/* first "-s" option encountered? */
				if (dss_pathnames == NULL) {
					/*
					 * Allocate maximum possible space
					 * required given cmdline arg count;
					 * "-s <path>" consumes two args.
					 */
					size_t sz = (ac / 2) * sizeof (char *);
					dss_pathnames = (char **)malloc(sz);
					if (dss_pathnames == NULL) {
						(void) fprintf(stderr, "%s: "
						    "dss paths malloc failed\n",
						    av[0]);
						exit(1);
					}
					(void) memset(dss_pathnames, 0, sz);
				}
				dss_pathnames[dss_npaths] = optarg;
				dss_npaths++;
			} else {
				(void) fprintf(stderr,
				    "%s: -s pathname too long.\n", av[0]);
			}
			break;

		case 't':
			provider = optarg;
			df_allflag = 0;
			opt_cnt++;
			break;

		case 'l':
			listen_backlog = atoi(optarg);
			break;

		case '?':
			usage();
			/* NOTREACHED */
		}
	}

	allflag = df_allflag;
	if (proto == NULL)
		proto = df_proto;
	if (provider == NULL)
		provider = df_provider;

	/*
	 * Conflict options error messages.
	 */
	if (opt_cnt > 1) {
		(void) fprintf(stderr, "\nConflicting options, only one of "
		    "the following options can be specified\n"
		    "on the command line:\n"
		    "\t-a\n"
		    "\t-p protocol\n"
		    "\t-t transport\n\n");
		usage();
	}

	if (proto != NULL &&
	    strncasecmp(proto, NC_UDP, strlen(NC_UDP)) == 0) {
		if (nfs_server_vers_max == NFS_V4) {
			if (nfs_server_vers_min == NFS_V4) {
				fprintf(stderr,
				    "NFS version 4 is not supported "
				    "with the UDP protocol.  Exiting\n");
				exit(3);
			} else {
				fprintf(stderr,
				    "NFS version 4 is not supported "
				    "with the UDP protocol.\n");
			}
		}
	}

	/*
	 * If there is exactly one more argument, it is the number of
	 * servers.
	 */
	if (optind == ac - 1) {
		maxservers = atoi(av[optind]);
		maxservers_set = 1;
	}
	/*
	 * If there are two or more arguments, then this is a usage error.
	 */
	else if (optind < ac - 1)
		usage();
	/*
	 * Check the ranges for min/max version specified
	 */
	else if ((nfs_server_vers_min > nfs_server_vers_max) ||
	    (nfs_server_vers_min < NFS_VERSMIN) ||
	    (nfs_server_vers_max > NFS_VERSMAX))
		usage();
	/*
	 * There are no additional arguments, and we haven't set maxservers
	 * explicitly via the config file, we use a default number of
	 * servers.  We will log this.
	 */
	else if (maxservers_set == 0)
		logmaxservers = 1;

	/*
	 * Basic Sanity checks on options
	 *
	 * max_conns_allowed must be positive, except for the special
	 * value of -1 which is used internally to mean unlimited, -1 isn't
	 * documented but we allow it anyway.
	 *
	 * maxservers must be positive
	 * listen_backlog must be positive or zero
	 */
	if (((max_conns_allowed != -1) && (max_conns_allowed <= 0)) ||
	    (listen_backlog < 0) || (maxservers <= 0)) {
		usage();
	}

	/*
	 * Set current dir to server root
	 */
	if (chdir(dir) < 0) {
		(void) fprintf(stderr, "%s:  ", MyName);
		perror(dir);
		exit(1);
	}

#ifndef DEBUG
	pipe_fd = daemonize_init();
#endif

	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	/*
	 * establish our lock on the lock file and write our pid to it.
	 * exit if some other process holds the lock, or if there's any
	 * error in writing/locking the file.
	 */
	pid = _enter_daemon_lock(NFSD);
	switch (pid) {
	case 0:
		break;
	case -1:
		fprintf(stderr, "error locking for %s: %s\n", NFSD,
		    strerror(errno));
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	/*
	 * If we've been given a list of paths to be used for distributed
	 * stable storage, and provided we're going to run a version
	 * that supports it, setup the DSS paths.
	 */
	if (dss_pathnames != NULL && nfs_server_vers_max >= DSS_VERSMIN) {
		if (dss_init(dss_npaths, dss_pathnames) != 0) {
			fprintf(stderr, "%s", "dss_init failed. Exiting.\n");
			exit(1);
		}
	}

	/*
	 * Block all signals till we spawn other
	 * threads.
	 */
	(void) sigfillset(&sgset);
	(void) thr_sigsetmask(SIG_BLOCK, &sgset, NULL);

	if (logmaxservers) {
		fprintf(stderr,
		    "Number of servers not specified. Using default of %d.\n",
		    maxservers);
	}

	/*
	 * Make sure to unregister any previous versions in case the
	 * user is reconfiguring the server in interesting ways.
	 */
	svc_unreg(NFS_PROGRAM, NFS_VERSION);
	svc_unreg(NFS_PROGRAM, NFS_V3);
	svc_unreg(NFS_PROGRAM, NFS_V4);
	svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V2);
	svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V3);

	/*
	 * Set up kernel RPC thread pool for the NFS server.
	 */
	if (nfssvcpool(maxservers)) {
		fprintf(stderr, "Can't set up kernel NFS service: %s. "
		    "Exiting.\n", strerror(errno));
		exit(1);
	}

	/*
	 * Set up blocked thread to do LWP creation on behalf of the kernel.
	 */
	if (svcwait(NFS_SVCPOOL_ID)) {
		fprintf(stderr, "Can't set up NFS pool creator: %s. Exiting.\n",
		    strerror(errno));
		exit(1);
	}

	/*
	 * RDMA start and stop thread.
	 * Per pool RDMA listener creation and
	 * destructor thread.
	 *
	 * start rdma services and block in the kernel.
	 * (only if proto or provider is not set to TCP or UDP)
	 */
	if ((proto == NULL) && (provider == NULL)) {
		if (svcrdma(NFS_SVCPOOL_ID, nfs_server_vers_min,
		    nfs_server_vers_max, nfs_server_delegation)) {
			fprintf(stderr,
			    "Can't set up RDMA creator thread : %s\n",
			    strerror(errno));
		}
	}

	/*
	 * Now open up for signal delivery
	 */

	(void) thr_sigsetmask(SIG_UNBLOCK, &sgset, NULL);
	sigset(SIGTERM, sigflush);
	sigset(SIGUSR1, quiesce);

	/*
	 * Build a protocol block list for registration.
	 */
	protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob));
	protobp->serv = "NFS";
	protobp->versmin = nfs_server_vers_min;
	protobp->versmax = nfs_server_vers_max;
	protobp->program = NFS_PROGRAM;

	protobp->next = (struct protob *)malloc(sizeof (struct protob));
	protobp = protobp->next;
	protobp->serv = "NFS_ACL";		/* not used */
	protobp->versmin = nfs_server_vers_min;
	/* XXX - this needs work to get the version just right */
	protobp->versmax = (nfs_server_vers_max > NFS_ACL_V3) ?
	    NFS_ACL_V3 : nfs_server_vers_max;
	protobp->program = NFS_ACL_PROGRAM;
	protobp->next = (struct protob *)NULL;

	if (allflag) {
		if (do_all(protobp0, nfssvc) == -1) {
			fprintf(stderr, "setnetconfig failed : %s\n",
			    strerror(errno));
			exit(1);
		}
	} else if (proto) {
		/* there's more than one match for the same protocol */
		struct netconfig *nconf;
		NCONF_HANDLE *nc;
		bool_t	protoFound = FALSE;
		if ((nc = setnetconfig()) == (NCONF_HANDLE *) NULL) {
			fprintf(stderr, "setnetconfig failed : %s\n",
			    strerror(errno));
			goto done;
		}
		while (nconf = getnetconfig(nc)) {
			if (strcmp(nconf->nc_proto, proto) == 0) {
				protoFound = TRUE;
				do_one(nconf->nc_device, NULL,
				    protobp0, nfssvc);
			}
		}
		(void) endnetconfig(nc);
		if (protoFound == FALSE) {
			fprintf(stderr,
			    "couldn't find netconfig entry for protocol %s\n",
			    proto);
		}
	} else if (provider)
		do_one(provider, proto, protobp0, nfssvc);
	else {
		for (providerp = defaultproviders;
		    *providerp != NULL; providerp++) {
			provider = *providerp;
			do_one(provider, NULL, protobp0, nfssvc);
		}
	}
done:

	free(protobp);
	free(protobp0);

	if (num_fds == 0) {
		fprintf(stderr, "Could not start NFS service for any protocol."
		    " Exiting.\n");
		exit(1);
	}

	end_listen_fds = num_fds;

	/*
	 * nfsd is up and running as far as we are concerned.
	 */
	daemonize_fini(pipe_fd);

	/*
	 * Get rid of unneeded privileges.
	 */
	__fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);

	/*
	 * Poll for non-data control events on the transport descriptors.
	 */
	poll_for_action();

	/*
	 * If we get here, something failed in poll_for_action().
	 */
	return (1);
}
Example #24
0
ssize_t					/* O - Total bytes on success, -1 on error */
backendRunLoop(
    int          print_fd,		/* I - Print file descriptor */
    int          device_fd,		/* I - Device file descriptor */
    int          snmp_fd,		/* I - SNMP socket or -1 if none */
    http_addr_t  *addr,			/* I - Address of device */
    int          use_bc,		/* I - Use back-channel? */
    int          update_state,		/* I - Update printer-state-reasons? */
    _cups_sccb_t side_cb)		/* I - Side-channel callback */
{
  int		nfds;			/* Maximum file descriptor value + 1 */
  fd_set	input,			/* Input set for reading */
		output;			/* Output set for writing */
  ssize_t	print_bytes,		/* Print bytes read */
		bc_bytes,		/* Backchannel bytes read */
		total_bytes,		/* Total bytes written */
		bytes;			/* Bytes written */
  int		paperout;		/* "Paper out" status */
  int		offline;		/* "Off-line" status */
  char		print_buffer[8192],	/* Print data buffer */
		*print_ptr,		/* Pointer into print data buffer */
		bc_buffer[1024];	/* Back-channel data buffer */
  struct timeval timeout;		/* Timeout for select() */
  time_t	curtime,		/* Current time */
		snmp_update = 0;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


  fprintf(stderr,
          "DEBUG: backendRunLoop(print_fd=%d, device_fd=%d, snmp_fd=%d, "
	  "addr=%p, use_bc=%d, side_cb=%p)\n",
          print_fd, device_fd, snmp_fd, addr, use_bc, side_cb);

 /*
  * If we are printing data from a print driver on stdin, ignore SIGTERM
  * so that the driver can finish out any page data, e.g. to eject the
  * current page.  We only do this for stdin printing as otherwise there
  * is no way to cancel a raw print job...
  */

  if (!print_fd)
  {
#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
    sigset(SIGTERM, SIG_IGN);
#elif defined(HAVE_SIGACTION)
    memset(&action, 0, sizeof(action));

    sigemptyset(&action.sa_mask);
    action.sa_handler = SIG_IGN;
    sigaction(SIGTERM, &action, NULL);
#else
    signal(SIGTERM, SIG_IGN);
#endif /* HAVE_SIGSET */
  }
  else if (print_fd < 0)
  {
   /*
    * Copy print data from stdin, but don't mess with the signal handlers...
    */

    print_fd = 0;
  }

 /*
  * Figure out the maximum file descriptor value to use with select()...
  */

  nfds = (print_fd > device_fd ? print_fd : device_fd) + 1;

 /*
  * Now loop until we are out of data from print_fd...
  */

  for (print_bytes = 0, print_ptr = print_buffer, offline = -1,
           paperout = -1, total_bytes = 0;;)
  {
   /*
    * Use select() to determine whether we have data to copy around...
    */

    FD_ZERO(&input);
    if (!print_bytes)
      FD_SET(print_fd, &input);
    if (use_bc)
      FD_SET(device_fd, &input);
    if (!print_bytes && side_cb)
      FD_SET(CUPS_SC_FD, &input);

    FD_ZERO(&output);
    if (print_bytes || (!use_bc && !side_cb))
      FD_SET(device_fd, &output);

    if (use_bc || side_cb)
    {
      timeout.tv_sec  = 5;
      timeout.tv_usec = 0;

      if (select(nfds, &input, &output, NULL, &timeout) < 0)
      {
       /*
	* Pause printing to clear any pending errors...
	*/

	if (errno == ENXIO && offline != 1 && update_state)
	{
	  fputs("STATE: +offline-report\n", stderr);
	  _cupsLangPrintFilter(stderr, "INFO",
	                       _("The printer is not connected."));
	  offline = 1;
	}
	else if (errno == EINTR && total_bytes == 0)
	{
	  fputs("DEBUG: Received an interrupt before any bytes were "
	        "written, aborting.\n", stderr);
          return (0);
	}

	sleep(1);
	continue;
      }
    }

   /*
    * Check if we have a side-channel request ready...
    */

    if (side_cb && FD_ISSET(CUPS_SC_FD, &input))
    {
     /*
      * Do the side-channel request, then start back over in the select
      * loop since it may have read from print_fd...
      */

      if ((*side_cb)(print_fd, device_fd, snmp_fd, addr, use_bc))
        side_cb = NULL;
      continue;
    }

   /*
    * Check if we have back-channel data ready...
    */

    if (FD_ISSET(device_fd, &input))
    {
      if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
      {
	fprintf(stderr,
	        "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n",
	        CUPS_LLCAST bc_bytes);
        cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0);
      }
      else if (bc_bytes < 0 && errno != EAGAIN && errno != EINTR)
      {
        fprintf(stderr, "DEBUG: Error reading back-channel data: %s\n",
	        strerror(errno));
	use_bc = 0;
      }
      else if (bc_bytes == 0)
        use_bc = 0;
    }

   /*
    * Check if we have print data ready...
    */

    if (FD_ISSET(print_fd, &input))
    {
      if ((print_bytes = read(print_fd, print_buffer,
                              sizeof(print_buffer))) < 0)
      {
       /*
        * Read error - bail if we don't see EAGAIN or EINTR...
	*/

	if (errno != EAGAIN || errno != EINTR)
	{
	  fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno));
	  _cupsLangPrintFilter(stderr, "ERROR",
	                       _("Unable to read print data."));
	  return (-1);
	}

        print_bytes = 0;
      }
      else if (print_bytes == 0)
      {
       /*
        * End of file, break out of the loop...
	*/

        break;
      }

      print_ptr = print_buffer;

      fprintf(stderr, "DEBUG: Read %d bytes of print data...\n",
              (int)print_bytes);
    }

   /*
    * Check if the device is ready to receive data and we have data to
    * send...
    */

    if (print_bytes && FD_ISSET(device_fd, &output))
    {
      if ((bytes = write(device_fd, print_ptr, print_bytes)) < 0)
      {
       /*
        * Write error - bail if we don't see an error we can retry...
	*/

        if (errno == ENOSPC)
	{
	  if (paperout != 1 && update_state)
	  {
	    fputs("STATE: +media-empty-warning\n", stderr);
	    fputs("DEBUG: Out of paper\n", stderr);
	    paperout = 1;
	  }
        }
	else if (errno == ENXIO)
	{
	  if (offline != 1 && update_state)
	  {
	    fputs("STATE: +offline-report\n", stderr);
	    _cupsLangPrintFilter(stderr, "INFO",
	                         _("The printer is not connected."));
	    offline = 1;
	  }
	}
	else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
	{
	  _cupsLangPrintError("ERROR", _("Unable to write print data"));
	  return (-1);
	}
      }
      else
      {
        if (paperout && update_state)
	{
	  fputs("STATE: -media-empty-warning\n", stderr);
	  paperout = 0;
	}

	if (offline && update_state)
	{
	  fputs("STATE: -offline-report\n", stderr);
	  _cupsLangPrintFilter(stderr, "INFO",
	                       _("The printer is now connected."));
	  offline = 0;
	}

        fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);

        print_bytes -= bytes;
	print_ptr   += bytes;
	total_bytes += bytes;
      }
    }

   /*
    * Do SNMP updates periodically...
    */

    if (snmp_fd >= 0 && time(&curtime) >= snmp_update)
    {
      if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
        snmp_update = INT_MAX;
      else
        snmp_update = curtime + 5;
    }
  }

 /*
  * Return with success...
  */

  return (total_bytes);
}
Example #25
0
int main(int argc,char *argv[],int *envp[]) {
	int fd11[2],fd12[2], fd21[2],fd22[2];
	int rc;
	pid_t pid1, pid2;
	int status1, status2;
	char String1[100],String2[100];
	int ende1=0,ende2=0;
	int flag=0;
	char ch;

	sigset(SIGUSR2,singal);
	sigset(SIGUSR1,weiter);
	
	rc = pipe(fd11);
	if(rc<0){
		perror("pipe");
		exit(1);
	}
	rc = pipe(fd12);
	if(rc<0){
		perror("pipe");
		exit(1);
	}

	pid1 = fork();
	switch(pid1) {
		case -1:
			perror("1: Es wurde kein Cildprozess erzeugt.\n");
			exit(1);
		case 0:
			close(fd11[0]); //child 1 schreibt nach fd11
			close(fd12[1]); //child 1 liest aus fd12
			/*close(fd21[1]); //child 1 interessiert fd21 und fd22 nicht
			close(fd22[1]);
			close(fd21[0]);
			close(fd22[0]);*/
			while(ende1==0){
				rc = read(fd12[0],String1,sizeof(String1));
				if(rc<0){
					perror("Child 1 Lesefehler:");
					close(fd11[1]); //im fehlerfall gehen beide zu
					close(fd12[0]);
					exit(5);
				}
				printf("%s,%d\n",String1,rc);
				printf("CP1: Bitte eine Eingabe machen oder mit Ctrl-D Beenden.\n");
				if(fgets(String1,100,stdin)==NULL){
					close(fd11[1]); //bei ctrl+d gehen beide zu
					close(fd12[0]);
					ende1=1;
				}else{
					write(fd11[1],String1,sizeof(String1));
				}
			}
			exit(0);
		default:
			close(fd11[1]); //parent liest aus fd11
			close(fd12[0]);	//parent schreibt nach fd12
			break;
	}
	
	rc = pipe(fd21);
	if(rc<0){
		perror("pipe");
		exit(1);
	}
	rc = pipe(fd22);
	if(rc<0){
		perror("pipe");
		exit(1);
	}

	pid2 = fork();
	switch(pid2) {
		case -1:
			perror("2: Es wurde kein Cildprozess erzeugt.\n");
			exit(1);
		case 0:
			close(fd21[0]); //child 2 schreibt nach fd21
			close(fd22[1]); //child 2 liest aus fd22		//child 2 interessiert fd11 und fd12 nicht
			close(fd12[1]);
			close(fd11[0]);
			
			while(ende2==0){
				rc = read(fd22[0],String2,sizeof(String2));
				if(rc<0){
					perror("Child2 : Lesefehler");
					close(fd21[1]); //im fehlerfall gehen beide zu
					close(fd22[0]);
					exit(5);
				}
				printf("%s,%d\n",String2,rc);
				printf("CP2: Bitte eine Eingabe machen oder mit Ctrl-D Beenden.\n");
				if(fgets(String2,100,stdin)==NULL){
					close(fd21[1]); //bei ctrl+d gehen beide zu
					close(fd22[0]);
					ende2=1;
				}else{
					write(fd21[1],String2,sizeof(String2));
				}
			}
			exit(0);
		default:
			close(fd21[1]); //parent liest aus fd21
			close(fd22[0]);	//parent schreibt nach fd22
			break;
	}


	while(ende1 == 0 || ende2 == 0){
		if(ende1==0){
			printf("Child 1 abfragen\n");
			rc = write(fd12[1],"anfang1",8);
			if(rc<=0){
				printf("write 1,%d,%d",pid1,pid2);
				perror("write");
				kill(pid1,SIGUSR2);
				pid1 = waitpid(pid1,&status1,0);
				kill(pid2,SIGUSR2);
				pid2 = waitpid(pid2,&status2,0);
				exit(3);
			}
			rc = read(fd11[0],String1,sizeof(String1));
			switch(rc){
				case -1:
					perror("read");		
					kill(pid1,SIGUSR2);
					pid1 = waitpid(pid1,&status1,0);
					kill(pid2,SIGUSR2);
					pid2 = waitpid(pid2,&status2,0);
					exit(4);
				case 0:
					printf("1 zu\n");
					close(fd12[1]); //leerer String: parent macht pipes zu
					close(fd11[0]);
					ende1=1;
					break;
				default: 
					printf("PP1: %s\n",String1);
					break;
			}
		}
		if(ende2==0){
			printf("%d\n",ende2);
			printf("Child 2 abfragen\n");
			rc = write(fd22[1],"anfang2",8);
			if(rc<=0){
				printf("write 2,%d,%d",pid1,pid2);
				perror("write");
				kill(pid1,SIGUSR2);
				pid1 = waitpid(pid1,&status1,0);
				kill(pid2,SIGUSR2);
				pid2 = waitpid(pid2,&status2,0);
				exit(3);
			}
			rc = read(fd21[0],String2,sizeof(String2));
			switch(rc){
				case -1:
					perror("read");		
					kill(pid1,SIGUSR2);
					pid1 = waitpid(pid1,&status1,0);
					kill(pid2,SIGUSR2);
					pid2 = waitpid(pid2,&status2,0);
					exit(4);
				case 0:
					printf("2 zu\n");
					printf("%d\n",ende2);
					close(fd22[1]); //leerer String: parent macht pipes zu
					close(fd21[0]);
					ende2=1;
					printf("%d\n",ende2);
					break;
				default: 
					printf("PP2: %s\n",String2);
					break;
			}
		}
	}

	pid1 = waitpid(pid1,&status1,0);
	pid2 = waitpid(pid2,&status2,0);

	printf("CP1: Child-PID = %d, status %x %x\n", pid1,(status1>>8) & 0xFF, status1 & 0x7F);
	printf("CP2: Child-PID = %d, status %x %x\n", pid2,(status2>>8) & 0xFF, status2 & 0x7F);
			
	printf("Parent-Prozess ist fertig!\n");
	return 0;
}
Example #26
0
File: kill12.c Project: 1587/ltp
/*--------------------------------------------------------------------*/
int main(int argc, char **argv)
{
/***** BEGINNING OF MAIN. *****/
	int pid, npid;
	int nsig, exno, nexno, status;
	int ret_val = 0;
	int core;
	void chsig();

#ifdef UCLINUX

	tst_parse_opts(argc, argv, NULL, NULL);

	maybe_run_child(&do_child, "dd", &temp, &sig);
#endif

	setup();
	//tempdir();            /* move to new directory */ 12/20/2003
	blenter();

	exno = 1;

	if (sigset(SIGCHLD, chsig) == SIG_ERR) {
		fprintf(temp, "\tsigset failed, errno = %d\n", errno);
		fail_exit();
	}

	for (sig = 1; sig < 14; sig++) {
		fflush(temp);
		chflag = 0;

		pid = FORK_OR_VFORK();
		if (pid < 0) {
			forkfail();
		}

		if (pid == 0) {
#ifdef UCLINUX
			if (self_exec(argv[0], "dd", temp, sig) < 0) {
				tst_brkm(TBROK, NULL, "self_exec FAILED - "
					 "terminating test.");
			}
#else
			do_child();
#endif
		} else {
			//fprintf(temp, "Testing signal %d\n", sig);

			while (!chflag)	/* wait for child */
				sleep(1);

			kill(pid, sig);	/* child should ignroe this sig */
			kill(pid, SIGCHLD);	/* child should exit */

#ifdef BCS
			while ((npid = wait(&status)) != pid
			       || (npid == -1 && errno == EINTR)) ;
			if (npid != pid) {
				fprintf(temp,
					"wait error: wait returned wrong pid\n");
				ret_val = 1;
			}
#else
			while ((npid = waitpid(pid, &status, 0)) != -1
			       || errno == EINTR) ;
#endif

			/*
			   nsig = status & 0177;
			   core = status & 0200;
			   nexno = (status & 0xff00) >> 8;
			 */
			/*****  LTP Port        *****/
			nsig = WTERMSIG(status);
#ifdef WCOREDUMP
			core = WCOREDUMP(status);
#endif
			nexno = WIFEXITED(status);
			/*****  **      **      *****/

			/* nsig is the signal number returned by wait
			   it should be 0, except when sig = 9          */

			if ((sig == 9) && (nsig != sig)) {
				fprintf(temp, "wait error: unexpected signal"
					" returned when the signal sent was 9"
					" The status of the process is %d \n",
					status);
				ret_val = 1;
			}
			if ((sig != 9) && (nsig != 0)) {
				fprintf(temp, "wait error: unexpected signal "
					"returned, the status of the process is "
					"%d  \n", status);
				ret_val = 1;
			}

			/* nexno is the exit number returned by wait
			   it should be 1, except when sig = 9          */

			if (sig == 9)
				if (nexno != 0) {
					fprintf(temp, "signal error: unexpected"
						" exit number returned when"
						" signal sent was 9, the status"
						" of the process is %d \n",
						status);
					ret_val = 1;
				} else;
			else if (nexno != 1) {
				fprintf(temp, "signal error: unexpected exit "
					"number returned,the status of the"
					" process is %d\n", status);
				ret_val = 1;
			}
		}
	}
	if (ret_val)
		local_flag = FAILED;

/*--------------------------------------------------------------------*/
	anyfail();
	tst_exit();
}					/******** END OF MAIN. ********/
Example #27
0
int			/* O - Exit status */
main(int  argc,		/* I - Number of command-line arguments (6 or 7) */
     char *argv[])	/* I - Command-line arguments */
{
  char		method[255],	/* Method in URI */
		hostname[1024],	/* Hostname */
		username[255],	/* Username info (not used) */
		resource[1024],	/* Resource info (device and options) */
		*options;	/* Pointer to options */
  int		port;		/* Port number (not used) */
  int		fp;		/* Print file */
  int		copies;		/* Number of copies to print */
  int		status;		/* Exit status */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;	/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Make sure status messages are not buffered...
  */

  setbuf(stderr, NULL);

 /*
  * Ignore SIGPIPE signals...
  */

#ifdef HAVE_SIGSET
  sigset(SIGPIPE, SIG_IGN);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &action, NULL);
#else
  signal(SIGPIPE, SIG_IGN);
#endif /* HAVE_SIGSET */

 /*
  * Check command-line...
  */

  if (argc == 1)
  {
    list_devices();
    return (CUPS_BACKEND_OK);
  }
  else if (argc < 6 || argc > 7)
  {
    _cupsLangPrintf(stderr,
                    _("Usage: %s job-id user title copies options [file]\n"),
		    argv[0]);
    return (CUPS_BACKEND_FAILED);
  }

 /*
  * If we have 7 arguments, print the file named on the command-line.
  * Otherwise, send stdin instead...
  */

  if (argc == 6)
  {
    fp     = 0;
    copies = 1;
  }
  else
  {
   /*
    * Try to open the print file...
    */

    if ((fp = open(argv[6], O_RDONLY)) < 0)
    {
      perror("ERROR: unable to open print file");
      return (CUPS_BACKEND_FAILED);
    }

    copies = atoi(argv[4]);
  }

 /*
  * Extract the device name and options from the URI...
  */

  httpSeparateURI(HTTP_URI_CODING_ALL, cupsBackendDeviceURI(argv),
                  method, sizeof(method), username, sizeof(username),
		  hostname, sizeof(hostname), &port,
		  resource, sizeof(resource));

 /*
  * See if there are any options...
  */

  if ((options = strchr(resource, '?')) != NULL)
  {
   /*
    * Yup, terminate the device name string and move to the first
    * character of the options...
    */

    *options++ = '\0';
  }

 /*
  * Finally, send the print file...
  */

  status = print_device(resource, fp, copies);

 /*
  * Close input file and return...
  */

  if (fp != 0)
    close(fp);

  return (status);
}
Example #28
0
File: dnssd.c Project: zdohnal/cups
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  const char	*name;			/* Backend name */
  cups_array_t	*devices;		/* Device array */
  cups_device_t	*device;		/* Current device */
  char		uriName[1024];		/* Unquoted fullName for URI */
#ifdef HAVE_DNSSD
  int		fd;			/* Main file descriptor */
  fd_set	input;			/* Input set for select() */
  struct timeval timeout;		/* Timeout for select() */
  DNSServiceRef	main_ref,		/* Main service reference */
		fax_ipp_ref,		/* IPP fax service reference */
		ipp_ref,		/* IPP service reference */
		ipp_tls_ref,		/* IPP w/TLS service reference */
		ipps_ref,		/* IPP service reference */
		local_fax_ipp_ref,	/* Local IPP fax service reference */
		local_ipp_ref,		/* Local IPP service reference */
		local_ipp_tls_ref,	/* Local IPP w/TLS service reference */
		local_ipps_ref,		/* Local IPP service reference */
		local_printer_ref,	/* Local LPD service reference */
		pdl_datastream_ref,	/* AppSocket service reference */
		printer_ref,		/* LPD service reference */
		riousbprint_ref;	/* Remote IO service reference */
#endif /* HAVE_DNSSD */
#ifdef HAVE_AVAHI
  AvahiClient	*client;		/* Client information */
  int		error;			/* Error code, if any */
#endif /* HAVE_AVAHI */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Don't buffer stderr, and catch SIGTERM...
  */

  setbuf(stderr, NULL);

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGTERM, sigterm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  action.sa_handler = sigterm_handler;
  sigaction(SIGTERM, &action, NULL);
#else
  signal(SIGTERM, sigterm_handler);
#endif /* HAVE_SIGSET */

 /*
  * Check command-line...
  */

  if (argc >= 6)
    exec_backend(argv);
  else if (argc != 1)
  {
    _cupsLangPrintf(stderr,
                    _("Usage: %s job-id user title copies options [file]"),
		    argv[0]);
    return (1);
  }

 /*
  * Only do discovery when run as "dnssd"...
  */

  if ((name = strrchr(argv[0], '/')) != NULL)
    name ++;
  else
    name = argv[0];

  if (strcmp(name, "dnssd"))
    return (0);

 /*
  * Create an array to track devices...
  */

  devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);

 /*
  * Browse for different kinds of printers...
  */

#ifdef HAVE_DNSSD
  if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
  {
    perror("ERROR: Unable to create service connection");
    return (1);
  }

  fd = DNSServiceRefSockFD(main_ref);

  fax_ipp_ref = main_ref;
  DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_fax-ipp._tcp", NULL, browse_callback, devices);

  ipp_ref = main_ref;
  DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp._tcp", NULL, browse_callback, devices);

  ipp_tls_ref = main_ref;
  DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp-tls._tcp", NULL, browse_callback, devices);

  ipps_ref = main_ref;
  DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipps._tcp", NULL, browse_callback, devices);

  local_fax_ipp_ref = main_ref;
  DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_fax-ipp._tcp", NULL, browse_local_callback, devices);

  local_ipp_ref = main_ref;
  DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_ipp._tcp", NULL, browse_local_callback, devices);

  local_ipp_tls_ref = main_ref;
  DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
                   "_ipp-tls._tcp", NULL, browse_local_callback, devices);

  local_ipps_ref = main_ref;
  DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_ipps._tcp", NULL, browse_local_callback, devices);

  local_printer_ref = main_ref;
  DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
                   "_printer._tcp", NULL, browse_local_callback, devices);

  pdl_datastream_ref = main_ref;
  DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0,
                   "_pdl-datastream._tcp", NULL, browse_callback, devices);

  printer_ref = main_ref;
  DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0,
                   "_printer._tcp", NULL, browse_callback, devices);

  riousbprint_ref = main_ref;
  DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
                   "_riousbprint._tcp", NULL, browse_callback, devices);
#endif /* HAVE_DNSSD */

#ifdef HAVE_AVAHI
  if ((simple_poll = avahi_simple_poll_new()) == NULL)
  {
    fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr);
    return (0);
  }

  avahi_simple_poll_set_func(simple_poll, poll_callback, NULL);

  client = avahi_client_new(avahi_simple_poll_get(simple_poll),
			    0, client_callback, simple_poll, &error);
  if (!client)
  {
    fputs("DEBUG: Unable to create Avahi client.\n", stderr);
    return (0);
  }

  browsers = 6;
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_fax-ipp._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipp._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipp-tls._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipps._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_pdl-datastream._tcp",
			    NULL, 0,
			    browse_callback,
			    devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_printer._tcp", NULL, 0,
			    browse_callback, devices);
#endif /* HAVE_AVAHI */

 /*
  * Loop until we are killed...
  */

  while (!job_canceled)
  {
    int announce = 0;			/* Announce printers? */

#ifdef HAVE_DNSSD
    FD_ZERO(&input);
    FD_SET(fd, &input);

    timeout.tv_sec  = 0;
    timeout.tv_usec = 500000;

    if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
      continue;

    if (FD_ISSET(fd, &input))
    {
     /*
      * Process results of our browsing...
      */

      DNSServiceProcessResult(main_ref);
    }
    else
      announce = 1;

#elif defined(HAVE_AVAHI)
    got_data = 0;

    if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0)
    {
     /*
      * We've been told to exit the loop.  Perhaps the connection to
      * Avahi failed.
      */

      break;
    }

    if (!got_data)
      announce = 1;
#endif /* HAVE_DNSSD */

/*    fprintf(stderr, "DEBUG: announce=%d\n", announce);*/

    if (announce)
    {
     /*
      * Announce any devices we've found...
      */

#ifdef HAVE_DNSSD
      DNSServiceErrorType status;	/* DNS query status */
#endif /* HAVE_DNSSD */
      cups_device_t *best;		/* Best matching device */
      char	device_uri[1024];	/* Device URI */
      int	count;			/* Number of queries */
      int	sent;			/* Number of sent */

      for (device = (cups_device_t *)cupsArrayFirst(devices),
               best = NULL, count = 0, sent = 0;
           device;
	   device = (cups_device_t *)cupsArrayNext(devices))
      {
        if (device->sent)
	  sent ++;

        if (device->ref)
	  count ++;

        if (!device->ref && !device->sent)
	{
	 /*
	  * Found the device, now get the TXT record(s) for it...
	  */

          if (count < 50)
	  {
	    fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName);

#ifdef HAVE_DNSSD
	    device->ref = main_ref;

	    status = DNSServiceQueryRecord(&(device->ref),
				           kDNSServiceFlagsShareConnection,
				           0, device->fullName,
					   kDNSServiceType_TXT,
				           kDNSServiceClass_IN, query_callback,
				           device);
            if (status != kDNSServiceErr_NoError)
	      fprintf(stderr,
	              "ERROR: Unable to query \"%s\" for TXT records: %d\n",
	              device->fullName, status);
	              			/* Users never see this */
	    else
	      count ++;

#else
	    if ((device->ref = avahi_record_browser_new(client, AVAHI_IF_UNSPEC,
	                                                AVAHI_PROTO_UNSPEC,
	                                                device->fullName,
	                                                AVAHI_DNS_CLASS_IN,
	                                                AVAHI_DNS_TYPE_TXT,
	                                                0,
				                        query_callback,
				                        device)) == NULL)
	      fprintf(stderr,
	              "ERROR: Unable to query \"%s\" for TXT records: %s\n",
	              device->fullName,
	              avahi_strerror(avahi_client_errno(client)));
	              			/* Users never see this */
	    else
	      count ++;
#endif /* HAVE_AVAHI */
          }
	}
	else if (!device->sent)
	{
#ifdef HAVE_DNSSD
	 /*
	  * Got the TXT records, now report the device...
	  */

	  DNSServiceRefDeallocate(device->ref);
#else
          avahi_record_browser_free(device->ref);
#endif /* HAVE_DNSSD */

	  device->ref = NULL;

          if (!best)
	    best = device;
	  else if (_cups_strcasecmp(best->name, device->name) ||
	           _cups_strcasecmp(best->domain, device->domain))
          {
	    unquote(uriName, best->fullName, sizeof(uriName));

            if (best->uuid)
	      httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
	                       sizeof(device_uri), "dnssd", NULL, uriName, 0,
			       best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
			       best->uuid);
	    else
	      httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
	                      sizeof(device_uri), "dnssd", NULL, uriName, 0,
			      best->cups_shared ? "/cups" : "/");

	    cupsBackendReport("network", device_uri, best->make_and_model,
	                      best->name, best->device_id, NULL);
	    best->sent = 1;
	    best       = device;

	    sent ++;
	  }
	  else if (best->priority > device->priority ||
	           (best->priority == device->priority &&
		    best->type < device->type))
          {
	    best->sent = 1;
	    best       = device;

	    sent ++;
	  }
	  else
	  {
	    device->sent = 1;

	    sent ++;
	  }
        }
      }

      if (best)
      {
	unquote(uriName, best->fullName, sizeof(uriName));

	if (best->uuid)
	  httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
			   sizeof(device_uri), "dnssd", NULL, uriName, 0,
			   best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
			   best->uuid);
	else
	  httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
			  sizeof(device_uri), "dnssd", NULL, uriName, 0,
			  best->cups_shared ? "/cups" : "/");

	cupsBackendReport("network", device_uri, best->make_and_model,
			  best->name, best->device_id, NULL);
	best->sent = 1;
	sent ++;
      }

      fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count);

#ifdef HAVE_AVAHI
      if (sent == cupsArrayCount(devices) && browsers == 0)
#else
      if (sent == cupsArrayCount(devices))
#endif /* HAVE_AVAHI */
	break;
    }
  }

  return (CUPS_BACKEND_OK);
}
Example #29
0
int
main(int argc, char **argv)
{
    int rflag = 0, sflag = 0, xflag = 0, Fflag = 0;
    int errflg = 0, Sflag = 0;
    int rc = 0;
    int opt;
    const char *bar8 = "-------";
    const char *bar16 = "----------";
    const char *bar;
    struct rlimit rlim;
    struct stat64 statbuf;
    char buf[128];
    int mapfd;
    int prg_gflags = PGRAB_RDONLY;
    int prr_flags = 0;
    boolean_t use_agent_lwp = B_FALSE;

    if ((command = strrchr(argv[0], '/')) != NULL)
        command++;
    else
        command = argv[0];

    while ((opt = getopt(argc, argv, "arsxSlLFA:")) != EOF) {
        switch (opt) {
        case 'a':		/* include shared mappings in -[xS] */
            aflag = 1;
            break;
        case 'r':		/* show reserved mappings */
            rflag = 1;
            break;
        case 's':		/* show hardware page sizes */
            sflag = 1;
            break;
        case 'S':		/* show swap reservations */
            Sflag = 1;
            break;
        case 'x':		/* show extended mappings */
            xflag = 1;
            break;
        case 'l':		/* show unresolved link map names */
            lflag = 1;
            break;
        case 'L':		/* show lgroup information */
            Lflag = 1;
            use_agent_lwp = B_TRUE;
            break;
        case 'F':		/* force grabbing (no O_EXCL) */
            Fflag = PGRAB_FORCE;
            break;
        case 'A':
            if (parse_addr_range(optarg, &start_addr, &end_addr)
                    != 0)
                errflg++;
            break;
        default:
            errflg = 1;
            break;
        }
    }

    argc -= optind;
    argv += optind;

    if ((Sflag && (xflag || rflag || sflag)) || (xflag && rflag) ||
            (aflag && (!xflag && !Sflag)) ||
            (Lflag && (xflag || Sflag))) {
        errflg = 1;
    }

    if (errflg || argc <= 0) {
        (void) fprintf(stderr,
                       "usage:\t%s [-rslF] [-A start[,end]] { pid | core } ...\n",
                       command);
        (void) fprintf(stderr,
                       "\t\t(report process address maps)\n");
        (void) fprintf(stderr,
                       "\t%s -L [-rslF] [-A start[,end]] pid ...\n", command);
        (void) fprintf(stderr,
                       "\t\t(report process address maps lgroups mappings)\n");
        (void) fprintf(stderr,
                       "\t%s -x [-aslF] [-A start[,end]] pid ...\n", command);
        (void) fprintf(stderr,
                       "\t\t(show resident/anon/locked mapping details)\n");
        (void) fprintf(stderr,
                       "\t%s -S [-alF] [-A start[,end]] { pid | core } ...\n",
                       command);
        (void) fprintf(stderr,
                       "\t\t(show swap reservations)\n\n");
        (void) fprintf(stderr,
                       "\t-a: include shared mappings in -[xS] summary\n");
        (void) fprintf(stderr,
                       "\t-r: show reserved address maps\n");
        (void) fprintf(stderr,
                       "\t-s: show hardware page sizes\n");
        (void) fprintf(stderr,
                       "\t-l: show unresolved dynamic linker map names\n");
        (void) fprintf(stderr,
                       "\t-F: force grabbing of the target process\n");
        (void) fprintf(stderr,
                       "\t-L: show lgroup mappings\n");
        (void) fprintf(stderr,
                       "\t-A start,end: limit output to the specified range\n");
        return (2);
    }

    /*
     * Make sure we'll have enough file descriptors to handle a target
     * that has many many mappings.
     */
    if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
        rlim.rlim_cur = rlim.rlim_max;
        (void) setrlimit(RLIMIT_NOFILE, &rlim);
        (void) enable_extended_FILE_stdio(-1, -1);
    }

    /*
     * The implementation of -L option creates an agent LWP in the target
     * process address space. The agent LWP issues meminfo(2) system calls
     * on behalf of the target process. If we are interrupted prematurely,
     * the target process remains in the stopped state with the agent still
     * attached to it. To prevent such situation we catch signals from
     * terminal and terminate gracefully.
     */
    if (use_agent_lwp) {
        /*
         * Buffer output to stdout, stderr while process is grabbed.
         * Prevents infamous deadlocks due to pmap `pgrep xterm` and
         * other variants.
         */
        (void) proc_initstdio();

        prg_gflags = PGRAB_RETAIN | Fflag;
        prr_flags = PRELEASE_RETAIN;

        if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
            (void) sigset(SIGHUP, intr);
        if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
            (void) sigset(SIGINT, intr);
        if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
            (void) sigset(SIGQUIT, intr);
        (void) sigset(SIGPIPE, intr);
        (void) sigset(SIGTERM, intr);
    }

    while (argc-- > 0) {
        char *arg;
        int gcode;
        psinfo_t psinfo;
        int tries = 0;

        if (use_agent_lwp)
            (void) proc_flushstdio();

        if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY,
                                prg_gflags, &gcode)) == NULL) {
            (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
                           command, arg, Pgrab_error(gcode));
            rc++;
            continue;
        }

        procname = arg;		/* for perr() */

        addr_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 16 : 8;
        size_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 11 : 8;
        bar = addr_width == 8 ? bar8 : bar16;
        (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
        proc_unctrl_psinfo(&psinfo);

        if (Pstate(Pr) != PS_DEAD) {
            (void) snprintf(buf, sizeof (buf),
                            "/proc/%d/map", (int)psinfo.pr_pid);
            if ((mapfd = open(buf, O_RDONLY)) < 0) {
                (void) fprintf(stderr, "%s: cannot "
                               "examine %s: lost control of "
                               "process\n", command, arg);
                rc++;
                Prelease(Pr, prr_flags);
                continue;
            }
        } else {
            mapfd = -1;
        }

again:
        map_count = 0;

        if (Pstate(Pr) == PS_DEAD) {
            (void) printf("core '%s' of %d:\t%.70s\n",
                          arg, (int)psinfo.pr_pid, psinfo.pr_psargs);

            if (rflag || sflag || xflag || Sflag || Lflag) {
                (void) printf("  -%c option is not compatible "
                              "with core files\n", xflag ? 'x' :
                              sflag ? 's' : rflag ? 'r' :
                              Lflag ? 'L' : 'S');
                Prelease(Pr, prr_flags);
                rc++;
                continue;
            }

        } else {
            (void) printf("%d:\t%.70s\n",
                          (int)psinfo.pr_pid, psinfo.pr_psargs);
        }

        if (!(Pstatus(Pr)->pr_flags & PR_ISSYS)) {
            struct totals t;

            /*
             * Since we're grabbing the process readonly, we need
             * to make sure the address space doesn't change during
             * execution.
             */
            if (Pstate(Pr) != PS_DEAD) {
                if (tries++ == MAX_TRIES) {
                    Prelease(Pr, prr_flags);
                    (void) close(mapfd);
                    (void) fprintf(stderr, "%s: cannot "
                                   "examine %s: address space is "
                                   "changing\n", command, arg);
                    continue;
                }

                if (fstat64(mapfd, &statbuf) != 0) {
                    Prelease(Pr, prr_flags);
                    (void) close(mapfd);
                    (void) fprintf(stderr, "%s: cannot "
                                   "examine %s: lost control of "
                                   "process\n", command, arg);
                    continue;
                }
            }

            nstacks = psinfo.pr_nlwp * 2;
            stacks = calloc(nstacks, sizeof (stacks[0]));
            if (stacks != NULL) {
                int n = 0;
                (void) Plwp_iter(Pr, getstack, &n);
                qsort(stacks, nstacks, sizeof (stacks[0]),
                      cmpstacks);
            }

            (void) memset(&t, 0, sizeof (t));

            if (Pgetauxval(Pr, AT_BASE) != -1L &&
                    Prd_agent(Pr) == NULL) {
                (void) fprintf(stderr, "%s: warning: "
                               "librtld_db failed to initialize; "
                               "shared library information will not be "
                               "available\n", command);
            }

            /*
             * Gather data
             */
            if (xflag)
                rc += xmapping_iter(Pr, gather_xmap, NULL, 0);
            else if (Sflag)
                rc += xmapping_iter(Pr, gather_xmap, NULL, 1);
            else {
                if (rflag)
                    rc += rmapping_iter(Pr, gather_map,
                                        NULL);
                else if (sflag)
                    rc += xmapping_iter(Pr, gather_xmap,
                                        NULL, 0);
                else if (lflag)
                    rc += Pmapping_iter(Pr,
                                        gather_map, NULL);
                else
                    rc += Pmapping_iter_resolved(Pr,
                                                 gather_map, NULL);
            }

            /*
             * Ensure mappings are consistent.
             */
            if (Pstate(Pr) != PS_DEAD) {
                struct stat64 newbuf;

                if (fstat64(mapfd, &newbuf) != 0 ||
                        memcmp(&newbuf.st_mtim, &statbuf.st_mtim,
                               sizeof (newbuf.st_mtim)) != 0) {
                    if (stacks != NULL) {
                        free(stacks);
                        stacks = NULL;
                    }
                    goto again;
                }
            }

            /*
             * Display data.
             */
            if (xflag) {
                (void) printf("%*s%*s%*s%*s%*s "
                              "%sMode   Mapped File\n",
                              addr_width, "Address",
                              size_width, "Kbytes",
                              size_width, "RSS",
                              size_width, "Anon",
                              size_width, "Locked",
                              sflag ? "Pgsz " : "");

                rc += iter_xmap(sflag ?  look_xmap :
                                look_xmap_nopgsz, &t);

                (void) printf("%s%s %s %s %s %s\n",
                              addr_width == 8 ? "-" : "------",
                              bar, bar, bar, bar, bar);

                (void) printf("%stotal Kb", addr_width == 16 ?
                              "        " : "");

                printK(t.total_size, size_width);
                printK(t.total_rss, size_width);
                printK(t.total_anon, size_width);
                printK(t.total_locked, size_width);

                (void) printf("\n");

            } else if (Sflag) {
                (void) printf("%*s%*s%*s Mode"
                              " Mapped File\n",
                              addr_width, "Address",
                              size_width, "Kbytes",
                              size_width, "Swap");

                rc += iter_xmap(look_xmap_nopgsz, &t);

                (void) printf("%s%s %s %s\n",
                              addr_width == 8 ? "-" : "------",
                              bar, bar, bar);

                (void) printf("%stotal Kb", addr_width == 16 ?
                              "        " : "");

                printK(t.total_size, size_width);
                printK(t.total_swap, size_width);

                (void) printf("\n");

            } else {

                if (rflag) {
                    rc += iter_map(look_map, &t);
                } else if (sflag) {
                    if (Lflag) {
                        (void) printf("%*s %*s %4s"
                                      " %-6s %s %s\n",
                                      addr_width, "Address",
                                      size_width,
                                      "Bytes", "Pgsz", "Mode ",
                                      "Lgrp", "Mapped File");
                        rc += iter_xmap(look_smap, &t);
                    } else {
                        (void) printf("%*s %*s %4s"
                                      " %-6s %s\n",
                                      addr_width, "Address",
                                      size_width,
                                      "Bytes", "Pgsz", "Mode ",
                                      "Mapped File");
                        rc += iter_xmap(look_smap, &t);
                    }
                } else {
                    rc += iter_map(look_map, &t);
                }

                (void) printf(" %stotal  %*luK\n",
                              addr_width == 16 ?
                              "        " : "",
                              size_width, t.total_size);
            }

            if (stacks != NULL) {
                free(stacks);
                stacks = NULL;
            }

        }

        Prelease(Pr, prr_flags);
        if (mapfd != -1)
            (void) close(mapfd);
    }

    if (use_agent_lwp)
        (void) proc_finistdio();

    return (rc);
}
Example #30
0
/* VARARGS */
int
main(int argc, char **argv)
{
    int c, rem;
    char *cmd, *cp, **ap, buf[RSH_BUFSIZ], **argv0, *args, *args_no_x;
    char *host = NULL, *user = NULL;
    int cc;
    boolean_t asrsh = B_FALSE;
    struct passwd *pwd;
    boolean_t readfrom_rem;
    boolean_t readfrom_rfd2;
    int one = 1;
    int omask;
    boolean_t nflag = B_FALSE;
    char *krb_realm = NULL;
    krb5_flags authopts;
    krb5_error_code status;
    enum kcmd_proto kcmd_proto = KCMD_NEW_PROTOCOL;
    uid_t uid = getuid();

    c = (argc + 1) * sizeof (char *);
    if ((argv0 = malloc(c)) == NULL) {
        perror("malloc");
        return (EXIT_FAILURE);
    }
    (void) memcpy(argv0, argv, c);

    (void) setlocale(LC_ALL, "");

    (void) textdomain(TEXT_DOMAIN);

    /*
     * Determine command name used to invoke to rlogin(1). Users can
     * create links named by a host pointing to the binary and type
     * "hostname" to log into that host afterwards.
     */
    cmd = strrchr(argv[0], '/');
    cmd = (cmd != NULL) ? (cmd + 1) : argv[0];

    /*
     *	Add "remsh" as an alias for "rsh" (System III, V networking
     *	add-ons often used this name for the remote shell since rsh
     *	was already taken for the restricted shell).  Note that this
     *	usurps the ability to use "remsh" as the name of a host (by
     *	symlinking it to rsh), so we go one step farther:  if the
     *	file "/usr/bin/remsh" does not exist, we behave as if "remsh"
     *	is a host name.  If it does exist, we accept "remsh" as an
     *	"rsh" alias.
     */
    if (strcmp(cmd, "remsh") == 0) {
        struct stat sb;

        if (stat("/usr/bin/remsh", &sb) < 0)
            host = cmd;
    } else if (strcmp(cmd, "rsh") != 0) {
        host = cmd;
    }

    /* Handle legacy synopsis "rsh hostname options [command]". */
    if (host == NULL) {
        if (argc < 2)
            usage();
        if (*argv[1] != '-') {
            host = argv[1];
            argc--;
            argv[1] = argv[0];
            argv++;
            asrsh = B_TRUE;
        }
    }

    while ((c = getopt(argc, argv,
                       DEBUGOPTSTRING "8AFKLP:ade:fk:l:nwx")) != -1) {
        switch (c) {
#ifdef DEBUG
        case 'D':
            portnumber = htons(atoi(optarg));
            krb5auth_flag++;
            break;
#endif /* DEBUG */
        case 'F':
            if (fflag)
                usage_forward();
            Fflag = 1;
            krb5auth_flag++;
            fwdable_done = B_TRUE;
            break;
        case 'f':
            if (Fflag)
                usage_forward();
            fflag = 1;
            krb5auth_flag++;
            fwd_done = B_TRUE;
            break;
        case 'P':
            if (strcmp(optarg, "N") == 0)
                kcmd_proto = KCMD_NEW_PROTOCOL;
            else if (strcmp(optarg, "O") == 0)
                kcmd_proto = KCMD_OLD_PROTOCOL;
            else
                die(gettext("rsh: Only -PN or -PO "
                            "allowed.\n"));
            if (rcmdoption_done)
                die(gettext("rsh: Only one of -PN and -PO "
                            "allowed.\n"));
            rcmdoption_done = B_TRUE;
            krb5auth_flag++;
            break;
        case 'a':
            krb5auth_flag++;
            break;
        case 'K':
            no_krb5auth_flag++;
            break;
        case 'd':
            options |= SO_DEBUG;
            break;
        case 'k':
            krb_realm = optarg;
            krb5auth_flag++;
            break;
        case 'l':
            user = optarg;
            break;
        case 'n':
            if (!nflag) {
                if (close(STDIN_FILENO) < 0) {
                    perror("close");
                    return (EXIT_FAILURE);
                }
                /*
                 * "STDION_FILENO" defined to 0 by POSIX
                 * and hence the lowest file descriptor.
                 * So the open(2) below is guaranteed to
                 * reopen it because we closed it above.
                 */
                if (open("/dev/null", O_RDONLY) < 0) {
                    perror("open");
                    return (EXIT_FAILURE);
                }
                nflag = B_TRUE;
            }
            break;
        case 'x':
            encrypt_flag = 1;
            krb5auth_flag++;
            encrypt_done = B_TRUE;
            break;
        /*
         * Ignore the -L, -w, -e and -8 flags to allow aliases with
         * rlogin to work. Actually rlogin(1) doesn't understand
         * -w either but because "rsh -w hostname command" used
         * to work we still accept it.
         */
        case '8':
        case 'L':
        case 'e':
        case 'w':
        /*
         * On the lines of the -L, -w, -e and -8 options above, we
         * ignore the -A option too, in order to allow aliases with
         * rlogin to work.
         *
         * Mind you !, the -a option to trigger Kerberos authentication
         * in rsh, has a totally different usage in rlogin, its the
         * -A option (in rlogin) which needs to be used to talk
         * Kerberos.
         */
        case 'A':
            break;
        default:
            usage();
        }
    }

    argc -= optind;
    argv += optind;

    if (host == NULL) {
        if (argc == 0)
            usage();
        argc--;
        host = *argv++;
        asrsh = B_TRUE;
    }

    if (argc == 0) {
        (void) setreuid(uid, uid);
        if (nflag)
            usage();
        if (asrsh)
            *argv0 = "rlogin";
        (void) execv(rlogin_path, argv0);
        perror(rlogin_path);

        (void) fprintf(stderr, gettext("No local rlogin "
                                       "program found.\n"));
        return (EXIT_FAILURE);
    }

    if (__init_suid_priv(0, PRIV_NET_PRIVADDR, NULL) == -1) {
        (void) fprintf(stderr,
                       gettext("Insufficient privileges, "
                               "rsh must be set-uid root\n"));
        return (EXIT_FAILURE);
    }

    pwd = getpwuid(uid);
    if (pwd == NULL) {
        (void) fprintf(stderr, gettext("who are you?\n"));
        return (EXIT_FAILURE);
    }
    if (user == NULL)
        user = pwd->pw_name;

    /*
     * if the user disables krb5 on the cmdline (-K), then skip
     * all krb5 setup.
     *
     * if the user does not disable krb5 or enable krb5 on the
     * cmdline, check krb5.conf to see if it should be enabled.
     */

    if (no_krb5auth_flag) {
        krb5auth_flag = 0;
        Fflag = fflag = encrypt_flag = 0;
    } else if (!krb5auth_flag) {
        /* is autologin set in krb5.conf? */
        status = krb5_init_context(&bsd_context);
        /* don't sweat failure here */
        if (!status) {
            /*
             * note that the call to profile_get_options_boolean
             * with autologin_option can affect value of
             * krb5auth_flag
             */
            (void) profile_get_options_boolean(bsd_context->profile,
                                               appdef,
                                               autologin_option);
        }
    }

    if (krb5auth_flag) {
        if (!bsd_context) {
            status = krb5_init_context(&bsd_context);
            if (status) {
                com_err("rsh", status,
                        "while initializing krb5");
                return (EXIT_FAILURE);

            }
        }

        /*
         * Get our local realm to look up local realm options.
         */
        status = krb5_get_default_realm(bsd_context, &realmdef[1]);
        if (status) {
            com_err("rsh", status,
                    gettext("while getting default realm"));
            return (EXIT_FAILURE);
        }
        /*
         * Check the realms section in krb5.conf for encryption,
         * forward & forwardable info
         */
        profile_get_options_boolean(bsd_context->profile, realmdef,
                                    option);
        /*
         * Check the appdefaults section
         */
        profile_get_options_boolean(bsd_context->profile, appdef,
                                    option);
        profile_get_options_string(bsd_context->profile, appdef,
                                   rcmdversion);
        /*
         * Set the *_flag variables, if the corresponding *_done are
         * set to 1, because we dont want the config file values
         * overriding the command line options.
         */
        if (encrypt_done)
            encrypt_flag = 1;
        if (fwd_done) {
            fflag = 1;
            Fflag = 0;
        } else if (fwdable_done) {
            Fflag = 1;
            fflag = 0;
        }
        if (!rcmdoption_done && (rcmdproto != NULL)) {
            if (strncmp(rcmdproto, "rcmdv2", 6) == 0) {
                kcmd_proto = KCMD_NEW_PROTOCOL;
            } else if (strncmp(rcmdproto, "rcmdv1", 6) == 0) {
                kcmd_proto = KCMD_OLD_PROTOCOL;
            } else {
                (void) fprintf(stderr, gettext("Unrecognized "
                                               "KCMD protocol (%s)"), rcmdproto);
                return (EXIT_FAILURE);
            }
        }


        if (encrypt_flag && (!krb5_privacy_allowed())) {
            (void) fprintf(stderr, gettext("rsh: Encryption not "
                                           "supported.\n"));
            return (EXIT_FAILURE);
        }
    }

    /*
     * Connect with the service (shell/kshell) on the daemon side
     */
    if (portnumber == 0) {
        while (!init_service(krb5auth_flag)) {
            /*
             * Connecting to the 'kshell' service failed,
             * fallback to normal rsh; Reset all KRB5 flags
             * and connect to 'shell' service on the server
             */
            krb5auth_flag = 0;
            encrypt_flag = fflag = Fflag = 0;
        }
    }

    cc = encrypt_flag ? strlen(dash_x) : 0;
    for (ap = argv; *ap != NULL; ap++)
        cc += strlen(*ap) + 1;
    cp = args = malloc(cc);
    if (cp == NULL)
        perror("malloc");
    if (encrypt_flag) {
        int length;

        length = strlcpy(args, dash_x, cc);
        cp += length;
        cc -= length;
    }
    args_no_x = args;

    for (ap = argv; *ap != NULL; ap++) {
        int length;

        length = strlcpy(cp, *ap, cc);
        assert(length < cc);
        cp += length;
        cc -= length;
        if (ap[1] != NULL) {
            *cp++ = ' ';
            cc--;
        }
    }

    if (krb5auth_flag) {
        authopts = AP_OPTS_MUTUAL_REQUIRED;
        /*
         * Piggy-back forwarding flags on top of authopts;
         * they will be reset in kcmd
         */
        if (fflag || Fflag)
            authopts |= OPTS_FORWARD_CREDS;
        if (Fflag)
            authopts |= OPTS_FORWARDABLE_CREDS;

        status = kcmd(&rem, &host, portnumber,
                      pwd->pw_name, user,
                      args, &rfd2, "host", krb_realm,
                      bsd_context, &auth_context, &cred,
                      NULL,	/* No need for sequence number */
                      NULL,	/* No need for server seq # */
                      authopts,
                      1,	/* Always set anyport */
                      &kcmd_proto);
        if (status != 0) {
            /*
             * If new protocol requested, we dont fallback to
             * less secure ones.
             */
            if (kcmd_proto == KCMD_NEW_PROTOCOL) {
                (void) fprintf(stderr, gettext("rsh: kcmdv2 "
                                               "to host %s failed - %s\n"
                                               "Fallback to normal rsh denied."),
                               host, error_message(status));
                return (EXIT_FAILURE);
            }
            /* check NO_TKT_FILE or equivalent... */
            if (status != -1) {
                (void) fprintf(stderr,
                               gettext("rsh: kcmd to host %s failed - %s\n"
                                       "trying normal rsh...\n\n"),
                               host, error_message(status));
            } else {
                (void) fprintf(stderr,
                               gettext("trying normal rsh...\n"));
            }
            /*
             * kcmd() failed, so we now fallback to normal rsh,
             * after resetting the KRB5 flags and the 'args' array
             */
            krb5auth_flag = 0;
            encrypt_flag = fflag = Fflag = 0;
            args = args_no_x;
            (void) init_service(B_FALSE);
        } else {
            /*
             * Set up buffers for desread and deswrite.
             */
            desinbuf.data = des_inbuf;
            desoutbuf.data = des_outbuf;
            desinbuf.length = sizeof (des_inbuf);
            desoutbuf.length = sizeof (des_outbuf);

            session_key = &cred->keyblock;

            if (kcmd_proto == KCMD_NEW_PROTOCOL) {
                status = krb5_auth_con_getlocalsubkey(
                             bsd_context,
                             auth_context,
                             &session_key);
                if (status) {
                    com_err("rsh", status,
                            "determining subkey for session");
                    return (EXIT_FAILURE);
                }
                if (session_key == NULL) {
                    com_err("rsh", 0, "no subkey "
                            "negotiated for connection");
                    return (EXIT_FAILURE);
                }
            }

            eblock.crypto_entry = session_key->enctype;
            eblock.key = (krb5_keyblock *)session_key;

            init_encrypt(encrypt_flag, bsd_context, kcmd_proto,
                         &desinbuf, &desoutbuf, CLIENT, &eblock);
            if (encrypt_flag) {
                char *s = gettext("This rsh session is using "
                                  "encryption for all data transmissions.");
                (void) write(STDERR_FILENO, s, strlen(s));
                (void) write(STDERR_FILENO, "\r\n", 2);
            }
        }
    }

    /*
     * Don't merge this with the "if" statement above because
     * "krb5auth_flag" might be set to false inside it.
     */
    if (!krb5auth_flag) {
        rem = rcmd_af(&host, portnumber, pwd->pw_name, user, args,
                      &rfd2, AF_INET6);
        if (rem < 0)
            return (EXIT_FAILURE);
    }
    __priv_relinquish();

    if (rfd2 < 0) {
        (void) fprintf(stderr, gettext("rsh: can't establish "
                                       "stderr\n"));
        return (EXIT_FAILURE);
    }
    if (options & SO_DEBUG) {
        if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, (char *)&one,
                       sizeof (one)) < 0)
            perror("rsh: setsockopt (stdin)");
        if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, (char *)&one,
                       sizeof (one)) < 0)
            perror("rsh: setsockopt (stderr)");
    }
    omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));

    if (sigdisp(SIGINT) != SIG_IGN)
        (void) sigset(SIGINT, sendsig);
    if (sigdisp(SIGQUIT) != SIG_IGN)
        (void) sigset(SIGQUIT, sendsig);
    if (sigdisp(SIGTERM) != SIG_IGN)
        (void) sigset(SIGTERM, sendsig);

    if (nflag) {
        (void) shutdown(rem, SHUT_WR);
    } else {
        child_pid = fork();
        if (child_pid < 0) {
            perror("rsh: fork");
            return (EXIT_FAILURE);
        }

        if (!encrypt_flag) {
            (void) ioctl(rfd2, FIONBIO, &one);
            (void) ioctl(rem, FIONBIO, &one);
        }

        if (child_pid == 0) {
            /* Child */
            fd_set remset;
            char *bp;
            int  wc;
            (void) close(rfd2);
reread:
            errno = 0;
            cc = read(0, buf, sizeof (buf));
            if (cc <= 0)
                goto done;
            bp = buf;
rewrite:
            FD_ZERO(&remset);
            FD_SET(rem, &remset);
            if (select(rem + 1, NULL, &remset, NULL, NULL) < 0) {
                if (errno != EINTR) {
                    perror("rsh: select");
                    return (EXIT_FAILURE);
                }
                goto rewrite;
            }
            if (!FD_ISSET(rem, &remset))
                goto rewrite;
            writeiv = B_FALSE;
            wc = desrshwrite(rem, bp, cc);
            if (wc < 0) {
                if (errno == EWOULDBLOCK)
                    goto rewrite;
                goto done;
            }
            cc -= wc;
            bp += wc;
            if (cc == 0)
                goto reread;
            goto rewrite;
done:
            (void) shutdown(rem, SHUT_WR);
            return (EXIT_SUCCESS);
        }
    }

#define	MAX(a, b)	(((a) > (b)) ? (a) : (b))

    sigsetmask(omask);
    readfrom_rem = B_TRUE;
    readfrom_rfd2 = B_TRUE;
    (void) sigset(SIGPIPE, sigpipehandler);
    do {
        fd_set readyset;

        FD_ZERO(&readyset);
        if (readfrom_rem)
            FD_SET(rem, &readyset);
        if (readfrom_rfd2)
            FD_SET(rfd2, &readyset);
        if (select(MAX(rem, rfd2) + 1, &readyset, NULL, NULL,
                   NULL) < 0) {
            if (errno != EINTR) {
                perror("rsh: select");
                return (EXIT_FAILURE);
            }
            continue;
        }
        if (FD_ISSET(rfd2, &readyset)) {
            errno = 0;
            readiv = B_TRUE;
            cc = desrshread(rfd2, buf, sizeof (buf));
            if (cc <= 0) {
                if (errno != EWOULDBLOCK)
                    readfrom_rfd2 = B_FALSE;
            } else {
                (void) write(STDERR_FILENO, buf, cc);
            }
        }
        if (FD_ISSET(rem, &readyset)) {
            errno = 0;
            readiv = B_FALSE;
            cc = desrshread(rem, buf, sizeof (buf));
            if (cc <= 0) {
                if (errno != EWOULDBLOCK)
                    readfrom_rem = B_FALSE;
            } else
                (void) write(STDOUT_FILENO, buf, cc);
        }
    } while (readfrom_rem || readfrom_rfd2);

    if (!nflag)
        (void) kill(child_pid, SIGKILL);
    return (EXIT_SUCCESS);
}