Ignore:
Timestamp:
Jul 6, 2011, 8:21:13 PM (14 years ago)
Author:
Herwig Bauernfeind
Message:

Samba 3.5: Update trunk to 3.5.9

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/server/source3/printing/print_cups.c

    r480 r599  
    2525#include "includes.h"
    2626#include "printing.h"
     27#include "librpc/gen_ndr/ndr_printcap.h"
    2728
    2829#ifdef HAVE_CUPS
     
    112113}
    113114
    114 static void send_pcap_info(const char *name, const char *info, void *pd)
    115 {
    116         int fd = *(int *)pd;
    117         size_t namelen = name ? strlen(name)+1 : 0;
    118         size_t infolen = info ? strlen(info)+1 : 0;
    119 
    120         DEBUG(11,("send_pcap_info: writing namelen %u\n", (unsigned int)namelen));
    121         if (sys_write(fd, &namelen, sizeof(namelen)) != sizeof(namelen)) {
    122                 DEBUG(10,("send_pcap_info: namelen write failed %s\n",
    123                         strerror(errno)));
    124                 return;
    125         }
    126         DEBUG(11,("send_pcap_info: writing infolen %u\n", (unsigned int)infolen));
    127         if (sys_write(fd, &infolen, sizeof(infolen)) != sizeof(infolen)) {
    128                 DEBUG(10,("send_pcap_info: infolen write failed %s\n",
    129                         strerror(errno)));
    130                 return;
    131         }
    132         if (namelen) {
    133                 DEBUG(11,("send_pcap_info: writing name %s\n", name));
    134                 if (sys_write(fd, name, namelen) != namelen) {
    135                         DEBUG(10,("send_pcap_info: name write failed %s\n",
    136                                 strerror(errno)));
    137                         return;
    138                 }
    139         }
    140         if (infolen) {
    141                 DEBUG(11,("send_pcap_info: writing info %s\n", info));
    142                 if (sys_write(fd, info, infolen) != infolen) {
    143                         DEBUG(10,("send_pcap_info: info write failed %s\n",
    144                                 strerror(errno)));
    145                         return;
    146                 }
    147         }
     115static bool send_pcap_blob(DATA_BLOB *pcap_blob, int fd)
     116{
     117        size_t ret;
     118
     119        ret = sys_write(fd, &pcap_blob->length, sizeof(pcap_blob->length));
     120        if (ret != sizeof(pcap_blob->length)) {
     121                return false;
     122        }
     123
     124        ret = sys_write(fd, pcap_blob->data, pcap_blob->length);
     125        if (ret != pcap_blob->length) {
     126                return false;
     127        }
     128
     129        DEBUG(10, ("successfully sent blob of len %ld\n", (int64_t)ret));
     130        return true;
    148131}
    149132
     133static bool recv_pcap_blob(TALLOC_CTX *mem_ctx, int fd, DATA_BLOB *pcap_blob)
     134{
     135        size_t blob_len;
     136        size_t ret;
     137
     138        ret = sys_read(fd, &blob_len, sizeof(blob_len));
     139        if (ret != sizeof(blob_len)) {
     140                return false;
     141        }
     142
     143        *pcap_blob = data_blob_talloc_named(mem_ctx, NULL, blob_len,
     144                                           "cups pcap");
     145        if (pcap_blob->length != blob_len) {
     146                return false;
     147        }
     148        ret = sys_read(fd, pcap_blob->data, blob_len);
     149        if (ret != blob_len) {
     150                talloc_free(pcap_blob->data);
     151                return false;
     152        }
     153
     154        DEBUG(10, ("successfully recvd blob of len %ld\n", (int64_t)ret));
     155        return true;
     156}
     157
     158static bool process_cups_printers_response(TALLOC_CTX *mem_ctx,
     159                                           ipp_t *response,
     160                                           struct pcap_data *pcap_data)
     161{
     162        ipp_attribute_t *attr;
     163        char *name;
     164        char *info;
     165        struct pcap_printer *printer;
     166        bool ret_ok = false;
     167
     168        for (attr = response->attrs; attr != NULL;) {
     169               /*
     170                * Skip leading attributes until we hit a printer...
     171                */
     172
     173                while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
     174                        attr = attr->next;
     175
     176                if (attr == NULL)
     177                        break;
     178
     179               /*
     180                * Pull the needed attributes from this printer...
     181                */
     182
     183                name       = NULL;
     184                info       = NULL;
     185
     186                while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
     187                        size_t size;
     188                        if (strcmp(attr->name, "printer-name") == 0 &&
     189                            attr->value_tag == IPP_TAG_NAME) {
     190                                if (!pull_utf8_talloc(mem_ctx,
     191                                                &name,
     192                                                attr->values[0].string.text,
     193                                                &size)) {
     194                                        goto err_out;
     195                                }
     196                        }
     197
     198                        if (strcmp(attr->name, "printer-info") == 0 &&
     199                            attr->value_tag == IPP_TAG_TEXT) {
     200                                if (!pull_utf8_talloc(mem_ctx,
     201                                                &info,
     202                                                attr->values[0].string.text,
     203                                                &size)) {
     204                                        goto err_out;
     205                                }
     206                        }
     207
     208                        attr = attr->next;
     209                }
     210
     211               /*
     212                * See if we have everything needed...
     213                */
     214
     215                if (name == NULL)
     216                        break;
     217
     218                if (pcap_data->count == 0) {
     219                        printer = talloc_array(mem_ctx, struct pcap_printer, 1);
     220                } else {
     221                        printer = talloc_realloc(mem_ctx, pcap_data->printers,
     222                                                 struct pcap_printer,
     223                                                 pcap_data->count + 1);
     224                }
     225                if (printer == NULL) {
     226                        goto err_out;
     227                }
     228                pcap_data->printers = printer;
     229                pcap_data->printers[pcap_data->count].name = name;
     230                pcap_data->printers[pcap_data->count].info = info;
     231                pcap_data->count++;
     232        }
     233
     234        ret_ok = true;
     235err_out:
     236        return ret_ok;
     237}
     238
     239/*
     240 * request printer list from cups, send result back to up parent via fd.
     241 * returns true if the (possibly failed) result was successfuly sent to parent.
     242 */
    150243static bool cups_cache_reload_async(int fd)
    151244{
    152245        TALLOC_CTX *frame = talloc_stackframe();
    153         struct pcap_cache *tmp_pcap_cache = NULL;
     246        struct pcap_data pcap_data;
    154247        http_t          *http = NULL;           /* HTTP connection to server */
    155248        ipp_t           *request = NULL,        /* IPP Request */
    156249                        *response = NULL;       /* IPP Response */
    157         ipp_attribute_t *attr;          /* Current attribute */
    158250        cups_lang_t     *language = NULL;       /* Default language */
    159         char            *name,          /* printer-name attribute */
    160                         *info;          /* printer-info attribute */
    161251        static const char *requested[] =/* Requested attributes */
    162252                        {
     
    165255                        };
    166256        bool ret = False;
    167         size_t size;
     257        enum ndr_err_code ndr_ret;
     258        DATA_BLOB pcap_blob;
     259
     260        ZERO_STRUCT(pcap_data);
     261        pcap_data.status = NT_STATUS_UNSUCCESSFUL;
    168262
    169263        DEBUG(5, ("reloading cups printcap cache\n"));
     
    174268
    175269        cupsSetPasswordCB(cups_passwd_cb);
    176 
    177        /*
    178         * Try to connect to the server...
    179         */
    180270
    181271        if ((http = cups_connect(frame)) == NULL) {
     
    210300                      NULL, requested);
    211301
    212        /*
    213         * Do the request and get back a response...
    214         */
    215 
    216302        if ((response = cupsDoRequest(http, request, "/")) == NULL) {
    217303                DEBUG(0,("Unable to get printer list - %s\n",
     
    220306        }
    221307
    222         for (attr = response->attrs; attr != NULL;) {
    223                /*
    224                 * Skip leading attributes until we hit a printer...
    225                 */
    226 
    227                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
    228                         attr = attr->next;
    229 
    230                 if (attr == NULL)
    231                         break;
    232 
    233                /*
    234                 * Pull the needed attributes from this printer...
    235                 */
    236 
    237                 name       = NULL;
    238                 info       = NULL;
    239 
    240                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
    241                         if (strcmp(attr->name, "printer-name") == 0 &&
    242                             attr->value_tag == IPP_TAG_NAME) {
    243                                 if (!pull_utf8_talloc(frame,
    244                                                 &name,
    245                                                 attr->values[0].string.text,
    246                                                 &size)) {
    247                                         goto out;
    248                                 }
    249                         }
    250 
    251                         if (strcmp(attr->name, "printer-info") == 0 &&
    252                             attr->value_tag == IPP_TAG_TEXT) {
    253                                 if (!pull_utf8_talloc(frame,
    254                                                 &info,
    255                                                 attr->values[0].string.text,
    256                                                 &size)) {
    257                                         goto out;
    258                                 }
    259                         }
    260 
    261                         attr = attr->next;
    262                 }
    263 
    264                /*
    265                 * See if we have everything needed...
    266                 */
    267 
    268                 if (name == NULL)
    269                         break;
    270 
    271                 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) {
    272                         goto out;
    273                 }
     308        ret = process_cups_printers_response(frame, response, &pcap_data);
     309        if (!ret) {
     310                DEBUG(0,("failed to process cups response\n"));
     311                goto out;
    274312        }
    275313
     
    302340                      NULL, requested);
    303341
    304        /*
    305         * Do the request and get back a response...
    306         */
    307 
    308342        if ((response = cupsDoRequest(http, request, "/")) == NULL) {
    309343                DEBUG(0,("Unable to get printer list - %s\n",
     
    312346        }
    313347
    314         for (attr = response->attrs; attr != NULL;) {
    315                /*
    316                 * Skip leading attributes until we hit a printer...
    317                 */
    318 
    319                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
    320                         attr = attr->next;
    321 
    322                 if (attr == NULL)
    323                         break;
    324 
    325                /*
    326                 * Pull the needed attributes from this printer...
    327                 */
    328 
    329                 name       = NULL;
    330                 info       = NULL;
    331 
    332                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
    333                         if (strcmp(attr->name, "printer-name") == 0 &&
    334                             attr->value_tag == IPP_TAG_NAME) {
    335                                 if (!pull_utf8_talloc(frame,
    336                                                 &name,
    337                                                 attr->values[0].string.text,
    338                                                 &size)) {
    339                                         goto out;
    340                                 }
    341                         }
    342 
    343                         if (strcmp(attr->name, "printer-info") == 0 &&
    344                             attr->value_tag == IPP_TAG_TEXT) {
    345                                 if (!pull_utf8_talloc(frame,
    346                                                 &info,
    347                                                 attr->values[0].string.text,
    348                                                 &size)) {
    349                                         goto out;
    350                                 }
    351                         }
    352 
    353                         attr = attr->next;
    354                 }
    355 
    356                /*
    357                 * See if we have everything needed...
    358                 */
    359 
    360                 if (name == NULL)
    361                         break;
    362 
    363                 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) {
    364                         goto out;
    365                 }
    366         }
    367 
    368         ret = True;
    369 
     348        ret = process_cups_printers_response(frame, response, &pcap_data);
     349        if (!ret) {
     350                DEBUG(0,("failed to process cups response\n"));
     351                goto out;
     352        }
     353
     354        pcap_data.status = NT_STATUS_OK;
    370355 out:
    371356        if (response)
     
    378363                httpClose(http);
    379364
    380         /* Send all the entries up the pipe. */
    381         if (tmp_pcap_cache) {
    382                 pcap_printer_fn_specific(tmp_pcap_cache,
    383                                 send_pcap_info,
    384                                 (void *)&fd);
    385 
    386                 pcap_cache_destroy_specific(&tmp_pcap_cache);
    387         }
     365        ret = false;
     366        ndr_ret = ndr_push_struct_blob(&pcap_blob, frame, NULL, &pcap_data,
     367                                       (ndr_push_flags_fn_t)ndr_push_pcap_data);
     368        if (ndr_ret == NDR_ERR_SUCCESS) {
     369                ret = send_pcap_blob(&pcap_blob, fd);
     370        }
     371
    388372        TALLOC_FREE(frame);
    389373        return ret;
     
    450434}
    451435
     436struct cups_async_cb_args {
     437        int pipe_fd;
     438        void (*post_cache_fill_fn)(void);
     439};
     440
    452441static void cups_async_callback(struct event_context *event_ctx,
    453442                                struct fd_event *event,
     
    456445{
    457446        TALLOC_CTX *frame = talloc_stackframe();
    458         int fd = *(int *)p;
     447        struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p;
    459448        struct pcap_cache *tmp_pcap_cache = NULL;
     449        bool ret_ok;
     450        struct pcap_data pcap_data;
     451        DATA_BLOB pcap_blob;
     452        enum ndr_err_code ndr_ret;
     453        int i;
    460454
    461455        DEBUG(5,("cups_async_callback: callback received for printer data. "
    462                 "fd = %d\n", fd));
    463 
    464         while (1) {
    465                 char *name = NULL, *info = NULL;
    466                 size_t namelen = 0, infolen = 0;
    467                 ssize_t ret = -1;
    468 
    469                 ret = sys_read(fd, &namelen, sizeof(namelen));
    470                 if (ret == 0) {
    471                         /* EOF */
     456                "fd = %d\n", cb_args->pipe_fd));
     457
     458        ret_ok = recv_pcap_blob(frame, cb_args->pipe_fd, &pcap_blob);
     459        if (!ret_ok) {
     460                DEBUG(0,("failed to recv pcap blob\n"));
     461                goto err_out;
     462        }
     463
     464        ndr_ret = ndr_pull_struct_blob(&pcap_blob, frame, NULL, &pcap_data,
     465                                       (ndr_pull_flags_fn_t)ndr_pull_pcap_data);
     466        if (ndr_ret != NDR_ERR_SUCCESS) {
     467                goto err_out;
     468        }
     469
     470        if (!NT_STATUS_IS_OK(pcap_data.status)) {
     471                DEBUG(0,("failed to retrieve printer list: %s\n",
     472                         nt_errstr(pcap_data.status)));
     473                goto err_out;
     474        }
     475
     476        for (i = 0; i < pcap_data.count; i++) {
     477                ret_ok = pcap_cache_add_specific(&tmp_pcap_cache,
     478                                                 pcap_data.printers[i].name,
     479                                                 pcap_data.printers[i].info);
     480                if (!ret_ok) {
     481                        DEBUG(0, ("failed to add to tmp pcap cache\n"));
    472482                        break;
    473483                }
    474                 if (ret != sizeof(namelen)) {
    475                         DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
    476                                 errno, strerror(errno)));
    477                         break;
    478                 }
    479 
    480                 DEBUG(11,("cups_async_callback: read namelen %u\n",
    481                         (unsigned int)namelen));
    482 
    483                 ret = sys_read(fd, &infolen, sizeof(infolen));
    484                 if (ret == 0) {
    485                         /* EOF */
    486                         break;
    487                 }
    488                 if (ret != sizeof(infolen)) {
    489                         DEBUG(10,("cups_async_callback: infolen read failed %s\n",
    490                                 strerror(errno)));
    491                         break;
    492                 }
    493 
    494                 DEBUG(11,("cups_async_callback: read infolen %u\n",
    495                         (unsigned int)infolen));
    496 
    497                 if (namelen) {
    498                         name = TALLOC_ARRAY(frame, char, namelen);
    499                         if (!name) {
    500                                 break;
    501                         }
    502                         ret = sys_read(fd, name, namelen);
    503                         if (ret == 0) {
    504                                 /* EOF */
    505                                 break;
    506                         }
    507                         if (ret != namelen) {
    508                                 DEBUG(10,("cups_async_callback: name read failed %s\n",
    509                                         strerror(errno)));
    510                                 break;
    511                         }
    512                         DEBUG(11,("cups_async_callback: read name %s\n",
    513                                 name));
    514                 } else {
    515                         name = NULL;
    516                 }
    517                 if (infolen) {
    518                         info = TALLOC_ARRAY(frame, char, infolen);
    519                         if (!info) {
    520                                 break;
    521                         }
    522                         ret = sys_read(fd, info, infolen);
    523                         if (ret == 0) {
    524                                 /* EOF */
    525                                 break;
    526                         }
    527                         if (ret != infolen) {
    528                                 DEBUG(10,("cups_async_callback: info read failed %s\n",
    529                                         strerror(errno)));
    530                                 break;
    531                         }
    532                         DEBUG(11,("cups_async_callback: read info %s\n",
    533                                 info));
    534                 } else {
    535                         info = NULL;
    536                 }
    537 
    538                 /* Add to our local pcap cache. */
    539                 pcap_cache_add_specific(&tmp_pcap_cache, name, info);
    540                 TALLOC_FREE(name);
    541                 TALLOC_FREE(info);
    542         }
    543 
    544         TALLOC_FREE(frame);
    545         if (tmp_pcap_cache) {
    546                 /* We got a namelist, replace our local cache. */
     484        }
     485
     486        if (!ret_ok) {
     487                DEBUG(0,("failed to read a new printer list\n"));
     488                pcap_cache_destroy_specific(&tmp_pcap_cache);
     489        } else {
     490                /* We got a possibly empty namelist, replace our local cache. */
    547491                pcap_cache_destroy_specific(&local_pcap_copy);
    548492                local_pcap_copy = tmp_pcap_cache;
     
    550494                /* And the systemwide pcap cache. */
    551495                pcap_cache_replace(local_pcap_copy);
    552         } else {
    553                 DEBUG(2,("cups_async_callback: failed to read a new "
    554                         "printer list\n"));
    555         }
    556         close(fd);
    557         TALLOC_FREE(p);
     496
     497                /* Caller may have requested post cache fill callback */
     498                if (cb_args->post_cache_fill_fn) {
     499                        cb_args->post_cache_fill_fn();
     500                }
     501        }
     502err_out:
     503        TALLOC_FREE(frame);
     504        close(cb_args->pipe_fd);
     505        TALLOC_FREE(cb_args);
    558506        TALLOC_FREE(cache_fd_event);
    559507}
    560508
    561 bool cups_cache_reload(void)
    562 {
    563         int *p_pipe_fd = TALLOC_P(NULL, int);
    564 
    565         if (!p_pipe_fd) {
     509bool cups_cache_reload(void (*post_cache_fill_fn)(void))
     510{
     511        struct cups_async_cb_args *cb_args;
     512        int *p_pipe_fd;
     513
     514        cb_args = TALLOC_P(NULL, struct cups_async_cb_args);
     515        if (!cb_args) {
    566516                return false;
    567517        }
    568 
     518        cb_args->post_cache_fill_fn = post_cache_fill_fn;
     519        p_pipe_fd = &cb_args->pipe_fd;
    569520        *p_pipe_fd = -1;
    570521
    571522        /* Set up an async refresh. */
    572523        if (!cups_pcap_load_async(p_pipe_fd)) {
     524                talloc_free(cb_args);
    573525                return false;
    574526        }
     
    583535                                        NULL,
    584536                                        EVENT_FD_READ,
    585                                         (void *)p_pipe_fd);
     537                                        (void *)cb_args);
    586538                if (!local_pcap_copy) {
    587539                        return false;
     
    600552                                        EVENT_FD_READ,
    601553                                        cups_async_callback,
    602                                         (void *)p_pipe_fd);
     554                                        (void *)cb_args);
    603555                if (!cache_fd_event) {
    604556                        close(*p_pipe_fd);
    605                         TALLOC_FREE(p_pipe_fd);
     557                        talloc_free(cb_args);
    606558                        return false;
    607559                }
     
    16451597        cups_lang_t     *language = NULL;       /* Default language */
    16461598        char            uri[HTTP_MAX_URI];
    1647         char *server = NULL;
    16481599        char *sharename = NULL;
    16491600        char *name = NULL;
     
    16861637                     "attributes-natural-language", NULL, language->language);
    16871638
    1688         if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
    1689                 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
    1690                         goto out;
    1691                 }
    1692         } else {
    1693                 server = talloc_strdup(frame,cupsServer());
    1694         }
    1695         if (server) {
    1696                 goto out;
    1697         }
    16981639        if (!push_utf8_talloc(frame, &sharename, printer->sharename, &size)) {
    16991640                goto out;
    17001641        }
    1701         slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
    1702                  server, sharename);
     1642        slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
     1643                 sharename);
    17031644
    17041645        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
     
    18011742                ippDelete(response);
    18021743
    1803         if (request) {
    1804                 ippDelete(request);
    1805         }
    1806 
    18071744        if (language)
    18081745                cupsLangFree(language);
Note: See TracChangeset for help on using the changeset viewer.