📄 mserver.c
字号:
/****************** Start of $RCSfile: mserver.c,v $ ****************** $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/mserver.c,v $* $Id: mserver.c,v 1.5 2005/01/15 08:56:22 alb Exp alb $* $Date: 2005/01/15 08:56:22 $* $Author: alb $********* description *********************************************************************************************************************/#include <conf.h>#include <version.h> static char * fileversion = "$RCSfile: mserver.c,v $ $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/mserver.c,v $ $Id: mserver.c,v 1.5 2005/01/15 08:56:22 alb Exp alb $ " PACKAGE " " VERSION_STRING;#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <stdarg.h>#include <sys/types.h>#include <signal.h>#include <fcntl.h>#ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#include <sys/socket.h>#include <netinet/in.h>#include <syslog.h>#include <x_types.h>#include <netutils.h>#include <genutils.h>#include <mvals.h>#include <fileutil.h>#include "cryptkey.h"#include "prot.h"#include "backup.h"#include "server.h"#define MPX_CHUNKSIZE 1000#define ER__(cmd, lerrfl) { if( (lerrfl = cmd) ) return(lerrfl); }#define EM__(nmem) { nomemfatal(nmem); }#define EEM__(st) { if(st) nomemfatal(NULL); }#define ENM__ nomemfatal(NULL)typedef struct __conn_stat__ { Int32 status; Int32 tape_status; UChar *inbuf; UChar *outbuf; Int32 commbufsiz; UChar *tapebuf; Int32 tapebufsiz; Int32 tapebufptr; Int32 headerlen; Uns32 inbuf_allocated; Uns32 outbuf_allocated; UChar *peername; UChar *clientid; struct sockaddr *peeraddr; int fd; Int32 req_cartset; Int32 req_cart; Int32 req_filenum; Uns32 pending_cmd; Flag pending; Flag newfilerequested; Uns8 req_streamermode;} ConnStatus;#define CONNSTAT_UNINITIALIZED 0#define CONNSTAT_WAIT_AUTH 1#define CONNSTAT_AUTHENTICATED 2#define CONNSTAT_CONNECTED 3#define PROC_ERROR_MASK (0xff << 16)#define PROC_ERROR(num) ((num << 16) & PROC_ERROR_MASK)#define PROC_ERRVAL(val) ((val & PROC_ERROR_MASK) >> 16)#define PROC_DEFAULT_PROC (1 << 24)#define PROC_POST_PROC (PROC_DEFAULT_PROC << 1)#define PROC_FINISH_CONN (PROC_DEFAULT_PROC << 2)#define PROC_PROC_MASK (PROC_DEFAULT_PROC | PROC_POST_PROC)Int32 server_status = NOT_OPEN;ConnStatus *connections = NULL;AFBProtocol **prot_items;UChar *backuphome = NULL;UChar *default_configfilenames[] = { \ DEFAULT_SERVER_CONFIGFILES, NULL, NULL };UChar *configfilename = NULL;UChar *loggingfile = NULL;UChar *syslog_ident = NULL;UChar *cryptfile = NULL;Flag edebug = NO;Flag unsecure = NO;Flag daemonize = NO;Flag nobuffering = NO;UChar *progname = NULL;char **sargv;char *sprog;Int32 cartset = 1;Int32 cartnum = 0;Int32 filenum = 0;Int32 wrcartnum = 0;Int32 wrfilenum = 0;Int32 rdcartnum = 0;Int32 rdfilenum = 0;Int32 numcarts = 0;Int32 numwrclients = 0;Int32 numrdclients = 0;Flag tapepos_valid = NO;Flag wrtapepos_valid = NO;Flag rdtapepos_valid = NO;Flag reading_in_sync = NO;Flag raw_mode = NO;UChar *tapebuf = NULL;Int32 tapebuf_allocated = 0;Int32 commbufsiz = DEFCOMMBUFSIZ;Int32 tapebufptr = 0;Int32 tapeblocksize = 0;Flag newfilerequested = NO;int tofd = -1;int fromfd = -1;int pid = -1;int pst;int lfd = 2;Flag interrupted = NO;UChar *vardir = NULL;UChar *bindir = NULL;UChar *libdir = NULL;UChar *confdir = NULL;ReplSpec replacements[] = { { "%B", NULL, &bindir }, { "%L", NULL, &libdir }, { "%V", NULL, &vardir }, { "%C", NULL, &confdir }, };typedef struct __ClientPos__ { UChar *clientname; Int32 cartnum; Int32 filenum;} ClientPos;ClientPos *prev_client_conns = NULL;ParamFileEntry entries[] = { { &cryptfile, NULL, (UChar *) "^[ \t]*\\([Ee]n\\)?[Cc]rypti?o?n?[-_ \t]*[Kk]ey[-_ \t]*[Ff]iles?:?[ \t]*", TypeUCharPTR }, { &loggingfile, NULL, (UChar *) "^[ \t]*[Ll]ogg?i?n?g?[-_ \t]*[Ff]ile:?[ \t]*", TypeUCharPTR }, { &vardir, NULL, (UChar *) "^[ \t]*[Vv][Aa][Rr][-_ \t]*[Dd]ire?c?t?o?r?y?:?[ \t]*", TypeUCharPTR },};#define repl_dirs(string) repl_substrings((string), replacements, \ sizeof(replacements) / sizeof(replacements[0]))static Int32 handle_prot_func(int, void *, Int32, void *, TcpMuxCallbDoneActions *, void *);static voiddo_exit(int est){ if(pid > 0){ kill(pid, SIGTERM); if(tofd >= 0) close(tofd); if(fromfd >= 0) close(fromfd); waitpid(pid, &pst, 0); est = WEXITSTATUS(pst); } exit(est);}static voidlogmsg(int prio, UChar * fmt, ...){ va_list args; FILE *fp, *lfp = NULL; va_start(args, fmt); if(loggingfile) lfp = fopen(loggingfile, "a"); fp = (lfp ? lfp : stderr); fprintf(fp, "%s, ", actimestr()); vfprintf(fp, fmt, args); fflush(fp); if(lfp) fclose(lfp); if(syslog_ident) gvsyslog(syslog_ident, LOG_CONS | LOG_PID, LOG_DAEMON, prio, fmt, args); va_end(args);}static voidfatal(UChar * msg){ logmsg(LOG_CRIT, "%s", msg); do_exit(1);}static voidnomemfatal(void * ptr){ if(!ptr) fatal("Error: Cannot allocate memory.\n");}#define request_new_file(fromfd, tofd, tcpmux_status) \ simple_command(REQUESTNEWFILE, fromfd, tofd, tcpmux_status)static Flagneed_new_tapefile_for_wrclient(UChar * name, Int32 cartn, Int32 filen){ Flag needit = NO; Int32 i; Int32 idx; /* uninitialized OK */ if(!prev_client_conns){ EM__(prev_client_conns = NEWP(ClientPos, 2)); idx = 0; SETZERO(prev_client_conns[1]); } else{ for(i = 0; prev_client_conns[i].clientname; i++){ if(!strcmp(prev_client_conns[i].clientname, name)){ needit = YES; idx = i; } } if(!needit){ EM__(prev_client_conns = RENEWP(prev_client_conns, ClientPos, i + 2)); idx = i; SETZERO(prev_client_conns[idx + 1]); } } if(needit){ if(filen != prev_client_conns[idx].filenum || cartn != prev_client_conns[idx].cartnum) needit = NO; } else{ EM__(prev_client_conns[idx].clientname = strdup(name)); } prev_client_conns[idx].cartnum = cartn; prev_client_conns[idx].filenum = filen; return(needit);}static voidfree_prev_wrclient_list(){ ClientPos *poss; if(prev_client_conns){ for(poss = prev_client_conns; poss->clientname; poss++) free(poss->clientname); ZFREE(prev_client_conns); }}static voidsig_handler(int sig){ signal(sig, sig_handler); switch(sig){ case SIGPIPE: logmsg(LOG_ERR, T_("Error: Connection to client lost. Exiting.\n")); do_exit(1); case SIGUSR1: edebug = 0; break; }}static Int8check_interrupted(ConnStatus * connstat){ int i; Int32 len[2]; nodeaddr peeraddr; if(interrupted){ return(1); } len[0] = len[1] = 0; /* I use 32 Bit int for len. See server.c for a *comment* */ *((int *) &(len[0])) = sizeof(peeraddr); i = getpeername(connstat->fd, (struct sockaddr *)(&peeraddr), (int *) &(len[0])); if(i && errno == ENOTCONN){ logmsg(LOG_ERR, T_("Error: Client disconnected. Exiting.\n")); kill(getpid(), SIGPIPE); } return(interrupted);}static voidusage(UChar * prnam){ logmsg(LOG_ERR, T_("Usage: %s [ -sbD ] [ <configuration-file> ] [ -l <logging-file> ] [ -L <locale> ]\n"), prnam); do_exit(1);}static Int32send_status(int fd, UChar statusc) /* utility */{ return(write_forced(fd, &statusc, 1) != 1 ? - errno : 0);}#define send_cmd send_statusstatic Int32result(int fromfd, void *tcpmux_status){ Int32 i; UChar c; i = (tcp_mux_long_read(tcpmux_status, fromfd, &c, 1) != 1); return(i ? - errno : (Int32) c); }static Int32simple_command(UChar cmd, int fromfd, int tofd, void * tcpmux_status){ Int32 i; ER__(send_cmd(tofd, cmd), i); return(result(fromfd, tcpmux_status));}static Int32num_conns(void * cs, Int32 index){ ConnStatus **csp; csp = (ConnStatus **) cs; csp -= index; for(index = 0; *csp; csp++, index++); return(index);}static Int32check_access( int fromfd, int tofd, void *tcpmux_status, UChar cmd, Int32 n, UChar *client){ UChar buf[264]; Int32 r; n = ABS(n); /* raw cartridge numbers (< 0) are allowed */ buf[0] = CHECKACCESS; buf[1] = cmd; Uns32_to_xref(buf + 1 + 1, n); strncpy(buf + 1 + 1 + 4, client, 256); if(write_forced(tofd, buf, 1 + 1 + 4 + 256) != 1 + 1 + 4 + 256) return(- errno); if( (r = result(fromfd, tcpmux_status)) ) logmsg(LOG_CRIT, T_("Warning: Client %s tried to access cartridge %s%d, denied.\n"), client, cmd == SETCARTSET ? T_("set ") : "", (int) n); return(r);}static Int32set_cryptkey_for_host(UChar * cryptfiles, UChar * hostname){ Int32 i; UChar *curkey; curkey = NULL; if(cryptfiles){ i = get_entry_by_host(cryptfiles, hostname, &curkey); if(i < 0){ logmsg(LOG_ERR, T_("Error: No authentication key file configured for %s.\n"), hostname); return(AUTHENTICATION); } } if(curkey){ if( (i = check_cryptfile(curkey)) ){ logmsg((i > 0 ? LOG_WARNING : LOG_ERR), T_("%s on encryption key file `%s': %s.\n"), (i > 0 ? T_("Warning") : T_("Error")), curkey, check_cryptfile_msg(i)); if(i < 0) return(AUTHENTICATION); logmsg(LOG_WARNING, T_("Warning: Ignoring file `%s', using compiled-in key.\n"), curkey); ZFREE(curkey); } } set_cryptkey(curkey, ACCESSKEYSTRING,#ifdef HAVE_DES_ENCRYPTION YES#else NO#endif ); ZFREE(curkey); return(0);}static UChar *set_client_id(ConnStatus * connstat, UChar * idstr){ ZFREE(connstat->clientid); connstat->clientid = strdup(idstr); connstat->headerlen = 1 + strlen(idstr) + 1; return(connstat->clientid);}static Int32resize_tapebuf(ConnStatus * connstat, Int32 newsize){ UChar *cbuf; if(newsize <= connstat->tapebufsiz) return(0); cbuf = RENEWP(connstat->tapebuf, UChar, newsize); if(!cbuf) return(FATAL_ERROR); connstat->tapebuf = cbuf; connstat->tapebufsiz = newsize; return(0);}static Int32flush_to_server( int fromfd, int tofd, void *tcpmux_status){ Int32 i, e; if(tapebufptr <= 2) return(0); memset(tapebuf + tapebufptr, 0, commbufsiz + 2 - tapebufptr); i = commbufsiz + 1; ER__((write_forced(tofd, tapebuf + 1, i) != i), e); /* send stuff */ return(result(fromfd, tcpmux_status));}static Int32write_to_server( UChar *buf, Int32 num, int fromfd, int tofd, void *tcpmux_status){ Int32 n, i, e; while(num > 0){ n = commbufsiz + 2 - tapebufptr; if(n > num){ memcpy(tapebuf + tapebufptr, buf, num); tapebufptr += num; return(0); } memcpy(tapebuf + tapebufptr, buf, n); if(newfilerequested){ ER__(request_new_file(fromfd, tofd, NULL), i); newfilerequested = NO; } i = commbufsiz + 1; /* send stuff */ ER__((tcp_mux_long_write(tcpmux_status, tofd, tapebuf + 1, i) != i), e); ER__(result(fromfd, tcpmux_status), e); /* get result */ num -= n; buf += n; tapebufptr = 2; } return(0);}static Int32writetotape( ConnStatus *connstat, int fromfd, int tofd, void *tcpmux_status){ Int32 i, n, tocb, inbufptr; tocb = connstat->commbufsiz; /* how much do we have to copy */ inbufptr = 0; /* where we are currently */ do{ n = MPX_CHUNKSIZE - connstat->tapebufptr; /* space in send buffer */ if(tocb < n){ /* rest fits into buffer */ memcpy(connstat->tapebuf + connstat->tapebufptr, /* copy it */ connstat->inbuf + 1 + inbufptr, tocb); connstat->tapebufptr += tocb; /* update pointer, that's it */ return(0); } if(n > 0) /* fill up send buffer */ memcpy(connstat->tapebuf + connstat->tapebufptr, connstat->inbuf + 1 + inbufptr, n); /* + 1 cause inbuf contains command "W" in 1st position */ if(connstat->newfilerequested){ newfilerequested = YES;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -