From b3c049c98557bde9a37807bceef3040020ca787c Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Fri, 15 Feb 2002 09:14:22 +0000 Subject: - plpbackup: more error handling; translation - Added plpprint stuff (yet not useful) - ccmalloc upgrade --- Makefile.am | 2 +- acconfig.h | 3 + configure.in | 47 +- plpbackup/Makefile.am | 2 +- plpbackup/plpbackup.cc | 1370 +++++++++++++++++++++++++++++++----------------- plpprint/.cvsignore | 5 + plpprint/Makefile.am | 10 + plpprint/plpprintd.cc | 310 +++++++++++ po/POTFILES.in | 1 + po/de.po | 178 ++++++- 10 files changed, 1393 insertions(+), 535 deletions(-) create mode 100644 plpprint/.cvsignore create mode 100644 plpprint/Makefile.am create mode 100644 plpprint/plpprintd.cc diff --git a/Makefile.am b/Makefile.am index 5775bc3..3f9a2ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ else KDESUB = endif -SUBDIRS = intl po lib ncpd plpnfsd plpftp plpbackup $(KDESUB) doc . +SUBDIRS = intl po lib ncpd plpnfsd plpftp plpbackup plpprint $(KDESUB) doc . EXTRA_DIST = CHANGES COPYING README TODO INSTALL README.mjg ABOUT-NLS include/*.h* etc/*magic etc/*.in patches conf/m4/kde/*.m4 conf/m4/plptools/*.m4 conf/[a-l]* conf/missing conf/mkinstalldirs DISTCLEANFILES = etc/psion AUTOMAKE_OPTIONS = foreign diff --git a/acconfig.h b/acconfig.h index 9c2812f..9c54f24 100644 --- a/acconfig.h +++ b/acconfig.h @@ -72,6 +72,9 @@ /* Define this, if sys/int_types.h is on your system */ #undef HAVE_SYS_INT_TYPES_H +/* Define this, if stdint.h is on your system */ +#undef HAVE_STDINT_H + /* Define this, if your int-types have an underscore after the first u/s */ #undef GNU_INTTYPES diff --git a/configure.in b/configure.in index 8f17acb..ecf62d4 100644 --- a/configure.in +++ b/configure.in @@ -2,6 +2,8 @@ AC_REVISION($Revision$)dnl revision of this configure.in script AC_CONFIG_AUX_DIR(conf) AC_INIT(Makefile.am) +AC_PROG_CC +AC_AIX AC_CANONICAL_SYSTEM AM_CONFIG_HEADER(include/config.h) AM_INIT_AUTOMAKE(plptools, 0.10) @@ -12,7 +14,6 @@ dnl Enable Maintainer stuff AM_MAINTAINER_MODE dnl checks for programs -AC_AIX AC_PROG_MAKE_SET AC_PROG_CXX PLP_CHECK_COMPILERS @@ -136,46 +137,15 @@ dnl Type of sighandlers AC_TYPE_SIGNAL dnl checks for header files -AC_CHECK_HEADERS(sys/time.h sys/ioctl.h sys/errno.h sys/ttold.h stdlib.h) - -PLP_HELP_MSG([Debugging (developer only!):]) -LIBCCMALLOC= -AC_ARG_WITH(ccmalloc, - [ --with-ccmalloc=DIR link against ccmalloc leak-checking lib], - [ - search_dirs="/usr/lib /lib /usr/local/lib" - case "${withval}" in - yes) - ccmalloc_dirs=${search_dirs} - ;; - no) - ccmalloc_dirs= - ;; - *) - ccmalloc_dirs="${withval} ${search_dirs}" - ;; - esac - AC_MSG_CHECKING(for libccmalloc) - save_LIBS="$LIBS" - ccmalloc_found=NO - for d in ${ccmalloc_dirs} ; do - LIBS="-L$d -lccmalloc -ldl" - AC_TRY_LINK_FUNC(ccmalloc_report,ccmalloc_found=$d ; break) - done - LIBS="$save_LIBS" - if test "${ccmalloc_found}" = "NO" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT(found) - LIBCCMALLOC="-L$ccmalloc_found -lccmalloc -ldl" - fi - ] +AC_CHECK_HEADERS( + sys/time.h sys/ioctl.h sys/errno.h sys/ttold.h stdlib.h \ + sys/int_types.h stdint.h ) -AC_SUBST(LIBCCMALLOC) +PLP_HELP_MSG([Debugging (developer only!):]) +AC_CHECK_CCMALLOC dnl special options for customization - PLP_HELP_MSG([Options for overriding builtin defaults:]) AC_ARG_WITH(serial, @@ -269,7 +239,7 @@ if test "x$ac_enable_kde" = "xyes" ; then kde_exec_prefix=${kde_prefix} fi AC_ARG_WITH(kdedir, - [ --with-kdedir=DIR specify KDE directory [\${prefix}]], + [ --with-kdedir=DIR specify KDE directory [${prefix:-${ac_default_prefix}}]], [ kde_prefix=${withval} kde_exec_prefix=${withval} @@ -307,6 +277,7 @@ AC_OUTPUT( kde2/doc/en/Makefile kde2/doc/de/Makefile plpbackup/Makefile + plpprint/Makefile doc/Makefile doc/api/Makefile include/config.h diff --git a/plpbackup/Makefile.am b/plpbackup/Makefile.am index a1a859b..c868bd5 100644 --- a/plpbackup/Makefile.am +++ b/plpbackup/Makefile.am @@ -3,7 +3,7 @@ INCLUDES=-I$(top_srcdir)/lib bin_PROGRAMS = plpbackup -plpbackup_LDADD = $(top_srcdir)/lib/libplp.la +plpbackup_LDADD = $(top_srcdir)/lib/libplp.la $(LIBCCMALLOC_CXX) plpbackup_SOURCES = plpbackup.cc maintainer-clean-local: diff --git a/plpbackup/plpbackup.cc b/plpbackup/plpbackup.cc index b10eff1..9b87024 100644 --- a/plpbackup/plpbackup.cc +++ b/plpbackup/plpbackup.cc @@ -1,23 +1,25 @@ -// $Id$ -// -// plpbackup - A backup program for Psion. -// -// Copyright (C) 2000 Fritz Elfert -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// +/* -*- Mode: C++ -*- + * $Id$ + * + * This file is part of plptools. + * + * Copyright (C) 2000-2001 Fritz Elfert + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ #ifdef HAVE_CONFIG_H #include @@ -25,525 +27,927 @@ #include #include -#include +#include +#include +#include +#include + #include #include #include -#include #include +#include #include #include #include #include #include -#include "ppsocket.h" -#include "rfsv.h" -#include "rfsvfactory.h" -#include "rpcs.h" -#include "rpcsfactory.h" -#include "bufferstore.h" -#include "bufferarray.h" -#include "Enum.h" +#include +#include +#include +#include +#include +#include +#include +#include -void -usage(ostream *hlp) -{ - *hlp - << "Usage: plpbackup OPTIONS [:] [:] ..." << endl - << endl - << " Options:" << endl - << " -h, --help Print this message and exit." << endl - << " -V, --version Print version and exit." << endl - << " -p, --port= Connect to ncpd using given port." << endl - << " -v, --verbose Increase verbosity." << endl - << " -q, --quiet Decrease verbosity." << endl - << " -f, --full Do a full backup (incremental otherwise)." << endl - << endl - << " A drive character. If none given, scan all drives." << endl - << endl; -} +bool full = false; +bool S5mx = false; +bool doRestore = false; +bool doBackup = false; +bool doFormat = false; +bool skipError = false; +bool doAbort = false; -bool full; -int verbose = 0; -PlpDir toBackup; +int verbose = 0; +int caughtSig = 0; unsigned long backupSize = 0; +unsigned long backupCount = 0; unsigned long totalBytes = 0; unsigned long fileSize = 0; -char home[1024]; + +PlpDir toBackup; +vector driveList; +vector archList; +vector savedCommands; +rfsv *Rfsv; +rpcs *Rpcs; + +static RETSIGTYPE +sig_handler(int sig) +{ + caughtSig = sig; + signal(sig, sig_handler); +}; + +static const char * const +getHomeDir() +{ + struct passwd *pw = getpwuid(getuid()); + if (pw && pw->pw_dir && strlen(pw->pw_dir)) + return pw->pw_dir; + else + cerr << _("Could not get user's home directory from /etc/passwd") + << endl; + return ""; +} + +static const char * const +generateBackupName() +{ + time_t now = time(0); + Enum res; + char tstr[80]; + static char nbuf[4096]; + + rpcs::machineInfo mi; + if ((res = Rpcs->getMachineInfo(mi)) != rfsv::E_PSI_GEN_NONE) { + cerr << _("Could not get machine UID") << endl; + exit(1); + } + strftime(tstr, sizeof(tstr), "-%Y-%m-%d-%H-%M-%S", localtime(&now)); + sprintf(nbuf, "%s/plpbackup/%16llx/%c%s.tar.gz", getHomeDir(), + mi.machineUID, full ? 'F' : 'I', tstr); + return nbuf; +} + +static const char * const +generateTmpDir() +{ + char *tmpdir; + static char nbuf[4096]; + + if (!(tmpdir = getenv("TMPDIR"))) + tmpdir = P_tmpdir; + sprintf(nbuf, "%s/plpbackup_%d", tmpdir, getpid()); + mkdir(nbuf, S_IRWXU|S_IRGRP|S_IXGRP); + return nbuf; +} + +static bool +checkAbort() +{ + if (caughtSig) { + if (verbose > 0) + cout << endl; + cout << _("Got signal "); + switch (caughtSig) { + case SIGTERM: + cout << "SIGTERM"; + break; + case SIGINT: + cout << "SIGINT"; + break; + default: + cout << caughtSig; + } + cout << endl; + cout << _("Abort? (y/N) ") << flush; + char *validA = _("Y"); + char answer; + cin >> answer; + caughtSig = 0; + if (toupper(answer) == *validA) + doAbort = true; + } + return doAbort; +} static int -killsave(rpcs *r, bool S5mx) { - Enum res; - bufferArray tmp; - char psfile[1024]; +stopPrograms() { + Enum res; + bufferArray tmp; - sprintf(psfile, "%s/.plpbackup.%d", home, getpid()); - if ((res = r->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) { + if (verbose > 0) + cout << _("Stopping programs ...") << endl; + if ((res = Rpcs->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) { + cerr << _("plpbackup: Could not get process list: ") << res << endl; + return 1; + } else { + while (!tmp.empty()) { + ostrstream pbuf; + bufferStore cmdargs; + bufferStore bs = tmp.pop(); + int pid = bs.getWord(0); + + pbuf << bs.getString(2) << ".$"; + if (S5mx) + pbuf << dec << setw(2) << setfill(0) << pid; + else + pbuf << dec << pid; + pbuf << '\0'; + bs = tmp.pop(); + if (Rpcs->getCmdLine(pbuf.str(), cmdargs) == 0) { + string cmdline = cmdargs.getString(0); + cmdline += " "; + cmdline += bs.getString(0); + savedCommands.push_back(cmdline); + if (verbose > 1) + cout << cmdline << endl; + } + Rpcs->stopProgram(pbuf.str()); + } + time_t tstart = time(0) + 5; + while (true) { + usleep(100000); + if (checkAbort()) + return 1; + if ((res = Rpcs->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) { cerr << "Could not get process list, Error: " << res << endl; return 1; - } else { - ofstream op(psfile); - if (!op) { - cerr << "Could not write processlist " << psfile << endl; - return 1; - } - op << "#plpbackup processlist" << endl; - while (!tmp.empty()) { - char pbuf[128]; - bufferStore cmdargs; - bufferStore bs = tmp.pop(); - int pid = bs.getWord(0); - const char *proc = bs.getString(2); - if (S5mx) - sprintf(pbuf, "%s.$%02d", proc, pid); - else - sprintf(pbuf, "%s.$%d", proc, pid); - bs = tmp.pop(); - if (r->getCmdLine(pbuf, cmdargs) == 0) - op << cmdargs.getString(0) << " " << bs.getString(0) << endl; - if (verbose > 1) - cout << cmdargs.getString(0) << " " << bs.getString(0) << endl; - r->stopProgram(pbuf); - } - op.close(); + } + if (tmp.empty()) + break; + if (time(0) > tstart) { + cout << _( + "Could not stop all processes. Please stop running\n" + "programs manually on the Psion, then hit return.") << flush; + cin.getline((char *)&tstart, 1); + tstart = time(0) + 5; + } } - return 0; + } + return 0; } static int -runrestore(rfsv *a, rpcs *r) { - Enum res; - bufferArray tmp; - char psfile[1024]; - - sprintf(psfile, "%s/.plpbackup.%d", home, getpid()); - ifstream ip(psfile); - char cmd[512]; - char arg[512]; - - if (!ip) { - cerr << "Could not read processlist " << psfile << endl; - return 1; - } - ip >> cmd >> arg; +startPrograms() { + Enum res; - if (strcmp(cmd, "#plpbackup") || strcmp(arg, "processlist")) { - ip.close(); - cerr << "Error: " << psfile << - " is not a process list saved with plpbackup" << endl; - return 1; - } - while (!ip.eof()) { - ip >> cmd >> arg; - ip.get(&arg[strlen(arg)], sizeof(arg) - strlen(arg), '\n'); - if (strlen(cmd) > 0) { - // Workaround for broken programs like Backlite. These do not store - // the full program path. In that case we try running the arg1 which - // results in starting the program via recog. facility. - if (verbose > 1) - cout << cmd << " " << arg << endl; - if ((strlen(arg) > 2) && (arg[1] == ':') && (arg[0] >= 'A') && - (arg[0] <= 'Z')) - res = r->execProgram(arg, ""); - else - res = r->execProgram(cmd, arg); - if (res != rfsv::E_PSI_GEN_NONE) { - // If we got an error here, that happened probably because - // we have no path at all (e.g. Macro5) and the program is - // not registered in the Psion's path properly. Now try - // the ususal \System\Apps\\.app - // on all drives. - if (strchr(cmd, '\\') == NULL) { - u_int32_t devbits; - char tmp[512]; - if ((res = a->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) { - int i; - for (i = 0; i < 26; i++) { - if (devbits & 1) { - sprintf(tmp, - "%c:\\System\\Apps\\%s\\%s.app", - 'A' + i, cmd, cmd); - res = r->execProgram(tmp, ""); - } - if (res == rfsv::E_PSI_GEN_NONE) - break; - } - } - } - } - if (res != rfsv::E_PSI_GEN_NONE) { - cerr << "Could not start " << cmd << " " << arg << endl; - cerr << "Error: " << res << endl; + if (verbose > 0) + cout << _("Restarting programs ...") << endl; + for (int i = 0; i < savedCommands.size(); i++) { + int firstBlank = savedCommands[i].find(' '); + string cmd = string(savedCommands[i], 0, firstBlank); + string arg = string(savedCommands[i], firstBlank + 1); + + if (!cmd.empty()) { + if (verbose > 1) + cout << cmd << " " << arg << endl; + + // Workaround for broken programs like Backlite. These do not store + // the full program path. In that case we try running the arg1 which + // results in starting the program via recog. facility. + if ((arg.size() > 2) && (arg[1] == ':') && (arg[0] >= 'A') && + (arg[0] <= 'Z')) + res = Rpcs->execProgram(arg.c_str(), ""); + else + res = Rpcs->execProgram(cmd.c_str(), arg.c_str()); + if (res != rfsv::E_PSI_GEN_NONE) { + // If we got an error here, that happened probably because + // we have no path at all (e.g. Macro5) and the program is + // not registered in the Psion's path properly. Now try + // the ususal \System\Apps\\.app + // on all drives. + if (cmd.find('\\') == -1) { + u_int32_t devbits; + if ((res = Rfsv->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) { + int i; + for (i = 0; i < 26; i++) { + if (devbits & 1) { + ostrstream tmp; + tmp << 'A' + i << "\\System\\Apps\\" + << cmd << "\\" << cmd << ".app"; + res = Rpcs->execProgram(tmp.str(), ""); + } + if (res == rfsv::E_PSI_GEN_NONE) + break; } + } } + } + if (res != rfsv::E_PSI_GEN_NONE) { + cerr << "Could not start " << cmd << " " << arg << endl; + cerr << "Error: " << res << endl; + } } - ip.close(); - unlink(psfile); - return 0; + } + return 0; +} + +string +unix2psion(const char * const path) { + string tmp = path; + int pos; + + while ((pos = tmp.find('/')) != -1) + tmp.replace(pos, 1, "\\"); + while ((pos = tmp.find("%2f")) != -1) + tmp.replace(pos, 3, "/"); + while ((pos = tmp.find("%25")) != -1) + tmp.replace(pos, 3, "%"); + return tmp; +} + +string +psion2unix(const char * const path) { + string tmp; + + for (const char *p = path; p && *p; p++) + switch (*p) { + case '%': + tmp += "%25"; + break; + case '/': + tmp += "%2f"; + break; + case '\\': + tmp += "/"; + break; + default: + tmp += *p; + } + return tmp; } static void -collectFiles(rfsv *a, char *dir) { - Enum res; - PlpDir files; - char tmp[1024]; - - strcpy(tmp, dir); - strcat(tmp, "\\"); - if ((res = a->dir(tmp, files)) != rfsv::E_PSI_GEN_NONE) - cerr << "Error: " << res << endl; - else - for (int i = 0; i < files.size(); i++) { - PlpDirent e = files[i]; - - // long size = s.getDWord(4); - long attr = e.getAttr(); - strcpy(tmp, dir); - strcat(tmp, "\\"); - strcat(tmp, e.getName()); - if (attr & rfsv::PSI_A_DIR) { - collectFiles(a, tmp); - } else { - if ((attr & rfsv::PSI_A_ARCHIVE) || full) { - e.setName(tmp); - toBackup.push_back(e); - } - } +collectFiles(bool &found, const char *dir) { + Enum res; + PlpDir files; + string tmp; + + tmp = dir; + tmp += "\\"; + if ((res = Rfsv->dir(tmp.c_str(), files)) != rfsv::E_PSI_GEN_NONE) + cerr << "Error: " << res << endl; + else + for (int i = 0; i < files.size(); i++) { + PlpDirent e = files[i]; + + if (checkAbort()) + return; + // long size = s.getDWord(4); + long attr = e.getAttr(); + tmp = dir; + tmp += "\\"; + tmp += e.getName(); + if (attr & rfsv::PSI_A_DIR) { + collectFiles(found, tmp.c_str()); + } else { + if ((attr & rfsv::PSI_A_ARCHIVE) || full) { + e.setName(tmp.c_str()); + toBackup.push_back(e); + found |= true; } + } + } } static int reportProgress(void *, u_int32_t size) { - unsigned long percent; - char pstr[10]; - char bstr[10]; - - switch (verbose) { - case -1: - case 0: - return 1; - case 1: - percent = (totalBytes + size) * 100 / backupSize; - break; - case 2: - percent = size * 100 / fileSize; - break; - } - sprintf(pstr, " %3d%%", percent); - memset(bstr, 8, sizeof(bstr)); - bstr[strlen(pstr)] = '\0'; - printf("%s%s", pstr, bstr); - fflush(stdout); + unsigned long percent; + char pstr[10]; + char bstr[10]; + + if (checkAbort()) + return 0; + if (verbose < 1) return 1; + switch (verbose) { + case 1: + percent = (totalBytes + size) * 100 / backupSize; + break; + case 2: + percent = size * 100 / fileSize; + break; + } + sprintf(pstr, " %3d%%", percent); + memset(bstr, 8, sizeof(bstr)); + bstr[strlen(pstr)] = '\0'; + printf("%s%s", pstr, bstr); + fflush(stdout); + return 1; } -int -mkdirp(char *path) { - char *p = strchr(path, '/'); - while (p) { - char csave = *(++p); - *p = '\0'; - switch (mkdir(path, S_IRWXU|S_IRWXG)) { - struct stat stbuf; - - case 0: - break; - default: - if (errno != EEXIST) { - perror(path); - return 1; - } - stat(path, &stbuf); - if (!S_ISDIR(stbuf.st_mode)) { - perror(path); - return 1; - } - break; +static cpCallback_t cab = reportProgress; + +static int +mkdirp(const char *_path) { + char *path = strdup(_path); + char *p = strchr(path, '/'); + + while (p) { + char csave = *(++p); + *p = '\0'; + switch (mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP)) { + struct stat stbuf; + + case 0: + break; + default: + if (errno != EEXIST) { + perror(path); + free(path); + return 1; + } + stat(path, &stbuf); + if (!S_ISDIR(stbuf.st_mode)) { + perror(path); + free(path); + return 1; } - *p++ = csave; - p = strchr(p, '/'); + break; } - return 0; + *p++ = csave; + p = strchr(p, '/'); + } + free(path); + return 0; } -static struct option opts[] = { - { "full", no_argument, 0, 'f' }, - { "help", no_argument, 0, 'h' }, - { "port", required_argument, 0, 'V' }, - { "verbose", no_argument, 0, 'v' }, - { "quiet", no_argument, 0, 'q' }, - { "version", no_argument, 0, 'V' }, - { 0, 0, 0, 0 }, -}; +static void +rmrf(const char *_path) +{ + DIR *d = opendir(_path); + if (d) { + struct dirent *de; + while ((de = readdir(d))) { + struct stat st; + if ((de->d_name[0] == '.') && + ((de->d_name[1] == '\0') || + ((de->d_name[1] == '.') && + (de->d_name[2] == '\0')))) + continue; + string path = _path; + path += "/"; + path += de->d_name; + if (stat(path.c_str(), &st) == 0) { + if (S_ISDIR(st.st_mode)) + rmrf(path.c_str()); + else + unlink(path.c_str()); + } + } + } + closedir(d); + rmdir(_path); +} -int -main(int argc, char **argv) +static void +startMessage(const char *arch) { - ppsocket *skt; - ppsocket *skt2; - rfsv *a; - rpcs *r; - cpCallback_t cab = reportProgress; - int status = 0; - int sockNum = DPORT; - int op; - char dstPath[1024]; - struct passwd *pw; - - struct servent *se = getservbyname("psion", "tcp"); - endservent(); - if (se != 0L) - sockNum = ntohs(se->s_port); - - // Command line parameter processing - opterr = 1; - while ((op = getopt_long(argc, argv, "qfhp:vV", opts, NULL)) != EOF) { - switch (op) { - case 'V': - cout << "plpbackup version " << VERSION << endl; - exit(0); - case 'h': - usage(&cout); - exit(0); - case 'f': - full = true; - break; - case 'v': - verbose++; - break; - case 'q': - verbose--; - break; - case 'p': - sockNum = atoi(optarg); - break; - default: - usage(&cerr); - exit(1); + if (verbose >= 0) { + cout << "Performing "; + if (doFormat) + cout << "format"; + if (doRestore) { + if (doFormat) + cout << " and "; + cout << "restore"; + } else + cout << (full ? "full" : "incremental") << " backup"; + cout << " of "; + if (driveList.empty()) + cout << "all drives"; + else { + cout << "Drive "; + for (int i = 0; i < driveList.size(); i++) { + cout << driveList[i++]; + if (i < (driveList.size() - 1)) + cout << ", "; + else { + if (driveList.size() > 1) + cout << " and "; } + } } - for (int i = optind; i < argc; i++) { - if ((strlen(argv[i]) != 2) || - (toupper(argv[i][0]) < 'A') || - (toupper(argv[i][0]) > 'Z') || - (argv[i][1] != ':')) { - usage(&cerr); - exit(1); - } + if (arch) { + if (doBackup) + cout << " to " << arch; + if (doRestore) + cout << " from " << arch; } + cout << endl; + } - pw = getpwuid(getuid()); - if (pw && pw->pw_dir && strlen(pw->pw_dir)) { - time_t now = time(0); - char tstr[80]; - strcpy(home, pw->pw_dir); - strftime(tstr, sizeof(tstr), "%Y-%m-%d-%H-%M-%S", - localtime(&now)); - sprintf(dstPath, "%s/plpbackup-%s/", home, tstr); - } else { - cerr << "Could not get user's home directory from /etc/passwd" << endl; - exit(-1); - } +} - skt = new ppsocket(); - if (!skt->connect(NULL, sockNum)) { - cerr << "plpbackup: could not connect to ncpd" << endl; - return 1; - } - skt2 = new ppsocket(); - if (!skt2->connect(NULL, sockNum)) { - cerr << "plpbackup: could not connect to ncpd" << endl; - return 1; - } - rfsvfactory *rf = new rfsvfactory(skt); - rpcsfactory *rp = new rpcsfactory(skt2); - a = rf->create(false); - r = rp->create(false); - if ((a != NULL) && (r != NULL)) { - Enum res; - Enum machType; - bool S5mx = false; - bool bErr = false; - int i; - unsigned long backupCount = 0; - char dest[1024]; - - r->getMachineType(machType); - if (machType == rpcs::PSI_MACH_S5) { - rpcs::machineInfo mi; - if ((res = r->getMachineInfo(mi)) == rfsv::E_PSI_GEN_NONE) { - if (!strcmp(mi.machineName, "SERIES5mx")) - S5mx = true; - } - } - if (verbose >= 0) { - cout << "Performing " << (full ? "full" : "incremental") << - " backup of "; - if (optind < argc) { - cout << "Drive "; - for (i = optind; i < argc; ) { - cout << argv[i++]; - if (i > optind) { - if (i < (argc - 1)) - cout << ", "; - else - if (i < argc) - cout << " and "; - } - } - } else - cout << "all drives"; - - cout << " to " << dstPath << endl; - } - if (verbose > 0) { - cout << "Stopping programs ..." << endl; +static double +tdiff(struct timeval *start, struct timeval *end) +{ + double s = (double)start->tv_sec * 1000000.0; + double e = (double)end->tv_sec * 1000000.0; + s += start->tv_usec; + e += end->tv_usec; + return (e - s) / 1000000.0; +} + +static int +runFormat() +{ + return 0; +} + +static void +runRestore() +{ + int i; + ostrstream tarcmd; + + for (i = 0; i < archList.size(); i++) { + tarcmd << "tar --to-stdout -xzf " << archList[i] + << " 'KPsion*Index'" << '\0'; + FILE *f = popen(tarcmd.str(), "r"); + pclose(f); + } +} + +static void +runBackup() +{ + vectorbackupDrives; + Enum res; + string dstPath; + string archPath; + bool bErr = false; + bool found; + int i; + struct timeval start_tv, end_tv, cstart_tv, cend_tv, sstart_tv, send_tv; + + gettimeofday(&start_tv, NULL); + if (archList.empty()) + archPath = generateBackupName(); + else + archPath = archList[0]; + dstPath = generateTmpDir(); + + startMessage(archPath.c_str()); + + // Stop all programs on Psion + stopPrograms(); + if (checkAbort()) { + // remove temporary dir + rmrf(dstPath.c_str()); + // restart previously killed programs + startPrograms(); + cout << _("Backup aborted by user") << endl; + return; + } + + gettimeofday(&sstart_tv, NULL); + // Scan for files to be backed up + backupCount = 0; + if (driveList.empty()) { + char drive[3]; + u_int32_t devbits; + + if (Rfsv->devlist(devbits) == rfsv::E_PSI_GEN_NONE) { + for (i = 0; i < 26; i++) { + PlpDrive psidr; + if ((devbits & 1) && Rfsv->devinfo(i + 'A', psidr) + == rfsv::E_PSI_GEN_NONE) { + if (psidr.getMediaType() != 7) { + sprintf(drive, "%c:\0", 'A' + i); + if (verbose > 0) + cout << _("Scanning Drive ") << drive << " ..." + << flush; + found = false; + collectFiles(found, drive); + if (verbose > 0) + cout << endl; + if (found) + backupDrives.push_back(drive); + } } - killsave(r, S5mx); - if (optind < argc) { - for (i = optind; i < argc; i++) { - if (verbose > 0) - cout << "Scanning Drive " << argv[i] << " ..." << endl; - collectFiles(a, argv[i]); - } + devbits >>= 1; + } + } else + cerr << _("plpbackup: Couldn't get Drive list") << endl; + } else { + for (i = 0; i < driveList.size(); i++) { + char *drive = (char *)driveList[i].c_str(); + if (verbose > 0) + cout << _("Scanning Drive ") << drive << " ..." << flush; + found = false; + collectFiles(found, drive); + if (verbose > 0) + cout << endl; + if (found) + backupDrives.push_back(drive); + } + } + gettimeofday(&send_tv, NULL); + if (checkAbort()) { + // remove temporary dir + rmrf(dstPath.c_str()); + // restart previously killed programs + startPrograms(); + cout << _("Backup aborted by user") << endl; + return; + } + + // Calculate number of files and total bytecount + for (i = 0; i < toBackup.size(); i++) { + backupSize += toBackup[i].getSize(); + backupCount++; + } + if (verbose > 0) + cout << _("Size of backup: ") << backupSize << _(" bytes in ") << + backupCount << _(" files.") << endl; + + if (backupCount == 0) + cerr << _("Nothing to backup") << endl; + else { + string dest; + + gettimeofday(&cstart_tv, NULL); + // copy all files to local temporary dir + for (i = 0; i < toBackup.size(); i++) { + PlpDirent e = toBackup[i]; + const char *fn = e.getName(); + + dest = dstPath; + dest += '/'; + dest += psion2unix(fn); + fileSize = e.getSize(); + if (verbose > 1) + cout << _("Backing up ") << fn << flush; + if (mkdirp(dest.c_str()) != 0) { + bErr = true; + break; + } + res = Rfsv->copyFromPsion(fn, dest.c_str(), NULL, cab); + if (checkAbort()) { + // remove temporary dir + rmrf(dstPath.c_str()); + // restart previously killed programs + startPrograms(); + cout << _("Backup aborted by user") << endl; + return; + } + if (verbose > 1) + cout << endl; + totalBytes += fileSize; + if (res != rfsv::E_PSI_GEN_NONE) { + if (skipError) { + e.setName("!"); + if (verbose > 0) + cerr << _("Skipping ") << fn << ": " + << res << endl; } else { - char drive[3]; - u_int32_t devbits; - - if (a->devlist(devbits) == rfsv::E_PSI_GEN_NONE) { - for (i = 0; i < 26; i++) { - PlpDrive psidr; - if ((devbits & 1) && a->devinfo(i + 'A', psidr) == rfsv::E_PSI_GEN_NONE) { - if (psidr.getMediaType() != 7) { - sprintf(drive, "%c:\0", 'A' + i); - if (verbose > 0) - cout << "Scanning Drive " << drive << " ..." << endl; - collectFiles(a, drive); - } - } - devbits >>= 1; - } - } else - cerr << "Couldn't get Drive list" << endl; + cerr << _("Error during backup of ") << fn << ": " + << res << endl; + if (isatty(0)) { + bool askLoop = true; + do { + char answer; + string vans = _("STAR"); + + cerr << _("(S)kip all, Skip (t)his, (A)bort, (R)etry: ") + << flush; + cin >> answer; + switch (vans.find(toupper(answer))) { + case 0: + skipError = true; + // fall thru + case 1: + e.setName("!"); + askLoop = false; + break; + case 2: + bErr = true; + i = toBackup.size(); + askLoop = false; + break; + case 3: + if (verbose > 1) + cout << _("Backing up ") << fn << flush; + break; + res = Rfsv->copyFromPsion(fn, dest.c_str(), NULL, cab); + if (checkAbort()) { + // remove temporary dir + rmrf(dstPath.c_str()); + // restart previously killed programs + startPrograms(); + cout << _("Backup aborted by user") + << endl; + return; + } + if (verbose > 1) + cout << endl; + if (res != rfsv::E_PSI_GEN_NONE) { + cerr << _("Error during backup of ") + << fn << ": " << res << endl; + } else + askLoop = false; + break; + } + } while (askLoop); + } else { + bErr = true; + break; + } } + } + } + gettimeofday(&cend_tv, NULL); + + // Create index file + if (!bErr) { + if (verbose > 0) + cout << _("Writing index ...") << endl; + dest = dstPath; + dest += "/KPsion"; + dest += ((full) ? "Full" : "Incremental"); + dest += "Index"; + ofstream op(dest.c_str()); + if (op) { + op << "#plpbackup index " << + (full ? "F" : "I") << endl; for (i = 0; i < toBackup.size(); i++) { - backupSize += toBackup[i].getSize(); - backupCount++; + PlpDirent e = toBackup[i]; + PsiTime t = e.getPsiTime(); + long attr = e.getAttr() & + ~rfsv::PSI_A_ARCHIVE; + op << hex + << setw(8) << setfill('0') << + t.getPsiTimeHi() << " " + << setw(8) << setfill('0') << + t.getPsiTimeLo() << " " + << setw(8) << setfill('0') << + e.getSize() << " " + << setw(8) << setfill('0') << + attr << " " + << setw(0) << e.getName() << endl; } - if (verbose > 0) - cout << "Size of backup: " << backupSize << " bytes in " << - backupCount << " files." << endl; - if (backupCount == 0) - cerr << "Nothing to backup" << endl; - else { - for (i = 0; i < toBackup.size(); i++) { - PlpDirent e = toBackup[i]; - const char *fn = e.getName(); - const char *p; - char *q; - char tmp[1024]; - - for (p = fn, q = tmp; *p; p++, q++) - switch (*p) { - case '%': - *q++ = '%'; - *q++ = '2'; - *q = '5'; - break; - case '/': - *q++ = '%'; - *q++ = '2'; - *q= 'f'; - break; - case '\\': - *q = '/'; - break; - default: - *q = *p; - } - *q = '\0'; - strcpy(dest, dstPath); - strcat(dest, tmp); - fileSize = e.getSize(); - if (verbose > 1) - cout << "Backing up " << fn << flush; - if (mkdirp(dest) != 0) { - bErr = true; - break; - } - res = a->copyFromPsion(fn, dest, NULL, cab); - if (verbose > 1) - cout << endl; - totalBytes += fileSize; - if (res != rfsv::E_PSI_GEN_NONE) { - cerr << "Error during backup of " << - fn << ": " << res << endl; - bErr = true; - break; - } - } - if (!bErr) { - if (verbose > 0) - cout << "Writing index ..." << endl; - strcpy(dest, dstPath); - strcat(dest, ".index"); - ofstream op(dest); - if (op) { - op << "#plpbackup index " << - (full ? "F" : "I") << endl; - for (i = 0; i < toBackup.size(); i++) { - PlpDirent e = toBackup[i]; - PsiTime t = e.getPsiTime(); - long attr = e.getAttr() & - ~rfsv::PSI_A_ARCHIVE; - op << hex - << setw(8) << setfill('0') << - t.getPsiTimeHi() << " " - << setw(8) << setfill('0') << - t.getPsiTimeLo() << " " - << setw(8) << setfill('0') << - e.getSize() << " " - << setw(8) << setfill('0') << - attr << " " - << setw(0) << e.getName() << endl; - } - op.close(); - } else { - cerr << "Could not write index " << dest << endl; - bErr = true; - } - } - if (!bErr) { - if (verbose > 0) - cout << "Resetting archive attributes ..." << endl; - for (i = 0; i < toBackup.size(); i++) { - PlpDirent e = toBackup[i]; - if (e.getAttr() & rfsv::PSI_A_ARCHIVE) { - res = a->fsetattr(e.getName(), 0, - rfsv::PSI_A_ARCHIVE); - if (res != rfsv::E_PSI_GEN_NONE) { - bErr = true; - break; - } - } - } - } + op.close(); + } else { + cerr << _("plpbackup: Could not write index ") << dest << endl; + bErr = true; + } + } + + // tar it all up + if (!bErr) { + ostrstream tarcmd; + + if (verbose > 0) + cout << _("Creating tar archive ...") << endl; + + tarcmd << "tar czCf"; + if (verbose > 1) + tarcmd << 'v'; + tarcmd << " " << dstPath << " " << archPath << " KPsion"; + tarcmd << (full ? "Full" : "Incremental") << "Index"; + for (i = 0; i < backupDrives.size(); i++) + tarcmd << " " << backupDrives[i]; + tarcmd << '\0'; + + mkdirp(archPath.c_str()); + if (system(tarcmd.str())) { + cerr << _("plpbackup: Error during execution of ") + << tarcmd.str() << endl; + unlink(archPath.c_str()); + bErr = true; + } + } + + // finally reset archive attributes + if (!bErr) { + if (verbose > 0) + cout << _("Resetting archive attributes ...") << endl; + for (i = 0; i < toBackup.size(); i++) { + PlpDirent e = toBackup[i]; + if (e.getAttr() & rfsv::PSI_A_ARCHIVE) { + res = Rfsv->fsetattr(e.getName(), 0, + rfsv::PSI_A_ARCHIVE); + if (res != rfsv::E_PSI_GEN_NONE) { + bErr = true; + break; + } } - if (bErr) - cerr << "Backup aborted due to error" << endl; - if (verbose > 0) - cout << "Restarting programs ..." << endl; - runrestore(a, r); - delete r; - delete a; - } else { - if (!a) - cerr << "plpbackup: could not create rfsv object" << endl; - if (!r) - cerr << "plpbackup: could not create rpcs object" << endl; - exit(1); + } } - return 0; + } + + // remove temporary dir + rmrf(dstPath.c_str()); + + if (bErr) + cerr << _("Backup aborted due to error") << endl; + + // restart previously killed programs + startPrograms(); + gettimeofday(&end_tv, NULL); + if (!checkAbort() && verbose > 0) { + cout << _("Total time elapsed: ") << tdiff(&start_tv, &end_tv) + << endl; + cout << _("Time for scanning: ") << tdiff(&sstart_tv, &send_tv) + << endl; + if (backupSize > 0) { + cout << _("Time for transfer: ") << tdiff(&cstart_tv, &cend_tv) + << endl; + cout << _("Average transfer speed: ") + << (double)backupSize / tdiff(&cstart_tv, &cend_tv) << endl; + } + } +} + +void +usage(ostream *hlp) +{ + if (hlp == &cout) { + *hlp << + _("Usage: plpbackup OPTIONS [:] [:] ...\n" + "\n" + " Options:\n" + " -h, --help Print this message and exit.\n" + " -V, --version Print version and exit.\n" + " -p, --port= Connect to ncpd using given port.\n" + " -v, --verbose Increase verbosity.\n" + " -q, --quiet Decrease verbosity.\n" + " -f, --full Do a full backup (incremental otherwise).\n" + " -b, --backup[=TGZ] Backup to specified archive TGZ.\n" + " -r, --restore=TGZ Restore from specified archive TGZ.\n" + " -F, --format Format drive (can be combined with restore).\n" + "\n" + " A drive character. If none given, scan all drives.\n" + "\n"); + exit(0); + } else { + *hlp << _("Try 'plpbackup --help' for more information.") << endl; + exit(1); + } +} + +static struct option opts[] = { + { "full", no_argument, 0, 'f' }, + { "help", no_argument, 0, 'h' }, + { "port", required_argument, 0, 'V' }, + { "verbose", no_argument, 0, 'v' }, + { "quiet", no_argument, 0, 'q' }, + { "backup", optional_argument, 0, 'b' }, + { "restore", required_argument, 0, 'r' }, + { "format", no_argument, 0, 'F' }, + { "version", no_argument, 0, 'V' }, + { 0, 0, 0, 0 }, +}; + +int +main(int argc, char **argv) +{ + ppsocket *skt; + ppsocket *skt2; + int sockNum = DPORT; + int op; + + setlocale (LC_ALL, ""); + textdomain(PACKAGE); + + struct servent *se = getservbyname("psion", "tcp"); + endservent(); + if (se != 0L) + sockNum = ntohs(se->s_port); + + // Command line parameter processing + opterr = 1; + while ((op = getopt_long(argc, argv, "fFhqvVp:r:b::", opts, NULL)) != EOF) { + switch (op) { + case 'V': + cout << _("plpbackup version ") << VERSION << endl; + exit(0); + case 'h': + usage(&cout); + break; + case 'f': + full = true; + break; + case 'v': + verbose++; + break; + case 'q': + verbose--; + break; + case 'b': + doBackup = true; + if (optarg) + archList.push_back(optarg); + break; + case 'r': + doRestore = true; + archList.push_back(optarg); + break; + case 'F': + doFormat = true; + break; + case 'p': + sockNum = atoi(optarg); + break; + default: + usage(&cerr); + } + } + for (int i = optind; i < argc; i++) { + if ((strlen(argv[i]) != 2) || + (toupper(argv[i][0]) < 'A') || + (toupper(argv[i][0]) > 'Z') || + (argv[i][1] != ':')) { + cerr << _("Invalid drive argument ") << argv[i] << endl; + usage(&cerr); + } + driveList.push_back(argv[i]); + } + if (doBackup && (doRestore || doFormat)) { + cerr << _("Backup mode can not be combined with format or restore.") + << endl; + usage(&cerr); + } + if (doFormat && driveList.empty()) { + cerr << _("Format mode needs at least one drive specified.") << endl; + usage(&cerr); + } + if (doBackup && (archList.size() > 1)) { + cerr << _("Backup can only create one archive at a time.") << endl; + usage(&cerr); + } + + signal(SIGTERM, sig_handler); + signal(SIGINT, sig_handler); + // Connect to Psion + skt = new ppsocket(); + if (!skt->connect(NULL, sockNum)) { + cerr << _("plpbackup: could not connect to ncpd") << endl; + return 1; + } + skt2 = new ppsocket(); + if (!skt2->connect(NULL, sockNum)) { + cerr << _("plpbackup: could not connect to ncpd") << endl; + return 1; + } + rfsvfactory *rf = new rfsvfactory(skt); + rpcsfactory *rp = new rpcsfactory(skt2); + Rfsv = rf->create(false); + if (Rfsv == NULL) { + cerr << "plpbackup: " << X_(rf->getError()) << endl; + exit(1); + } + Rpcs = rp->create(false); + if (Rpcs == NULL) { + cerr << "plpbackup: " << X_(rp->getError()) << endl; + exit(1); + } + + Enum res; + Enum machType; + + Rpcs->getMachineType(machType); + if (machType == rpcs::PSI_MACH_S5) { + rpcs::machineInfo mi; + if ((res = Rpcs->getMachineInfo(mi)) == + rfsv::E_PSI_GEN_NONE) { + if (!strcmp(mi.machineName, "SERIES5mx")) + S5mx = true; + } + } + if (doBackup) + runBackup(); + if (doRestore) + runRestore(); + if (doFormat) + runFormat(); + delete Rpcs; + delete Rfsv; + return 0; } diff --git a/plpprint/.cvsignore b/plpprint/.cvsignore new file mode 100644 index 0000000..067f1e1 --- /dev/null +++ b/plpprint/.cvsignore @@ -0,0 +1,5 @@ +Makefile.in +Makefile +.libs +.deps +plpprintd diff --git a/plpprint/Makefile.am b/plpprint/Makefile.am new file mode 100644 index 0000000..f0d0a4e --- /dev/null +++ b/plpprint/Makefile.am @@ -0,0 +1,10 @@ +# $Id$ +# +INCLUDES=-I$(top_srcdir)/lib + +sbin_PROGRAMS = plpprintd +plpprintd_LDADD = $(top_srcdir)/lib/libplp.la +plpprintd_SOURCES = plpprintd.cc + +maintainer-clean-local: + rm -f Makefile.in diff --git a/plpprint/plpprintd.cc b/plpprint/plpprintd.cc new file mode 100644 index 0000000..7cf4006 --- /dev/null +++ b/plpprint/plpprintd.cc @@ -0,0 +1,310 @@ +/*-*-c++-*- + * $Id$ + * + * This file is part of plptools. + * + * Copyright (C) 1999-2001 Fritz Elfert + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define _GNU_SOURCE +#include + +#define TEMPLATE "plpprint_XXXXXX" + +char *spooldir = "/var/spool/plpprint"; +char *printcmd = "lpr -Ppsion"; +wprt *wPrt; +bool serviceLoop; +bool debug = false; +int verbose = 0; + +#define alloc_print(p) \ +do { \ + /* Guess we need no more than 100 bytes. */ \ + int n, size = 100; \ + va_list ap; \ + if ((p = (char *)malloc(size)) == NULL) \ + return 0; \ + while (1) { \ + /* Try to print in the allocated space. */ \ + va_start(ap, fmt); \ + n = vsnprintf(p, size, fmt, ap); \ + va_end(ap); \ + /* If that worked, return the string. */ \ + if (n > -1 && n < size) \ + break; \ + /* Else try again with more space. */ \ + if (n > -1) /* glibc 2.1 */ \ + size = n+1; /* precisely what is needed */ \ + else /* glibc 2.0 */ \ + size *= 2; /* twice the old size */ \ + if ((p = (char *)realloc(p, size)) == NULL) \ + return 0; \ + } \ +} while (0) + +int +debuglog(char *fmt, ...) +{ + char *buf; + alloc_print(buf); + if (debug) + cout << buf << endl; + else + syslog(LOG_DEBUG, buf); + free(buf); + return 0; +} + +int +errorlog(char *fmt, ...) +{ + char *buf; + alloc_print(buf); + if (debug) + cerr << buf << endl; + else + syslog(LOG_ERR, buf); + free(buf); + return 0; +} + +int +infolog(char *fmt, ...) +{ + char *buf; + alloc_print(buf); + if (debug) + cout << buf << endl; + else + syslog(LOG_INFO, buf); + free(buf); + return 0; +} + +static void +convert_job(const char *jobname) +{ + // ... To be done ... + unlink(jobname); +} + +static void +service_loop() +{ + serviceLoop = true; + while (serviceLoop) { + bool spoolOpen = false; + bufferStore c; + int fd; + char *jname = + (char *)malloc(strlen(spooldir) + + strlen(TEMPLATE) + 2); + + while (1) { + /* Job loop */ + c.init(); + if (wPrt->getData(c) != rfsv::E_PSI_GEN_NONE) { + if (spoolOpen) { + unlink(jname); + close(fd); + errorlog("Job aborted"); + } + free(jname); + return; + } + if ((c.getLen() == 15) && (c.getWord(0) == 0x2a2a)) { + sprintf(jname, "%s/%s", spooldir, TEMPLATE); + if ((fd = mkstemp(jname)) != -1) { + debuglog("Receiving new job %s", jname); + write(fd, c.getString(0), c.getLen()); + spoolOpen = true; + } else + errorlog("Could not create spool file."); + } else { + if (spoolOpen) + write(fd, c.getString(0), c.getLen()); + if (c.getWord(0) == 0xffff) + break; + } + } + if (spoolOpen) { + close(fd); + spoolOpen = false; + debuglog("Job received, start conversion ..."); + convert_job(jname); + } + free(jname); + } +} + +static void +help() { + cout << + "Options of plpprintd:\n" + "\n" + " -d, --debug Debugging, do not fork.\n" + " -h, --help Display this text.\n" + " -v, --verbose Increase verbosity.\n" + " -V, --version Print version and exit.\n" + " -p, --port=NUM Connect to port NUM.\n" + " -s, --spooldir=DIR Specify spooldir DIR.\n" + " -c, --printcmd=CMD Specify print command.\n"; +} + +static void +usage() { + cerr << "Usage: plpprintd [OPTIONS]" << endl + << "Use --help for more information" << endl; +} + +static struct option opts[] = { + {"debug", no_argument, 0, 'd'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {"port", required_argument, 0, 'p'}, + {"spooldir", required_argument, 0, 's'}, + {"printcmd", required_argument, 0, 'c'}, + {NULL, 0, 0, 0 } +}; + +int +main(int argc, char **argv) +{ + ppsocket *skt; + int status = 0; + int sockNum = DPORT; + int ret = 0; + int c; + + struct servent *se = getservbyname("psion", "tcp"); + endservent(); + if (se != 0L) + sockNum = ntohs(se->s_port); + + while (1) { + c = getopt_long(argc, argv, "dhVvp:s:c:", opts, NULL); + if (c == -1) + break; + switch (c) { + case '?': + usage(); + return -1; + case 'd': + debug = true; + break; + case 'v': + verbose++; + break; + case 'V': + cout << "plpprintd Version " << VERSION << endl; + return 0; + case 'h': + help(); + return 0; + case 'p': + sscanf(optarg, "%hd", &sockNum); + break; + case 's': + spooldir = strdup(optarg); + break; + case 'c': + printcmd = strdup(optarg); + break; + } + } + if (optind < argc) { + usage(); + return -1; + } + + skt = new ppsocket(); + if (!skt->connect(NULL, sockNum)) { + cout << _("plpprintd: could not connect to ncpd") << endl; + return 1; + } + if (!debug) + ret = fork(); + switch (ret) { + case 0: + /* child */ + setsid(); + chdir("/"); + if (!debug) { + openlog("plpprintd", LOG_PID|LOG_CONS, LOG_DAEMON); + int devnull = + open("/dev/null", O_RDWR, 0); + if (devnull != -1) { + dup2(devnull, STDIN_FILENO); + dup2(devnull, STDOUT_FILENO); + dup2(devnull, STDERR_FILENO); + if (devnull > 2) + close(devnull); + } + } + infolog("started, waiting for requests.\n"); + serviceLoop = true; + while (serviceLoop) { + wPrt = new wprt(skt); + if (wPrt) { + Enum ret; + ret = wPrt->initPrinter(); + if (ret == rfsv::E_PSI_GEN_NONE) + service_loop(); + else + debuglog("plpprintd: could not connect: %s", + ret.toString().c_str()); + delete wPrt; + } else { + errorlog("plpprintd: Could not create wprt object"); + exit(1); + } + } + break; + case -1: + cerr << "plpprintd: fork failed" << endl; + return 1; + default: + /* parent */ + break; + } + return 0; +} + +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ diff --git a/po/POTFILES.in b/po/POTFILES.in index 2beda20..d7672ba 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -7,3 +7,4 @@ lib/rfsvfactory.cc plpftp/main.cc plpftp/ftp.cc +plpbackup/plpbackup.cc diff --git a/po/de.po b/po/de.po index e7a2063..c1ee92b 100644 --- a/po/de.po +++ b/po/de.po @@ -4,15 +4,15 @@ # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2001-05-21 17:29+0200\n" -"PO-Revision-Date: 2001-02-28 02:44CET\n" +"Project-Id-Version: plptools 0.11\n" +"POT-Creation-Date: 2002-02-13 19:00+0100\n" +"PO-Revision-Date: 2002-02-13 19:10CET\n" "Last-Translator: Fritz Elfert \n" "Language-Team: Deutsch \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 0.8\n" +"X-Generator: KBabel 0.9.5\n" #: lib/rfsv.cc:31 lib/rfsvfactory.cc:43 lib/rpcsfactory.cc:43 msgid "no error" @@ -296,7 +296,7 @@ msgstr "beendet" #: lib/rfsv.cc:101 msgid "died" -msgstr "abgestürtzt" +msgstr "abgestürzt" #: lib/rfsv.cc:102 msgid "bad handle" @@ -424,7 +424,7 @@ msgstr "Schweizer Deutsch" #: lib/rpcs.cc:75 msgid "Portugese" -msgstr "Potugiesisch" +msgstr "Portugiesisch" #: lib/rpcs.cc:76 msgid "Turkish" @@ -464,7 +464,7 @@ msgstr "Österreichisch" #: lib/rpcs.cc:85 msgid "New Zealand" -msgstr "Neu-Seeländisch" +msgstr "Neuseeländisch" #. FIXME: not shure about ISO code #: lib/rpcs.cc:86 @@ -654,7 +654,7 @@ msgstr "Dies ist freie Software. Sie können Sie unter den Bedingungen" #: plpftp/main.cc:59 msgid "under GPL conditions; see the COPYING file in the distribution." -msgstr "der GPL weitergeben. Siehe die Datei COPYING im Packet." +msgstr "der GPL weitergeben. Siehe die Datei COPYING im Paket." #: plpftp/main.cc:61 msgid "FTP like interface started. Type \"?\" for help." @@ -714,7 +714,7 @@ msgstr "Lokaler Ordner: \"" #: plpftp/ftp.cc:295 msgid "Psion dir: \"" -msgstr "Psion Orner: \"" +msgstr "Psion Ordner: \"" #: plpftp/ftp.cc:300 plpftp/ftp.cc:310 plpftp/ftp.cc:319 plpftp/ftp.cc:327 #: plpftp/ftp.cc:335 plpftp/ftp.cc:345 plpftp/ftp.cc:357 plpftp/ftp.cc:403 @@ -722,7 +722,7 @@ msgstr "Psion Orner: \"" #: plpftp/ftp.cc:519 plpftp/ftp.cc:545 plpftp/ftp.cc:582 plpftp/ftp.cc:610 #: plpftp/ftp.cc:671 plpftp/ftp.cc:691 plpftp/ftp.cc:698 plpftp/ftp.cc:705 #: plpftp/ftp.cc:761 plpftp/ftp.cc:771 plpftp/ftp.cc:831 plpftp/ftp.cc:873 -#: plpftp/ftp.cc:883 plpftp/ftp.cc:914 plpftp/ftp.cc:950 plpftp/ftp.cc:1006 +#: plpftp/ftp.cc:883 plpftp/ftp.cc:914 plpftp/ftp.cc:950 plpftp/ftp.cc:1016 msgid "Error: " msgstr "Fehler: " @@ -746,9 +746,9 @@ msgstr "Behalte ursprünglichen Ordner \"" msgid "Transfer complete, (" msgstr "Übertragung abgeschlossen, (" -#: plpftp/ftp.cc:537 plpftp/ftp.cc:628 +#: plpbackup/plpbackup.cc:499 plpftp/ftp.cc:537 plpftp/ftp.cc:628 msgid " bytes in " -msgstr " bytes in " +msgstr " Bytes in " #: plpftp/ftp.cc:538 plpftp/ftp.cc:629 msgid " secs = " @@ -925,3 +925,157 @@ msgstr "Kein solcher Prozess" #: plpftp/ftp.cc:966 msgid "syntax error. Try \"help\"" msgstr "Syntaxfehler. Probieren Sie \"help\"" + +#: plpbackup/plpbackup.cc:83 +msgid "Could not get user's home directory from /etc/passwd" +msgstr "Konnte das persönliche Verzeichnis nicht ermitteln" + +#: plpbackup/plpbackup.cc:98 +msgid "Could not get machine UID" +msgstr "Konnte Geräte-UID nicht ermitteln" + +#: plpbackup/plpbackup.cc:126 +msgid "Stopping programs ..." +msgstr "Stoppe Programme ..." + +#: plpbackup/plpbackup.cc:128 +msgid "plpbackup: Could not get process list: " +msgstr "plpbackup: Konnte Prozessliste nicht lesen " + +#: plpbackup/plpbackup.cc:162 +msgid "Restarting programs ..." +msgstr "Starte Programme ..." + +#: plpbackup/plpbackup.cc:469 plpbackup/plpbackup.cc:485 +msgid "Scanning Drive " +msgstr "Durchsuche Laufwerk " + +#: plpbackup/plpbackup.cc:480 +msgid "plpbackup: Couldn't get Drive list" +msgstr "plpbackup: Konnte Laufwerks-Liste nicht ermitteln" + +#: plpbackup/plpbackup.cc:499 +msgid "Size of backup: " +msgstr "Umfang der Sicherung: " + +#: plpbackup/plpbackup.cc:500 +msgid " files." +msgstr " Dateien." + +#: plpbackup/plpbackup.cc:503 +msgid "Nothing to backup" +msgstr "Nichts zu sichern" + +#: plpbackup/plpbackup.cc:518 plpbackup/plpbackup.cc:560 +msgid "Backing up " +msgstr "Sichere " + +#: plpbackup/plpbackup.cc:531 +msgid "Skipping " +msgstr "Überspringe " + +#: plpbackup/plpbackup.cc:534 plpbackup/plpbackup.cc:566 +msgid "Error during backup of " +msgstr "Fehler beim Sichern von " + +#: plpbackup/plpbackup.cc:540 +# This are the characters for valid answers +# of the next message. +msgid "STAR" +msgstr "SDAW" + +#: plpbackup/plpbackup.cc:542 +msgid "(S)kip all, Skip (t)his, (A)bort, (R)etry: " +msgstr "Über(S)pringe alle, Überspringe (D)iese, (A)bbruch, (W)iederholen: " + +#: plpbackup/plpbackup.cc:584 +msgid "Writing index ..." +msgstr "Schreibe Index ..." + +#: plpbackup/plpbackup.cc:611 +msgid "plpbackup: Could not write index " +msgstr "plpbackup: Konnte Index nicht schreiben " + +#: plpbackup/plpbackup.cc:621 +msgid "Creating tar archive ..." +msgstr "Lege tar-Archiv an ..." + +#: plpbackup/plpbackup.cc:631 +msgid "plpbackup: Error during execution of " +msgstr "plpbackup: Fehler beim Ausführen von " + +#: plpbackup/plpbackup.cc:640 +msgid "Resetting archive attributes ..." +msgstr "Archiv-Attribute zurücksetzen ..." + +#: plpbackup/plpbackup.cc:660 +msgid "Backup aborted due to error" +msgstr "Sicherung wegen Fehler abgebrochen" + +#: plpbackup/plpbackup.cc:671 +msgid "" +"Usage: plpbackup OPTIONS [:] [:] ...\n" +"\n" +" Options:\n" +" -h, --help Print this message and exit.\n" +" -V, --version Print version and exit.\n" +" -p, --port= Connect to ncpd using given port.\n" +" -v, --verbose Increase verbosity.\n" +" -q, --quiet Decrease verbosity.\n" +" -f, --full Do a full backup (incremental otherwise).\n" +" -b, --backup[=TGZ] Backup to specified archive TGZ.\n" +" -r, --restore=TGZ Restore from specified archive TGZ.\n" +" -F, --format Format drive (can be combined with restore).\n" +"\n" +" A drive character. If none given, scan all drives.\n" +"\n" +msgstr "" +"Benutzung: plpbackup OPTIONEN [:] [:] ...\n" +"\n" +" Optionen:\n" +" -h, --help Anzeige dieses Textes und beenden.\n" +" -V, --version Anzeige der Version und beenden.\n" +" -p, --port= Mit ncpd über angegebenen Port verbinden.\n" +" -v, --verbose Ausführlichere Meldungen.\n" +" -q, --quiet Weniger ausführliche Meldungen.\n" +" -f, --full Komplettsicherung durchführen (andernfalls " +"inkrementell).\n" +" -b, --backup[=TGZ] Sicherung in das angegebene Archiv TGZ.\n" +" -r, --restore=TGZ Rücksicherung vom angegebenen Archiv TGZ.\n" +" -F, --format Formatiere Laufwerk (kann mit restore kombiniert " +"werden).\n" +"\n" +" Ein Laufwerksbuchstabe. Wird keiner angegeben, durchsuche alle " +"Laufwerke.\n" +"\n" + +#: plpbackup/plpbackup.cc:688 +msgid "Try 'plpbackup --help' for more information." +msgstr "Versuchen Sie 'plpbackup --help' für weitere Informationen." + +#: plpbackup/plpbackup.cc:727 +msgid "plpbackup version " +msgstr "plpbackup Version " + +#: plpbackup/plpbackup.cc:765 +msgid "Invalid drive argument " +msgstr "Ungültiges Laufwerk " + +#: plpbackup/plpbackup.cc:771 +msgid "Backup mode can not be combined with format or restore." +msgstr "" +"Sicherungs-Modus kann nicht mit Formatieren oder Rücksicherung kombiniert " +"werden." + +#: plpbackup/plpbackup.cc:776 +msgid "Format mode needs at least one drive specified." +msgstr "Formatier-Modus benötigt mindestens eine Laufwerksangabe." + +#: plpbackup/plpbackup.cc:780 +msgid "Backup can only create one archive at a time." +msgstr "Die Sicherung kann nur jeweils ein Archiv zu einer Zeit anlegen." + +#: plpbackup/plpbackup.cc:787 plpbackup/plpbackup.cc:792 +msgid "plpbackup: could not connect to ncpd" +msgstr "plpbackup: Konnte ncpd nicht kontaktieren" + -- cgit v1.2.3