static GCS_BACKEND_DESTROY_FN(dummy_destroy) { dummy_t* dummy = backend->conn; if (!dummy || dummy->state != DUMMY_CLOSED) return -EBADFD; // gu_debug ("Deallocating message queue (serializer)"); gu_fifo_destroy (dummy->gc_q); if (dummy->memb) gu_free (dummy->memb); gu_free (dummy); backend->conn = NULL; return 0; }
void font_info_delete(struct FONT_INFO *p) { if(p->font_family) gu_free(p->font_family); if(p->font_weight) gu_free(p->font_weight); if(p->font_slant) gu_free(p->font_slant); if(p->font_width) gu_free(p->font_width); if(p->font_psname) gu_free(p->font_psname); if(p->font_encoding) gu_free(p->font_encoding); if(p->font_type) gu_free(p->font_type); if(p->ascii_subst_font) gu_free(p->ascii_subst_font); gu_free(p); }
static void free_and_zero(void **p) { if(*p) { gu_free(*p); *p = (void*)NULL; } }
static inline long dummy_msg_destroy (dummy_msg_t *msg) { if (msg) { gu_free (msg); } return 0; }
long gu_to_destroy (gu_to_t** to) { gu_to_t *t = *to; long ret; ssize_t i; gu_mutex_lock (&t->lock); if (t->used) { gu_mutex_unlock (&t->lock); return -EBUSY; } for (i = 0; i < t->qlen; i++) { to_waiter_t *w = t->queue + i; #ifdef TO_USE_SIGNAL if (gu_cond_destroy (&w->cond)) { // @todo: what if someone is waiting? gu_warn ("Failed to destroy condition %d. Should not happen", i); } #else if (pthread_mutex_destroy (&w->mtx)) { // @todo: what if someone is waiting? gu_warn ("Failed to destroy mutex %d. Should not happen", i); } #endif } t->qlen = 0; gu_mutex_unlock (&t->lock); /* What else can be done here? */ ret = gu_mutex_destroy (&t->lock); if (ret) return -ret; // application can retry gu_free (t->queue); gu_free (t); *to = NULL; return 0; }
int h3m_get_filename_from_gm1(const char *filename_gm1, char *filename_h3m, size_t n) { unsigned char *buf = NULL; long buf_size = 0; size_t len = 0; unsigned char *loc = NULL; if (0 != gu_decompress_file_to_mem(filename_gm1, (void **)&buf, &buf_size)) { return 1; } if (NULL == (loc = memmem(buf, (size_t)buf_size, (uint8_t *)".h3m", sizeof(".h3m") - 1))) { gu_free(buf); return 2; } while (((isalnum(*(loc - 1))) || (isspace(*(loc - 1))) || (ispunct(*(loc - 1))) || ('(' == *(loc - 1)) || ('(' == *(loc - 1)) || ('_' == *(loc - 1))) && loc > buf) { --loc; } if (n <= (len = strlen((char *)loc))) { gu_free(buf); return 3; } strcpy(filename_h3m, (char *)loc); gu_free(buf); return 0; }
/* Free nodes array */ static void group_nodes_free (gcs_group_t* group) { int i; /* cleanup after disappeared members */ for (i = 0; i < group->num; i++) { gcs_node_free (&group->nodes[i]); } if (group->nodes) gu_free (group->nodes); group->nodes = NULL; group->num = 0; group->my_idx = -1; }
gu_to_t *gu_to_create (int len, gu_seqno_t seqno) { gu_to_t *ret; assert (seqno >= 0); if (len <= 0) { gu_error ("Negative length parameter: %d", len); return NULL; } ret = GU_CALLOC (1, gu_to_t); if (ret) { /* Make queue length a power of 2 */ ret->qlen = 1; while (ret->qlen < len) { // unsigned, can be bigger than any integer ret->qlen = ret->qlen << 1; } ret->qmask = ret->qlen - 1; ret->seqno = seqno; ret->queue = GU_CALLOC (ret->qlen, to_waiter_t); if (ret->queue) { ssize_t i; for (i = 0; i < ret->qlen; i++) { to_waiter_t *w = ret->queue + i; #ifdef TO_USE_SIGNAL gu_cond_init (&w->cond, NULL); #else pthread_mutex_init (&w->mtx, NULL); #endif w->state = RELEASED; } gu_mutex_init (&ret->lock, NULL); return ret; } gu_free (ret); } return NULL; }
/* ** Set the group "ACLs:" line. */ int group_acls(const char *argv[]) { const char *group = argv[0]; char *acls; int retval; if(!group) { fputs(_("You must specify a group and a (possibly empty) list\n" "of PPR access control lists.\n"), errors); return EXIT_SYNTAX; } acls = list_to_string(&argv[1]); retval = conf_set_name(QUEUE_TYPE_GROUP, group, "ACLs", acls ? "%s" : NULL, acls); if(acls) gu_free(acls); return retval; } /* end of group_acls() */
/* ** Set the group "PassThru:" line. */ int group_passthru(const char *argv[]) { const char *group = argv[0]; char *passthru; int retval; if(!group) { fputs(_("You must specify a group and a (possibly empty) list\n" "of file types. These file types should be the same as\n" "those used with the \"ppr -T\" option.\n"), errors); return EXIT_SYNTAX; } passthru = list_to_string(&argv[1]); retval = conf_set_name(QUEUE_TYPE_GROUP, group, "PassThru", passthru ? "%s" : NULL, passthru); if(passthru) gu_free(passthru); return retval; } /* end of group_passthru() */
/* Creates FIFO object. Since it practically consists of array of (void*), * the length can be chosen arbitrarily high - to minimize the risk * of overflow situation. */ gcs_fifo_lite_t* gcs_fifo_lite_create (size_t length, size_t item_size) { gcs_fifo_lite_t* ret = NULL; uint64_t l = 1; /* check limits */ if (length < 1 || item_size < 1) return NULL; /* Find real length. It must be power of 2*/ while (l < length) l = l << 1; if (l * item_size > (uint64_t)GU_LONG_MAX) { gu_error ("Resulting FIFO size %lld exceeds signed limit: %lld", (long long)(l*item_size), (long long)GU_LONG_MAX); return NULL; } ret = GU_CALLOC (1, gcs_fifo_lite_t); if (ret) { ret->length = l; ret->item_size = item_size; ret->mask = ret->length - 1; ret->closed = true; ret->queue = gu_malloc (ret->length * item_size); if (ret->queue) { gu_mutex_init (&ret->lock, NULL); gu_cond_init (&ret->put_cond, NULL); gu_cond_init (&ret->get_cond, NULL); /* everything else must be initialized to 0 by calloc */ } else { gu_free (ret); ret = NULL; } } return ret; }
long gcs_fifo_lite_destroy (gcs_fifo_lite_t* f) { if (f) { if (gu_mutex_lock (&f->lock)) { abort(); } if (f->destroyed) { gu_mutex_unlock (&f->lock); return -EALREADY; } f->closed = true; f->destroyed = true; /* get rid of "put" threads waiting for lock or signal */ while (pthread_cond_destroy (&f->put_cond)) { if (f->put_wait <= 0) { gu_fatal ("Can't destroy condition while nobody's waiting"); abort(); } f->put_wait = 0; gu_cond_broadcast (&f->put_cond); } while (f->used) { /* there are some items in FIFO - and that means * no gcs_fifo_lite_safe_get() is waiting on condition */ gu_mutex_unlock (&f->lock); /* let them get remaining items from FIFO, * we don't know how to deallocate them ourselves. * unfortunately this may take some time */ usleep (10000); /* sleep a bit to avoid busy loop */ gu_mutex_lock (&f->lock); } f->length = 0; /* now all we have - "get" threads waiting for lock or signal */ while (pthread_cond_destroy (&f->get_cond)) { if (f->get_wait <= 0) { gu_fatal ("Can't destroy condition while nobody's waiting"); abort(); } f->get_wait = 0; gu_cond_broadcast (&f->get_cond); } /* at this point there are only functions waiting for lock */ gu_mutex_unlock (&f->lock); while (gu_mutex_destroy (&f->lock)) { /* this should be fast provided safe get and safe put are * wtitten correctly. They should immediately freak out. */ gu_mutex_lock (&f->lock); gu_mutex_unlock (&f->lock); } /* now nobody's waiting for anything */ gu_free (f->queue); gu_free (f); return 0; } return -EINVAL; }
/* ** Show a groups members, its rotate setting, and its comment. */ int group_show(const char *argv[]) { const char *function = "group_show"; const char *group = argv[0]; /* The name of the group to show is the argument. */ int x; char *ptr; int rotate = TRUE; /* Is rotate set for this group? */ char *comment = (char*)NULL; /* Group comment. */ int member_count = 0; /* Keep count of members. */ char *members[MAX_GROUPSIZE]; /* The names of the members. */ char *deffiltopts = (char*)NULL; /* The default filter options string. */ char *switchset = (char*)NULL; /* The compressed switchset string. */ char *passthru = (char*)NULL; char *acls = (char*)NULL; #define MAX_ADDONS 32 char *addon[MAX_ADDONS]; int addon_count = 0; if(! group) { fputs(_("You must supply the name of a group to show.\n"), errors); return EXIT_SYNTAX; } if(grpopen(group, FALSE, FALSE)) /* Open the configuration file. */ { fprintf(errors, _("The group \"%s\" does not exist.\n"), group); return EXIT_BADDEST; } while(confread()) /* Read all the lines in the config file. */ { if(lmatch(confline, "Rotate:")) { rotate = gu_torf(&confline[7]); continue; } if(gu_sscanf(confline, "Comment: %A", &ptr) == 1) { if(comment) gu_free(comment); comment = ptr; continue; } if(gu_sscanf(confline, "Printer: %S", &ptr) == 1) { if(member_count < MAX_GROUPSIZE) { members[member_count++] = ptr; } else { fprintf(errors, "%s(): too many members: %s\n", function, ptr); gu_free(ptr); } continue; } if(gu_sscanf(confline, "Switchset: %Z", &ptr) == 1) { if(switchset) gu_free(switchset); switchset = ptr; continue; } if(gu_sscanf(confline, "DefFiltOpts: %Z", &ptr) == 1) { if(deffiltopts) gu_free(deffiltopts); deffiltopts = ptr; continue; } if(gu_sscanf(confline, "PassThru: %Z", &ptr) == 1) { if(passthru) gu_free(passthru); passthru = ptr; continue; } if(gu_sscanf(confline, "ACLs: %Z", &ptr) == 1) { if(acls) gu_free(acls); acls = ptr; continue; } if(confline[0] >= 'a' && confline[0] <= 'z') /* if in addon name space */ { if(addon_count >= MAX_ADDONS) { fprintf(errors, "%s(): addon[] overflow\n", function); } else { addon[addon_count++] = gu_strdup(confline); } continue; } } /* end of line reading while() loop */ confclose(); /* We are done with the configuration file. */ if(!machine_readable) { printf(_("Group name: %s\n"), group); printf(_("Comment: %s\n"), comment ? comment : ""); PUTS(_("Members:")); for(x=0;x<member_count;x++) /* Show what printers are members. */ { if(x==0) printf(" %s", members[x]); else printf(", %s", members[x]); } putchar('\n'); /* End group members line. */ printf(_("Rotate: %s\n"), rotate ? _("True") : _("False")); { const char *s = _("Default Filter Options: "); PUTS(s); if(deffiltopts) print_wrapped(deffiltopts, strlen(s)); putchar('\n'); } PUTS(_("Switchset: ")); if(switchset) print_switchset(switchset); putchar('\n'); /* This rare parameter is shown only when it has a value. */ if(passthru) printf(_("PassThru types: %s\n"), passthru); /* Only displayed if set. */ if(acls) printf(_("ACLs: %s\n"), acls); /* Print the assembed addon settings. */ if(addon_count > 0) { int x; PUTS(_("Addon:")); for(x = 0; x < addon_count; x++) { printf("\t%s\n", addon[x]); gu_free(addon[x]); } } } else { printf("name\t%s\n", group); printf("comment\t%s\n", comment ? comment : ""); PUTS("members\t"); for(x=0; x < member_count; x++) printf("%s%s", x > 0 ? " " : "", members[x]); PUTS("\n"); printf("rotate\t%s\n", rotate ? "yes" : "no"); printf("deffiltopts\t%s\n", deffiltopts ? deffiltopts : ""); PUTS("switchset\t"); if(switchset) print_switchset(switchset); putchar('\n'); printf("passthru\t%s\n", passthru ? passthru : ""); printf("acls\t%s\n", acls ? acls : ""); /* Addon lines */ if(addon_count > 0) { int x; char *p; for(x = 0; x < addon_count; x++) { if((p = strchr(addon[x], ':'))) { *p = '\0'; p++; p += strspn(p, " \t"); printf("addon %s\t%s\n", addon[x], p); } else { printf("addon\t%s\n", addon[x]); } gu_free(addon[x]); } } } if(comment) gu_free(comment); for(x=0;x<member_count;x++) gu_free(members[x]); if(deffiltopts) gu_free(deffiltopts); if(switchset) gu_free(switchset); if(passthru) gu_free(passthru); if(acls) gu_free(acls); return EXIT_OK; } /* end of group_show() */
/* ** This routine is passed information about a PostScript error. It looks up ** the error in a list in a file and hopefully finds a description. In ** addition to the name of the failed PostScript command and the PostScript ** error message it receives the string from the "%%Creator:" line in the ** document. Since this often indicates the program or printer driver that ** generated the document, it can help us to explain the error in context. ** ** Information about the error is sent to the job log and to the queue file. ** ** This function is called from pprdrv_feedback.c _before_ the PostScript ** error is logged. */ void describe_postscript_error(const char creator[], const char errormsg[], const char command[]) { const char function[] = "describe_postscript_error"; const char filename[] = PSERRORS_CONF; FILE *f; gu_boolean found = FALSE; #if 0 debug("describe_postscript_error(creator=\"%s\",errormsg=\"%s\",command=\"%s\")", creator ? creator : "", errormsg ? errormsg : "", command ? command : ""); #endif log_puts("==============================================================================\n"); log_printf(_("The PostScript error indicated below occured while printing on \"%s\".\n"), printer.Name); /* If we have someting to go on... */ if(errormsg && command) { /* Look in. */ if((f = fopen(filename, "r"))) { const char *safe_creator = creator ? creator : ""; char *line = NULL; int line_space = 80; int linenum = 0; char *p, *f1, *f2, *f3, *f4; while((line = gu_getline(line, &line_space, f))) { linenum++; if(line[0] == ';' || line[0] == '#' || line[0] == '\0') continue; /* Parse the line into three colon separated fields. */ p = line; if(!(f1 = gu_strsep(&p, ":")) || !(f2 = gu_strsep(&p, ":")) || !(f3 = gu_strsep(&p, ":")) || !(f4 = gu_strsep(&p, ":"))) { error("%s(): syntax error in \"%s\" line %d", function, filename, linenum); continue; } if(gu_wildmat(safe_creator, f1) && gu_wildmat(errormsg, f2) && gu_wildmat(command, f3)) { int i; log_puts(_("Probable cause: ")); for(i=0; f4[i]; i++) { switch(f4[i]) { case ',': log_puts(", "); break; case '|': log_putc(' '); break; default: log_putc(f4[i]); break; } } log_putc('\n'); give_reason(f4); gu_free(line); found = TRUE; break; } } fclose(f); } } log_puts("==============================================================================\n"); /* If nothing was found above, use the generic message. */ if(!found) give_reason("PostScript error"); } /* end of describe_postscript_error() */
/* ** Read an ASCII string and store it in job as the mask of pages ** to be printed. */ int pagemask_encode(struct QFileEntry *job, const char pages[]) { int bytes; int page; gu_boolean range; const char *p; /* If there is an old page mask, deallocate it. */ if(job->page_list.mask) gu_free(job->page_list.mask); /* Allocate enough memory and set it to all zeros. */ bytes = (job->attr.pages + 5) / 6; job->page_list.mask = gu_alloc(bytes+1, 1); memset(job->page_list.mask, 0, bytes+1); /* This is the parser loop. */ for(p=pages, range=FALSE, page=1; *p; ) { /* This inner loop ends if the string ends or we hit a comma. That gives us a change to consider whether we have an unclosed range. */ while(*p) { /* Spaces have no value except to terminate numbers. */ if(isspace(*p)) { p++; continue; } /* If a number, interpretation depends on context. */ if(isdigit(*p)) { /* Parse the digits and move the read pointer past them. */ int value = atoi(p); p += strspn(p, "0123456789"); /* If we aren't in a range, move the starting page up to this number. */ if(!range) page = value; /* Step from the starting value to the ending value (the number we read just now) or the end of the document, whichever comes first, setting bits as we go. */ for( ; page <= value && page <= job->attr.pages; page++) { int offset = (page - 1); job->page_list.mask[offset / 6] |= (1 << (offset % 6)); } /* If we finished a range, reset things. */ if(range) { range = FALSE; page = 1; } continue; } /* We must break out of this inner loop at comma to see if there is an open range that needs closing. */ if(*p == ',') { p++; break; } /* If we see a hyphen, that means the previous number (or one if there was none) was the tart of a range. */ if(*p == '-') { range = TRUE; p++; continue; } /* Other characters are invalid. */ return -1; } /* inner loop until comma */ /* If we ended with an unclosed range, run it to the end of the pages. */ if(range) { for( ; page <= job->attr.pages; page++) { int offset = (page - 1); job->page_list.mask[offset / 6] |= (1 << (offset % 6)); } range = FALSE; } } /* outer loop til end of string */ /* Count the number of bits set in each byte and then add 33 to each byre to convert it to printable ASCII. */ { int x, y; job->page_list.count = 0; for(x=0; x<bytes; x++) { for(y=0; y < 6; y++) if(job->page_list.mask[x] & (1 << y)) job->page_list.count++; job->page_list.mask[x] += 33; } } return 0; } /* end of pagemask_encode() */
void gcs_sm_destroy (gcs_sm_t* sm) { gu_mutex_destroy(&sm->lock); gu_free (sm); }
static int drivers_import(void) { TDB_CONTEXT *tdb_drivers; char *line = NULL; int line_available = 256; int linenum = 0; char keytext[256]; TDB_DATA key, data; char *lineptr; char *field_cversion, /* OS Print Driver Version */ *field_drivername, /* Long Name of Printer Driver */ *field_os, /* Long OS Name */ *field_driverpath, /* Path the Driver DLL */ *field_datafile, /* Path the Configuration DLL */ *field_configfile, /* Path the PPD file */ *field_helpfile, /* Path to .HLP file */ *field_monitorname, /* Port Monitor (NULL for Samba) */ *field_defaultdatatype, /* Default Data Type (RAW) */ *field_dependentfile; char **packlist[] = { &field_drivername, &field_os, &field_driverpath, &field_datafile, &field_configfile, &field_helpfile, &field_monitorname, &field_defaultdatatype, NULL}; const char *architecture; char *scratch = NULL; int scratch_available = 0; int scratch_len; /* Open the TDB database that contains NT driver information. */ if(!(tdb_drivers = tdb_open((char*)tdb_drivers_file, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600))) { fprintf(stderr, "%s: can't open \"%s\", errno=%d (%s)\n", myname, tdb_drivers_file, errno, strerror(errno)); return EXIT_INTERNAL; } while((line = gu_getline(line, &line_available, stdin))) { linenum++; lineptr = line; if(!(field_os = gu_strsep(&lineptr, ":")) || !(field_cversion = gu_strsep(&lineptr, ":")) || !(field_drivername = gu_strsep(&lineptr, ":")) || !(field_driverpath = gu_strsep(&lineptr, ":")) || !(field_datafile = gu_strsep(&lineptr, ":")) || !(field_configfile = gu_strsep(&lineptr, ":")) || !(field_helpfile = gu_strsep(&lineptr, ":")) || !(field_monitorname = gu_strsep(&lineptr, ":")) || !(field_defaultdatatype = gu_strsep(&lineptr, ":")) ) { fprintf(stderr, "%s: parse error on line %d.\n", myname, linenum); break; } if(strcmp(field_os, "Windows NT x86") == 0) architecture = "W32X86"; else if(strcmp(field_os, "Windows 4.0") == 0) architecture = "WIN40"; else { fprintf(stderr, "Unrecognized OS: %s\n", field_os); break; } /* Create the TDB key. Note that the Samba code converts this to the Unix codepage but we don't. */ snprintf(keytext, sizeof(keytext), "DRIVERS/%s/%d/%s", architecture, atoi(field_cversion), field_drivername); /* Make sure scratch buffer is big enough. */ if((line_available + 10) > scratch_available) { scratch_available = line_available + 10; scratch = gu_realloc(scratch, scratch_available, sizeof(char)); } scratch_len = 0; /* Copy the little-endian 32 bit integer field. */ { unsigned int val = atoi(field_cversion); int x; for(x=0; x<4; x++) { scratch[scratch_len++] = val & 0xFF; val >>= 8; } } /* Copy the text fields. */ { int x; char **p; for(x = 0; (p = packlist[x]); x++) { int len = strlen(*p) + 1; memcpy(&scratch[scratch_len], *p, len); scratch_len += len; } } /* Now add the list of other files that must be downloaded. */ for( ; (field_dependentfile = gu_strsep(&lineptr, ":")); ) { int len = strlen(field_dependentfile) + 1; memcpy(&scratch[scratch_len], field_dependentfile, len); scratch_len += len; } key.dptr = keytext; key.dsize = strlen(keytext)+1; data.dptr = scratch; data.dsize = scratch_len; if(tdb_store(tdb_drivers, key, data, TDB_REPLACE)) { fprintf(stderr, "Failed to insert key \"%s\", %s.\n", keytext, tdb_errorstr(tdb_drivers)); break; } } tdb_close(tdb_drivers); /* If the line buffer hasn't been freed, it means there was an error. */ if(line) { gu_free(line); return EXIT_INTERNAL; } return EXIT_OK; }
/*! Destroys component message */ void gcs_comp_msg_delete (gcs_comp_msg_t* comp) { gu_free (comp); }