* cfstr_create_trim() - Create CFString and trim whitespace characters.
* parse_options() - Parse uri options.
* setup_cfLanguage() - Create AppleLanguages array from LANG environment var.
-* run_ppc_backend() - Re-exec i386 backend as ppc.
+* run_legacy_backend() - Re-exec backend as ppc or i386.
* sigterm_handler() - SIGTERM handler.
* next_line() - Find the next line in a buffer.
* parse_pserror() - Scan the backchannel data for postscript errors.
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
+#include <spawn.h>
#include <pthread.h>
+extern char **environ;
+
/*
* WAIT_EOF_DELAY is number of seconds we'll wait for responses from
static void soft_reset();
static void status_timer_cb(CFRunLoopTimerRef timer, void *info);
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
static pid_t child_pid; /* Child PID */
-static void run_ppc_backend(int argc, char *argv[], int fd); /* Starts child backend process running as a ppc executable */
+static void run_legacy_backend(int argc, char *argv[], int fd); /* Starts child backend process running as a ppc executable */
static void sigterm_handler(int sig); /* SIGTERM handler */
-#endif /* __i386__ */
+#endif /* __i386__ || __x86_64__ */
#ifdef PARSE_PS_ERRORS
static const char *next_line (const char *buffer);
status = registry_open(&driverBundlePath);
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
/*
- * If we were unable to load the class drivers for this printer it's probably because they're ppc-only.
- * In this case try to fork & exec this backend as a ppc executable so we can use them...
+ * If we were unable to load the class drivers for this printer it's
+ * probably because they're ppc or i386. In this case try to run this
+ * backend as i386 or ppc executables so we can use them...
*/
if (status == -2)
{
- run_ppc_backend(argc, argv, print_fd);
+ run_legacy_backend(argc, argv, print_fd);
/* Never returns here */
}
-#endif /* __i386__ */
+#endif /* __i386__ || __x86_64__ */
if (status == -2)
{
if (print_fd != STDIN_FILENO)
{
- fputs("PAGE: 1 1", stderr);
+ fputs("PAGE: 1 1\n", stderr);
lseek(print_fd, 0, SEEK_SET);
}
httpAssembleURI(HTTP_URI_CODING_ALL, uristr, sizeof(uristr), "usb", NULL, makestr, 0, modelstr);
strncat(uristr, optionsstr, sizeof(uristr));
- printf("direct %s \"%s\" \"%s USB\" \"%s\"\n", uristr, make_modelstr,
- make_modelstr, idstr);
+ cupsBackendReport("direct", uristr, make_modelstr, make_modelstr, idstr,
+ NULL);
release_deviceinfo(&make, &model, &serial);
CFRelease(deviceIDString);
void *info)
{
fputs("STATE: +offline-error\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is currently offline.\n"));
+ _cupsLangPuts(stderr, _("INFO: Printer is offline.\n"));
if (getenv("CLASS") != NULL)
{
}
#pragma mark -
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
/*!
- * @function run_ppc_backend
+ * @function run_legacy_backend
*
- * @abstract Starts child backend process running as a ppc executable.
+ * @abstract Starts child backend process running as a ppc or i386 executable.
*
* @result Never returns; always calls exit().
*
* @discussion
*/
-static void run_ppc_backend(int argc,
- char *argv[],
- int fd)
+static void run_legacy_backend(int argc,
+ char *argv[],
+ int fd)
{
int i;
int exitstatus = 0;
int childstatus;
pid_t waitpid_status;
char *my_argv[32];
- char *usb_ppc_status;
+ char *usb_legacy_status;
- /*
- * If we're running as i386 and couldn't load the class driver (because they'it's
- * ppc-only) then try to re-exec ourselves in ppc mode to try again. If we don't have
- * a ppc architecture we may be running i386 again so guard against this by setting
- * and testing an environment variable...
- */
- usb_ppc_status = getenv("USB_PPC_STATUS");
+ /*
+ * If we're running as x86_64 or i386 and couldn't load the class driver
+ * (because it's ppc or i386), then try to re-exec ourselves in ppc or i386
+ * mode to try again. If we don't have a ppc or i386 architecture we may be
+ * running with the same architecture again so guard against this by setting
+ * and testing an environment variable...
+ */
- if (usb_ppc_status == NULL)
+# ifdef __x86_64__
+ usb_legacy_status = getenv("USB_I386_STATUS");
+# else
+ usb_legacy_status = getenv("USB_PPC_STATUS");
+# endif /* __x86_64__ */
+
+ if (!usb_legacy_status)
{
/*
* Setup a SIGTERM handler then block it before forking...
sigaddset(&newmask, SIGTERM);
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
- if ((child_pid = fork()) == 0)
- {
- /*
- * Child comes here...
- */
-
- setenv("USB_PPC_STATUS", "1", false);
-
- /*
- * Unblock signals before doing the exec...
- */
-
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_handler = SIG_DFL;
- sigaction(SIGTERM, &action, NULL);
+ /*
+ * Set the environment variable...
+ */
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
+# ifdef __x86_64__
+ setenv("USB_I386_STATUS", "1", false);
+# else
+ setenv("USB_PPC_STATUS", "1", false);
+# endif /* __x86_64__ */
- /*
- * Tell the kernel the next exec call should favor the ppc architecture...
- */
+ /*
+ * Tell the kernel to use the specified CPU architecture...
+ */
- int mib[] = { CTL_KERN, KERN_AFFINITY, 1, 1 };
- int namelen = 4;
- sysctl(mib, namelen, NULL, NULL, NULL, 0);
+# ifdef __x86_64__
+ cpu_type_t cpu = CPU_TYPE_I386;
+# else
+ cpu_type_t cpu = CPU_TYPE_POWERPC;
+# endif /* __x86_64__ */
+ size_t ocount = 0;
+ posix_spawnattr_t attrs;
- /*
- * Set up the arguments and call exec...
- */
+ if (!posix_spawnattr_init(&attrs))
+ {
+ posix_spawnattr_setsigdefault(attrs, &oldmask);
+ posix_spawnattr_setbinpref_np(attrs, 1, &cpu, &ocount);
+ }
- for (i = 0; i < argc && i < (sizeof(my_argv)/sizeof(my_argv[0])) - 1; i++)
- my_argv[i] = argv[i];
+ /*
+ * Set up the arguments and call posix_spawn...
+ */
- my_argv[i] = NULL;
+ for (i = 0; i < argc && i < (sizeof(my_argv) / sizeof(my_argv[0])) - 1; i ++)
+ my_argv[i] = argv[i];
- execv("/usr/libexec/cups/backend/usb", my_argv);
+ my_argv[i] = NULL;
- _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n"));
- perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb");
- exit(errno);
- }
- else if (child_pid < 0)
+ if (posix_spawn(&child_pid, "/usr/libexec/cups/backend/usb", NULL, &attrs,
+ my_argv, environ))
{
- /*
- * Error - couldn't fork a new process!
- */
-
_cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n"));
- perror("DEBUG: Unable to fork");
- exit(errno);
+ perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb");
+ exit(CUPS_BACKEND_STOP);
}
/*
if (WIFSIGNALED(childstatus))
{
- exitstatus = WTERMSIG(childstatus);
+ exitstatus = CUPS_BACKEND_STOP;
fprintf(stderr, "DEBUG: usb(legacy) backend %d crashed on signal %d!\n",
- child_pid, exitstatus);
+ child_pid, WTERMSIG(childstatus));
}
else
{
else
{
fputs("DEBUG: usb(legacy) backend running native again\n", stderr);
- exitstatus = ENOENT;
+ exitstatus = CUPS_BACKEND_STOP;
}
exit(exitstatus);
exit(1);
}
-#endif /* __i386__ */
+#endif /* __i386__ || __x86_64__ */
#ifdef PARSE_PS_ERRORS