home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / rsync221.zip / log.c < prev    next >
C/C++ Source or Header  |  1999-03-04  |  7KB  |  327 lines

  1. /* 
  2.    Copyright (C) Andrew Tridgell 1998
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*
  20.   logging and utility functions
  21.  
  22.   tridge, May 1998
  23.   */
  24. #include "rsync.h"
  25.  
  26. static FILE *logfile;
  27.  
  28.  
  29. static void logit(int priority, char *buf)
  30. {
  31.     if (logfile) {
  32.         fprintf(logfile,"%s [%d] %s", 
  33.             timestring(time(NULL)), (int)getpid(), buf);
  34.         fflush(logfile);
  35.     } else {
  36.         syslog(priority, "%s", buf);
  37.     }
  38. }
  39.  
  40. void log_open(void)
  41. {
  42.     static int initialised;
  43.     int options = LOG_PID;
  44.     time_t t;
  45.     char *logf;
  46.  
  47.     if (initialised) return;
  48.     initialised = 1;
  49.  
  50.     /* this looks pointless, but it is needed in order for the
  51.        C library on some systems to fetch the timezone info
  52.        before the chroot */
  53.     t = time(NULL);
  54.     localtime(&t);
  55.  
  56.     /* optionally use a log file instead of syslog */
  57.     logf = lp_log_file();
  58.     if (logf && *logf) {
  59.         extern int orig_umask;
  60.         int old_umask = umask(022 | orig_umask);
  61.         logfile = fopen(logf, "a");
  62.         umask(old_umask);
  63.         return;
  64.     }
  65.  
  66. #ifdef LOG_NDELAY
  67.     options |= LOG_NDELAY;
  68. #endif
  69.  
  70. #ifdef LOG_DAEMON
  71.     openlog("rsyncd", options, lp_syslog_facility());
  72. #else
  73.     openlog("rsyncd", options);
  74. #endif
  75.  
  76. #ifndef LOG_NDELAY
  77.     logit(LOG_INFO,"rsyncd started\n");
  78. #endif
  79. }
  80.         
  81.  
  82. /* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
  83.  void rprintf(int fd, const char *format, ...)
  84. {
  85.     va_list ap;  
  86.     char buf[1024];
  87.     int len;
  88.     FILE *f=NULL;
  89.     extern int am_daemon;
  90.     /* recursion can happen with certain fatal conditions */
  91.  
  92.     va_start(ap, format);
  93.     len = vslprintf(buf, sizeof(buf), format, ap);
  94.     va_end(ap);
  95.  
  96.     if (len < 0) exit_cleanup(RERR_MESSAGEIO);
  97.  
  98.     if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
  99.  
  100.     buf[len] = 0;
  101.  
  102.     if (fd == FLOG) {
  103.         if (am_daemon) logit(LOG_INFO, buf);
  104.         return;
  105.     }
  106.  
  107.     if (am_daemon) {
  108.         static int depth;
  109.         int priority = LOG_INFO;
  110.         if (fd == FERROR) priority = LOG_WARNING;
  111.  
  112.         if (depth) return;
  113.  
  114.         depth++;
  115.  
  116.         log_open();
  117.         if (!io_multiplex_write(fd, buf, strlen(buf))) {
  118.             logit(priority, buf);
  119.         }
  120.  
  121.         depth--;
  122.         return;
  123.     }
  124.  
  125.     if (fd == FERROR) {
  126.         f = stderr;
  127.     } 
  128.  
  129.     if (fd == FINFO) {
  130.         extern int am_server;
  131.         if (am_server) 
  132.             f = stderr;
  133.         else
  134.             f = stdout;
  135.     } 
  136.  
  137.     if (!f) exit_cleanup(RERR_MESSAGEIO);
  138.  
  139.     if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
  140.  
  141.     if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
  142. }
  143.  
  144. void rflush(int fd)
  145. {
  146.     FILE *f = NULL;
  147.     extern int am_daemon;
  148.     
  149.     if (am_daemon) {
  150.         return;
  151.     }
  152.  
  153.     if (fd == FLOG) {
  154.         return;
  155.     } 
  156.  
  157.     if (fd == FERROR) {
  158.         f = stderr;
  159.     } 
  160.  
  161.     if (fd == FINFO) {
  162.         extern int am_server;
  163.         if (am_server) 
  164.             f = stderr;
  165.         else
  166.             f = stdout;
  167.     } 
  168.  
  169.     if (!f) exit_cleanup(RERR_MESSAGEIO);
  170.     fflush(f);
  171. }
  172.  
  173.  
  174.  
  175. /* a generic logging routine for send/recv, with parameter
  176.    substitiution */
  177. static void log_formatted(int fd,
  178.               char *format, char *op, struct file_struct *file,
  179.               struct stats *initial_stats)
  180. {
  181.     extern int module_id;
  182.     extern char *auth_user;
  183.     char buf[1024];
  184.     char buf2[1024];
  185.     char *p, *s, *n;
  186.     int l;
  187.     extern struct stats stats;        
  188.     extern int am_sender;
  189.     extern int am_daemon;
  190.     int64 b;
  191.  
  192.     strlcpy(buf, format, sizeof(buf));
  193.     
  194.     for (s=&buf[0]; 
  195.          s && (p=strchr(s,'%')); ) {
  196.         n = NULL;
  197.         s = p + 1;
  198.  
  199.         switch (p[1]) {
  200.         case 'h': if (am_daemon) n = client_name(0); break;
  201.         case 'a': if (am_daemon) n = client_addr(0); break;
  202.         case 'l': 
  203.             slprintf(buf2,sizeof(buf2),"%.0f", 
  204.                  (double)file->length); 
  205.             n = buf2;
  206.             break;
  207.         case 'p': 
  208.             slprintf(buf2,sizeof(buf2),"%d", 
  209.                  (int)getpid()); 
  210.             n = buf2;
  211.             break;
  212.         case 'o': n = op; break;
  213.         case 'f': 
  214.             slprintf(buf2, sizeof(buf2), "%s/%s", 
  215.                  file->basedir?file->basedir:"", 
  216.                  f_name(file));
  217.             clean_fname(buf2);
  218.             n = buf2; 
  219.             if (*n == '/') n++;
  220.             break;
  221.         case 'm': n = lp_name(module_id); break;
  222.         case 't': n = timestring(time(NULL)); break;
  223.         case 'P': n = lp_path(module_id); break;
  224.         case 'u': n = auth_user; break;
  225.         case 'b': 
  226.             if (am_sender) {
  227.                 b = stats.total_written - 
  228.                     initial_stats->total_written;
  229.             } else {
  230.                 b = stats.total_read - 
  231.                     initial_stats->total_read;
  232.             }
  233.             slprintf(buf2,sizeof(buf2),"%.0f", (double)b); 
  234.             n = buf2;
  235.             break;
  236.         case 'c': 
  237.             if (!am_sender) {
  238.                 b = stats.total_written - 
  239.                     initial_stats->total_written;
  240.             } else {
  241.                 b = stats.total_read - 
  242.                     initial_stats->total_read;
  243.             }
  244.             slprintf(buf2,sizeof(buf2),"%.0f", (double)b); 
  245.             n = buf2;
  246.             break;
  247.         }
  248.  
  249.         if (!n) continue;
  250.  
  251.         l = strlen(n);
  252.  
  253.         if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
  254.             rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
  255.                 p[0]);
  256.             exit_cleanup(RERR_MESSAGEIO);
  257.         }
  258.  
  259.         if (l != 2) {
  260.             memmove(s+(l-1), s+1, strlen(s+1)+1);
  261.         }
  262.         memcpy(p, n, l);
  263.  
  264.         s = p+l;
  265.     }
  266.  
  267.     rprintf(fd,"%s\n", buf);
  268. }
  269.  
  270. /* log the outgoing transfer of a file */
  271. void log_send(struct file_struct *file, struct stats *initial_stats)
  272. {
  273.     extern int module_id;
  274.     extern int am_server;
  275.     extern char *log_format;
  276.  
  277.     if (lp_transfer_logging(module_id)) {
  278.         log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
  279.     } else if (log_format && !am_server) {
  280.         log_formatted(FINFO, log_format, "send", file, initial_stats);
  281.     }
  282. }
  283.  
  284. /* log the incoming transfer of a file */
  285. void log_recv(struct file_struct *file, struct stats *initial_stats)
  286. {
  287.     extern int module_id;
  288.     extern int am_server;
  289.     extern char *log_format;
  290.  
  291.     if (lp_transfer_logging(module_id)) {
  292.         log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
  293.     } else if (log_format && !am_server) {
  294.         log_formatted(FINFO, log_format, "send", file, initial_stats);
  295.     }
  296. }
  297.  
  298. /* called when the transfer is interrupted for some reason */
  299. void log_exit(int code, const char *file, int line)
  300. {
  301.     if (code == 0) {
  302.         extern struct stats stats;        
  303.         rprintf(FLOG,"wrote %.0f bytes  read %.0f bytes  total size %.0f\n",
  304.             (double)stats.total_written,
  305.             (double)stats.total_read,
  306.             (double)stats.total_size);
  307.     } else {
  308.         rprintf(FLOG,"transfer interrupted (code %d) at %s(%d)\n", 
  309.             code, file, line);
  310.     }
  311. }
  312.  
  313. /* log the incoming transfer of a file for interactive use, this
  314.    will be called at the end where the client was run 
  315.    
  316.    it i called when a file starts to be transferred
  317. */
  318. void log_transfer(struct file_struct *file, const char *fname)
  319. {
  320.     extern int verbose;
  321.  
  322.     if (!verbose) return;
  323.  
  324.     rprintf(FINFO,"%s\n", fname);
  325. }
  326.  
  327.