|
SASC-NG
DVBSoftCAM
|
00001 /* 00002 DVBLoopback 00003 Copyright Alan Nisota 2006 00004 00005 This file is part of DVBLoopback. 00006 00007 DVBLoopback is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 DVBLoopback is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with DVBLoopback; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #include <stdlib.h> 00022 #include <stdio.h> 00023 #include <fcntl.h> 00024 #include <pthread.h> 00025 #include <string.h> 00026 #include <getopt.h> 00027 #include <unistd.h> 00028 #include <dirent.h> 00029 00030 #include <signal.h> 00031 #include <errno.h> 00032 00033 #include <sys/time.h> 00034 #include <sys/resource.h> 00035 #include <sys/ioctl.h> 00036 00037 #include <sched.h> 00038 #include <linux/dvb/frontend.h> 00039 #include <linux/dvb/dmx.h> 00040 00041 #include <syslog.h> 00042 #include <stdarg.h> 00043 #include <time.h> 00044 00045 #include <sys/types.h> 00046 #include <sys/socket.h> 00047 #include <netinet/in.h> 00048 00049 #include "process_req.h" 00050 #include "plugin_getsid.h" 00051 #include "plugin_ringbuf.h" 00052 #include "msg_passing.h" 00053 00054 struct t_adaptermap { 00055 char name[128]; 00056 int adapter; 00057 int used; 00058 }; 00059 00060 LIST_HEAD(plugin_cmdlist); 00061 unsigned int _dbglvl; 00062 void * listen_loop(void * arg); 00063 extern const char *source_version; 00064 pthread_attr_t default_attr; 00065 static pthread_t main_thread; 00066 static pthread_mutex_t tmprintf_mutex = PTHREAD_MUTEX_INITIALIZER; 00067 00068 static char logfile[512] = ""; 00069 static char pidfile[512] = ""; 00070 enum { 00071 LOGMODE_STDOUT = 0x01, 00072 LOGMODE_SYSLOG = 0x02, 00073 LOGMODE_LOGFILE = 0x04, 00074 }; 00075 static struct { 00076 unsigned int logmode; 00077 } logcfg = {LOGMODE_STDOUT}; 00078 00079 int tmprintf(const char *plugin, const char *fmt, ...) 00080 { 00081 va_list args; 00082 struct timeval tv; 00083 struct tm tm; 00084 unsigned long usec; 00085 char stamp[32], logmsg[1024]; 00086 gettimeofday(&tv, NULL); 00087 localtime_r(&tv.tv_sec, &tm); 00088 strftime(stamp,sizeof(stamp),"%b %e %T",localtime_r(&tv.tv_sec, &tm)); 00089 usec = tv.tv_usec; 00090 pthread_mutex_lock(&tmprintf_mutex); 00091 /* 00092 ** Display the remainder of the message 00093 */ 00094 va_start(args,fmt); 00095 vsnprintf(logmsg,sizeof(logmsg),fmt,args); 00096 va_end(args); 00097 if(logcfg.logmode & LOGMODE_STDOUT) 00098 fprintf(stdout, "%s.%03lu %s: %s", stamp, usec/1000, plugin, logmsg); 00099 if(logcfg.logmode & LOGMODE_SYSLOG) 00100 syslog(LOG_INFO, "%s: %s", plugin, logmsg); 00101 pthread_mutex_unlock(&tmprintf_mutex); 00102 return 0; 00103 } 00104 00105 int get_adapters(struct t_adaptermap **adaptermap) 00106 { 00107 int count = 0; 00108 struct dirent **adptrlist; 00109 int i, n, fd, adapter; 00110 char frontend[30]; 00111 struct dvb_frontend_info fe; 00112 00113 n = scandir("/dev/dvb/", &adptrlist, NULL, alphasort); 00114 if(n < 0) { 00115 perror("scandir"); 00116 return 0; 00117 } 00118 *adaptermap = (struct t_adaptermap *)malloc(n * sizeof(struct t_adaptermap)); 00119 for(i = 0; i < n; i++) { 00120 if(1 == sscanf(adptrlist[i]->d_name, "adapter%d", &adapter)) { 00121 snprintf(frontend, 30, "/dev/dvb/adapter%d/frontend0", adapter); 00122 fd = open(frontend, O_RDONLY); 00123 if(fd >= 0) { 00124 if(ioctl(fd, FE_GET_INFO, &fe) >=0) { 00125 (*adaptermap)[count].adapter = adapter; 00126 snprintf((*adaptermap)[count].name, 128, "%s", fe.name); 00127 (*adaptermap)[count].used = 0; 00128 count++; 00129 } 00130 close(fd); 00131 } 00132 } 00133 free(adptrlist[i]); 00134 } 00135 free(adptrlist); 00136 if(count == 0) 00137 free(*adaptermap); 00138 return count; 00139 } 00140 00141 void show_help() 00142 { 00143 struct list_head *ptr; 00144 int i; 00145 printf("sasc-ng [options] -j <real>:<virtual> ...\n"); 00146 printf("Version: %s-%s\n\n", RELEASE_VERSION, source_version); 00147 printf(" -j//--join <real>:<virt>\n"); 00148 printf(" : Connect real and loopback dvb adapters\n"); 00149 printf(" This option can be specified multiple times\n"); 00150 printf(" to support multiple loopback adapters.\n"); 00151 printf(" NOTE: <real> can be either the adapter number\n"); 00152 printf(" or the adapter name (see --identify)\n"); 00153 printf("Optional args:\n"); 00154 printf(" -h/--help : This help message\n"); 00155 printf(" -i/--identify : List all available adpaters\n"); 00156 printf(" -b/--buffer <num> : Set size of read buffer (default: 2M)\n"); 00157 printf(" -d/--debug <num> : Set debug level (this is a 32bit bitmask)\n"); 00158 printf(" -l/--log : Set log file for output\n"); 00159 printf(" -n/--noload <num> : Don't load module <num>. Use with care!\n"); 00160 printf(" -o/--osd : Enable passthrough for cards with mpeg2 decoders\n"); 00161 printf(" -p/--port <num> : Set debug port to listen on (default 5456)\n"); 00162 printf(" -D/--daemon : Enable daemon/background mode (logs to syslog unless -l is set)\n"); 00163 printf(" -P/--pidfile : write pid to file\n"); 00164 list_for_each(ptr, &plugin_cmdlist) { 00165 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00166 if(cmd->parse_args) { 00167 printf("\nOptions for %s module:\n", cmd->name); 00168 cmd->parse_args(ARG_HELP); 00169 } 00170 } 00171 printf("\nDebug bitmask:\n"); 00172 printf(" 0x%08x : %s\n", 3, dnames[3]); 00173 printf(" 0x%08x : %s\n", 3<<2, dnames[4]); 00174 printf(" 0x%08x : %s\n", 3<<4, dnames[5]); 00175 printf(" 0x%08x : %s\n", 3<<6, dnames[6]); 00176 for(i = 8; i < 32; i+=2) { 00177 list_for_each(ptr, &plugin_cmdlist) { 00178 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00179 if(cmd->plugin == i) { 00180 printf(" 0x%08x : %s\n", 3<<i, cmd->name); 00181 break; 00182 } 00183 } 00184 } 00185 } 00186 00187 int init_osd(int real, int virt) { 00188 FILE *FH; 00189 char str[256]; 00190 int tmp; 00191 int link[] = {0, 1, 8}; //video, audio, osd 00192 //Link real adapter to virtual adapter 00193 sprintf(str, "/proc/dvbloopback/adapter%d/adapter", virt); 00194 FH = fopen(str, "w"); 00195 if(! FH) 00196 return 0; 00197 fprintf(FH, "%d", real); 00198 fclose(FH); 00199 FH = fopen(str, "r"); 00200 fscanf(FH,"%d", &tmp); 00201 fclose(FH); 00202 if(tmp != real) { 00203 dprintf("Could not setup adapter link: %d != %d\n", real, tmp); 00204 return 0; 00205 } 00206 for(int i=0; i < 3; i++) { 00207 sprintf(str, "/proc/dvbloopback/adapter%d/%s", virt, dnames[link[i]]); 00208 FH = fopen(str, "w"); 00209 if(! FH) 00210 return 0; 00211 fprintf(FH, "1"); 00212 fclose(FH); 00213 FH = fopen(str, "r"); 00214 fscanf(FH,"%d", &tmp); 00215 fclose(FH); 00216 if(tmp != 1) { 00217 dprintf("Could not setup device %s: %d != 1\n", dnames[link[i]], tmp); 00218 return 0; 00219 } 00220 } 00221 return 1; 00222 } 00223 00224 int log_rotate(int report_error) 00225 { 00226 /* http://www.gossamer-threads.com/lists/mythtv/dev/110113 */ 00227 00228 int new_logfd = open(logfile, O_WRONLY|O_CREAT|O_APPEND|O_SYNC|O_LARGEFILE, 0664); 00229 if (new_logfd < 0) { 00230 // If we can't open the new logfile, send data to /dev/null 00231 if (report_error) { 00232 fprintf(stderr, "cannot open logfile %s\n",logfile); 00233 return 0; 00234 } 00235 new_logfd = open("/dev/null", O_WRONLY); 00236 if (new_logfd < 0) { 00237 // There's not much we can do, so punt. 00238 return 0; 00239 } 00240 } 00241 while (dup2(new_logfd, 1) < 0 && errno == EINTR) 00242 ; 00243 while (dup2(new_logfd, 2) < 0 && errno == EINTR) 00244 ; 00245 while (close(new_logfd) < 0 && errno == EINTR) 00246 ; 00247 return 1; 00248 } 00249 00250 void log_rotate_handler(int) 00251 { 00252 log_rotate(0); 00253 } 00254 00255 static void exit_handler(int type) 00256 { 00257 if(type == SIGTERM && ! pthread_equal(pthread_self(), main_thread)) { 00258 pthread_exit(NULL); 00259 return; 00260 } 00261 //take care of main message handler. Main thread will do the rest 00262 msg_terminate(MSG_LOW_PRIORITY); 00263 } 00264 00265 int main(int argc, char *argv[]) 00266 { 00267 unsigned long bufsize = 2000000; 00268 struct parser_adpt pc_all[8]; 00269 struct common_data common[8]; 00270 struct list_head *ptr; 00271 pthread_t msg_highpri_thread; 00272 pthread_t socket_thread; 00273 int virt_adapt[8], real_adapt[8], adapter_cnt=0; 00274 unsigned long debug_port = 5456; 00275 int longopt = 0; 00276 int c, Option_Index = 0; 00277 int illegal_opt = 0; 00278 int use_osd = 0; 00279 struct t_adaptermap *adptrmap; 00280 int adptrmap_count; 00281 struct option *LongOpts; 00282 int optcount; 00283 int use_daemon = 0; 00284 static struct option Long_Options[] = { 00285 {"buffer", 1, 0, 'b'}, 00286 {"debug", 1, 0, 'd'}, 00287 {"help", 0, 0, 'h'}, 00288 {"identify", 0, 0, 'i'}, 00289 {"join", 1, 0, 'j'}, 00290 {"noload", 1, 0, 'n'}, 00291 {"osd", 0, 0, 'o'}, 00292 {"port", 0, 0, 'p'}, 00293 {"daemon", 0, 0, 'D'}, 00294 {"log", 1, 0, 'l'}, 00295 {"pidfile", 1, 0, 'P'}, 00296 }; 00297 00298 pthread_attr_init(&default_attr); 00299 pthread_attr_setstacksize(&default_attr, PTHREAD_STACK_MIN + 0x4000); 00300 main_thread = pthread_self(); 00301 00302 _dbglvl = 0; 00303 //enable unbuffered stdout 00304 setbuf(stdout, 0); 00305 00306 //enable a core dump file 00307 struct rlimit rl = {RLIM_INFINITY, RLIM_INFINITY}; 00308 setrlimit(RLIMIT_CORE, &rl); 00309 00310 adptrmap_count = get_adapters(&adptrmap); 00311 if(adptrmap_count == 0) { 00312 dprintf("Didn't find any DVB adapters!\n"); 00313 return(-1); 00314 } 00315 00316 //get all plugin args 00317 optcount = sizeof(Long_Options) / sizeof(struct option); 00318 LongOpts = (struct option *)malloc(sizeof(struct option) * (optcount+1)); 00319 memcpy(LongOpts, Long_Options, sizeof(Long_Options)); 00320 00321 list_for_each(ptr, &plugin_cmdlist) { 00322 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00323 if(cmd->parse_args) { 00324 struct option *optstr; 00325 optstr = cmd->parse_args(ARG_INIT); 00326 if(! optstr) 00327 continue; 00328 while(optstr->name) { 00329 LongOpts = (struct option *)realloc(LongOpts, 00330 sizeof(struct option) * (optcount+2)); 00331 memcpy(LongOpts+optcount, optstr, sizeof(struct option)); 00332 optstr++; 00333 optcount++; 00334 } 00335 } 00336 } 00337 memset(LongOpts+optcount, 0, sizeof(struct option)); 00338 00339 while (1) { 00340 00341 c = getopt_long(argc, argv, "b:d:hij:l:n:op:DP:", LongOpts, &Option_Index); 00342 if (c == EOF) 00343 break; 00344 switch (c) { 00345 case 'b': 00346 { 00347 char type; 00348 int l = sscanf(optarg, "%lu%c", &bufsize,&type); 00349 if(l == 2) { 00350 if (type == 'M') { 00351 bufsize *= 1000000; 00352 } else if (type == 'k') { 00353 bufsize *= 1024; 00354 } 00355 break; 00356 } 00357 } 00358 case 'd': 00359 _dbglvl = strtol(optarg, NULL, 0); 00360 break; 00361 case 'D': 00362 use_daemon = 1; 00363 break; 00364 case 'h': 00365 show_help(); 00366 return(0); 00367 break; 00368 case 'i': 00369 { 00370 int i; 00371 for(i = 0; i < adptrmap_count; i++) 00372 printf("%d: %s\n", adptrmap[i].adapter, adptrmap[i].name); 00373 return(0); 00374 } 00375 case 'j': 00376 { 00377 int r, v, len, i; 00378 char *v_chr, *r_end; 00379 if((v_chr = strrchr(optarg, ':')) == NULL) { 00380 illegal_opt++; 00381 break; 00382 } 00383 v = strtol(v_chr+1, NULL, 0); 00384 r = strtol(optarg, &r_end, 0); 00385 len = v_chr - optarg; 00386 if (len > 128) 00387 len = 128; 00388 for(i = 0; i < adptrmap_count; i++) { 00389 if((r_end != v_chr && strncmp(optarg, adptrmap[i].name, len) == 0) || (r_end == v_chr && adptrmap[i].adapter == r)) { 00390 if(adptrmap[i].used) { 00391 dprintf("Adapter %d is already in use\n", r); 00392 return(-1); 00393 } 00394 adptrmap[i].used = 1; 00395 real_adapt[adapter_cnt] = adptrmap[i].adapter; 00396 virt_adapt[adapter_cnt] = v; 00397 adapter_cnt++; 00398 break; 00399 } 00400 } 00401 if(i == adptrmap_count) { 00402 dprintf("Could not find adapter for %s\n", optarg); 00403 return(-1); 00404 } 00405 break; 00406 } 00407 case 'l': 00408 strncpy(logfile, optarg, sizeof(logfile)-1); 00409 logfile[sizeof(logfile)-1] = 0; 00410 break; 00411 case 'n': 00412 { 00413 int val = atoi(optarg); 00414 list_for_each(ptr, &plugin_cmdlist) { 00415 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00416 if(cmd->plugin == val) { 00417 list_del(&cmd->list); 00418 break; 00419 } 00420 } 00421 break; 00422 } 00423 case 'o': 00424 use_osd = 1; 00425 break; 00426 case 'p': 00427 debug_port = atoi(optarg); 00428 break; 00429 case 'P': 00430 strncpy(pidfile, optarg, sizeof(pidfile)-1); 00431 pidfile[sizeof(pidfile)-1] = 0; 00432 break; 00433 case 0: 00434 if(! longopt) { 00435 list_for_each(ptr, &plugin_cmdlist) { 00436 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00437 if(cmd->parse_args) { 00438 cmd->parse_args(ARG_PARSE); 00439 } 00440 } 00441 break; 00442 } 00443 break; 00444 case '?': 00445 illegal_opt++; 00446 break; 00447 } 00448 } 00449 free(LongOpts); 00450 free(adptrmap); 00451 00452 if (illegal_opt) { 00453 dprintf("Illegal options specified. Aborting!\n"); 00454 return(-1); 00455 } 00456 if (adapter_cnt == 0) { 00457 show_help(); 00458 return(-1); 00459 } 00460 00461 if(bufsize < 1000000 || bufsize > 20000000) { 00462 dprintf("Buffer size is out of range. 1000000 <= size <= 20000000\n"); 00463 return(-1); 00464 } 00465 00466 if (use_daemon) { 00467 if(logfile[0] == 0) { 00468 logcfg.logmode = LOGMODE_SYSLOG; 00469 openlog(argv[0],LOG_PID,LOG_LOCAL0); 00470 } 00471 if (daemon(0,1) < -1) { 00472 dprintf("Couldnt go into background. Aborting!\n"); 00473 return(-1); 00474 } 00475 } 00476 00477 if (pidfile[0] != 0 ) { 00478 FILE *f = fopen(pidfile,"wt"); 00479 if (f) { 00480 fprintf(f,"%d\n",getpid()); 00481 fclose(f); 00482 } 00483 } 00484 00485 if (logfile[0] != 0 ) { 00486 if (! log_rotate(1)) 00487 fprintf(stderr, "cannot open logfile; using stdout/stderr\n"); 00488 else 00489 signal(SIGHUP, &log_rotate_handler); 00490 } 00491 00492 dprintf("Version: %s-%s\n", RELEASE_VERSION, source_version); 00493 00494 //Need to init msg_loop early in case some plugins setup messages during init 00495 msg_loop_init(); 00496 00497 //setup exit_handler afer msg_loop_init! 00498 signal(SIGTERM, &exit_handler); 00499 signal(SIGQUIT, &exit_handler); 00500 signal(SIGINT, &exit_handler); 00501 00502 for(int i = 0; i < adapter_cnt; i++) { 00503 if (use_osd) { 00504 if(init_osd(real_adapt[i], virt_adapt[i])) { 00505 dprintf("Initiailized osd on adapter pair %d:%d\n", 00506 real_adapt[i], virt_adapt[i]); 00507 } 00508 } 00509 common[i].virt_adapt = virt_adapt[i]; 00510 common[i].real_adapt = real_adapt[i]; 00511 common[i].private_data = NULL; 00512 common[i].buffersize = bufsize; 00513 pthread_mutex_init(&common[i].cond_lock, NULL); 00514 pthread_cond_init(&common[i].cond, NULL); 00515 common[i].cond_count = 0; 00516 init_parser(&pc_all[i], &common[i]); 00517 if(! pc_all[i].frontend || ! pc_all[i].demux || ! pc_all[i].dvr) { 00518 dprintf("Could not connect to loopback device %d\n", virt_adapt[i]); 00519 dprintf("Are you sure you have loaded the dvbloopback module\n"); 00520 dprintf("properly and/or used the correct values to the '-j' switch\n"); 00521 return(-1); 00522 } 00523 list_for_each(ptr, &plugin_cmdlist) { 00524 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00525 if(cmd->connect) 00526 cmd->connect(&pc_all[i]); 00527 } 00528 00529 } 00530 00531 for(int i = 0; i < adapter_cnt; i++) { 00532 launch_processors(&pc_all[i]); 00533 pthread_mutex_lock(&common[i].cond_lock); 00534 while (common[i].cond_count > 0) { 00535 pthread_cond_wait(&common[i].cond, &common[i].cond_lock); 00536 } 00537 pthread_mutex_unlock(&common[i].cond_lock); 00538 } 00539 00540 list_for_each(ptr, &plugin_cmdlist) { 00541 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00542 if(cmd->launch) 00543 cmd->launch(); 00544 } 00545 pthread_create(&socket_thread, &default_attr, listen_loop, 00546 (void *)debug_port); 00547 pthread_create(&msg_highpri_thread, &default_attr, msg_loop, 00548 (void *) MSG_HIGH_PRIORITY); 00549 00550 msg_loop((void *)MSG_LOW_PRIORITY); 00551 //Shutting down 00552 msg_terminate(MSG_HIGH_PRIORITY); 00553 pthread_join(msg_highpri_thread, NULL); 00554 pthread_kill(socket_thread, SIGTERM); 00555 pthread_join(socket_thread, NULL); 00556 //Now kill the device handlers 00557 for(int i = 0; i < adapter_cnt; i++) 00558 shutdown_parser(&pc_all[i]); 00559 //Lastly kill the plugins 00560 list_for_each(ptr, &plugin_cmdlist) { 00561 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00562 if(cmd->shutdown) 00563 cmd->shutdown(); 00564 } 00565 dprintf("Exiting...\n"); 00566 fflush(stdout); 00567 fflush(stderr); 00568 return 0; 00569 } 00570 00571 void * listen_loop(void * arg) 00572 { 00573 unsigned long port = (unsigned long)arg; 00574 struct list_head *ptr; 00575 int sockfd, opt = 0; 00576 unsigned int len; 00577 char buf[256]; 00578 struct sockaddr_in serv_addr, cli_addr; 00579 00580 sockfd = socket(AF_INET, SOCK_STREAM, 0); 00581 if(sockfd < 0) { 00582 perror("Socket creation failed"); 00583 return NULL; 00584 } 00585 00586 dprintf("Listening on port %d\n", port); 00587 00588 len = sizeof(opt); 00589 getsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, 00590 (socklen_t *)&len); 00591 opt |= 1; 00592 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); 00593 serv_addr.sin_family = AF_INET; 00594 serv_addr.sin_addr.s_addr = INADDR_ANY; 00595 serv_addr.sin_port = htons(port); 00596 00597 if(bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { 00598 perror("Failed to bind to debug port:"); 00599 tmprintf("DEBUG","The debug port will not be available"); 00600 return NULL; 00601 } 00602 if(listen(sockfd, 1) < 0) { 00603 perror("Listen failed:"); 00604 return NULL; 00605 } 00606 while(1) { 00607 int connfd; 00608 int found; 00609 len = sizeof(cli_addr); 00610 connfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *)&len); 00611 if(connfd < 0) { 00612 perror("Connection failed:"); 00613 continue; 00614 } 00615 len = read(connfd, buf, 256); 00616 found = 0; 00617 list_for_each(ptr, &plugin_cmdlist) { 00618 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00619 if(cmd->user_msg) { 00620 if(strncasecmp(buf, cmd->name, strlen(cmd->name)) == 0 && buf[strlen(cmd->name)] == ' ') { 00621 char *p; 00622 printf("xx %s yy\n", buf); 00623 if((p = strchr(buf, '\r')) || (p = strchr(buf, '\n'))) { *p = '\0'; } 00624 printf("XX %s YY\n", buf); 00625 cmd->user_msg(&buf[strlen(cmd->name)+1]); 00626 found = 1; 00627 break; 00628 } 00629 } 00630 } 00631 if(! found) { 00632 if(len < sizeof(int)) { 00633 tmprintf("DEBUG","Got bad command\n"); 00634 } else { 00635 /* This isn't thread safe, but that's ok*/ 00636 _dbglvl = *(unsigned int *)&buf; 00637 tmprintf("DEBUG","Got debug value: %u\n", _dbglvl); 00638 } 00639 } 00640 close(connfd); 00641 } 00642 }