📄 conf.c
字号:
if (strlen(val)==0) fprintf(conffile,"; thread /usr/local/etc/thread1.conf\n"); free(val); } else if (thread==0) { fprintf(conffile,"%s\n", config_params[i].param_help); fprintf(conffile,"; %s value\n\n", config_params[i].param_name); } } } fprintf(conffile, "\n"); fclose(conffile); conffile=NULL; }}/************************************************************************** * conf_load is the main function, called from motion.c * The function sets the important context structure "cnt" including * loading the config parameters from config files and command line. * The following takes place in the function: * - The default start values for cnt stored in the struct conf_template * are copied to cnt[0] which is the default context structure common to * all threads. * - All config (cnt.conf) struct members pointing to a string are changed * so that they point to a malloc'ed piece of memory containing a copy of * the string given in conf_template. * - motion.conf is opened and processed. The process populates the cnt[0] and * for each thread config file it populates a cnt[1], cnt[2]... for each * thread * - Finally it process the options given in the command line. This is done * for each thread cnt[i] so that the command line options overrides any * option given by motion.conf or a thread config file. **************************************************************************/struct context ** conf_load (struct context **cnt){ FILE *fp=NULL; char filename[PATH_MAX]; int i; /* We preserve argc and argv because they get overwritten by the memcpy command */ char **argv = cnt[0]->conf.argv; int argc = cnt[0]->conf.argc; /* Copy the template config structure with all the default config values * into cnt[0]->conf */ memcpy(&cnt[0]->conf, &conf_template, sizeof(struct config)); /* For each member of cnt[0] which is a pointer to a string * if the member points to a string in conf_template and is not NULL * 1. Reserve (malloc) memory for the string * 2. Copy the conf_template given string to the reserved memory * 3. Change the cnt[0] member (char*) pointing to the string in reserved memory * This ensures that we can free and malloc the string when changed * via http remote control or config file or command line options */ malloc_strings(cnt[0]); /* Restore the argc and argv */ cnt[0]->conf.argv = argv; cnt[0]->conf.argc = argc; /* Open the motion.conf file. We try in this sequence: * 1. commandline * 2. current working directory * 3. $HOME/.motion/motion.conf * 4. sysconfig/motion.conf */ /* Get filename & pid file from commandline */ cnt[0]->conf_filename[0] = 0; cnt[0]->pid_file[0] = 0; conf_cmdline(cnt[0], -1); if (cnt[0]->conf_filename[0]){ /* User has supplied filename on commandline*/ strcpy(filename, cnt[0]->conf_filename); fp = fopen (filename, "r"); } if (!fp){ /* Commandline didn't work, try current dir */ char *path = NULL; if (cnt[0]->conf_filename[0]) motion_log(-1, 1, "Configfile %s not found - trying defaults.", filename); if ( (path = get_current_dir_name()) == NULL){ motion_log(LOG_ERR, 1, "Error get_current_dir_name"); exit(-1); } snprintf(filename, PATH_MAX, "%s/motion.conf", path); fp = fopen (filename, "r"); free(path); } if (!fp) { /* specified file does not exist... try default file */ snprintf(filename, PATH_MAX, "%s/.motion/motion.conf", getenv("HOME")); fp = fopen(filename, "r"); if (!fp) { snprintf(filename, PATH_MAX, "%s/motion.conf", sysconfdir); fp = fopen(filename, "r"); if (!fp) /* there is no config file.... use defaults */ motion_log(-1, 1, "could not open configfile %s",filename); } } /* Now we process the motion.conf config file and close it*/ if (fp) { strcpy(cnt[0]->conf_filename, filename); motion_log(LOG_INFO, 0, "Processing thread 0 - config file %s",filename); cnt=conf_process(cnt, fp); fclose(fp); }else{ motion_log(LOG_INFO, 0, "Not config file to process using default values"); } /* For each thread (given by cnt[i]) being not null * cnt is an array of pointers to a context type structure * cnt[0] is the default context structure * cnt[1], cnt[2], ... are context structures for each thread * Command line options always wins over config file options * so we go through each thread and overrides any set command line * options */ i=-1; while(cnt[++i]) conf_cmdline(cnt[i], i); /* if pid file was passed from command line copy to main thread conf struct */ if (cnt[0]->pid_file[0]) cnt[0]->conf.pid_file = mystrcpy(cnt[0]->conf.pid_file, cnt[0]->pid_file); return cnt;}/* malloc_strings goes through the members of a context structure. * For each context structure member which is a pointer to a string it does this: * If the member points to a string and is not NULL * 1. Reserve (malloc) memory for the string * 2. Copy the original string to the reserved memory * 3. Change the cnt member (char*) pointing to the string in reserved memory * This ensures that we can free and malloc the string if it is later changed */void malloc_strings (struct context * cnt){ unsigned short int i = 0; char **val; while( config_params[i].param_name != NULL ) { if (config_params[i].copy == copy_string) { /* if member is a string */ /* val is made to point to a pointer to the current string */ val = (char **)((char *)cnt+config_params[i].conf_value); /* if there is a string, malloc() space for it, copy * the string to new space, and point to the new * string. we don't free() because we're copying a * static string. */ *val = mystrdup(*val); } i++; }}/************************************************************************ * copy functions * * copy_bool - convert a bool representation to int * copy_int - convert a string to int * copy_short - convert a string to short * copy_string - just a string copy * * @param str - A char *, pointing to a string representation of the * value. * @param val_ptr - points to the place where to store the value relative * to pointer pointing to the given context structure * @cnt - points to a context structure for a thread * * The function is given a pointer cnt to a context structure and a pointer val_ptr * which is an integer giving the position of the structure member relative to the * pointer of the context structure. * If the context structure is for thread 0 (cnt[0]->threadnr is zero) then the * function also sets the value for all the child threads since thread 0 is the * global thread. * If the thread given belongs to a child thread (cnt[0]->threadnr is not zero) * the function will only assign the value for the given thread. ***********************************************************************//* copy_bool assigns a config option to a new boolean value. * The boolean is given as a string in str which is converted to 0 or 1 * by the function. Values 1, yes and on are converted to 1 ignoring case. * Any other value is converted to 0. */static struct context **copy_bool (struct context **cnt, const char *str, int val_ptr){ void *tmp; int i; i=-1; while(cnt[++i]) { tmp = (char *)cnt[i]+(int)val_ptr; if ( !strcmp(str, "1") || !strcasecmp(str, "yes") || !strcasecmp(str,"on")) { *((int *)tmp) = 1; } else { *((int *)tmp) = 0; } if (cnt[0]->threadnr) return cnt; } return cnt;}/* copy_int assigns a config option to a new integer value. * The integer is given as a string in str which is converted to integer by the function. */static struct context ** copy_int(struct context **cnt, const char *str, int val_ptr){ void *tmp; int i; i=-1; while(cnt[++i]) { tmp = (char *)cnt[i]+val_ptr; *((int *)tmp) = atoi(str); if (cnt[0]->threadnr) return cnt; } return cnt;}/* copy_short assigns a config option to a new short value. * The integer is given as a string in str which is converted to short by the function. */ static struct context ** copy_short(struct context **cnt, const char *str, int val_ptr){ void *tmp; int i; i=-1; while(cnt[++i]) { tmp = (char *)cnt[i]+val_ptr; *((short int *)tmp) = atoi(str); if (cnt[0]->threadnr) return cnt; } return cnt;}/* copy_string assigns a new string value to a config option. * Strings are handled differently from bool and int. * the char *conf->option that we are working on is free()'d * (if memory for it has already been malloc()'d), and set to * a freshly malloc()'d string with the value from str, * or NULL if str is blank */struct context **copy_string(struct context **cnt, const char *str, int val_ptr){ char **tmp; int i; i=-1; while(cnt[++i]) { tmp = (char **)((char *)cnt[i] + val_ptr); /* mystrcpy assigns the new string value * including free'ing and reserving new memory for it. */ *tmp = mystrcpy(*tmp, str); /* set the option on all threads if setting the option * for thread 0; otherwise just set that one thread's option */ if (cnt[0]->threadnr) return cnt; } return cnt;}/* mystrcpy is used to assign string type fields (e.g. config options) * In a way so that we the memory is malloc'ed to fit the string. * If a field is already pointing to a string (not NULL) the memory of the * old string is free'd and new memory is malloc'ed and filled with the * new string is copied into the the memory and with the char pointer * pointing to the new string. * * from - pointer to the new string we want to copy * to - the pointer to the current string (or pointing to NULL) * If not NULL the memory it points to is free'd. * function returns pointer to the new string which is in malloc'ed memory * FIXME The strings that are malloc'ed with this function should be freed * when the motion program is terminated normally instead of relying on the * OS to clean up. */char *mystrcpy(char *to, const char *from){ /* free the memory used by the to string, if such memory exists, * and return a pointer to a freshly malloc()'d string with the * same value as from. */ if (to != NULL) free(to); return mystrdup(from);}/* mystrdup return a pointer to a freshly malloc()'d string with the same * value as the string that the input parameter 'from' points to, * or NULL if the from string is 0 characters. * The function truncates the string to the length given by the environment * variable PATH_MAX to ensure that config options can always contain * a really long path but no more than that. */char *mystrdup(const char *from){ char *tmp; int stringlength; if (from == NULL || !strlen(from)) { tmp = NULL; } else { stringlength = strlen(from); stringlength = (stringlength < PATH_MAX ? stringlength : PATH_MAX); tmp = (char *)mymalloc(stringlength + 1); strncpy(tmp, from, stringlength); /* We must ensure the string always has a NULL terminator. * This necessary because strncpy will not append a NULL terminator * if the original string is greater than stringlength. */ tmp += stringlength; *tmp = '\0'; tmp -= stringlength; } return tmp;}const char *config_type(config_param *configparam){ if (configparam->copy == copy_string) return "string"; if (configparam->copy == copy_int) return "int"; if (configparam->copy == copy_short) return "short"; if (configparam->copy == copy_bool) return "bool"; return "unknown";}static const char *print_bool(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr){ int val=config_params[parm].conf_value; if (threadnr && *(int*)((char *)cnt[threadnr] + val) == *(int*)((char *)cnt[0] + val)) return NULL; if (*(int*)((char *)cnt[threadnr] + val)) return "on"; else return "off";}/* print_string returns a pointer to a string containing the value of the config option * If the option is not defined NULL is returned. * If the thread number is not 0 the string is compared with the value of the same * option in thread 0. If the value is the same, NULL is returned which means that * the option is not written to the thread config file. */static const char *print_string(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr){ int val=config_params[parm].conf_value; const char **cptr0, **cptr1; /* strcmp does not like NULL so we have to check for this also */ cptr0 = (const char **)((char *)cnt[0] + val); cptr1 = (const char **)((char *)cnt[threadnr] + val); if ((threadnr) && (*cptr0 != NULL) && (*cptr1 != NULL) && (!strcmp(*cptr0, *cptr1))) return NULL; return *cptr1;}static const char *print_int(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr){ static char retval[20]; int val = config_params[parm].conf_value; if (threadnr && *(int*)((char *)cnt[threadnr] + val) == *(int*)((char *)cnt[0] + val)) return NULL; sprintf(retval, "%d", *(int*)((char *)cnt[threadnr] + val)); return retval;}static const char *print_short(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr) { static char retval[20]; int val = config_params[parm].conf_value; if (threadnr && *(short int*)((char *)cnt[threadnr] + val) == *(short int*)((char *)cnt[0] + val)) return NULL; sprintf(retval, "%d", *(short int*)((char *)cnt[threadnr] + val)); return retval;}static const char *print_thread(struct context **cnt, char **str, int parm ATTRIBUTE_UNUSED, unsigned short int threadnr){ char *retval; unsigned short int i=0; if (!str || threadnr) return NULL; retval = mymalloc(1); retval[0] = 0; while (cnt[++i]) { retval = myrealloc(retval, strlen(retval) + strlen(cnt[i]->conf_filename)+10, "print_thread"); sprintf(retval + strlen(retval), "thread %s\n", cnt[i]->conf_filename); } *str = retval; return NULL;}/* config_thread() is called during initial config file loading each time Motion * finds a thread option in motion.conf * The size of the context array is increased and the main context's values are * copied to the new thread. * * cnt - pointer to the array of pointers pointing to the context structures * str - pointer to a string which is the filename of the thread config file * val - is not used. It is defined to be function header compatible with * copy_int, copy_bool and copy_string. */static struct context **config_thread(struct context **cnt, const char *str, int val ATTRIBUTE_UNUSED){ int i; FILE *fp; if (cnt[0]->threadnr) return cnt; fp=fopen(str, "r"); if (!fp) { motion_log(LOG_ERR, 1, "Thread config file %s not found",str); return cnt; } /* Find the current number of threads defined. */ i=-1; while (cnt[++i]); /* Make space for the threads + the terminating NULL pointer * in the array of pointers to context structures * First thread is 0 so the number of threads is i+1 * plus an extra for the NULL pointer. This gives i+2 */ cnt = myrealloc(cnt, sizeof(struct context *)*(i+2), "config_thread"); /* Now malloc space for an additional context structure for thread nr. i */ cnt[i] = mymalloc(sizeof(struct context)); /* And make this an exact clone of the context structure for thread 0 */ memcpy(cnt[i], cnt[0], sizeof(struct context)); /* All the integers are copies of the actual value. * The strings are all pointers to strings so we need to create * unique malloc'ed space for all the strings that are not NULL and * change the string pointers to point to the new strings. * malloc_strings takes care of this. */ malloc_strings(cnt[i]); /* Mark the end if the array of pointers to context structures */ cnt[i+1] = NULL; /* process the thread's config file and notify user on console */ strcpy(cnt[i]->conf_filename, str); motion_log(LOG_INFO, 0, "Processing config file %s", str); conf_process(cnt+i, fp); /* Finally we close the thread config file */ fclose(fp); return cnt;}static void usage (){ printf("motion Version "VERSION", Copyright 2000-2005 Jeroen Vreeken/Folkert van Heusden/Kenneth Lavrsen\n"); printf("\nusage:\tmotion [options]\n"); printf("\n\n"); printf("Possible options:\n\n"); printf("-n\t\t\tRun in non-daemon mode.\n"); printf("-s\t\t\tRun in setup mode.\n"); printf("-c config\t\tFull path and filename of config file.\n"); printf("-d level\t\tDebug mode.\n"); printf("-p process_id_file\tFull path and filename of process id file (pid file).\n"); printf("-h\t\t\tShow this screen.\n"); printf("\n"); printf("Motion is configured using a config file only. If none is supplied,\n"); printf("it will read motion.conf from current directory, ~/.motion or %s.\n", sysconfdir); printf("\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -