#include <ctype.h>
#include <errno.h>
#include <libc.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/fcntl.h>
#include <CoreFoundation/CoreFoundation.h>
#include "../scheduler/mime.h"
#define HAVE_TM_GMTOFF 1
#define MAX_FILTERS 20
#define ErrorFile stderr
#define L_PAGE -1
#define L_NONE 0
#define L_EMERG 1
#define L_ALERT 2
#define L_CRIT 3
#define L_ERROR 4
#define L_WARN 5
#define L_NOTICE 6
#define L_INFO 7
#define L_DEBUG 8
#define L_DEBUG2 9
static int ConvertJob(const char *filename, mime_type_t *inMimeType, const char *options, const char *ppdPath, mime_type_t *outMimeType, mime_t *mimeDatabase, const char *out, const char *userName, const char *jobName, const char *numCopies);
int LogMessage(int level, const char *message, ...);
char *getDateTime(time_t t);
static int start_process(const char *command, const char *const argv[], const char *const envp[], int infd, int outfd, int errfd, int root);
static mime_type_t *getMimeType(mime_t *mimeDatabase, const char *mimeStr);
static const char *appleLangDefault(void);
static int getCupsLogLevelFromUserPrefs(void);
char ServerBin[1024] = "/usr/libexec/cups";
static int FilterLevel = 0;
static const char *RIPCache = "8m";
static const char *ServerRoot = "/etc/cups";
static const char *TempDir = "/tmp";
static const char *DataDir = "/usr/share/cups";
static const char *FontPath = "/usr/share/cups/fonts";
static int LogLevel = L_ERROR;
static int MaxFDs = 0;
int main (int argc, char *argv[])
{
mime_t *mimeDatabase = NULL;
mime_type_t *inMimeType;
mime_type_t *outMimeType;
const char *options = "";
const char *ppd = "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/Resources/English.lproj/Generic.ppd";
const char *outMimeStr = "application/pdf";
const char *inMimeStr = NULL; const char *filename = NULL; const char *outFilename = NULL;
const char *userName = "unknown"; const char *jobName = "unknown"; const char *numCopies = "1"; int unlinkPPD = FALSE;
int unlinkInputFile = FALSE;
char c = 0;
int status = 0;
int waitStatus = 0;
int waitErr = 0;
while ((c = getopt(argc, argv, "f:o:i:j:P:a:uU:J:c:D")) != -1) {
switch(c) {
case 'f':
filename = optarg;
break;
case 'o':
outFilename = optarg;
break;
case 'i':
inMimeStr = optarg;
break;
case 'j':
outMimeStr = optarg;
break;
case 'P':
ppd = optarg;
break;
case 'a':
options = optarg;
break;
case 'u':
unlinkPPD = TRUE;
break;
case 'U':
userName = optarg;
break;
case 'J':
jobName = optarg;
break;
case 'c':
numCopies = optarg;
break;
case 'D':
unlinkInputFile = TRUE;
break;
case '?':
default:
fprintf(stderr, "Ignoring unexpected parameter: %s\n", argv[optind - 1]);
}
}
if (argc != optind) {
fprintf(stderr, "Usage: %s [-f <input filename>] [-o <output filename>] [-i <input mimetype>] [-j <output mimetype>] [-P <PPD filename>] [-u] [-a <attribute string>] [-U <username>] [-J <jobname] [-c <copies>] [-D]\n", argv[0]);
status = 1;
} else {
char directory[1024];
LogLevel = getCupsLogLevelFromUserPrefs();
snprintf(directory, sizeof(directory), "%s/filter", ServerBin);
mimeDatabase = mimeNew();
mimeMerge(mimeDatabase, ServerRoot, directory);
if (inMimeStr == NULL) {
inMimeType = mimeFileType(mimeDatabase, filename, NULL);
} else {
inMimeType = getMimeType(mimeDatabase, inMimeStr);
}
outMimeType = getMimeType(mimeDatabase, outMimeStr);
status = ConvertJob(filename, inMimeType, options, ppd, outMimeType, mimeDatabase, outFilename, userName, jobName, numCopies);
do {
waitErr = wait(&waitStatus);
} while (waitErr != -1);
}
if (unlinkInputFile && filename && filename[0]){
unlink(filename);
}
if (unlinkPPD && ppd != NULL) {
unlink(ppd);
}
return status;
}
static int ConvertJob(const char *filename, mime_type_t *inMimeType, const char *options, const char *ppdPath, mime_type_t *outMimeType, mime_t *mimeDatabase, const char *out, const char *userName, const char *jobName, const char *numCopies)
{
int i;
int slot;
int num_filters;
mime_filter_t *filters;
char method[255];
int pid;
int statusfds[2],
filterfds[2][2];
int envc;
const char *argv[8];
const char *envp[100];
char command[1024],
#ifdef __APPLE__
processPath[1050],
#endif
path[1024],
ipp_port[1024],
language[255],
charset[255],
content_type[1024],
device_uri[1024],
ppd[1024],
printer_name[255],
root[1024],
cache[255],
tmpdir[1024],
ld_library_path[1024],
ld_preload[1024],
dyld_library_path[1024],
shlib_path[1024],
nlspath[1024],
datadir[1024],
fontpath[1050],
vg_args[1024],
ld_assume_kernel[1024];
int currentCost = 0;
int id = 1;
char out_url[1024];
static const char *outputURL = "file://dev/stdout";
struct rlimit limit;
static const int FilterLimit = 0; char *TZ = getenv("TZ");;
if (out != NULL) {
snprintf(out_url, sizeof(out_url), "file:/%s", out);
outputURL = out_url;
}
getrlimit(RLIMIT_NOFILE, &limit);
if (limit.rlim_max > FD_SETSIZE)
MaxFDs = FD_SETSIZE;
else
MaxFDs = limit.rlim_max;
limit.rlim_cur = MaxFDs;
setrlimit(RLIMIT_NOFILE, &limit);
num_filters = 0;
currentCost = 0;
{
filters = mimeFilter(mimeDatabase, inMimeType, outMimeType, &num_filters, NULL);
if (num_filters == 0)
{
LogMessage(L_ERROR, "Unable to convert file to printable format!");
return EINVAL;
}
for (i = 0; i < num_filters;)
if (strcmp(filters[i].filter, "-") == 0)
{
num_filters --;
if (i < num_filters)
memcpy(filters + i, filters + i + 1,
(num_filters - i) * sizeof(mime_filter_t));
}
else
i ++;
if (num_filters == 0)
{
free(filters);
filters = NULL;
}
else
{
for (i = 0; i < num_filters; i ++)
currentCost += filters[i].cost;
}
}
if ((FilterLevel + currentCost) > FilterLimit && FilterLevel > 0 &&
FilterLimit > 0)
{
if (filters != NULL)
free(filters);
LogMessage(L_INFO, "Holding job %d because filter limit has been reached.",
id);
LogMessage(L_DEBUG, "StartJob: id = %d, file = %d, "
"cost = %d, level = %d, limit = %d",
id, 1, currentCost, FilterLevel,
FilterLimit);
return EPROCLIM;
}
FilterLevel += currentCost;
argv[0] = "tofile";
argv[1] = "1";
argv[2] = userName;
argv[3] = jobName;
argv[4] = numCopies;
argv[5] = options;
argv[6] = filename;
argv[7] = NULL;
LogMessage(L_DEBUG, "StartJob: argv = \"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"",
argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
snprintf(language, sizeof(language), "LANG=%s", appleLangDefault());
strcpy(charset, "CHARSET=utf-8");
snprintf(path, sizeof(path), "PATH=%s/filter:/bin:/usr/bin", ServerBin);
snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
inMimeType->super,
inMimeType->type);
snprintf(device_uri, sizeof(device_uri), "DEVICE_URI=%s", outputURL);
snprintf(ppd, sizeof(ppd), "PPD=%s", ppdPath);
snprintf(printer_name, sizeof(printer_name), "PRINTER=%s", ".tofile");
snprintf(cache, sizeof(cache), "RIP_MAX_CACHE=%s", RIPCache);
snprintf(root, sizeof(root), "CUPS_SERVERROOT=%s", ServerRoot);
snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
snprintf(datadir, sizeof(datadir), "CUPS_DATADIR=%s", DataDir);
snprintf(fontpath, sizeof(fontpath), "CUPS_FONTPATH=%s", FontPath);
sprintf(ipp_port, "IPP_PORT=%d", 631);
envc = 0;
envp[envc ++] = path;
envp[envc ++] = "SOFTWARE=CUPS/1.1";
envp[envc ++] = "USER=root";
envp[envc ++] = charset;
envp[envc ++] = language;
if (TZ && TZ[0])
envp[envc ++] = TZ;
envp[envc ++] = ppd;
envp[envc ++] = root;
envp[envc ++] = cache;
envp[envc ++] = tmpdir;
envp[envc ++] = content_type;
envp[envc ++] = device_uri;
envp[envc ++] = printer_name;
envp[envc ++] = datadir;
envp[envc ++] = fontpath;
envp[envc ++] = "CUPS_SERVER=localhost";
envp[envc ++] = ipp_port;
if (getenv("VG_ARGS") != NULL)
{
snprintf(vg_args, sizeof(vg_args), "VG_ARGS=%s", getenv("VG_ARGS"));
envp[envc ++] = vg_args;
}
if (getenv("LD_ASSUME_KERNEL") != NULL)
{
snprintf(ld_assume_kernel, sizeof(ld_assume_kernel), "LD_ASSUME_KERNEL=%s",
getenv("LD_ASSUME_KERNEL"));
envp[envc ++] = ld_assume_kernel;
}
if (getenv("LD_LIBRARY_PATH") != NULL)
{
snprintf(ld_library_path, sizeof(ld_library_path), "LD_LIBRARY_PATH=%s",
getenv("LD_LIBRARY_PATH"));
envp[envc ++] = ld_library_path;
}
if (getenv("LD_PRELOAD") != NULL)
{
snprintf(ld_preload, sizeof(ld_preload), "LD_PRELOAD=%s",
getenv("LD_PRELOAD"));
envp[envc ++] = ld_preload;
}
if (getenv("DYLD_LIBRARY_PATH") != NULL)
{
snprintf(dyld_library_path, sizeof(dyld_library_path), "DYLD_LIBRARY_PATH=%s",
getenv("DYLD_LIBRARY_PATH"));
envp[envc ++] = dyld_library_path;
}
if (getenv("SHLIB_PATH") != NULL)
{
snprintf(shlib_path, sizeof(shlib_path), "SHLIB_PATH=%s",
getenv("SHLIB_PATH"));
envp[envc ++] = shlib_path;
}
if (getenv("NLSPATH") != NULL)
{
snprintf(nlspath, sizeof(nlspath), "NLSPATH=%s", getenv("NLSPATH"));
envp[envc ++] = nlspath;
}
#ifdef __APPLE__
strlcpy(processPath, "<CFProcessPath>", sizeof(processPath));
envp[envc ++] = processPath;
#endif
envp[envc] = NULL;
for (i = 0; i < envc; i ++)
LogMessage(L_DEBUG, "StartJob: envp[%d]=\"%s\"", i, envp[i]);
#if 0
if (pipe(statusfds))
{
LogMessage(L_ERROR, "Unable to create job status pipes - %s.",
strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to create status pipes - %s.", strerror(errno));
AddPrinterHistory(printer);
return;
}
LogMessage(L_DEBUG, "StartJob: statusfds = [ %d %d ]",
statusfds[0], statusfds[1]);
current->pipe = statusfds[0];
current->status = 0;
memset(current->procs, 0, sizeof(current->procs));
#else
statusfds[0] = -1;
if (LogLevel < L_DEBUG)
statusfds[1] = open("/dev/null", O_WRONLY);
else
statusfds[1] = STDERR_FILENO;
#endif
filterfds[1][0] = open("/dev/null", O_RDONLY);
filterfds[1][1] = -1;
LogMessage(L_DEBUG, "StartJob: filterfds[%d] = [ %d %d ]", 1, filterfds[1][0],
filterfds[1][1]);
for (i = 0, slot = 0; i < num_filters; i ++)
{
if (filters[i].filter[0] != '/')
snprintf(command, sizeof(command), "%s/filter/%s", ServerBin,
filters[i].filter);
else
strlcpy(command, filters[i].filter, sizeof(command));
#ifdef __APPLE__
{
char linkbuf[1024];
int linkbufbytes;
if ((linkbufbytes = readlink(command, linkbuf, sizeof(linkbuf) - 1)) > 0)
{
linkbuf[linkbufbytes] = '\0';
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s", dirname(command), linkbuf);
}
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
LogMessage(L_DEBUG, "StartJob: %s\n", processPath);
}
#endif
if (i < (num_filters - 1) ||
strncmp(outputURL, "file:", 5) != 0)
pipe(filterfds[slot]);
else
{
filterfds[slot][0] = -1;
if (strncmp(outputURL, "file:/dev/", 10) == 0)
filterfds[slot][1] = open(outputURL + 5,
O_WRONLY | O_EXCL);
else
filterfds[slot][1] = open(outputURL + 5,
O_WRONLY | O_CREAT | O_TRUNC, 0600);
}
LogMessage(L_DEBUG, "StartJob: filter = \"%s\"", command);
LogMessage(L_DEBUG, "StartJob: filterfds[%d] = [ %d %d ]",
slot, filterfds[slot][0], filterfds[slot][1]);
pid = start_process(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], statusfds[1], 0);
close(filterfds[!slot][0]);
close(filterfds[!slot][1]);
if (pid == 0)
{
LogMessage(L_ERROR, "Unable to start filter \"%s\" - %s.",
filters[i].filter, strerror(errno));
return errno;
}
LogMessage(L_INFO, "Started filter %s (PID %d) for job %d.",
command, pid, 1);
argv[6] = NULL;
slot = !slot;
}
if (filters != NULL)
free(filters);
if (strncmp(outputURL, "file:", 5) != 0)
{
sscanf(outputURL, "%254[^:]", method);
snprintf(command, sizeof(command), "%s/backend/%s", ServerBin, method);
#ifdef __APPLE__
{
char linkbuf[1024];
int linkbufbytes;
if ((linkbufbytes = readlink(command, linkbuf, sizeof(linkbuf) - 1)) > 0)
{
linkbuf[linkbufbytes] = '\0';
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s", dirname(command), linkbuf);
}
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
LogMessage(L_DEBUG, "StartJob: %s\n", processPath);
}
#endif
argv[0] = (char*)outputURL;
filterfds[slot][0] = -1;
filterfds[slot][1] = open("/dev/null", O_WRONLY);
LogMessage(L_DEBUG, "StartJob: backend = \"%s\"", command);
LogMessage(L_DEBUG, "StartJob: filterfds[%d] = [ %d %d ]",
slot, filterfds[slot][0], filterfds[slot][1]);
pid = start_process(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], statusfds[1], 1);
close(filterfds[!slot][0]);
close(filterfds[!slot][1]);
if (pid == 0)
{
LogMessage(L_ERROR, "Unable to start backend \"%s\" - %s.",
method, strerror(errno));
return errno;
}
else
{
LogMessage(L_INFO, "Started backend %s (PID %d) for job %d.", command, pid,
1);
}
}
else
{
filterfds[slot][0] = -1;
filterfds[slot][1] = -1;
close(filterfds[!slot][0]);
close(filterfds[!slot][1]);
}
close(filterfds[slot][0]);
close(filterfds[slot][1]);
close(statusfds[1]);
return 0;
}
int
LogMessage(int level,
const char *message,
...)
{
int len;
char line[1024];
va_list ap;
static char levels[] =
{
' ',
'X',
'A',
'C',
'E',
'W',
'N',
'I',
'D',
'd'
};
#ifdef HAVE_VSYSLOG
static int syslevels[] =
{
0,
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG,
LOG_DEBUG
};
#endif
if (level > LogLevel)
return (1);
fprintf(ErrorFile, "%c %s ", levels[level], getDateTime(time(NULL)));
va_start(ap, message);
len = vsnprintf(line, sizeof(line), message, ap);
va_end(ap);
fputs(line, ErrorFile);
if (len > 0 && line[len - 1] != '\n')
putc('\n', ErrorFile);
fflush(ErrorFile);
return (1);
}
char *
getDateTime(time_t t)
{
struct tm *date;
static char s[1024];
static const char *months[12] =
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
date = localtime(&t);
snprintf(s, sizeof(s), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]",
date->tm_mday, months[date->tm_mon], 1900 + date->tm_year,
date->tm_hour, date->tm_min, date->tm_sec,
#ifdef HAVE_TM_GMTOFF
date->tm_gmtoff / 3600, (date->tm_gmtoff / 60) % 60);
#else
timezone / 3600, (timezone / 60) % 60);
#endif
return (s);
}
static int
start_process(const char *command,
const char *const argv[],
const char *const envp[],
int infd,
int outfd,
int errfd,
int root)
{
int fd;
int pid;
LogMessage(L_DEBUG, "start_process(\"%s\", %08x, %08x, %d, %d, %d)",
command, argv, envp, infd, outfd, errfd);
if ((pid = fork()) == 0)
{
close(0);
dup(infd);
close(1);
dup(outfd);
if (errfd > 2)
{
close(2);
dup(errfd);
}
for (fd = 3; fd < MaxFDs; fd ++)
close(fd);
#if 0
if (!root && getuid() == 0)
{
if (setgid(Group))
exit(errno);
if (setuid(User))
exit(errno);
}
#endif
#if CHANGE_PERM
#ifdef __APPLE__
initgroups(UserName, Group);
#else
setgroups(0, NULL);
#endif
umask(077);
#endif
execve(command, (char *const*) argv, (char *const*) envp);
perror(command);
exit(errno);
}
else if (pid < 0)
{
LogMessage(L_ERROR, "Unable to fork %s - %s.", command, strerror(errno));
return (0);
}
return (pid);
}
static mime_type_t *getMimeType(mime_t *mimeDatabase, const char *mimeStr)
{
char super[MIME_MAX_SUPER];
char type[MIME_MAX_TYPE];
const char *inStr = NULL;
char *inSuper = super;
char *inType = type;
inStr = mimeStr;
while (*inStr != '/' && *inStr != '\0' && (inSuper - super + 1) < sizeof(super)) {
*inSuper++ = tolower(*inStr++);
}
*inSuper = '\0';
if (*inStr != '/') {
fprintf(stderr, "Invalid format for mime type: %s\n", mimeStr);
} else {
++inStr;
while(*inStr != '\0' && (type - type + 1) < sizeof(type)) {
*inType++ = tolower(*inStr++);
}
*inType++ = '\0';
}
return mimeType(mimeDatabase, super, type);
}
typedef struct
{
const char * const name;
const char * const locale;
} apple_name_locale_t;
static const apple_name_locale_t apple_name_locale[] =
{
{ "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
{ "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
{ "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
{ "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
{ "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
{ "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
{ "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
{ "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
{ "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
{ "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
{ "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
{ "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
{ "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
{ "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
{ "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
{ "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
{ "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
{ "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
{ "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
{ "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
{ "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
{ "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
{ "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
{ "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
{ "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
{ "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
{ "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
{ "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
{ "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
{ "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
{ "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
{ "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
{ "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
{ "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
{ "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
{ "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
{ "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
{ "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
{ "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
{ "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
{ "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
{ "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
{ "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
{ "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
{ "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
{ "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
{ "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
{ "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
{ "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
{ "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
{ "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
{ "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
{ "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
{ "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
{ "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
{ "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
{ "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
{ "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
{ "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
};
static const char *
appleLangDefault(void)
{
int i;
CFPropertyListRef localizationList;
CFStringRef localizationName;
char buff[256];
static const char *language = NULL;
if (language == NULL)
{
localizationList =
CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
kCFPreferencesCurrentApplication);
if (localizationList != NULL)
{
if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
CFArrayGetCount(localizationList) > 0)
{
localizationName = CFArrayGetValueAtIndex(localizationList, 0);
if (localizationName != NULL &&
CFGetTypeID(localizationName) == CFStringGetTypeID())
{
CFIndex length = CFStringGetLength(localizationName);
if (length <= sizeof(buff) &&
CFStringGetCString(localizationName, buff, sizeof(buff),
kCFStringEncodingASCII))
{
buff[sizeof(buff) - 1] = '\0';
for (i = 0;
i < sizeof(apple_name_locale) / sizeof(apple_name_locale[0]);
i++)
{
if (strcasecmp(buff, apple_name_locale[i].name) == 0)
{
language = apple_name_locale[i].locale;
break;
}
}
}
}
}
CFRelease(localizationList);
}
if (language == NULL)
language = apple_name_locale[0].locale;
}
return (language);
}
static int getCupsLogLevelFromUserPrefs(void)
{
int loglevel = L_ERROR;
int i;
char loglevelstr[64];
static struct cups_loglevel_tbl_t {
int loglevel;
const char * const str;
} cups_loglevel_tbl[] = {
{ L_NONE, "NONE" },
{ L_ERROR, "ERROR" },
{ L_WARN, "WARN" },
{ L_INFO, "INFO" },
{ L_DEBUG, "DEBUG" },
{ L_DEBUG2, "DEBUG2"}
};
CFStringRef loglevelRef = (CFStringRef)CFPreferencesCopyValue(CFSTR("cupsloglevel"),
CFSTR("com.apple.print"), kCFPreferencesCurrentUser,
kCFPreferencesAnyHost);
if (loglevelRef)
{
if (CFGetTypeID(loglevelRef) == CFStringGetTypeID() &&
CFStringGetCString(loglevelRef, loglevelstr, sizeof(loglevelstr), kCFStringEncodingASCII))
{
for (i = 0; i < sizeof(cups_loglevel_tbl)/sizeof(cups_loglevel_tbl[0]); i++)
{
if (strcasecmp(loglevelstr, cups_loglevel_tbl[i].str) == 0)
{
loglevel = cups_loglevel_tbl[i].loglevel;
break;
}
}
}
CFRelease(loglevelRef);
}
return loglevel;
}