From 9cf1a68977d56d342ca7dbe8f07c725221dc1148 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Wed, 24 Sep 2008 09:53:21 -0700 Subject: printing: Rename new parameter "cups timeout" to "cups connection timeout". Karolin --- source3/param/loadparm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index db9e990e64..87af7a3411 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -341,7 +341,7 @@ struct global { int iKeepalive; int iminreceivefile; struct param_opt_struct *param_opt; - int cups_timeout; + int cups_connection_timeout; }; static struct global Globals; @@ -2597,10 +2597,10 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL, }, { - .label = "cups timeout", + .label = "cups connection timeout", .type = P_INTEGER, .p_class = P_GLOBAL, - .ptr = &Globals.cups_timeout, + .ptr = &Globals.cups_connection_timeout, .special = NULL, .enum_list = NULL, .flags = FLAG_ADVANCED, @@ -4805,7 +4805,7 @@ static void init_globals(bool first_time_only) * to never expire, though, when this runs out the afs client will * forget the token. Set to 0 to get NEVERDATE.*/ Globals.iAfsTokenLifetime = 604800; - Globals.cups_timeout = CUPS_DEFAULT_TIMEOUT; + Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT; /* these parameters are set to defaults that are more appropriate for the increasing samba install base: @@ -5247,7 +5247,7 @@ FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList) FN_LOCAL_STRING(lp_cups_options, szCupsOptions) FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer) FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer) -FN_GLOBAL_INTEGER(lp_cups_timeout, &Globals.cups_timeout) +FN_GLOBAL_INTEGER(lp_cups_connection_timeout, &Globals.cups_connection_timeout) FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket) FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses) FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering) -- cgit From 21c4061414f0e1af9106c50958dd5653a6f5368d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 27 Sep 2008 22:06:27 +0200 Subject: [s3]loadparm: add a command test_lp_load to test the lp_load function. This is not like testparm, just a simple tool that runs lp_load_with_registry_shares the requested number of times. Michael --- source3/param/test_lp_load.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 source3/param/test_lp_load.c (limited to 'source3/param') diff --git a/source3/param/test_lp_load.c b/source3/param/test_lp_load.c new file mode 100644 index 0000000000..db1bad4726 --- /dev/null +++ b/source3/param/test_lp_load.c @@ -0,0 +1,88 @@ +/* + * Unix SMB/CIFS implementation. + * Test for lp_load() + * Copyright (C) Michael Adam 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "includes.h" + +extern bool AllowDebugChange; + +int main(int argc, const char **argv) +{ + const char *config_file = get_dyn_CONFIGFILE(); + int ret = 0; + poptContext pc; + char *count_str = NULL; + int i, count = 1; + + struct poptOption long_options[] = { + POPT_AUTOHELP + {"count", 'c', POPT_ARG_STRING, &count_str, 1, + "Load config number of times"}, + POPT_COMMON_DEBUGLEVEL + POPT_TABLEEND + }; + + TALLOC_CTX *frame = talloc_stackframe(); + + load_case_tables(); + DEBUGLEVEL_CLASS[DBGC_ALL] = 0; + + pc = poptGetContext(NULL, argc, argv, long_options, + POPT_CONTEXT_KEEP_FIRST); + poptSetOtherOptionHelp(pc, "[OPTION...] "); + + while(poptGetNextOpt(pc) != -1); + + setup_logging(poptGetArg(pc), True); + + if (poptPeekArg(pc)) { + config_file = poptGetArg(pc); + } + + poptFreeContext(pc); + + if (count_str != NULL) { + count = atoi(count_str); + } + + dbf = x_stderr; + /* Don't let the debuglevel be changed by smb.conf. */ + AllowDebugChange = False; + + for (i=0; i < count; i++) { + printf("call lp_load() #%d: ", i+1); + if (!lp_load_with_registry_shares(config_file, + False, /* global only */ + True, /* save defaults */ + False, /*add_ipc */ + True)) /*init globals */ + { + printf("ERROR.\n"); + ret = 1; + goto done; + } + printf("ok.\n"); + } + + +done: + TALLOC_FREE(frame); + gfree_loadparm(); + return ret; +} + -- cgit From b38ed2674b42c27ec4183a84b6e73dfa1387b398 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 24 Sep 2008 20:31:39 +0200 Subject: [s3]loadparm: rename process_registry_service() to process_smbconf_service(). There is nothing registry-specific in that function. Michael --- source3/param/loadparm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 87af7a3411..a879859e75 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -6560,7 +6560,7 @@ static struct smbconf_ctx *lp_smbconf_ctx(void) return conf_ctx; } -static bool process_registry_service(struct smbconf_service *service) +static bool process_smbconf_service(struct smbconf_service *service) { uint32_t count; bool ret; @@ -6616,7 +6616,7 @@ static bool process_registry_globals(void) goto done; } - ret = process_registry_service(service); + ret = process_smbconf_service(service); if (!ret) { goto done; } @@ -6654,7 +6654,7 @@ static bool process_registry_shares(void) if (strequal(service[count]->name, GLOBAL_NAME)) { continue; } - ret = process_registry_service(service[count]); + ret = process_smbconf_service(service[count]); if (!ret) { goto done; } -- cgit From 612aa3915f92a4309d24f9ba7f33f26c275fab48 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 24 Sep 2008 21:59:34 +0200 Subject: [s3]loadparm: refactor freeing of parametric options into free_param_opts(). This code was there in three places. Michael --- source3/param/loadparm.c | 75 ++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index a879859e75..74dff837c0 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -5390,6 +5390,7 @@ static bool do_section(const char *pszSectionName, void *userdata); static void init_copymap(struct service *pservice); static bool hash_a_service(const char *name, int number); static void free_service_byindex(int iService); +static void free_param_opts(struct param_opt_struct **popts); static char * canonicalize_servicename(const char *name); static void show_parameter(int parmIndex); static bool is_synonym_of(int parm1, int parm2, bool *inverse); @@ -5644,6 +5645,35 @@ static void init_service(struct service *pservice) copy_service(pservice, &sDefault, NULL); } +/** + * free a param_opts structure. + * param_opts handling should be moved to talloc; + * then this whole functions reduces to a TALLOC_FREE(). + */ + +static void free_param_opts(struct param_opt_struct **popts) +{ + struct param_opt_struct *opt, *next_opt; + + if (popts == NULL) { + return; + } + + if (*popts != NULL) { + DEBUG(5, ("Freeing parametrics:\n")); + } + opt = *popts; + while (opt != NULL) { + string_free(&opt->key); + string_free(&opt->value); + TALLOC_FREE(opt->list); + next_opt = opt->next; + SAFE_FREE(opt); + opt = next_opt; + } + *popts = NULL; +} + /*************************************************************************** Free the dynamically allocated parts of a service struct. ***************************************************************************/ @@ -5651,7 +5681,6 @@ static void init_service(struct service *pservice) static void free_service(struct service *pservice) { int i; - struct param_opt_struct *data, *pdata; if (!pservice) return; @@ -5677,18 +5706,7 @@ static void free_service(struct service *pservice) &sDefault)))); } - data = pservice->param_opt; - if (data) - DEBUG(5,("Freeing parametrics:\n")); - while (data) { - DEBUG(5,("[%s = %s]\n", data->key, data->value)); - string_free(&data->key); - string_free(&data->value); - TALLOC_FREE(data->list); - pdata = data->next; - SAFE_FREE(data); - data = pdata; - } + free_param_opts(&pservice->param_opt); ZERO_STRUCTP(pservice); } @@ -5730,7 +5748,6 @@ static int add_a_service(const struct service *pservice, const char *name) int i; struct service tservice; int num_to_alloc = iNumServices + 1; - struct param_opt_struct *data, *pdata; tservice = *pservice; @@ -5740,16 +5757,7 @@ static int add_a_service(const struct service *pservice, const char *name) if (i >= 0) { /* Clean all parametric options for service */ /* They will be added during parsing again */ - data = ServicePtrs[i]->param_opt; - while (data) { - string_free(&data->key); - string_free(&data->value); - TALLOC_FREE(data->list); - pdata = data->next; - SAFE_FREE(data); - data = pdata; - } - ServicePtrs[i]->param_opt = NULL; + free_param_opts(&ServicePtrs[i]->param_opt); return (i); } } @@ -8765,9 +8773,6 @@ bool lp_is_in_client(void) return in_client; } - - - /*************************************************************************** Load the services array from the services file. Return True on success, False on failure. @@ -8783,7 +8788,6 @@ bool lp_load_ex(const char *pszFname, { char *n2 = NULL; bool bRetval; - struct param_opt_struct *data, *pdata; bRetval = False; @@ -8801,22 +8805,11 @@ bool lp_load_ex(const char *pszFname, lp_save_defaults(); } + free_param_opts(&Globals.param_opt); + /* We get sections first, so have to start 'behind' to make up */ iServiceIndex = -1; - if (Globals.param_opt != NULL) { - data = Globals.param_opt; - while (data) { - string_free(&data->key); - string_free(&data->value); - TALLOC_FREE(data->list); - pdata = data->next; - SAFE_FREE(data); - data = pdata; - } - Globals.param_opt = NULL; - } - if (lp_config_backend_is_file()) { n2 = alloc_sub_basic(get_current_username(), current_user_info.domain, -- cgit From 33d18c76f1bf5e10b52e873af5b29fabd1db7f3c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 24 Sep 2008 22:19:26 +0200 Subject: [s3]loadparm: fix memory error - free the right param_opt->list in copy_service. Michael --- source3/param/loadparm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 74dff837c0..dbfd5853f5 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -6487,7 +6487,7 @@ static void copy_service(struct service *pserviceDest, struct service *pserviceS /* If we already have same option, override it */ if (strwicmp(pdata->key, data->key) == 0) { string_free(&pdata->value); - TALLOC_FREE(data->list); + TALLOC_FREE(pdata->list); pdata->value = SMB_STRDUP(data->value); not_added = False; break; -- cgit From aa388a20053dc1809e8fcf12dbc6eddcec23d77e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 25 Sep 2008 00:52:11 +0200 Subject: [s3]loadparm: refactor setting parametric options in list out into new function set_param_opt(). This unifies and clarifies two instances of the code. Michael --- source3/param/loadparm.c | 97 ++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 52 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index dbfd5853f5..fda086cacf 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -6416,13 +6416,51 @@ static int getservicebyname(const char *pszServiceName, struct service *pservice If pcopymapDest is NULL then copy all fields ***************************************************************************/ +/** + * Add a parametric option to a param_opt_struct, + * replacing old value, if already present. + */ +static void set_param_opt(struct param_opt_struct **opt_list, + const char *opt_name, + const char *opt_value) +{ + struct param_opt_struct *new_opt, *opt; + bool not_added; + + if (opt_list == NULL) { + return; + } + + opt = *opt_list; + not_added = true; + + /* Traverse destination */ + while (opt) { + /* If we already have same option, override it */ + if (strwicmp(opt->key, opt_name) == 0) { + string_free(&opt->value); + TALLOC_FREE(opt->list); + opt->value = SMB_STRDUP(opt_value); + not_added = false; + break; + } + opt = opt->next; + } + if (not_added) { + new_opt = SMB_XMALLOC_P(struct param_opt_struct); + new_opt->key = SMB_STRDUP(opt_name); + new_opt->value = SMB_STRDUP(opt_value); + new_opt->list = NULL; + DLIST_ADD(*opt_list, new_opt); + } +} + static void copy_service(struct service *pserviceDest, struct service *pserviceSource, struct bitmap *pcopymapDest) { int i; bool bcopyall = (pcopymapDest == NULL); - struct param_opt_struct *data, *pdata, *paramo; - bool not_added; + struct param_opt_struct *data; for (i = 0; parm_table[i].label; i++) if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL && @@ -6480,27 +6518,7 @@ static void copy_service(struct service *pserviceDest, struct service *pserviceS data = pserviceSource->param_opt; while (data) { - not_added = True; - pdata = pserviceDest->param_opt; - /* Traverse destination */ - while (pdata) { - /* If we already have same option, override it */ - if (strwicmp(pdata->key, data->key) == 0) { - string_free(&pdata->value); - TALLOC_FREE(pdata->list); - pdata->value = SMB_STRDUP(data->value); - not_added = False; - break; - } - pdata = pdata->next; - } - if (not_added) { - paramo = SMB_XMALLOC_P(struct param_opt_struct); - paramo->key = SMB_STRDUP(data->key); - paramo->value = SMB_STRDUP(data->value); - paramo->list = NULL; - DLIST_ADD(pserviceDest->param_opt, paramo); - } + set_param_opt(&pserviceDest->param_opt, data->key, data->value); data = data->next; } } @@ -7165,8 +7183,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue int parmnum, i; void *parm_ptr = NULL; /* where we are going to store the result */ void *def_ptr = NULL; - struct param_opt_struct *paramo, *data; - bool not_added; + struct param_opt_struct **opt_list; parmnum = map_parameter(pszParmName); @@ -7185,33 +7202,9 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue frame = talloc_stackframe(); - not_added = True; - data = (snum < 0) - ? Globals.param_opt : ServicePtrs[snum]->param_opt; - /* Traverse destination */ - while (data) { - /* If we already have same option, override it */ - if (strwicmp(data->key, pszParmName) == 0) { - string_free(&data->value); - TALLOC_FREE(data->list); - data->value = SMB_STRDUP(pszParmValue); - not_added = False; - break; - } - data = data->next; - } - if (not_added) { - paramo = SMB_XMALLOC_P(struct param_opt_struct); - paramo->key = SMB_STRDUP(pszParmName); - paramo->value = SMB_STRDUP(pszParmValue); - paramo->list = NULL; - if (snum < 0) { - DLIST_ADD(Globals.param_opt, paramo); - } else { - DLIST_ADD(ServicePtrs[snum]->param_opt, - paramo); - } - } + opt_list = (snum < 0) + ? &Globals.param_opt : &ServicePtrs[snum]->param_opt; + set_param_opt(opt_list, pszParmName, pszParmValue); TALLOC_FREE(frame); return (True); -- cgit From 1578610aefe28be1b121f3a957787e98a5536b85 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 25 Sep 2008 00:54:45 +0200 Subject: [s3]loadparm: remove superfluous talloc context / talloc_stackframe call. Michael --- source3/param/loadparm.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index fda086cacf..dc7026268b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -7188,8 +7188,6 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue parmnum = map_parameter(pszParmName); if (parmnum < 0) { - TALLOC_CTX *frame; - if (strchr(pszParmName, ':') == NULL) { DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName)); @@ -7200,13 +7198,10 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue * We've got a parametric option */ - frame = talloc_stackframe(); - opt_list = (snum < 0) ? &Globals.param_opt : &ServicePtrs[snum]->param_opt; set_param_opt(opt_list, pszParmName, pszParmValue); - TALLOC_FREE(frame); return (True); } -- cgit From e56c89b5e85f565e03818abc4fa5354bdf473dee Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 27 Sep 2008 22:13:17 +0200 Subject: [s3]loadparm: in lp_do_parameter() use function lp_local_ptr() instead of hard coded calculation. Michael --- source3/param/loadparm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index dc7026268b..025e3e92ad 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -7222,9 +7222,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue pszParmName)); return (True); } - parm_ptr = - ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr, - &sDefault); + parm_ptr = lp_local_ptr(snum, def_ptr); } if (snum >= 0) { -- cgit From 3358a139d2dc77eb4c842d41722b1acc24bd2cb2 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 27 Sep 2008 22:19:56 +0200 Subject: [s3]loadparm: refactor freeing of parameter data out and reduce memleak. Add new functions free_parameter(), free_parameters() and free_global_parameters() and use these in the appropriate places, reducing code duplication. Also, always TALLOC_FREE data of type P_LIST, thus reducing mem-leaks: This had not been done in init_globals before. Michael --- source3/param/loadparm.c | 88 +++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 35 deletions(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 025e3e92ad..94660317f8 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4572,6 +4572,54 @@ static void init_printer_values(struct service *pService) } } +/** + * Free the allocated data for one parameter for a given share. + */ +static void free_parameter(int snum, struct parm_struct parm) +{ + void *parm_ptr; + + if (parm.ptr == NULL); { + return; + } + + if (snum < 0) { + parm_ptr = parm.ptr; + } else if (parm.p_class != P_LOCAL) { + return; + } else { + parm_ptr = lp_local_ptr(snum, parm.ptr); + } + + if ((parm.type == P_STRING) || + (parm.type == P_USTRING)) + { + string_free((char**)parm_ptr); + } else if (parm.type == P_LIST) { + TALLOC_FREE(*((char***)parm_ptr)); + } +} + +/** + * Free the allocated parameter data for a share. + */ +static void free_parameters(int snum) +{ + uint32_t i; + + for (i=0; parm_table[i].label; i++) { + free_parameter(snum, parm_table[i]); + } +} + +/** + * Free the allocated global parameters. + */ +static void free_global_parameters(void) +{ + free_parameters(GLOBAL_SECTION_SNUM); +} + /*************************************************************************** Initialise the global parameter structure. ***************************************************************************/ @@ -4596,14 +4644,7 @@ static void init_globals(bool first_time_only) } done_init = True; } else { - for (i = 0; parm_table[i].label; i++) { - if ((parm_table[i].type == P_STRING || - parm_table[i].type == P_USTRING) && - parm_table[i].ptr) - { - string_free((char **)parm_table[i].ptr); - } - } + free_global_parameters(); } memset((void *)&Globals, '\0', sizeof(Globals)); @@ -5645,6 +5686,7 @@ static void init_service(struct service *pservice) copy_service(pservice, &sDefault, NULL); } + /** * free a param_opts structure. * param_opts handling should be moved to talloc; @@ -5680,7 +5722,6 @@ static void free_param_opts(struct param_opt_struct **popts) static void free_service(struct service *pservice) { - int i; if (!pservice) return; @@ -5688,24 +5729,11 @@ static void free_service(struct service *pservice) DEBUG(5, ("free_service: Freeing service %s\n", pservice->szService)); + free_parameters(getservicebyname(pservice->szService, NULL)); + string_free(&pservice->szService); bitmap_free(pservice->copymap); - for (i = 0; parm_table[i].label; i++) { - if ((parm_table[i].type == P_STRING || - parm_table[i].type == P_USTRING) && - parm_table[i].p_class == P_LOCAL) - string_free((char **) - (((char *)pservice) + - PTR_DIFF(parm_table[i].ptr, &sDefault))); - else if (parm_table[i].type == P_LIST && - parm_table[i].p_class == P_LOCAL) - TALLOC_FREE(*((char ***) - (((char *)pservice) + - PTR_DIFF(parm_table[i].ptr, - &sDefault)))); - } - free_param_opts(&pservice->param_opt); ZERO_STRUCTP(pservice); @@ -8728,17 +8756,7 @@ void gfree_loadparm(void) /* Now release all resources allocated to global parameters and the default service */ - for (i = 0; parm_table[i].label; i++) - { - if ( parm_table[i].type == P_STRING - || parm_table[i].type == P_USTRING ) - { - string_free( (char**)parm_table[i].ptr ); - } - else if (parm_table[i].type == P_LIST) { - TALLOC_FREE( *((char***)parm_table[i].ptr) ); - } - } + free_global_parameters(); } -- cgit From eada8f8abe6e4b770b7a2e279fc897a4272b6fa5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Oct 2008 11:55:14 -0700 Subject: If you have a large number of cups printers, then scanning for print info can cause a client to timeout (it takes longer than 30 seconds to enumerate them). Make scanning for printers async with a callback from the main loop. This fixes a bug that was irritating *me* :-). Jeremy. --- source3/param/loadparm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/param') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 94660317f8..1191c3d3aa 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -7848,7 +7848,7 @@ static void lp_add_auto_services(char *str) Auto-load one printer. ***************************************************************************/ -void lp_add_one_printer(char *name, char *comment) +void lp_add_one_printer(const char *name, const char *comment, void *pdata) { int printers = lp_servicenumber(PRINTERS_NAME); int i; -- cgit