#define _MAIN_C_
#include "cupsd.h"
#include <sys/resource.h>
#include <syslog.h>
#include <grp.h>
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
# include <malloc.h>
#endif
#ifdef __APPLE__
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#ifdef HAVE_NOTIFY_H
#include <notify.h>
static time_t NotifyPostDelay = 0;
#endif
static kern_return_t registerBootstrapService();
static kern_return_t destroyBootstrapService();
static mach_port_t server_priv_port;
static char service_name[] = "/usr/sbin/cupsd";
#endif
static void parent_handler(int sig);
static void process_children(void);
static void sigchld_handler(int sig);
static void sighup_handler(int sig);
static void sigterm_handler(int sig);
static long select_timeout(int fds);
static void usage(void);
static int parent_signal = 0;
static int holdcount = 0;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
static sigset_t holdmask;
#endif
static int dead_children = 0;
static int stop_scheduler = 0;
int
main(int argc,
char *argv[])
{
int i;
char *opt;
int fg;
int fds;
fd_set *input,
*output;
client_t *con;
job_t *job,
*next;
listener_t *lis;
time_t activity;
time_t browse_time;
time_t senddoc_time;
#ifdef HAVE_MDNS
printer_t *p;
mdns_resolve_t *mdnsResolve,
*nextMdnsResolve;
#endif
#ifdef HAVE_MALLINFO
time_t mallinfo_time;
#endif
struct timeval timeout;
struct rlimit limit;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
#ifdef __sgi
cups_file_t *fp;
struct stat statbuf;
#endif
#ifdef __APPLE__
int debug = 0;
#endif
fg = 0;
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
for (opt = argv[i] + 1; *opt != '\0'; opt ++)
switch (*opt)
{
case 'c' :
i ++;
if (i >= argc)
usage();
if (argv[i][0] == '/')
{
SetString(&ConfigurationFile, argv[i]);
}
else
{
char current[1024];
getcwd(current, sizeof(current));
SetStringf(&ConfigurationFile, "%s/%s", current, argv[i]);
}
break;
case 'f' :
fg = 1;
break;
case 'F' :
fg = -1;
break;
#ifdef __APPLE__
case 'd' :
debug = 1;
break;
#endif
default :
fprintf(stderr, "cupsd: Unknown option \'%c\' - aborting!\n", *opt);
usage();
break;
}
else
{
fprintf(stderr, "cupsd: Unknown argument \'%s\' - aborting!\n", argv[i]);
usage();
}
if (!ConfigurationFile)
SetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");
if (!fg)
{
#ifdef HAVE_SIGSET
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
if (fork() > 0)
{
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);
}
return (0);
}
}
if (fg < 1)
{
chdir("/");
#ifndef DEBUG
getrlimit(RLIMIT_CORE, &limit);
limit.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &limit);
close(0);
close(1);
close(2);
setsid();
#endif
}
if (getenv("TZ") != NULL)
SetStringf(&TZ, "TZ=%s", getenv("TZ"));
else
SetString(&TZ, "");
tzset();
#ifdef LC_TIME
setlocale(LC_TIME, "");
#endif
getrlimit(RLIMIT_NOFILE, &limit);
if (limit.rlim_max > CUPS_MAX_FDS)
MaxFDs = CUPS_MAX_FDS;
else
MaxFDs = limit.rlim_max;
limit.rlim_cur = MaxFDs;
setrlimit(RLIMIT_NOFILE, &limit);
SetSize = (MaxFDs + 31) / 8 + 4;
if (SetSize < sizeof(fd_set))
SetSize = sizeof(fd_set);
InputSet = (fd_set *)calloc(1, SetSize);
OutputSet = (fd_set *)calloc(1, SetSize);
input = (fd_set *)calloc(1, SetSize);
output = (fd_set *)calloc(1, SetSize);
if (InputSet == NULL || OutputSet == NULL || input == NULL || output == NULL)
{
syslog(LOG_LPR, "Unable to allocate memory for select() sets - exiting!");
return (1);
}
if (!ReadConfiguration())
{
syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
ConfigurationFile);
return (1);
}
#ifdef HAVE_SIGSET
if (RunAsUser)
sigset(SIGHUP, sigterm_handler);
else
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, SIGHUP);
if (RunAsUser)
action.sa_handler = sigterm_handler;
else
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
if (RunAsUser)
signal(SIGHUP, sigterm_handler);
else
signal(SIGHUP, sighup_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGTERM, sigterm_handler);
#endif
#ifdef __sgi
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
InitCerts();
if (!fg)
kill(getppid(), SIGUSR1);
#ifdef __APPLE__
if (!debug)
registerBootstrapService();
#endif
if (RunAsUser)
{
setgid(Group);
setgroups(1, &Group);
setuid(User);
}
CheckJobs();
#ifdef HAVE_NOTIFY_POST
NotifyPost = (CUPS_NOTIFY_PRINTER_LIST | CUPS_NOTIFY_JOB);
#endif
#ifdef HAVE_MALLINFO
mallinfo_time = 0;
#endif
browse_time = time(NULL);
senddoc_time = time(NULL);
fds = 1;
while (!stop_scheduler)
{
#ifdef DEBUG
LogMessage(L_DEBUG2, "main: Top of loop, dead_children=%d, NeedReload=%d",
dead_children, NeedReload);
#endif
if (dead_children)
process_children();
if (NeedReload)
{
job_t *job;
if (NumClients > 0)
{
for (i = NumClients, con = Clients; i > 0; i --, con ++)
if (con->http.state == HTTP_WAITING)
{
CloseClient(con);
con --;
}
else
con->http.keep_alive = HTTP_KEEPALIVE_OFF;
PauseListening();
}
for (job = Jobs; job; job = job->next)
if (job->state->values[0].integer == IPP_JOB_PROCESSING)
break;
if ((NumClients == 0 && !job) || (time(NULL) - ReloadTime) >= 60)
{
if (!ReadConfiguration())
{
syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
ConfigurationFile);
break;
}
}
}
memcpy(input, InputSet, SetSize);
memcpy(output, OutputSet, SetSize);
timeout.tv_sec = select_timeout(fds);
timeout.tv_usec = 0;
if ((fds = select(MaxFDs, input, output, NULL, &timeout)) < 0)
{
char s[16384],
*sptr;
int slen;
if (errno == EINTR)
continue;
LogMessage(L_EMERG, "select() failed - %s!", strerror(errno));
strcpy(s, "InputSet =");
slen = 10;
sptr = s + 10;
for (i = 0; i < MaxFDs; i ++)
if (FD_ISSET(i, InputSet))
{
snprintf(sptr, sizeof(s) - slen, " %d", i);
slen += strlen(sptr);
sptr += strlen(sptr);
}
LogMessage(L_EMERG, s);
strcpy(s, "OutputSet =");
slen = 11;
sptr = s + 11;
for (i = 0; i < MaxFDs; i ++)
if (FD_ISSET(i, OutputSet))
{
snprintf(sptr, sizeof(s) - slen, " %d", i);
slen += strlen(sptr);
sptr += strlen(sptr);
}
LogMessage(L_EMERG, s);
for (i = 0, con = Clients; i < NumClients; i ++, con ++)
LogMessage(L_EMERG, "Clients[%d] = %d, file = %d, state = %d",
i, con->http.fd, con->file, con->http.state);
for (i = 0, lis = Listeners; i < NumListeners; i ++, lis ++)
LogMessage(L_EMERG, "Listeners[%d] = %d", i, lis->fd);
LogMessage(L_EMERG, "BrowseSocket = %d", BrowseSocket);
for (job = Jobs; job != NULL; job = job->next)
LogMessage(L_EMERG, "Jobs[%d] = %d", job->id, job->pipe);
LogMessage(L_EMERG, "SysEventPipes[0] = %d", SysEventPipes[0]);
#ifdef HAVE_MDNS
LogMessage(L_EMERG, "BrowseMDNSfd = %d", BrowseMDNSfd);
for (mdnsResolve = MDNSPendingResolves; mdnsResolve; mdnsResolve = mdnsResolve->next)
LogMessage(L_EMERG, "mdnsResolve fd = %d", mdnsResolve->fd);
for (p = Printers; p != NULL; p = p->next)
LogMessage(L_EMERG, "printer[%s] %d, %d, %d", p->name, p->mdns_lpd_fd,
p->mdns_ipp_fd, p->mdns_query_fd);
#endif
break;
}
for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
if (FD_ISSET(lis->fd, input))
AcceptClient(lis);
for (i = NumClients, con = Clients; i > 0; i --, con ++)
{
if (FD_ISSET(con->http.fd, input) || con->http.used)
if (!ReadClient(con))
{
con --;
continue;
}
if (con->pipe_pid && FD_ISSET(con->file, input))
{
con->file_ready = 1;
#ifdef DEBUG
LogMessage(L_DEBUG2, "main: Data ready file %d!", con->file);
#endif
if (!FD_ISSET(con->http.fd, output))
{
LogMessage(L_DEBUG2, "main: Removing fd %d from InputSet...", con->file);
FD_CLR(con->file, InputSet);
}
}
if (FD_ISSET(con->http.fd, output) &&
(!con->pipe_pid || con->file_ready))
if (!WriteClient(con))
{
con --;
continue;
}
activity = time(NULL) - Timeout;
if (con->http.activity < activity && !con->pipe_pid)
{
LogMessage(L_DEBUG, "Closing client %d after %d seconds of inactivity...",
con->http.fd, Timeout);
CloseClient(con);
con --;
continue;
}
}
for (job = Jobs; job != NULL; job = next)
{
next = job->next;
if (job->pipe && FD_ISSET(job->pipe, input))
{
FD_CLR(job->pipe, input);
UpdateJob(job);
}
}
if (CGIPipes[0] >= 0 && FD_ISSET(CGIPipes[0], input))
UpdateCGI();
#ifdef __APPLE__
if (SysEventPipes[0] >= 0 && FD_ISSET(SysEventPipes[0], input))
UpdateSysEventMonitor();
#endif
if (Browsing && BrowseProtocols)
{
if (BrowseSocket >= 0 && FD_ISSET(BrowseSocket, input))
UpdateCUPSBrowse();
if (PollPipe >= 0 && FD_ISSET(PollPipe, input))
UpdatePolling();
#ifdef HAVE_LIBSLP
if ((BrowseProtocols & BROWSE_SLP) && BrowseSLPRefresh <= time(NULL))
UpdateSLPBrowse();
#endif
#ifdef HAVE_MDNS
if (BrowseMDNSRef && FD_ISSET(BrowseMDNSfd, input))
DNSServiceProcessResult(BrowseMDNSRef);
for (mdnsResolve = MDNSPendingResolves; mdnsResolve;)
{
nextMdnsResolve = mdnsResolve->next;
if (mdnsResolve->sdRef && FD_ISSET(mdnsResolve->fd, input))
DNSServiceProcessResult(mdnsResolve->sdRef);
mdnsResolve = nextMdnsResolve;
}
for (p = Printers; p != NULL; p = p->next)
{
if (p->mdns_lpd_ref && FD_ISSET(p->mdns_lpd_fd, input))
DNSServiceProcessResult(p->mdns_lpd_ref);
if (p->mdns_ipp_ref && FD_ISSET(p->mdns_ipp_fd, input))
DNSServiceProcessResult(p->mdns_ipp_ref);
if (p->mdns_query_ref && FD_ISSET(p->mdns_query_fd, input))
DNSServiceProcessResult(p->mdns_query_ref);
}
#endif
if (time(NULL) > browse_time)
{
SendBrowseList();
browse_time = time(NULL);
}
}
if ((time(NULL) - senddoc_time) >= 10)
{
CheckJobs();
senddoc_time = time(NULL);
}
#ifdef HAVE_MALLINFO
if ((time(NULL) - mallinfo_time) >= 60 && LogLevel >= L_DEBUG)
{
struct mallinfo mem;
mem = mallinfo();
LogMessage(L_DEBUG, "mallinfo: arena = %d, used = %d, free = %d\n",
mem.arena, mem.usmblks + mem.uordblks,
mem.fsmblks + mem.fordblks);
mallinfo_time = time(NULL);
}
#endif
if ((time(NULL) - RootCertTime) >= RootCertDuration && RootCertDuration)
{
DeleteCert(0);
AddCert(0, "root");
}
#ifdef HAVE_NOTIFY_POST
if (NotifyPost && NotifyPostDelay <= time(NULL))
{
#ifdef DEBUG
static time_t first_notify_post = 0;
if (!first_notify_post) first_notify_post = time(NULL);
fprintf(stderr, "%d notify_post()\n", (int)(time(NULL) - first_notify_post));
#endif
if ((NotifyPost & CUPS_NOTIFY_PRINTER_LIST))
notify_post("com.apple.printerListChange");
if ((NotifyPost & CUPS_NOTIFY_PRINTER_HISTORY))
notify_post("com.apple.printerHistoryChange");
if ((NotifyPost & CUPS_NOTIFY_JOB))
notify_post("com.apple.jobChange");
NotifyPost = 0;
NotifyPostDelay = time(NULL) + 1;
}
#endif
}
if (stop_scheduler)
LogMessage(L_INFO, "Scheduler shutting down normally.");
else
LogMessage(L_ERROR, "Scheduler shutting down due to program error.");
StopServer();
StopAllJobs();
#ifdef HAVE_NOTIFY_POST
fprintf(stderr, "notify_post(com.apple.printerListChange) last\n");
notify_post("com.apple.printerListChange");
#endif
#ifdef __sgi
if (!stat("/var/spool/lp/FIFO", &statbuf))
if (!S_ISFIFO(statbuf.st_mode))
unlink("/var/spool/lp/SCHEDLOCK");
#endif
#ifdef __APPLE__
destroyBootstrapService();
#endif
free(InputSet);
free(OutputSet);
free(input);
free(output);
return (!stop_scheduler);
}
void
CatchChildSignals(void)
{
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
#ifdef HAVE_SIGSET
sigset(SIGCHLD, sigchld_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);
#else
signal(SIGCLD, sigchld_handler);
#endif
}
void
ClearString(char **s)
{
if (s && *s)
{
free(*s);
*s = NULL;
}
}
void
HoldSignals(void)
{
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
sigset_t newmask;
#endif
holdcount ++;
if (holdcount > 1)
return;
#ifdef HAVE_SIGSET
sighold(SIGTERM);
sighold(SIGCHLD);
#elif defined(HAVE_SIGACTION)
sigemptyset(&newmask);
sigaddset(&newmask, SIGTERM);
sigaddset(&newmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &newmask, &holdmask);
#endif
}
void
IgnoreChildSignals(void)
{
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
#ifdef HAVE_SIGSET
sigset(SIGCHLD, SIG_DFL);
#elif defined(HAVE_SIGACTION)
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, SIGCHLD);
action.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &action, NULL);
#else
signal(SIGCLD, SIG_DFL);
#endif
}
void
ReleaseSignals(void)
{
holdcount --;
if (holdcount > 0)
return;
#ifdef HAVE_SIGSET
sigrelse(SIGTERM);
sigrelse(SIGCHLD);
#elif defined(HAVE_SIGACTION)
sigprocmask(SIG_SETMASK, &holdmask, NULL);
#endif
}
void
SetString(char **s,
const char *v)
{
if (!s || *s == v)
return;
if (*s)
free(*s);
if (v)
*s = strdup(v);
else
*s = NULL;
}
void
SetStringf(char **s,
const char *f,
...)
{
char v[1024];
va_list ap;
char *olds;
if (!s)
return;
olds = *s;
if (f)
{
va_start(ap, f);
vsnprintf(v, sizeof(v), f, ap);
va_end(ap);
*s = strdup(v);
}
else
*s = NULL;
if (olds)
free(olds);
}
static void
parent_handler(int sig)
{
parent_signal = sig;
}
static void
process_children(void)
{
int status;
int pid;
job_t *job;
int i;
dead_children = 0;
#ifdef HAVE_WAITPID
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
#elif defined(HAVE_WAIT3)
while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
#else
if ((pid = wait(&status)) > 0)
#endif
{
DEBUG_printf(("process_children: pid = %d, status = %d\n", pid, status));
if (status == SIGTERM)
status = 0;
if (status)
{
if (WIFSTOPPED(status))
LogMessage(L_ERROR, "PID %d crashed on signal %d!", pid,
WSTOPSIG(status));
else
LogMessage(L_ERROR, "PID %d stopped with status %d!", pid,
WEXITSTATUS(status));
if (LogLevel < L_DEBUG)
LogMessage(L_INFO, "Hint: Try setting the LogLevel to \"debug\" to find out more.");
}
else
LogMessage(L_DEBUG2, "PID %d exited with no errors.", pid);
if (pid)
DeleteCert(pid);
for (job = Jobs; job != NULL; job = job->next)
if (job->state != NULL &&
job->state->values[0].integer == IPP_JOB_PROCESSING)
{
for (i = 0; job->procs[i]; i ++)
if (job->procs[i] == pid)
break;
if (job->procs[i])
{
job->procs[i] = -pid;
if (status && job->status >= 0)
{
if (!job->procs[i + 1])
job->status = -status;
else
job->status = status;
}
break;
}
}
}
}
static void
sigchld_handler(int sig)
{
(void)sig;
dead_children = 1;
#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
signal(SIGCLD, sigchld_handler);
#endif
}
static void
sighup_handler(int sig)
{
(void)sig;
NeedReload = RELOAD_ALL;
ReloadTime = time(NULL);
#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
signal(SIGHUP, sighup_handler);
#endif
}
static void
sigterm_handler(int sig)
{
(void)sig;
stop_scheduler = 1;
}
static long
select_timeout(int fds)
{
int i;
long timeout;
time_t now;
client_t *con;
printer_t *p;
job_t *job;
const char *why;
for (i = NumClients, con = Clients; i > 0; i --, con ++)
if (con->http.used > 0)
return (0);
if (fds || NumClients > 50)
return (1);
#ifdef HAVE_NOTIFY_POST
if (NotifyPost)
return (1);
#endif
now = time(NULL);
timeout = 2147483647;
why = "do nothing";
for (i = NumClients, con = Clients; i > 0; i --, con ++)
if ((con->http.activity + Timeout) < timeout)
{
timeout = con->http.activity + Timeout;
why = "timeout a client connection";
}
if (Browsing && BrowseProtocols)
{
#ifdef HAVE_LIBSLP
if ((BrowseProtocols & BROWSE_SLP) && (BrowseSLPRefresh < timeout))
{
timeout = BrowseSLPRefresh;
why = "update SLP browsing";
}
#endif
if (BrowseProtocols & BROWSE_CUPS)
{
for (p = Printers; p != NULL; p = p->next)
{
if (p->type & CUPS_PRINTER_REMOTE)
{
if (p->browse_time + BrowseTimeout < timeout)
{
timeout = p->browse_time + BrowseTimeout;
why = "browse timeout a printer";
}
}
else if (!(p->type & CUPS_PRINTER_IMPLICIT))
{
if (BrowseInterval && p->browse_time + BrowseInterval < timeout)
{
timeout = p->browse_time + BrowseInterval;
why = "send browse update";
}
}
}
}
}
if (timeout > (now + 10))
{
for (job = Jobs; job != NULL; job = job->next)
if (job->state->values[0].integer <= IPP_JOB_PROCESSING)
{
timeout = now + 10;
why = "process active jobs";
break;
}
}
#ifdef HAVE_MALLINFO
if (LogLevel >= L_DEBUG && (mallinfo_time + 60) < timeout)
{
timeout = mallinfo_time + 60;
why = "display memory usage";
}
#endif
if (RootCertDuration && (RootCertTime + RootCertDuration) < timeout)
{
timeout = RootCertTime + RootCertDuration;
why = "update root certificate";
}
if (timeout != 2147483647)
{
timeout = timeout - now + 1;
if (timeout < 1)
timeout = 1;
}
LogMessage(L_DEBUG2, "select_timeout: %ld seconds to %s", timeout, why);
return (timeout);
}
static void
usage(void)
{
#ifdef __APPLE__
fputs("Usage: cupsd [-c config-file] [-f] [-F] [-d]\n", stderr);
#else
fputs("Usage: cupsd [-c config-file] [-f] [-F]\n", stderr);
#endif
exit(1);
}
#ifdef __APPLE__
static kern_return_t registerBootstrapService()
{
kern_return_t status;
mach_port_t service_send_port, service_rcv_port;
status = bootstrap_check_in(bootstrap_port, (char*)service_name, &service_rcv_port);
if (status == KERN_SUCCESS)
{
server_priv_port = bootstrap_port;
}
else if (status == BOOTSTRAP_UNKNOWN_SERVICE)
{
status = bootstrap_create_server(bootstrap_port, "/usr/sbin/cupsd -f", getuid(),
FALSE , &server_priv_port);
if (status != KERN_SUCCESS)
return status;
status = bootstrap_create_service(server_priv_port, (char*)service_name, &service_send_port);
if (status != KERN_SUCCESS)
{
mach_port_deallocate(mach_task_self(), server_priv_port);
return status;
}
status = bootstrap_check_in(server_priv_port, (char*)service_name, &service_rcv_port);
if (status != KERN_SUCCESS)
{
mach_port_deallocate(mach_task_self(), server_priv_port);
mach_port_deallocate(mach_task_self(), service_send_port);
return status;
}
}
mach_port_destroy(mach_task_self(), service_rcv_port);
return status;
}
static kern_return_t destroyBootstrapService()
{
return bootstrap_register(server_priv_port, (char*)service_name, MACH_PORT_NULL);
}
#endif