00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #define FORMAT_BUFR_MAX ( sizeof( format_bufr ) - 1 )
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 XFILE *dbf = NULL;
00082 pstring debugf = "";
00083 BOOL debug_warn_unknown_class = True;
00084 BOOL debug_auto_add_unknown_class = True;
00085 BOOL AllowDebugChange = True;
00086
00087
00088
00089
00090
00091 BOOL override_logfile;
00092
00093
00094
00095
00096
00097
00098 static int debug_all_class_hack = 1;
00099 static BOOL debug_all_class_isset_hack = True;
00100
00101 static int debug_num_classes = 0;
00102 int *DEBUGLEVEL_CLASS = &debug_all_class_hack;
00103 BOOL *DEBUGLEVEL_CLASS_ISSET = &debug_all_class_isset_hack;
00104
00105
00106 int DEBUGLEVEL = &debug_all_class_hack;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 static BOOL stdout_logging = False;
00137 static int debug_count = 0;
00138 #ifdef WITH_SYSLOG
00139 static int syslog_level = 0;
00140 #endif
00141 static pstring format_bufr = { '\0' };
00142 static size_t format_pos = 0;
00143 static BOOL log_overflow = False;
00144
00145
00146
00147
00148
00149
00150 static const char *default_classname_table[] = {
00151 "all",
00152 "tdb",
00153 "printdrivers",
00154 "lanman",
00155 "smb",
00156 "rpc_parse",
00157 "rpc_srv",
00158 "rpc_cli",
00159 "passdb",
00160 "sam",
00161 "auth",
00162 "winbind",
00163 "vfs",
00164 "idmap",
00165 "quota",
00166 "acls",
00167 "locking",
00168 "msdfs",
00169 "dmapi",
00170 NULL
00171 };
00172
00173 static char **classname_table = NULL;
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 void gfree_debugsyms(void)
00185 {
00186 int i;
00187
00188 if ( classname_table ) {
00189 for ( i = 0; i < debug_num_classes; i++ ) {
00190 SAFE_FREE( classname_table[i] );
00191 }
00192 SAFE_FREE( classname_table );
00193 }
00194
00195 if ( DEBUGLEVEL_CLASS != &debug_all_class_hack )
00196 SAFE_FREE( DEBUGLEVEL_CLASS );
00197
00198 if ( DEBUGLEVEL_CLASS_ISSET != &debug_all_class_isset_hack )
00199 SAFE_FREE( DEBUGLEVEL_CLASS_ISSET );
00200 }
00201
00202
00203
00204
00205
00206 #define MAX_CLASS_NAME_SIZE 1024
00207
00208 static char *debug_list_class_names_and_levels(void)
00209 {
00210 int i, dim;
00211 char **list;
00212 char *buf = NULL;
00213 char *b;
00214 BOOL err = False;
00215
00216 if (DEBUGLEVEL_CLASS == &debug_all_class_hack) {
00217 return NULL;
00218 }
00219
00220 list = SMB_CALLOC_ARRAY(char *, debug_num_classes + 1);
00221 if (!list) {
00222 return NULL;
00223 }
00224
00225
00226 for (i = 0, dim = 0; i < debug_num_classes; i++) {
00227 int l = asprintf(&list[i],
00228 "%s:%d ",
00229 classname_table[i],
00230 DEBUGLEVEL_CLASS_ISSET[i]?DEBUGLEVEL_CLASS[i]:DEBUGLEVEL);
00231 if (l < 0 || l > MAX_CLASS_NAME_SIZE) {
00232 err = True;
00233 goto done;
00234 }
00235 dim += l;
00236 }
00237
00238
00239 b = buf = (char *)SMB_MALLOC(dim+1);
00240 if (!buf) {
00241 err = True;
00242 goto done;
00243 }
00244 for (i = 0; i < debug_num_classes; i++) {
00245 int l = strlen(list[i]);
00246 strncpy(b, list[i], l);
00247 b = b + l;
00248 }
00249 b[-1] = '\n';
00250 b[0] = '\0';
00251
00252 done:
00253
00254 for (i = 0; i < debug_num_classes; i++) {
00255 SAFE_FREE(list[i]);
00256 }
00257 SAFE_FREE(list);
00258
00259 if (err) {
00260 return NULL;
00261 } else {
00262 return buf;
00263 }
00264 }
00265
00266
00267
00268
00269
00270 const char *debug_classname_from_index(int ndx)
00271 {
00272 if (ndx < 0 || ndx >= debug_num_classes)
00273 return NULL;
00274 else
00275 return classname_table[ndx];
00276 }
00277
00278
00279
00280
00281
00282 static int debug_lookup_classname_int(const char* classname)
00283 {
00284 int i;
00285
00286 if (!classname) return -1;
00287
00288 for (i=0; i < debug_num_classes; i++) {
00289 if (strcmp(classname, classname_table[i])==0)
00290 return i;
00291 }
00292 return -1;
00293 }
00294
00295
00296
00297
00298
00299 int debug_add_class(const char *classname)
00300 {
00301 int ndx;
00302 void *new_ptr;
00303
00304 if (!classname)
00305 return -1;
00306
00307
00308 debug_init();
00309
00310 ndx = debug_lookup_classname_int(classname);
00311 if (ndx >= 0)
00312 return ndx;
00313 ndx = debug_num_classes;
00314
00315 new_ptr = DEBUGLEVEL_CLASS;
00316 if (DEBUGLEVEL_CLASS == &debug_all_class_hack) {
00317
00318 new_ptr = NULL;
00319 }
00320 new_ptr = SMB_REALLOC_ARRAY(new_ptr, int, debug_num_classes + 1);
00321 if (!new_ptr)
00322 return -1;
00323 DEBUGLEVEL_CLASS = (int *)new_ptr;
00324 DEBUGLEVEL_CLASS[ndx] = 0;
00325
00326
00327 if (ndx==0) {
00328
00329 DEBUGLEVEL_CLASS[ndx] = DEBUGLEVEL;
00330 }
00331 debug_level = DEBUGLEVEL_CLASS;
00332
00333 new_ptr = DEBUGLEVEL_CLASS_ISSET;
00334 if (new_ptr == &debug_all_class_isset_hack) {
00335 new_ptr = NULL;
00336 }
00337 new_ptr = SMB_REALLOC_ARRAY(new_ptr, BOOL, debug_num_classes + 1);
00338 if (!new_ptr)
00339 return -1;
00340 DEBUGLEVEL_CLASS_ISSET = (int *)new_ptr;
00341 DEBUGLEVEL_CLASS_ISSET[ndx] = False;
00342
00343 new_ptr = SMB_REALLOC_ARRAY(classname_table, char *, debug_num_classes + 1);
00344 if (!new_ptr)
00345 return -1;
00346 classname_table = (char **)new_ptr;
00347
00348 classname_table[ndx] = SMB_STRDUP(classname);
00349 if (! classname_table[ndx])
00350 return -1;
00351
00352 debug_num_classes++;
00353
00354 return ndx;
00355 }
00356
00357
00358
00359
00360
00361 int debug_lookup_classname(const char *classname)
00362 {
00363 int ndx;
00364
00365 if (!classname || !*classname)
00366 return -1;
00367
00368 ndx = debug_lookup_classname_int(classname);
00369
00370 if (ndx != -1)
00371 return ndx;
00372
00373 if (debug_warn_unknown_class) {
00374 DEBUG(0, ("debug_lookup_classname(%s): Unknown class\n",
00375 classname));
00376 }
00377 if (debug_auto_add_unknown_class) {
00378 return debug_add_class(classname);
00379 }
00380 return -1;
00381 }
00382
00383
00384
00385
00386
00387 static void debug_dump_status(int level)
00388 {
00389 int q;
00390
00391 DEBUG(level, ("INFO: Current debug levels:\n"));
00392 for (q = 0; q < debug_num_classes; q++) {
00393 DEBUGADD(level, (" %s: %s/%d\n",
00394 classname_table[q],
00395 (DEBUGLEVEL_CLASS_ISSET[q]
00396 ? "True" : "False"),
00397 DEBUGLEVEL_CLASS[q]));
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406 static BOOL debug_parse_params(char **params)
00407 {
00408 int i, ndx;
00409 char *class_name;
00410 char *class_level;
00411
00412 if (!params)
00413 return False;
00414
00415
00416
00417
00418 if (isdigit((int)params[0][0])) {
00419 DEBUGLEVEL_CLASS[DBGC_ALL] = atoi(params[0]);
00420 DEBUGLEVEL_CLASS_ISSET[DBGC_ALL] = True;
00421 i = 1;
00422 } else {
00423 i = 0;
00424 }
00425
00426
00427 for (; i < debug_num_classes && params[i]; i++) {
00428 if ((class_name=strtok(params[i],":")) &&
00429 (class_level=strtok(NULL, "\0")) &&
00430 ((ndx = debug_lookup_classname(class_name)) != -1)) {
00431 DEBUGLEVEL_CLASS[ndx] = atoi(class_level);
00432 DEBUGLEVEL_CLASS_ISSET[ndx] = True;
00433 } else {
00434 DEBUG(0,("debug_parse_params: unrecognized debug class name or format [%s]\n", params[i]));
00435 return False;
00436 }
00437 }
00438
00439 return True;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 BOOL debug_parse_levels(const char *params_str)
00449 {
00450 char **params;
00451
00452
00453 debug_init();
00454
00455 if (AllowDebugChange == False)
00456 return True;
00457
00458 params = str_list_make(params_str, NULL);
00459
00460 if (debug_parse_params(params)) {
00461 debug_dump_status(5);
00462 str_list_free(¶ms);
00463 return True;
00464 } else {
00465 str_list_free(¶ms);
00466 return False;
00467 }
00468 }
00469
00470
00471
00472
00473
00474 static void debug_message(int msg_type, struct process_id src,
00475 void *buf, size_t len, void *private_data)
00476 {
00477 const char *params_str = (const char *)buf;
00478
00479
00480 if (params_str[len-1] != '\0') {
00481 DEBUG(1, ("Invalid debug message from pid %u to pid %u\n",
00482 (unsigned int)procid_to_pid(&src),
00483 (unsigned int)getpid()));
00484 return;
00485 }
00486
00487 DEBUG(3, ("INFO: Remote set of debug to `%s' (pid %u from pid %u)\n",
00488 params_str, (unsigned int)getpid(),
00489 (unsigned int)procid_to_pid(&src)));
00490
00491 debug_parse_levels(params_str);
00492 }
00493
00494
00495
00496
00497
00498 void debug_message_send(pid_t pid, const char *params_str)
00499 {
00500 if (!params_str)
00501 return;
00502 message_send_pid(pid_to_procid(pid), MSG_DEBUG,
00503 params_str, strlen(params_str) + 1,
00504 False);
00505 }
00506
00507
00508
00509
00510
00511 static void debuglevel_message(int msg_type, struct process_id src,
00512 void *buf, size_t len, void *private_data)
00513 {
00514 char *message = debug_list_class_names_and_levels();
00515
00516 if (!message) {
00517 DEBUG(0,("debuglevel_message - debug_list_class_names_and_levels returned NULL\n"));
00518 return;
00519 }
00520
00521 DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n",
00522 (unsigned int)procid_to_pid(&src)));
00523 message_send_pid(src, MSG_DEBUGLEVEL, message, strlen(message) + 1, True);
00524
00525 SAFE_FREE(message);
00526 }
00527
00528
00529
00530
00531
00532 void debug_init(void)
00533 {
00534 static BOOL initialised = False;
00535 const char **p;
00536
00537 if (initialised)
00538 return;
00539
00540 initialised = True;
00541
00542 message_register(MSG_DEBUG, debug_message, NULL);
00543 message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message, NULL);
00544
00545 for(p = default_classname_table; *p; p++) {
00546 debug_add_class(*p);
00547 }
00548 }
00549
00550
00551
00552
00553
00554 void setup_logging(const char *pname, BOOL interactive)
00555 {
00556 debug_init();
00557
00558
00559
00560 stdout_logging = False;
00561 if (dbf) {
00562 x_fflush(dbf);
00563 (void) x_fclose(dbf);
00564 }
00565
00566 dbf = NULL;
00567
00568 if (interactive) {
00569 stdout_logging = True;
00570 dbf = x_stdout;
00571 x_setbuf( x_stdout, NULL );
00572 }
00573 #ifdef WITH_SYSLOG
00574 else {
00575 const char *p = strrchr_m( pname,'/' );
00576 if (p)
00577 pname = p + 1;
00578 #ifdef LOG_DAEMON
00579 openlog( pname, LOG_PID, SYSLOG_FACILITY );
00580 #else
00581
00582 openlog( pname, LOG_PID );
00583 #endif
00584 }
00585 #endif
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 BOOL reopen_logs( void )
00597 {
00598 pstring fname;
00599 mode_t oldumask;
00600 XFILE *new_dbf = NULL;
00601 XFILE *old_dbf = NULL;
00602 BOOL ret = True;
00603
00604 if (stdout_logging)
00605 return True;
00606
00607 oldumask = umask( 022 );
00608
00609 pstrcpy(fname, debugf );
00610 debugf[0] = '\0';
00611
00612 if (lp_loaded()) {
00613 char *logfname;
00614
00615 logfname = lp_logfile();
00616 if (*logfname)
00617 pstrcpy(fname, logfname);
00618 }
00619
00620 pstrcpy( debugf, fname );
00621 new_dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644);
00622
00623 if (!new_dbf) {
00624 log_overflow = True;
00625 DEBUG(0, ("Unable to open new log file %s: %s\n", debugf, strerror(errno)));
00626 log_overflow = False;
00627 if (dbf)
00628 x_fflush(dbf);
00629 ret = False;
00630 } else {
00631 x_setbuf(new_dbf, NULL);
00632 old_dbf = dbf;
00633 dbf = new_dbf;
00634 if (old_dbf)
00635 (void) x_fclose(old_dbf);
00636 }
00637
00638
00639
00640
00641
00642 force_check_log_size();
00643 (void)umask(oldumask);
00644
00645
00646 if (dbf && sys_dup2(x_fileno(dbf), 2) == -1) {
00647 close_low_fds(True);
00648
00649 }
00650
00651 return ret;
00652 }
00653
00654
00655
00656
00657
00658 void force_check_log_size( void )
00659 {
00660 debug_count = 100;
00661 }
00662
00663
00664
00665
00666
00667 BOOL need_to_check_log_size( void )
00668 {
00669 int maxlog;
00670
00671 if( debug_count < 100 )
00672 return( False );
00673
00674 maxlog = lp_max_log_size() * 1024;
00675 if( !dbf || maxlog <= 0 ) {
00676 debug_count = 0;
00677 return(False);
00678 }
00679 return( True );
00680 }
00681
00682
00683
00684
00685
00686 void check_log_size( void )
00687 {
00688 int maxlog;
00689 SMB_STRUCT_STAT st;
00690
00691
00692
00693
00694
00695
00696 if( geteuid() != 0 )
00697 return;
00698
00699 if(log_overflow || !need_to_check_log_size() )
00700 return;
00701
00702 maxlog = lp_max_log_size() * 1024;
00703
00704 if( sys_fstat( x_fileno( dbf ), &st ) == 0 && st.st_size > maxlog ) {
00705 (void)reopen_logs();
00706 if( dbf && get_file_size( debugf ) > maxlog ) {
00707 pstring name;
00708
00709 slprintf( name, sizeof(name)-1, "%s.old", debugf );
00710 (void)rename( debugf, name );
00711
00712 if (!reopen_logs()) {
00713
00714 (void)rename(name, debugf);
00715 }
00716 }
00717 }
00718
00719
00720
00721
00722
00723 if(dbf == NULL) {
00724
00725
00726
00727
00728
00729
00730
00731 dbf = x_fopen( "/dev/console", O_WRONLY, 0);
00732 if(dbf) {
00733 DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n",
00734 debugf ));
00735 } else {
00736
00737
00738
00739 abort();
00740 }
00741 }
00742 debug_count = 0;
00743 }
00744
00745
00746
00747
00748
00749
00750 int Debug1( const char *format_str, ... )
00751 {
00752 va_list ap;
00753 int old_errno = errno;
00754
00755 debug_count++;
00756
00757 if( stdout_logging ) {
00758 va_start( ap, format_str );
00759 if(dbf)
00760 (void)x_vfprintf( dbf, format_str, ap );
00761 va_end( ap );
00762 errno = old_errno;
00763 return( 0 );
00764 }
00765
00766
00767
00768 if( debugf[0] == '\0')
00769 return( 0 );
00770
00771 #ifdef WITH_SYSLOG
00772 if( !lp_syslog_only() )
00773 #endif
00774 {
00775 if( !dbf ) {
00776 mode_t oldumask = umask( 022 );
00777
00778 dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644 );
00779 (void)umask( oldumask );
00780 if( dbf ) {
00781 x_setbuf( dbf, NULL );
00782 } else {
00783 errno = old_errno;
00784 return(0);
00785 }
00786 }
00787 }
00788
00789 #ifdef WITH_SYSLOG
00790 if( syslog_level < lp_syslog() ) {
00791
00792
00793
00794 static int priority_map[] = {
00795 LOG_ERR,
00796 LOG_WARNING,
00797 LOG_NOTICE,
00798 LOG_INFO,
00799 };
00800 int priority;
00801 pstring msgbuf;
00802
00803 if( syslog_level >= ( sizeof(priority_map) / sizeof(priority_map[0]) ) || syslog_level < 0)
00804 priority = LOG_DEBUG;
00805 else
00806 priority = priority_map[syslog_level];
00807
00808 va_start( ap, format_str );
00809 vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap );
00810 va_end( ap );
00811
00812 msgbuf[255] = '\0';
00813 syslog( priority, "%s", msgbuf );
00814 }
00815 #endif
00816
00817 check_log_size();
00818
00819 #ifdef WITH_SYSLOG
00820 if( !lp_syslog_only() )
00821 #endif
00822 {
00823 va_start( ap, format_str );
00824 if(dbf)
00825 (void)x_vfprintf( dbf, format_str, ap );
00826 va_end( ap );
00827 if(dbf)
00828 (void)x_fflush( dbf );
00829 }
00830
00831 errno = old_errno;
00832
00833 return( 0 );
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843 static void bufr_print( void )
00844 {
00845 format_bufr[format_pos] = '\0';
00846 (void)Debug1( "%s", format_bufr );
00847 format_pos = 0;
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 static void format_debug_text( const char *msg )
00867 {
00868 size_t i;
00869 BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded())));
00870
00871 for( i = 0; msg[i]; i++ ) {
00872
00873 if(timestamp && 0 == format_pos) {
00874 format_bufr[0] = format_bufr[1] = ' ';
00875 format_pos = 2;
00876 }
00877
00878
00879 if( format_pos < FORMAT_BUFR_MAX )
00880 format_bufr[format_pos++] = msg[i];
00881
00882
00883 if( '\n' == msg[i] )
00884 bufr_print();
00885
00886
00887
00888
00889 if( format_pos >= FORMAT_BUFR_MAX ) {
00890 bufr_print();
00891 (void)Debug1( " +>\n" );
00892 }
00893 }
00894
00895
00896 format_bufr[format_pos] = '\0';
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906 void dbgflush( void )
00907 {
00908 bufr_print();
00909 if(dbf)
00910 (void)x_fflush( dbf );
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 BOOL dbghdr( int level, const char *file, const char *func, int line )
00936 {
00937
00938 int old_errno = errno;
00939
00940 if( format_pos ) {
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 return( True );
00951 }
00952
00953 #ifdef WITH_SYSLOG
00954
00955 syslog_level = level;
00956 #endif
00957
00958
00959 if( stdout_logging )
00960 return( True );
00961
00962
00963
00964
00965 if( lp_timestamp_logs() || lp_debug_prefix_timestamp() || !(lp_loaded()) ) {
00966 char header_str[200];
00967
00968 header_str[0] = '\0';
00969
00970 if( lp_debug_pid())
00971 slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)sys_getpid());
00972
00973 if( lp_debug_uid()) {
00974 size_t hs_len = strlen(header_str);
00975 slprintf(header_str + hs_len,
00976 sizeof(header_str) - 1 - hs_len,
00977 ", effective(%u, %u), real(%u, %u)",
00978 (unsigned int)geteuid(), (unsigned int)getegid(),
00979 (unsigned int)getuid(), (unsigned int)getgid());
00980 }
00981
00982
00983 if( lp_debug_prefix_timestamp() ) {
00984 (void)Debug1( "[%s, %d%s] ",
00985 current_timestring(lp_debug_hires_timestamp()), level,
00986 header_str);
00987 } else {
00988 (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
00989 current_timestring(lp_debug_hires_timestamp()), level,
00990 header_str, file, func, line );
00991 }
00992 }
00993
00994 errno = old_errno;
00995 return( True );
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 BOOL dbgtext( const char *format_str, ... )
01012 {
01013 va_list ap;
01014 pstring msgbuf;
01015
01016 va_start( ap, format_str );
01017 vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap );
01018 va_end( ap );
01019
01020 format_debug_text( msgbuf );
01021
01022 return( True );
01023 }