void *consumerFunc(void * arg) // 消费者线程 { while(true) { dispatch_semaphore_wait(full, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(mutex, DISPATCH_TIME_FOREVER); remove_item(); print_items(); dispatch_semaphore_signal(mutex); dispatch_semaphore_signal(empty); sleep(5); } }
void *producerFunc(void *arg) // 生产者线程 { int item; while(true) { dispatch_semaphore_wait(empty, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(mutex, DISPATCH_TIME_FOREVER); item = product_NO++; insert_item(item); print_items(); dispatch_semaphore_signal(mutex); dispatch_semaphore_signal(full); sleep(3); } }
/** try to wait for the semaphore until timeout * * \return true, if the value can be decremented * false, otherweise */ bool timed_wait(struct timespec const & absolute_timeout) { dispatch_time_t timeout = dispatch_walltime(&absolute_timeout, 0); long status = dispatch_semaphore_wait(sem, timeout); return status == 0; }
/* * pj_sem_wait() */ PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem) { #if PJ_HAS_THREADS int result; PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sem, PJ_EINVAL); PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s is waiting", pj_thread_this(sem->inst_id)->obj_name)); #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 result = dispatch_semaphore_wait(sem->sem, DISPATCH_TIME_FOREVER ); #else result = sem_wait( sem->sem); #endif if (result == 0) { PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", pj_thread_this(sem->inst_id)->obj_name)); } else { PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s FAILED to acquire", pj_thread_this(sem->inst_id)->obj_name)); } if (result == 0) return PJ_SUCCESS; else return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); #else pj_assert( sem == (pj_sem_t*) 1 ); return PJ_SUCCESS; #endif }
static void cancelRepeatingTimer(struct nodeInstanceData *ctx) { dispatch_source_cancel(ctx->timer); dispatch_release(ctx->timer); ctx->timer = NULL; dispatch_semaphore_wait(ctx->timerCanceled, DISPATCH_TIME_FOREVER); }
int smb_gss_get_cred_list(struct smb_gss_cred_list **list, gss_OID mech) { struct cred_iter_ctx ctx; ctx.s = dispatch_semaphore_create(0); if (ctx.s == NULL) return ENOMEM; ctx.clist = malloc(sizeof (struct smb_gss_cred_list)); if (ctx.clist == NULL) { dispatch_release(ctx.s); return ENOMEM; } TAILQ_INIT(ctx.clist); gss_iter_creds_f(NULL, 0, mech, &ctx, cred_iter); dispatch_semaphore_wait(ctx.s, DISPATCH_TIME_FOREVER); dispatch_release(ctx.s); *list = ctx.clist; return 0; }
int main (int argc, const char * argv[]) { dispatch_group_t mg = dispatch_group_create(); dispatch_semaphore_t ds; __block int numRunning = 0; int qWidth = 5; int numWorkBlocks = 100; if (argc >= 2) { qWidth = atoi(argv[1]); // use the command 1st line parameter as the queue width if (qWidth==0) qWidth=1; // protect against bad values } if (argc >=3) { numWorkBlocks = atoi(argv[2]); // use the 2nd command line parameter as the queue width if (numWorkBlocks==0) numWorkBlocks=1; // protect against bad values } printf("Starting dispatch semaphore test to simulate a %d wide dispatch queue\n", qWidth ); ds = dispatch_semaphore_create(qWidth); int i; for (i=0; i<numWorkBlocks; i++) { // synchronize the whole shebang every 25 work units... if (i % 25 == 24) { dispatch_group_async(mg,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ // wait for all pending work units to finish up... for (int x=0; x<qWidth; x++) dispatch_semaphore_wait(ds, DISPATCH_TIME_FOREVER); // do the thing that is critical here printf("doing something critical...while %d work units are running \n",numRunning); // and let work continue unimpeeded for (int x=0; x<qWidth; x++) dispatch_semaphore_signal(ds); }); } else {
void dispatch_group_enter(dispatch_group_t dg) { dispatch_semaphore_t dsema = (dispatch_semaphore_t)dg; (void)dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER); }
void SDMMD_USBMuxListenerSend(SDMMD_USBMuxListenerRef listener, struct USBMuxPacket **packet) { listener->ivars.semaphore = dispatch_semaphore_create(0x0); SDMMD_USBMuxSend(listener->ivars.socket, *packet); dispatch_semaphore_wait(listener->ivars.semaphore, (*packet)->timeout); CFMutableArrayRef updateWithRemove = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0x0, listener->ivars.responses); struct USBMuxPacket *responsePacket = NULL; uint32_t removeCounter = 0x0; for (uint32_t i = 0x0; i < CFArrayGetCount(listener->ivars.responses); i++) { struct USBMuxPacket *response = (struct USBMuxPacket *)CFArrayGetValueAtIndex(listener->ivars.responses, i); if ((*packet)->body.tag == response->body.tag) { responsePacket = response; CFArrayRemoveValueAtIndex(updateWithRemove, i-removeCounter); removeCounter++; } } CFSafeRelease(listener->ivars.responses); listener->ivars.responses = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0x0, updateWithRemove); CFSafeRelease(updateWithRemove); USBMuxPacketRelease(*packet); if (!responsePacket) { responsePacket = (struct USBMuxPacket *)calloc(0x1, sizeof(struct USBMuxPacket)); } *packet = responsePacket; dispatch_release(listener->ivars.semaphore); }
void lock() { #if defined (DEBUG) uint64_t timeout = NSEC_PER_SEC; uint64_t locktime = 0; while (dispatch_semaphore_wait(sem_, dispatch_time(DISPATCH_TIME_NOW, timeout))) { locktime += (timeout/NSEC_PER_SEC); printf("WARNING: mutex %p locking for %llu seconds\n", this, locktime); if (timeout < 64*NSEC_PER_SEC) timeout *= 2; } #else dispatch_semaphore_wait(sem_, DISPATCH_TIME_FOREVER); #endif }
/* * call-seq: * sema.wait(timeout) => true or false * * Waits (blocks the thread) until a signal arrives or the timeout expires. * Timeout defaults to DISPATCH_TIME_FOREVER. * * Returns true if signalled, false if timed out. * * gcdq = Dispatch::Queue.new('doc') * sema = Dispatch::Semaphore.new(0) * gcdq.async { sleep 0.1; sema.signal } * sema.wait #=> true * */ static VALUE rb_semaphore_wait(VALUE self, SEL sel, int argc, VALUE *argv) { VALUE num; rb_scan_args(argc, argv, "01", &num); return dispatch_semaphore_wait(RSemaphore(self)->sem, rb_num2timeout(num)) == 0 ? Qtrue : Qfalse; }
bool __Platform_Red_Threading_Semaphore_TimeoutWait ( __Platform_Semaphore_t & Target, const Red::Util::Time :: Duration & Timeout ) { dispatch_time_t Delta = dispatch_time ( DISPATCH_TIME_NOW, Timeout.GetTotalNanoSeconds () ); return dispatch_semaphore_wait ( Target, Delta ) != 0; }
void SDMMD_USBMuxListenerSend(SDMMD_USBMuxListenerRef listener, struct USBMuxPacket **packet) { __block struct USBMuxPacket *block_packet = *packet; dispatch_sync(listener->ivars.operationQueue, ^{ // This semaphore will be signaled when a response is received listener->ivars.semaphore = dispatch_semaphore_create(0); // Send the outgoing packet SDMMD_USBMuxSend(listener->ivars.socket, block_packet); // Wait for a response-type packet to be received dispatch_semaphore_wait(listener->ivars.semaphore, block_packet->timeout); CFMutableArrayRef updateWithRemove = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, listener->ivars.responses); // Search responses for a packet that matches the one sent struct USBMuxPacket *responsePacket = NULL; uint32_t removeCounter = 0; for (uint32_t i = 0; i < CFArrayGetCount(listener->ivars.responses); i++) { struct USBMuxPacket *response = (struct USBMuxPacket *)CFArrayGetValueAtIndex(listener->ivars.responses, i); if ((*packet)->body.tag == response->body.tag) { // Equal tags indicate response to request if (responsePacket) { // Found additional response, destroy old one USBMuxPacketRelease(responsePacket); } // Each matching packet is removed from the responses list responsePacket = response; CFArrayRemoveValueAtIndex(updateWithRemove, i - removeCounter); removeCounter++; } } if (responsePacket == NULL) { // Didn't find an appropriate response, initialize an empty packet to return responsePacket = (struct USBMuxPacket *)calloc(1, sizeof(struct USBMuxPacket)); } CFSafeRelease(listener->ivars.responses); listener->ivars.responses = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, updateWithRemove); CFSafeRelease(updateWithRemove); // Destroy sent packet USBMuxPacketRelease(block_packet); // Return response packet to caller block_packet = responsePacket; // Discard "waiting for response" semaphore dispatch_release(listener->ivars.semaphore); });
bool SemHelper::wait(int timeout) { #ifdef WIN32 if (timeout <= 0) { timeout = INFINITE; } if (WaitForSingleObject(_hSem, timeout) != WAIT_OBJECT_0) { return false; } #elif defined(__APPLE__) if (dispatch_semaphore_wait(_semid, dispatch_time(DISPATCH_TIME_NOW, timeout*1000)) != 0) { return false; } #else if (timeout <= 0) { return (sem_wait(&_semid) == 0); } else { struct timeval tm; gettimeofday(&tm, NULL); long long endtime = tm.tv_sec *1000 + tm.tv_usec/1000 + timeout; do { sleepMillisecond(50); int ret = sem_trywait(&_semid); if (ret == 0) { return true; } struct timeval tv_cur; gettimeofday(&tv_cur, NULL); if (tv_cur.tv_sec*1000 + tv_cur.tv_usec/1000 > endtime) { return false; } if (ret == -1 && errno == EAGAIN) { continue; } else { return false; } } while (true); return false; } #endif return true; }
static int smb_acquire_cred(const char *user, const char *domain, const char *password, gss_OID mech, void **gssCreds) { gss_auth_identity_desc identity; struct smb_gss_cred_ctx aq_cred_ctx; uint32_t maj = !GSS_S_COMPLETE; if (password == NULL || user == NULL || *user == '\0') return 0; identity.type = GSS_AUTH_IDENTITY_TYPE_1; identity.flags = 0; identity.username = strdup(user); identity.realm = strdup(domain ? domain : ""); identity.password = strdup(password); identity.credentialsRef = NULL; if (identity.username == NULL || identity.realm == NULL || identity.password == NULL) goto out; aq_cred_ctx.sem = dispatch_semaphore_create(0); if (aq_cred_ctx.sem == NULL) goto out; maj = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0, GSS_C_INDEFINITE, mech, GSS_C_INITIATE, &identity, &aq_cred_ctx, acquire_cred_complete); if (maj == GSS_S_COMPLETE) { dispatch_semaphore_wait(aq_cred_ctx.sem, DISPATCH_TIME_FOREVER); maj = aq_cred_ctx.maj; *gssCreds = aq_cred_ctx.creds; } if (maj != GSS_S_COMPLETE) smb_log_info("Acquiring NTLM creds for %s\%s failed. GSS returned %d", ASL_LEVEL_INFO, domain, user, maj); dispatch_release(aq_cred_ctx.sem); out: free(identity.username); free(identity.realm); free(identity.password); return (maj == GSS_S_COMPLETE); }
static void finalize_thread(void* _state) { SnDispatchThreadState* s = (SnDispatchThreadState*)_state; dispatch_semaphore_signal(s->gc_barrier); // when finalizing a thread during gc, we don't want to wait for this. dispatch_semaphore_wait(state_lock, DISPATCH_TIME_FOREVER); if (s->next) s->next->previous = s->previous; if (s->previous) s->previous->next = s->next; state = s->next; dispatch_semaphore_signal(state_lock); dispatch_release(s->gc_barrier); snow_free(s); }
void* OSXQueueThreadProc(void *data) { platform_work_queue* Queue = (platform_work_queue*)data; for(;;) { if(OSXDoNextWorkQueueEntry(Queue)) { dispatch_semaphore_wait(Queue->SemaphoreHandle, DISPATCH_TIME_FOREVER); } } return(0); }
// Wait //------------------------------------------------------------------------------ void Semaphore::Wait( uint32_t timeoutMS ) { if ( timeoutMS == 0 ) { // Wait forever #if defined( __WINDOWS__ ) VERIFY( WaitForSingleObject( m_Semaphore, INFINITE ) == WAIT_OBJECT_0 ); #elif defined( __APPLE__ ) dispatch_semaphore_wait( m_Semaphore, DISPATCH_TIME_FOREVER ); #elif defined( __LINUX__ ) VERIFY( sem_wait( &m_Semaphore ) == 0 ); #endif } else { // Wait with timeout #if defined( __WINDOWS__ ) DWORD result = WaitForSingleObject( m_Semaphore, timeoutMS ); ASSERT( ( result == WAIT_OBJECT_0 ) || ( result == WAIT_TIMEOUT ) ); (void)result; #elif defined( __APPLE__ ) dispatch_semaphore_wait( m_Semaphore, dispatch_time( DISPATCH_TIME_NOW, timeoutMS * 1000000 ) ); #elif defined( __LINUX__ ) struct timespec ts; VERIFY( clock_gettime( CLOCK_REALTIME, &ts ) == 0 ); uint64_t totalNS = (uint64_t)ts.tv_sec * (uint64_t)1000000000; totalNS += (uint64_t)ts.tv_nsec; totalNS += (uint64_t)timeoutMS * 1000000; ts.tv_sec = totalNS / 1000000000; ts.tv_nsec = totalNS % 1000000000; if ( sem_timedwait( &m_Semaphore, &ts ) != 0 ) { ASSERT( errno == ETIMEDOUT ); // anything else is a usage error? } #endif } }
void dispatch_semaphore_blocks() { static size_t total; dispatch_semaphore_t dsema; MU_BEGIN_TEST(dispatch_semaphore_blocks); dsema = dispatch_semaphore_create(1); MU_ASSERT_NOT_NULL(dsema); dispatch_apply(LAPS, dispatch_queue_create(0,0), ^(size_t idx) { dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER); total++; dispatch_semaphore_signal(dsema); });
void load_image(ConvertContext *context) { int result = RESULT_OK; char *error_desc; ExceptionType error_type; // wait for resources to be available dispatch_semaphore_wait(context->conv_semaphore, DISPATCH_TIME_FOREVER); // load image if (MagickReadImage(context->mw, context->src_path) == MagickFalse) { // deal with error error_desc = MagickGetException(context->mw, &error_type); asprintf(&context->results.message,"Error loading image (%s): %s\n",error_desc,context->src_path); error_desc = (char *)MagickRelinquishMemory(error_desc); result += RESULT_ERROR; } if (result == RESULT_OK) { // get image info context->hasAlphaChannel = MagickGetImageAlphaChannel(context->mw); if (context->hasAlphaChannel == MagickTrue) { context->imageWidth = MagickGetImageWidth(context->mw); context->imageHeight = MagickGetImageHeight(context->mw); // get pixel data context->pixel_count = context->imageWidth * context->imageHeight; context->pixels = malloc(context->pixel_count * sizeof(PixelData)); if (context->pixels == NULL) { asprintf(&context->results.message, "Error allocating memory for pixel data: %s\n",context->src_path); result += RESULT_ERROR; } else { if (MagickExportImagePixels(context->mw, 0, 0, context->imageWidth, context->imageHeight, "ARGB", CharPixel, context->pixels) == MagickFalse) { error_desc = MagickGetException(context->mw, &error_type); asprintf(&context->results.message, "Error exporting pixel data (%s): %s\n",error_desc,context->src_path); error_desc = (char *)MagickRelinquishMemory(error_desc); result += RESULT_ERROR; } } } } if (result != RESULT_OK) { // clean up mess context->results.result = result; dispatch_group_async_f(context->conv_group, dispatch_get_main_queue(), context, (void (*)(void *))finish_image); } else { // move to next step dispatch_group_async_f(context->conv_group, context->conv_queue, context, (void (*)(void *))conv_image); } }
int main(void) { static long total; dispatch_semaphore_t dsema; dispatch_test_start("Dispatch Semaphore"); dsema = dispatch_semaphore_create(1); assert(dsema); dispatch_apply(LAPS, dispatch_get_global_queue(0, 0), ^(size_t idx __attribute__((unused))) { dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER); total++; dispatch_semaphore_signal(dsema); });
static void pauseAudio(struct nodeInstanceData *context) { if( VuoMovie_containsAudio(context->movie) ) { if(context->audio_timer) { dispatch_source_cancel(context->audio_timer); dispatch_semaphore_wait(context->audio_timerCanceled, DISPATCH_TIME_FOREVER); dispatch_release(context->audio_timer); } context->audio_timer = NULL; if(context->lastAudioSamples) { VuoRelease(context->lastAudioSamples); context->lastAudioSamples = NULL; } } }
int main(int argc, const char *argv[]) { done = dispatch_semaphore_create(0); dispatch_queue_t queue = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT); dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGHUP, 0, queue); global = 42; dispatch_source_set_registration_handler_f(source, handler); dispatch_resume(source); dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER); return 0; }
void RTMPSession::write(uint8_t* data, size_t size, std::chrono::steady_clock::time_point packetTime, bool isKeyframe) { if(size > 0) { std::shared_ptr<Buffer> buf = std::make_shared<Buffer>(size); buf->put(data, size); m_throughputSession.addBufferSizeSample(m_bufferSize); increaseBuffer(size); if(isKeyframe) { m_sentKeyframe = packetTime; } if(m_bufferSize > kMaxSendbufferSize && isKeyframe) { m_clearing = true; } m_networkQueue.enqueue([=]() { size_t tosend = size; uint8_t* p ; buf->read(&p, size); while(tosend > 0 && !this->m_ending && (!this->m_clearing || this->m_sentKeyframe == packetTime)) { this->m_clearing = false; size_t sent = m_streamSession->write(p, tosend); p += sent; tosend -= sent; this->m_throughputSession.addSentBytesSample(sent); if( sent == 0 ) { #ifdef __APPLE__ dispatch_semaphore_wait(m_networkWaitSemaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC))); #else std::unique_lock<std::mutex> l(m_networkMutex); m_networkCond.wait_until(l, std::chrono::steady_clock::now() + std::chrono::milliseconds(1000)); l.unlock(); #endif } } this->increaseBuffer(-int64_t(size)); }); } }
static SnDispatchThreadState* init_thread() { ASSERT(pthread_getspecific(state_key) == NULL); SnDispatchThreadState* s = (SnDispatchThreadState*)snow_malloc(sizeof(SnDispatchThreadState)); s->current_task = NULL; s->gc_barrier = dispatch_semaphore_create(0); // starts locked s->previous = NULL; // prepend this state to the list of thread states dispatch_semaphore_wait(state_lock, DISPATCH_TIME_FOREVER); s->next = state; if (s->next) { ASSERT(s->next->previous == NULL); s->next->previous = s; } state = s; dispatch_semaphore_signal(state_lock); pthread_setspecific(state_key, s); return s; }
static void pauseMovie(struct nodeInstanceData *context) { if (! context->movie) return; if(context->movie_timer) { dispatch_source_cancel(context->movie_timer); dispatch_semaphore_wait(context->movie_timerCanceled, DISPATCH_TIME_FOREVER); dispatch_release(context->movie_timer); } context->movie_timer = NULL; if(context->lastImage) { VuoRelease(context->lastImage); context->lastImage = NULL; } pauseAudio(context); }
long heim_ipc_semaphore_wait(heim_isemaphore s, time_t t) { #ifdef HAVE_GCD uint64_t timeout; if (t == HEIM_IPC_WAIT_FOREVER) timeout = DISPATCH_TIME_FOREVER; else timeout = (uint64_t)t * NSEC_PER_SEC; return dispatch_semaphore_wait((dispatch_semaphore_t)s, timeout); #elif !defined(ENABLE_PTHREAD_SUPPORT) heim_assert(0, "no semaphore support w/o pthreads"); return 0; #else HEIMDAL_MUTEX_lock(&s->mutex); /* if counter hits below zero, we get to wait */ if (--s->counter < 0) { int ret; if (t == HEIM_IPC_WAIT_FOREVER) ret = pthread_cond_wait(&s->cond, &s->mutex); else { struct timespec ts; ts.tv_sec = t; ts.tv_nsec = 0; ret = pthread_cond_timedwait(&s->cond, &s->mutex, &ts); } if (ret) { HEIMDAL_MUTEX_unlock(&s->mutex); return errno; } } HEIMDAL_MUTEX_unlock(&s->mutex); return 0; #endif }
PJ_DEF(pj_status_t) pj_sem_trywait2(pj_sem_t *sem) { #if 1 pj_status_t result; uint64_t delay_ms = 1000000; dispatch_time_t delay_t = dispatch_time(DISPATCH_TIME_NOW, delay_ms); if(dispatch_semaphore_wait(sem->sem, delay_t)){ usleep(1000); return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); }else return PJ_SUCCESS; #else pj_status_t st = -1; unsigned long start_t, curr_t; //uint64_t tstart; //struct timespec tstart={0,0}, tend={0,0}; //clock_serv_t cclock; //clock_gettime(cclock , &tstart); struct timeval tstart,tcurr; gettimeofday(&tstart, NULL); start_t = 1000000*tstart.tv_sec+ tstart.tv_usec; while(st = pj_sem_trywait(sem) == -1 ){ if(errno == EAGAIN){ //clock_gettime(cclock, &tend); gettimeofday(&tcurr, NULL); curr_t = 1000000*tcurr.tv_sec + tcurr.tv_usec; if(curr_t-start_t > 1000) { st = -1; break; } else usleep(10); }else{ st = -1; break; } } return st; #endif }
int gbDB_IncDecrementWithSemaphore(int* x, dispatch_semaphore_t sema, const bool isInc, const bool isDec) { int retVal = -1; dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); if (isInc) { *x = *x + 1; }//if else if (isDec) { *x = *x - 1; }//else if retVal = *x; dispatch_semaphore_signal(sema); return retVal; }//gbDB_IncDecrementWithSemaphore
int /* O - 0 on success, -1 on error */ _cupsSetNegotiateAuthString( http_t *http, /* I - Connection to server */ const char *method, /* I - Request method ("GET", "POST", "PUT") */ const char *resource) /* I - Resource path */ { OM_uint32 minor_status, /* Minor status code */ major_status; /* Major status code */ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; /* Output token */ (void)method; (void)resource; # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (&gss_init_sec_context == NULL) { DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos " "framework is not present"); return (-1); } # endif /* __APPLE__ */ if (http->gssname == GSS_C_NO_NAME) { http->gssname = cups_gss_getname(http, _cupsGSSServiceName()); } if (http->gssctx != GSS_C_NO_CONTEXT) { gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER); http->gssctx = GSS_C_NO_CONTEXT; } major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &http->gssctx, http->gssname, http->gssmech, GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, &http->gssmech, &output_token, NULL, NULL); #ifdef HAVE_GSS_ACQUIRE_CRED_EX_F if (major_status == GSS_S_NO_CRED) { /* * Ask the user for credentials... */ char prompt[1024], /* Prompt for user */ userbuf[256]; /* Kerberos username */ const char *username, /* Username string */ *password; /* Password string */ _cups_gss_acquire_t data; /* Callback data */ gss_auth_identity_desc identity; /* Kerberos user identity */ _cups_globals_t *cg = _cupsGlobals(); /* Per-thread global data */ if (!cg->lang_default) cg->lang_default = cupsLangDefault(); snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), http->gsshost); if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) return (-1); /* * Try to acquire credentials... */ username = cupsUser(); if (!strchr(username, '@')) { snprintf(userbuf, sizeof(userbuf), "%s@%s", username, http->gsshost); username = userbuf; } identity.type = GSS_AUTH_IDENTITY_TYPE_1; identity.flags = 0; identity.username = (char *)username; identity.realm = (char *)""; identity.password = (char *)password; identity.credentialsRef = NULL; data.sem = dispatch_semaphore_create(0); data.major = 0; data.creds = NULL; if (data.sem) { major_status = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0, GSS_C_INDEFINITE, GSS_KRB5_MECHANISM, GSS_C_INITIATE, &identity, &data, cups_gss_acquire); if (major_status == GSS_S_COMPLETE) { dispatch_semaphore_wait(data.sem, DISPATCH_TIME_FOREVER); major_status = data.major; } dispatch_release(data.sem); if (major_status == GSS_S_COMPLETE) { OM_uint32 release_minor; /* Minor status from releasing creds */ major_status = gss_init_sec_context(&minor_status, data.creds, &http->gssctx, http->gssname, http->gssmech, GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, &http->gssmech, &output_token, NULL, NULL); gss_release_cred(&release_minor, &data.creds); } } } #endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */ if (GSS_ERROR(major_status)) { cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Unable to initialize " "security context"); return (-1); } #ifdef DEBUG else if (major_status == GSS_S_CONTINUE_NEEDED) cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Continuation needed!"); #endif /* DEBUG */ if (output_token.length > 0 && output_token.length <= 65536) { /* * Allocate the authorization string since Windows KDCs can have * arbitrarily large credentials... */ int authsize = 10 + /* "Negotiate " */ (int)output_token.length * 4 / 3 + 1 + 1; /* Base64 + nul */ httpSetAuthString(http, NULL, NULL); if ((http->authstring = malloc((size_t)authsize)) == NULL) { http->authstring = http->_authstring; authsize = sizeof(http->_authstring); } strlcpy(http->authstring, "Negotiate ", (size_t)authsize); httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value, (int)output_token.length); gss_release_buffer(&minor_status, &output_token); } else { DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos credentials too " "large - %d bytes!", (int)output_token.length)); gss_release_buffer(&minor_status, &output_token); return (-1); } return (0); }